[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