[clang] 1b4e7f4 - [Clang] Enforce the same size limits for `vector_size` and `ext_vector_type` (#226375)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 25 14:06:49 PDT 2026
Author: Akash Manna
Date: 2026-09-25T14:06:42-07:00
New Revision: 1b4e7f41268eb3db5300e79256764140e509e3f5
URL: https://github.com/llvm/llvm-project/commit/1b4e7f41268eb3db5300e79256764140e509e3f5
DIFF: https://github.com/llvm/llvm-project/commit/1b4e7f41268eb3db5300e79256764140e509e3f5.diff
LOG: [Clang] Enforce the same size limits for `vector_size` and `ext_vector_type` (#226375)
Fixes #165458
A `bool` vector declared with `ext_vector_type` isn't lowered as an LLVM
vector in memory: `ConvertTypeForMem` packs it into a single integer
with one bit per element. `BuildExtVectorType` only checked that the
element count fits in 32 bits, though, so a vector of 187,553,262 bools
got through Sema and the first consumer that needed its memory type (the
zero initializer of a tentative definition here) asked
`IntegerType::get` for far more than the 2^23 bits it supports. The
count matters for every element type, not just `bool`, because Sema also
forms bool vectors out of other vectors (`c ? true : false` with a
`char` vector condition), and `vector_size` was no better off with its
limits of 2^32 elements and 2^61 bytes.
Both attributes now go through the same two limits when the type is
built, reusing the existing "vector size too large" error: at most
`llvm::IntegerType::MAX_INT_BITS` (2^23) elements, and at most 2^28
bytes so that the natural alignment, the size rounded up to a power of
two, still fits in the `unsigned` alignment of `TypeInfo`. These replace
the old `isIntN(61)` and `UINT32_MAX` checks in `BuildVectorType`.
Added:
Modified:
clang/docs/ReleaseNotes.md
clang/lib/Sema/SemaType.cpp
clang/test/Sema/large-bit-int.c
clang/test/Sema/types.c
clang/test/SemaCXX/vector.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 4cd09971f5dcd..cf7e5183b1a40 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -583,6 +583,10 @@ features cannot lower the translation-unit ABI level;
- Fixed crash (assertion) when the `alloc_align` attribute was applied to a declaration whose type has a `FunctionProtoType` but which is not itself a `FunctionDecl`, such as a function-pointer variable. (#GH122058)
+- Fixed a crash on `bool` vectors declared with `ext_vector_type` and more than
+ 2^23 elements; `ext_vector_type` and `vector_size` now both reject vectors
+ with more than 2^23 elements or larger than 2^28 bytes. (#GH165458)
+
- The `counted_by`/`counted_by_or_null` diagnostic that rejects a pointer whose
pointee is a struct with a flexible array member (e.g.
``struct with_fam * __sized_by(size) ptr;``) was incorrectly also applied to
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 2796ac2929f46..b5c71d72a23ff 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2374,6 +2374,12 @@ static bool CheckBitIntElementType(Sema &S, SourceLocation AttrLoc,
return false;
}
+// A bool vector is stored as an integer with one bit per element and can be
+// formed from any vector (e.g. by the conditional operator); the size bound
+// keeps the natural alignment within TypeInfo::Align.
+static constexpr uint64_t MaxVectorElements = llvm::IntegerType::MAX_INT_BITS;
+static constexpr uint64_t MaxVectorSizeInBits = 1ULL << 31;
+
QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
SourceLocation AttrLoc) {
// The base type must be integer (not Boolean or enumeration) or float, and
@@ -2414,8 +2420,7 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
VectorKind::Generic);
// vecSize is specified in bytes - convert to bits.
- if (!VecSize->isIntN(61)) {
- // Bit size will overflow uint64.
+ if (VecSize->ugt(MaxVectorSizeInBits / 8)) {
Diag(AttrLoc, diag::err_attribute_size_too_large)
<< SizeExpr->getSourceRange() << "vector";
return QualType();
@@ -2435,7 +2440,7 @@ QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
return QualType();
}
- if (VectorSizeBits / TypeSize > std::numeric_limits<uint32_t>::max()) {
+ if (VectorSizeBits / TypeSize > MaxVectorElements) {
Diag(AttrLoc, diag::err_attribute_size_too_large)
<< SizeExpr->getSourceRange() << "vector";
return QualType();
@@ -2483,13 +2488,13 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *SizeExpr,
return QualType();
}
- if (!VecSize->isIntN(32)) {
+ // Unlike gcc's vector_size attribute, the size is specified as the
+ // number of elements, not the number of bytes.
+ if (VecSize->ugt(MaxVectorElements)) {
Diag(AttrLoc, diag::err_attribute_size_too_large)
<< SizeExpr->getSourceRange() << "vector";
return QualType();
}
- // Unlike gcc's vector_size attribute, the size is specified as the
- // number of elements, not the number of bytes.
unsigned VectorSize = static_cast<unsigned>(VecSize->getZExtValue());
if (VectorSize == 0) {
@@ -2498,6 +2503,13 @@ QualType Sema::BuildExtVectorType(QualType T, Expr *SizeExpr,
return QualType();
}
+ if (!T->isDependentType() &&
+ VectorSize * Context.getTypeSize(T) > MaxVectorSizeInBits) {
+ Diag(AttrLoc, diag::err_attribute_size_too_large)
+ << SizeExpr->getSourceRange() << "vector";
+ return QualType();
+ }
+
return Context.getExtVectorType(T, VectorSize);
}
diff --git a/clang/test/Sema/large-bit-int.c b/clang/test/Sema/large-bit-int.c
index 4c1abf091ab4b..e570f1a3759e4 100644
--- a/clang/test/Sema/large-bit-int.c
+++ b/clang/test/Sema/large-bit-int.c
@@ -9,3 +9,9 @@ void f() {
_BitInt(8388609) c; // expected-error {{signed _BitInt of bit sizes greater than 1024 not supported}}
unsigned _BitInt(0xFFFFFFFFFF) d; // expected-error {{unsigned _BitInt of bit sizes greater than 1024 not supported}}
}
+
+// Wide elements hit the 2^28 byte limit before the element limit.
+typedef _BitInt(1024) too_large_vs __attribute__((vector_size(1 << 29))); // expected-error {{vector size too large}}
+typedef _BitInt(1024) too_large_ev __attribute__((ext_vector_type(1 << 22))); // expected-error {{vector size too large}}
+typedef _BitInt(1024) largest_vs __attribute__((vector_size(1 << 28)));
+typedef _BitInt(1024) largest_ev __attribute__((ext_vector_type(1 << 21)));
diff --git a/clang/test/Sema/types.c b/clang/test/Sema/types.c
index 2be0e6544f3d7..858e2433b5629 100644
--- a/clang/test/Sema/types.c
+++ b/clang/test/Sema/types.c
@@ -75,6 +75,18 @@ typedef int __attribute__((ext_vector_type(0x100000000))) e2; // expected-e
typedef int __attribute__((vector_size((__int128_t)1 << 100))) e3; // expected-error {{vector size too large}}
typedef int __attribute__((ext_vector_type(0))) e4; // expected-error {{zero vector size}}
+// GH165458: at most 2^23 elements and 2^28 bytes for both attributes.
+typedef _Bool bool512 __attribute__((ext_vector_type(187553262))); // expected-error {{vector size too large}}
+bool512 gh165458;
+typedef _Bool __attribute__((ext_vector_type(8388609))) e5; // expected-error {{vector size too large}}
+typedef int __attribute__((ext_vector_type(8388609))) e6; // expected-error {{vector size too large}}
+typedef _Bool __attribute__((ext_vector_type(8388608))) e7;
+typedef int __attribute__((ext_vector_type(8388608))) e8;
+typedef _Bool __attribute__((ext_vector_type(4096))) e9;
+char __attribute__((vector_size(8388609))) v5; // expected-error {{vector size too large}}
+char __attribute__((vector_size(8388608))) v6;
+int __attribute__((vector_size(0x10000001))) v7; // expected-error {{vector size too large}}
+
// no support for vector enum type
enum { e_2 } x3 __attribute__((vector_size(64))); // expected-error {{invalid vector element type}}
diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp
index 355d93a2b8cee..87dfa3760541d 100644
--- a/clang/test/SemaCXX/vector.cpp
+++ b/clang/test/SemaCXX/vector.cpp
@@ -378,6 +378,15 @@ void Init() {
const PR15730<8, char>::type2 PR15730_2 = {};
}
+template <unsigned long long N>
+struct GH165458 {
+ typedef bool __attribute__((ext_vector_type(N))) type; // #GH165458
+};
+// expected-error@#GH165458 {{vector size too large}}
+// expected-note at +1 {{in instantiation of template class 'Templates::GH165458<187553262>' requested here}}
+typedef GH165458<187553262>::type GH165458_TooLarge;
+typedef GH165458<8388608>::type GH165458_Max;
+
} // namespace Templates
typedef int inte2 __attribute__((__ext_vector_type__(2)));
More information about the cfe-commits
mailing list