[llvm] Fix APInt::concat for zero-width operands (PR #207475)

Yi Zhang via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 6 12:56:03 PDT 2026


https://github.com/cathyzhyi updated https://github.com/llvm/llvm-project/pull/207475

>From 9a3d743da5544dc6650c52964488eee218811639 Mon Sep 17 00:00:00 2001
From: Yi Zhang <cathyzhyi at google.com>
Date: Fri, 3 Jul 2026 20:36:46 -0400
Subject: [PATCH] [Support][APint] Fix concat for zero-width operands

APInt::concat triggered undefined behavior (invalid shift exponent) when
concatenating a zero-width operand with a 64-bit operand on the fast path
(combined width <= 64). For example, `I0.concat(I64)` resulted in
`U.VAL << 64`, which is UB.
Fix by checking for zero-width operands early and returning the other
operand. Added regression tests to `APIntTest.cpp`.
---
 llvm/include/llvm/ADT/APInt.h    | 2 ++
 llvm/unittests/ADT/APIntTest.cpp | 1 +
 2 files changed, 3 insertions(+)

diff --git a/llvm/include/llvm/ADT/APInt.h b/llvm/include/llvm/ADT/APInt.h
index 026efbe866a93..b59d3e9321bae 100644
--- a/llvm/include/llvm/ADT/APInt.h
+++ b/llvm/include/llvm/ADT/APInt.h
@@ -952,6 +952,8 @@ class [[nodiscard]] APInt {
   /// equivalent to:
   ///   (this->zext(NewWidth) << NewLSB.getBitWidth()) | NewLSB.zext(NewWidth)
   APInt concat(const APInt &NewLSB) const {
+    if (getBitWidth() == 0)
+      return NewLSB;
     /// If the result will be small, then both the merged values are small.
     unsigned NewWidth = getBitWidth() + NewLSB.getBitWidth();
     if (NewWidth <= APINT_BITS_PER_WORD)
diff --git a/llvm/unittests/ADT/APIntTest.cpp b/llvm/unittests/ADT/APIntTest.cpp
index 0eea32480d0bf..9a0ff612c4985 100644
--- a/llvm/unittests/ADT/APIntTest.cpp
+++ b/llvm/unittests/ADT/APIntTest.cpp
@@ -3132,6 +3132,7 @@ TEST(APIntTest, concat) {
 
   APInt I65(65, 0x3ULL);
   APInt I0 = APInt::getZeroWidth();
+  EXPECT_EQ(I64, I0.concat(I64));
   EXPECT_EQ(I65, I65.concat(I0));
   EXPECT_EQ(I65, I0.concat(I65));
 }



More information about the llvm-commits mailing list