[clang] 317aa53 - [clang] Fix crash in __builtin_stdc_bit_ceil for a 1-bit _BitInt (#214822)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 10 11:50:58 PDT 2026
Author: NagaChaitanya Vellanki
Date: 2026-08-10T11:50:53-07:00
New Revision: 317aa53cbc0866a82d41e162144118797e4f3615
URL: https://github.com/llvm/llvm-project/commit/317aa53cbc0866a82d41e162144118797e4f3615
DIFF: https://github.com/llvm/llvm-project/commit/317aa53cbc0866a82d41e162144118797e4f3615.diff
LOG: [clang] Fix crash in __builtin_stdc_bit_ceil for a 1-bit _BitInt (#214822)
The literal 2 as an ArgType constant requires at least 2 bits. For a
1-bit unsigned _BitInt, this triggers an assertion failure in APInt's
constructor (and silently computes a corrupted result in NDEBUG builds).
Compute the value via a shift of the always-valid constant 1 instead, so
it never depends on ArgType's width.
Fixes: #214478
Added:
Modified:
clang/lib/CodeGen/CGBuiltin.cpp
clang/test/CodeGen/builtin-stdc-bit-functions.c
clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
Removed:
################################################################################
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 4c1318f6543c1..3521fc10f1387 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4164,10 +4164,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_stdc_bit_ceil: {
Value *ArgValue = EmitScalarExpr(E->getArg(0));
llvm::Type *ArgType = ArgValue->getType();
- unsigned BitWidth = ArgType->getIntegerBitWidth();
Value *One = ConstantInt::get(ArgType, 1);
- Value *Two = ConstantInt::get(ArgType, 2);
-
Value *IsLEOne = Builder.CreateICmpULE(ArgValue, One, "isleone");
BasicBlock *EntryBB = Builder.GetInsertBlock();
@@ -4183,8 +4180,10 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
// 2<<(BitWidth-1-LZ) to get the next power of two. The shift
// amount is always in [0, BitWidth-1], so when LZ==0 (argument has its MSB
// set), the result wraps to 0
+ unsigned BitWidth = ArgType->getIntegerBitWidth();
Value *ShiftAmt =
Builder.CreateSub(ConstantInt::get(ArgType, BitWidth - 1), LZ);
+ Value *Two = Builder.CreateShl(One, One);
Value *Tmp = Builder.CreateShl(Two, ShiftAmt);
Builder.CreateBr(MergeBB);
diff --git a/clang/test/CodeGen/builtin-stdc-bit-functions.c b/clang/test/CodeGen/builtin-stdc-bit-functions.c
index 1d7b99122135f..e4fd8f77b0e35 100644
--- a/clang/test/CodeGen/builtin-stdc-bit-functions.c
+++ b/clang/test/CodeGen/builtin-stdc-bit-functions.c
@@ -319,6 +319,13 @@ void test_bitint_first_and_count(unsigned _BitInt(9) bi9) {
r = __builtin_stdc_count_zeros(bi9);
}
+// CHECK-LABEL: test_bit_ceil_bitint1
+// CHECK: shl i1 poison, %{{.*}}
+// CHECK: phi i1 [ true, %{{.*}} ], [ %{{.*}}, %bitceil.calc ]
+void test_bit_ceil_bitint1(unsigned _BitInt(1) bi1) {
+ volatile unsigned _BitInt(1) r = __builtin_stdc_bit_ceil(bi1);
+}
+
// CHECK-LABEL: test_bit_floor_all_ones_bitint
// CHECK: store volatile i32 65536, ptr %r
void test_bit_floor_all_ones_bitint(void) {
diff --git a/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp b/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
index 8bcaa16e991ad..9354c65432fc1 100644
--- a/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
+++ b/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
@@ -355,6 +355,10 @@ static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(37))0x11) == 0x20, "");
static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(17))(-1)) ==
(unsigned _BitInt(17))(0), "");
+// _BitInt(1):
+static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(1))0) == 1, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(1))1) == 1, "");
+
// _BitInt(128): sparse pattern, leading zero count, popcount.
constexpr unsigned _BitInt(128) bi128_pattern = 0x123456789ABCDEF0ULL;
static_assert(__builtin_stdc_count_ones(bi128_pattern) == 32, "");
More information about the cfe-commits
mailing list