[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