[clang] [Clang] Fix crash on comparisons of `_BitInt` vectors wider than 128 bits (PR #232797)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 16 08:50:52 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Akash Manna (akash-manna-sky)
<details>
<summary>Changes</summary>
Fixes #<!-- -->200665
`Sema::GetSignedVectorType` picks the element type for the result of a vector comparison by matching the element's size against `char`, `short`, `int`, `__int128`, `long` and `long long`, and asserts when nothing matches. Since `_BitInt` became a legal vector element in Clang 16, any `_BitInt` wider than 128 bits falls off the end of that chain: `a > 0` on a `_BitInt(512)` vector trips the assertion, and a release build hands back a `long long` vector instead. Sub-byte widths had the opposite problem: `_BitInt(4)` reports a padded size of 8, so its comparisons quietly came back as `char` vectors. The malformed input in the report is incidental; a plain `v3i512 f(v3i512 a) { return a > 0; }` crashes the same way.
A `_BitInt` element is now handled before the size chain: the result is the signed `_BitInt` of the same width, in the same vector kind and with the same element count, which is what the comparison semantics call for anyway. The builtin chain is unchanged, so no other element type is affected, and `_BitInt(128)` keeps its `_BitInt` type rather than turning into `__int128`, so the result always mirrors the operand.
AI assisted.
---
Full diff: https://github.com/llvm/llvm-project/pull/232797.diff
5 Files Affected:
- (modified) clang/docs/ReleaseNotes.md (+1)
- (modified) clang/lib/Sema/SemaExpr.cpp (+8)
- (modified) clang/test/CodeGenCXX/ext-int.cpp (+44)
- (modified) clang/test/Sema/ext-int.c (+49)
- (added) clang/test/SemaCXX/ext-int-vector.cpp (+93)
``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 3f0c48cf36644..a69c3f13b41d7 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -725,6 +725,7 @@ features cannot lower the translation-unit ABI level;
- Fixed an ICE hat occurred when using `__imag int/float` as lvalue in assignment. (#GH119498)
- Fixed a C23 rejects-valid where `auto T x;` (with `T` a typedef-name) was rejected as a missing initializer. (#GH164930)
- Fixed an assertion failure in `-Wsign-compare` when a negated or complemented vector of unsigned integers was compared against a signed constant. (#GH203575)
+- Fixed a crash when comparing vectors of `_BitInt` wider than 128 bits. (#GH200665)
- Fixed an assertion failure when a constant statement expression that declares a variable is used as a bound of an OpenMP loop. A statement expression in a bound of a non-rectangular loop is now diagnosed. (#GH153987)
- Fixed a bug where a bit-field accessed as the result of a statement expression
(e.g. `({ s.b; })`) was not subject to integer promotion, unlike an ordinary
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index e29caaab8e3f3..3bdcc5b9df100 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -13633,6 +13633,14 @@ QualType Sema::CheckCompareOperands(ExprResult &LHS, ExprResult &RHS,
QualType Sema::GetSignedVectorType(QualType V) {
const VectorType *VTy = V->castAs<VectorType>();
+ if (const auto *BIT = VTy->getElementType()->getAs<BitIntType>()) {
+ QualType EltTy =
+ Context.getBitIntType(/*IsUnsigned=*/false, BIT->getNumBits());
+ if (isa<ExtVectorType>(VTy))
+ return Context.getExtVectorType(EltTy, VTy->getNumElements());
+ return Context.getVectorType(EltTy, VTy->getNumElements(),
+ VectorKind::Generic);
+ }
unsigned TypeSize = Context.getTypeSize(VTy->getElementType());
if (isa<ExtVectorType>(VTy)) {
diff --git a/clang/test/CodeGenCXX/ext-int.cpp b/clang/test/CodeGenCXX/ext-int.cpp
index a45720c53e877..6f78adc34e4be 100644
--- a/clang/test/CodeGenCXX/ext-int.cpp
+++ b/clang/test/CodeGenCXX/ext-int.cpp
@@ -618,6 +618,50 @@ uint2_t2 TestBitIntVector2x2Alloca(uint2_t2 v1, uint2_t2 v2) {
return v1 + v2;
}
+typedef _BitInt(512) vint512_t3 __attribute__((ext_vector_type(3)));
+typedef _BitInt(256) vint256_t2 __attribute__((vector_size(64)));
+typedef unsigned _BitInt(256) uvint256_t2 __attribute__((vector_size(64)));
+
+vint512_t3 VectorCompareGTZero(vint512_t3 a) {
+ // CHECK: %[[CMP:.+]] = icmp sgt <3 x i512> %{{.+}}, zeroinitializer
+ // CHECK: %[[SEXT:.+]] = sext <3 x i1> %[[CMP]] to <3 x i512>
+ return a > 0;
+}
+
+vint256_t2 VectorCompareEQ(vint256_t2 a, vint256_t2 b) {
+ // CHECK: %[[CMP:.+]] = icmp eq <2 x i256> %{{.+}}, %{{.+}}
+ // CHECK: %[[SEXT:.+]] = sext <2 x i1> %[[CMP]] to <2 x i256>
+ return a == b;
+}
+
+vint256_t2 VectorCompareULT(uvint256_t2 a, uvint256_t2 b) {
+ // CHECK: %[[CMP:.+]] = icmp ult <2 x i256> %{{.+}}, %{{.+}}
+ // CHECK: %[[SEXT:.+]] = sext <2 x i1> %[[CMP]] to <2 x i256>
+ return a < b;
+}
+
+vint512_t3 VectorLogicalNot(vint512_t3 a) {
+ // CHECK: %[[CMP:.+]] = icmp eq <3 x i512> %{{.+}}, zeroinitializer
+ // CHECK: %[[SEXT:.+]] = sext <3 x i1> %[[CMP]] to <3 x i512>
+ return !a;
+}
+
+vint256_t2 VectorLogicalAnd(vint256_t2 a, vint256_t2 b) {
+ // CHECK: %[[LHS:.+]] = icmp ne <2 x i256> %{{.+}}, zeroinitializer
+ // CHECK: %[[RHS:.+]] = icmp ne <2 x i256> %{{.+}}, zeroinitializer
+ // CHECK: %[[AND:.+]] = and <2 x i1> %[[LHS]], %[[RHS]]
+ // CHECK: %[[SEXT:.+]] = sext <2 x i1> %[[AND]] to <2 x i256>
+ return a && b;
+}
+
+vint512_t3 VectorSelect(vint512_t3 a, vint512_t3 b, vint512_t3 c) {
+ // CHECK: %[[CMP:.+]] = icmp slt <3 x i512> %{{.+}}, zeroinitializer
+ // CHECK: %[[SEXT:.+]] = sext <3 x i1> %[[CMP]] to <3 x i512>
+ // CHECK: %[[COND:.+]] = icmp slt <3 x i512> %[[SEXT]], zeroinitializer
+ // CHECK: select <3 x i1> %[[COND]], <3 x i512> %{{.+}}, <3 x i512> %{{.+}}
+ return a < 0 ? b : c;
+}
+
// Ensure that these types don't alias the normal int types.
void TBAATest(_BitInt(sizeof(int) * 8) ExtInt,
unsigned _BitInt(sizeof(int) * 8) ExtUInt,
diff --git a/clang/test/Sema/ext-int.c b/clang/test/Sema/ext-int.c
index ebc5bc61260b4..0b72ee5660ec4 100644
--- a/clang/test/Sema/ext-int.c
+++ b/clang/test/Sema/ext-int.c
@@ -73,3 +73,52 @@ void FromPaper1(void) {
void FromPaper2(_BitInt(8) a1, _BitInt(24) a2) {
_Static_assert(EXPR_HAS_TYPE(a1 * (_BitInt(32))a2, _BitInt(32)), "");
}
+
+typedef _BitInt(4) ExtVec4x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(8) ExtVec8x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(32) ExtVec32x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(128) ExtVec128x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(256) ExtVec256x2 __attribute__((ext_vector_type(2)));
+typedef _BitInt(512) ExtVec512x3 __attribute__((ext_vector_type(3)));
+typedef _BitInt(1024) ExtVec1024x2 __attribute__((ext_vector_type(2)));
+typedef unsigned _BitInt(512) ExtUVec512x3 __attribute__((ext_vector_type(3)));
+typedef _BitInt(8) GnuVec8x4 __attribute__((vector_size(4)));
+typedef _BitInt(64) GnuVec64x4 __attribute__((vector_size(32)));
+typedef _BitInt(256) GnuVec256x2 __attribute__((vector_size(64)));
+typedef _BitInt(1024) GnuVec1024x2 __attribute__((vector_size(256)));
+typedef unsigned _BitInt(256) GnuUVec256x2 __attribute__((vector_size(64)));
+
+void GH200665(ExtVec4x4 e4a, ExtVec4x4 e4b, ExtVec8x4 e8a, ExtVec8x4 e8b,
+ ExtVec32x4 e32a, ExtVec32x4 e32b, ExtVec128x4 e128a,
+ ExtVec128x4 e128b, ExtVec256x2 e256a, ExtVec256x2 e256b,
+ ExtVec512x3 e512a, ExtVec512x3 e512b, ExtVec1024x2 e1024a,
+ ExtVec1024x2 e1024b, ExtUVec512x3 eu512a, ExtUVec512x3 eu512b,
+ GnuVec8x4 g8a, GnuVec8x4 g8b, GnuVec64x4 g64a, GnuVec64x4 g64b,
+ GnuVec256x2 g256a, GnuVec256x2 g256b, GnuVec1024x2 g1024a,
+ GnuVec1024x2 g1024b, GnuUVec256x2 gu256a, GnuUVec256x2 gu256b) {
+ _Static_assert(EXPR_HAS_TYPE(e4a == e4b, ExtVec4x4), "");
+ _Static_assert(EXPR_HAS_TYPE(e8a != e8b, ExtVec8x4), "");
+ _Static_assert(EXPR_HAS_TYPE(e32a < e32b, ExtVec32x4), "");
+ _Static_assert(EXPR_HAS_TYPE(e128a <= e128b, ExtVec128x4), "");
+ _Static_assert(EXPR_HAS_TYPE(e256a > e256b, ExtVec256x2), "");
+ _Static_assert(EXPR_HAS_TYPE(e512a >= e512b, ExtVec512x3), "");
+ _Static_assert(EXPR_HAS_TYPE(e512a > 0, ExtVec512x3), "");
+ _Static_assert(EXPR_HAS_TYPE(0 == e1024a, ExtVec1024x2), "");
+ _Static_assert(EXPR_HAS_TYPE(e1024a != e1024b, ExtVec1024x2), "");
+ _Static_assert(EXPR_HAS_TYPE(eu512a == eu512b, ExtVec512x3), "");
+ _Static_assert(EXPR_HAS_TYPE(!e4a, ExtVec4x4), "");
+ _Static_assert(EXPR_HAS_TYPE(!e512a, ExtVec512x3), "");
+ _Static_assert(EXPR_HAS_TYPE(!eu512a, ExtVec512x3), "");
+ _Static_assert(EXPR_HAS_TYPE(e512a && e512b, ExtVec512x3), "");
+ _Static_assert(EXPR_HAS_TYPE(e4a || e4b, ExtVec4x4), "");
+ _Static_assert(EXPR_HAS_TYPE(e512a ? e512a : e512b, ExtVec512x3), "");
+ _Static_assert(EXPR_HAS_TYPE((e512a > 0) ? e512a : e512b, ExtVec512x3), "");
+ _Static_assert(EXPR_HAS_TYPE((eu512a == eu512b) ? eu512a : eu512b, ExtUVec512x3), "");
+
+ _Static_assert(EXPR_HAS_TYPE(g8a == g8b, GnuVec8x4), "");
+ _Static_assert(EXPR_HAS_TYPE(g64a < g64b, GnuVec64x4), "");
+ _Static_assert(EXPR_HAS_TYPE(g256a > g256b, GnuVec256x2), "");
+ _Static_assert(EXPR_HAS_TYPE(g256a >= 0, GnuVec256x2), "");
+ _Static_assert(EXPR_HAS_TYPE(g1024a != g1024b, GnuVec1024x2), "");
+ _Static_assert(EXPR_HAS_TYPE(gu256a <= gu256b, GnuVec256x2), "");
+}
diff --git a/clang/test/SemaCXX/ext-int-vector.cpp b/clang/test/SemaCXX/ext-int-vector.cpp
new file mode 100644
index 0000000000000..0c683a2916243
--- /dev/null
+++ b/clang/test/SemaCXX/ext-int-vector.cpp
@@ -0,0 +1,93 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -triple x86_64-linux-gnu %s
+
+namespace GH200665 {
+typedef _BitInt(2) ExtVec2x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(4) ExtVec4x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(8) ExtVec8x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(16) ExtVec16x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(32) ExtVec32x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(64) ExtVec64x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(128) ExtVec128x4 __attribute__((ext_vector_type(4)));
+typedef _BitInt(256) ExtVec256x2 __attribute__((ext_vector_type(2)));
+typedef _BitInt(512) ExtVec512x3 __attribute__((ext_vector_type(3)));
+typedef _BitInt(1024) ExtVec1024x2 __attribute__((ext_vector_type(2)));
+typedef unsigned _BitInt(4) ExtUVec4x4 __attribute__((ext_vector_type(4)));
+typedef unsigned _BitInt(128) ExtUVec128x4 __attribute__((ext_vector_type(4)));
+typedef unsigned _BitInt(512) ExtUVec512x3 __attribute__((ext_vector_type(3)));
+
+typedef _BitInt(4) GnuVec4x2 __attribute__((vector_size(2)));
+typedef _BitInt(8) GnuVec8x4 __attribute__((vector_size(4)));
+typedef _BitInt(16) GnuVec16x4 __attribute__((vector_size(8)));
+typedef _BitInt(32) GnuVec32x4 __attribute__((vector_size(16)));
+typedef _BitInt(64) GnuVec64x4 __attribute__((vector_size(32)));
+typedef _BitInt(128) GnuVec128x2 __attribute__((vector_size(32)));
+typedef _BitInt(256) GnuVec256x2 __attribute__((vector_size(64)));
+typedef _BitInt(512) GnuVec512x2 __attribute__((vector_size(128)));
+typedef _BitInt(1024) GnuVec1024x2 __attribute__((vector_size(256)));
+typedef unsigned _BitInt(256) GnuUVec256x2 __attribute__((vector_size(64)));
+
+template <typename V, typename R = V> void check(V a, V b) {
+ static_assert(__is_same(decltype(a == b), R), "");
+ static_assert(__is_same(decltype(a != b), R), "");
+ static_assert(__is_same(decltype(a < b), R), "");
+ static_assert(__is_same(decltype(a <= b), R), "");
+ static_assert(__is_same(decltype(a > b), R), "");
+ static_assert(__is_same(decltype(a >= b), R), "");
+ static_assert(__is_same(decltype(a > 0), R), "");
+ static_assert(__is_same(decltype(0 < a), R), "");
+ static_assert(__is_same(decltype(!a), R), "");
+ static_assert(__is_same(decltype(a && b), R), "");
+ static_assert(__is_same(decltype(a || b), R), "");
+ static_assert(__is_same(decltype(a ? a : b), V), "");
+ static_assert(__is_same(decltype((a < b) ? a : b), V), "");
+ static_assert(__is_same(decltype(!a ? b : a), V), "");
+}
+
+template void check<ExtVec2x4>(ExtVec2x4, ExtVec2x4);
+template void check<ExtVec4x4>(ExtVec4x4, ExtVec4x4);
+template void check<ExtVec8x4>(ExtVec8x4, ExtVec8x4);
+template void check<ExtVec16x4>(ExtVec16x4, ExtVec16x4);
+template void check<ExtVec32x4>(ExtVec32x4, ExtVec32x4);
+template void check<ExtVec64x4>(ExtVec64x4, ExtVec64x4);
+template void check<ExtVec128x4>(ExtVec128x4, ExtVec128x4);
+template void check<ExtVec256x2>(ExtVec256x2, ExtVec256x2);
+template void check<ExtVec512x3>(ExtVec512x3, ExtVec512x3);
+template void check<ExtVec1024x2>(ExtVec1024x2, ExtVec1024x2);
+template void check<ExtUVec4x4, ExtVec4x4>(ExtUVec4x4, ExtUVec4x4);
+template void check<ExtUVec128x4, ExtVec128x4>(ExtUVec128x4, ExtUVec128x4);
+template void check<ExtUVec512x3, ExtVec512x3>(ExtUVec512x3, ExtUVec512x3);
+
+template void check<GnuVec4x2>(GnuVec4x2, GnuVec4x2);
+template void check<GnuVec8x4>(GnuVec8x4, GnuVec8x4);
+template void check<GnuVec16x4>(GnuVec16x4, GnuVec16x4);
+template void check<GnuVec32x4>(GnuVec32x4, GnuVec32x4);
+template void check<GnuVec64x4>(GnuVec64x4, GnuVec64x4);
+template void check<GnuVec128x2>(GnuVec128x2, GnuVec128x2);
+template void check<GnuVec256x2>(GnuVec256x2, GnuVec256x2);
+template void check<GnuVec512x2>(GnuVec512x2, GnuVec512x2);
+template void check<GnuVec1024x2>(GnuVec1024x2, GnuVec1024x2);
+template void check<GnuUVec256x2, GnuVec256x2>(GnuUVec256x2, GnuUVec256x2);
+
+typedef __int128 Int128x4 __attribute__((ext_vector_type(4)));
+typedef __int128 GnuInt128x2 __attribute__((vector_size(32)));
+void keeps_bitint(ExtVec128x4 a, ExtVec128x4 b, GnuVec128x2 c, GnuVec128x2 d) {
+ static_assert(!__is_same(decltype(a == b), Int128x4), "");
+ static_assert(!__is_same(decltype(c == d), GnuInt128x2), "");
+}
+
+// expected-error at +1{{'_BitInt' vector element width must be a power of 2}}
+typedef _BitInt(7) __attribute__((ext_vector_type(4))) ExtVec7x4;
+// expected-error at +1{{'_BitInt' vector element width must be a power of 2}}
+typedef _BitInt(255) __attribute__((ext_vector_type(2))) ExtVec255x2;
+// expected-error at +1{{'_BitInt' vector element width must be a power of 2}}
+typedef _BitInt(255) __attribute__((vector_size(64))) GnuVec255x2;
+} // namespace GH200665
+
+// Original reproducer of GH200665.
+// expected-error at +1{{expected ')'}}
+using i512x3 = _BitInt(512) __attribute__((ext_vector_type(3));
+// expected-note at -1{{'i512x3' declared here}}
+// expected-error at +3{{unknown type name 'v3i512x3'; did you mean 'i512x3'?}}
+// expected-warning at +2{{variable 'a' is uninitialized when used within its own initialization}}
+// expected-error at +1{{expected ';' after top level declarator}}
+v3i512x3 a {a>0}
``````````
</details>
https://github.com/llvm/llvm-project/pull/232797
More information about the cfe-commits
mailing list