https://github.com/akash-manna-sky updated 
https://github.com/llvm/llvm-project/pull/226899

>From 7fa7a3ec8b0f286948cc4369196a2da1d93d77da Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Mon, 28 Sep 2026 12:31:57 +0530
Subject: [PATCH 1/3] [clang] Fix crash constant-evaluating huge arrays of
 zero-sized elements

The array size limit in Sema only considered the total size in bytes, so
an array of zero-sized elements such as `T s[-sizeof(0)][0]` was accepted
with any element count. When the constant evaluator later default-
constructed or copied such an array, it truncated the element count to
unsigned and tried to allocate an APValue for every element, running out
of memory, or asserted in SubobjectDesignator::adjustIndex.

Check the element count against the limit as well, and route the array
construction and ArrayInitLoopExpr paths in the evaluator through the
existing CheckArraySize guard.

Fixes #173728
---
 clang/docs/ReleaseNotes.md                    |  4 ++
 clang/lib/AST/ExprConstant.cpp                |  4 ++
 clang/lib/Sema/SemaType.cpp                   | 14 +++---
 clang/test/CodeGenCXX/stmtexpr.cpp            |  5 +++
 clang/test/Sema/array-size-64.c               |  7 +++
 .../cxx2a-constexpr-dynalloc-limits.cpp       | 34 +++++++++++++++
 clang/test/SemaCXX/zero-length-arrays.cpp     | 43 ++++++++++++++++++-
 7 files changed, 103 insertions(+), 8 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 3c6acf353f93f..9e1006db2c423 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -792,6 +792,10 @@ features cannot lower the translation-unit ABI level;
   that was inherited from a different declarator, for example when
   ``__typeof__`` resolves to the type of another, already-processed
   declaration. (#GH217489)
+- Fixed a crash when constant-evaluating a default-constructed or copied local
+  array with a huge number of zero-sized elements, e.g. ``T s[N][0]``. Such
+  arrays are now also diagnosed as too large when their element count exceeds
+  the limit that already applies to their size in bytes. (#GH173728)
 - Fixed an assertion failure when instantiating a block that captures
   `this` via a member access through a dependent base class.
 - Fixed `DiagnoseUnguardedAvailability::TraverseIfStmt` dereferencing a nullptr
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 2df754dc9007f..5e3cfb6edba85 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -15860,6 +15860,8 @@ bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const 
ArrayInitLoopExpr *E) {
     return false;
 
   auto *CAT = cast<ConstantArrayType>(E->getType()->castAsArrayTypeUnsafe());
+  if (!CheckArraySize(Info, CAT, E->getExprLoc()))
+    return false;
 
   uint64_t Elements = CAT->getZExtSize();
   Result = APValue(APValue::UninitArray(), Elements, Elements);
@@ -15906,6 +15908,8 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const 
CXXConstructExpr *E,
   bool HadZeroInit = Value->hasValue();
 
   if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) {
+    if (!CheckArraySize(Info, CAT, E->getExprLoc()))
+      return false;
     unsigned FinalSize = CAT->getZExtSize();
 
     // Preserve the array filler if we had prior zero-initialization.
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index b5c71d72a23ff..85139ec4dd145 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2307,12 +2307,14 @@ QualType Sema::BuildArrayType(QualType T, 
ArraySizeModifier ASM,
           return QualType();
       }
 
-      // Is the array too large?
-      unsigned ActiveSizeBits =
-          (!T->isDependentType() && !T->isVariablyModifiedType() &&
-           !T->isIncompleteType() && !T->isUndeducedType())
-              ? ConstantArrayType::getNumAddressingBits(Context, T, ConstVal)
-              : ConstVal.getActiveBits();
+      // Is the array too large? Check the element count too, for zero-sized
+      // elements.
+      unsigned ActiveSizeBits = ConstVal.getActiveBits();
+      if (!T->isDependentType() && !T->isVariablyModifiedType() &&
+          !T->isIncompleteType() && !T->isUndeducedType())
+        ActiveSizeBits = std::max(
+            ActiveSizeBits,
+            ConstantArrayType::getNumAddressingBits(Context, T, ConstVal));
       if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
         Diag(ArraySize->getBeginLoc(), diag::err_array_too_large)
             << toString(ConstVal, 10, ConstVal.isSigned(),
diff --git a/clang/test/CodeGenCXX/stmtexpr.cpp 
b/clang/test/CodeGenCXX/stmtexpr.cpp
index 6e19ce864813f..ff3802b417c1c 100644
--- a/clang/test/CodeGenCXX/stmtexpr.cpp
+++ b/clang/test/CodeGenCXX/stmtexpr.cpp
@@ -78,6 +78,11 @@ int foo5(bool b) {
   G: return y;
 }
 
+// CHECK-LABEL: define{{.*}} i32 @gh173728()
+extern "C" int gh173728() {
+  return ({ struct T {} s[0xFFFFFFFFu][0]; 0; });
+}
+
 // When we emit a full expression with cleanups that contains branches out of
 // the full expression, the result of the inner expression (the call to
 // call_with_cleanups in this case) may not dominate the fallthrough 
destination
diff --git a/clang/test/Sema/array-size-64.c b/clang/test/Sema/array-size-64.c
index 3e6339bd6a640..1a0c1923ab3f5 100644
--- a/clang/test/Sema/array-size-64.c
+++ b/clang/test/Sema/array-size-64.c
@@ -10,3 +10,10 @@ void pr8256(void) {
   typedef char b[(long long)sizeof(a)-1];
 }
 
+void gh173728(void) {
+  struct S {} a[-sizeof(0)][0]; // expected-error {{array is too large}}
+  int b[1ULL << 61][0];         // expected-error {{array is too large}}
+  int c[(1ULL << 61) - 1][0];
+  int d[1ULL << 40][0];
+}
+
diff --git a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp 
b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
index 7537b47780aeb..73ce6d14108f3 100644
--- a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
+++ b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
@@ -99,3 +99,37 @@ void ohno() {
 }
 
 }
+
+namespace GH173728 {
+struct T {};
+
+template <auto N>
+constexpr int default_construct() {
+  T s[N][0]; // #gh173728-construct
+  return 0;
+}
+
+template <auto N>
+constexpr int capture_copy() {
+  T s[N][0] = {};
+  return [s] { return 0; }(); // #gh173728-capture
+}
+
+static_assert(default_construct<4>() == 0);
+static_assert(capture_copy<4>() == 0);
+
+static_assert(default_construct<1025>() == 0); // expected-error {{static 
assertion expression is not an integral constant expression}} \
+                                               // expected-note {{in call}}
+// expected-note@#gh173728-construct {{cannot allocate array; evaluated array 
bound 1025 exceeds the limit (1024)}}
+// expected-note@#gh173728-construct {{use -fconstexpr-steps}}
+
+#if __SIZEOF_SIZE_T__ == 8
+static_assert(default_construct<(1ULL << 33) - 1>() == 0); // expected-error 
{{static assertion expression is not an integral constant expression}} \
+                                                           // expected-note 
{{in call}}
+// expected-note@#gh173728-construct {{cannot allocate array; evaluated array 
bound 8589934591 is too large}}
+
+static_assert(capture_copy<(1ULL << 33) - 1>() == 0); // expected-error 
{{static assertion expression is not an integral constant expression}} \
+                                                      // expected-note {{in 
call}}
+// expected-note@#gh173728-capture {{cannot allocate array; evaluated array 
bound 8589934591 is too large}}
+#endif
+}
diff --git a/clang/test/SemaCXX/zero-length-arrays.cpp 
b/clang/test/SemaCXX/zero-length-arrays.cpp
index 6bfc7a5fd2e35..af1b61d4c0dd5 100644
--- a/clang/test/SemaCXX/zero-length-arrays.cpp
+++ b/clang/test/SemaCXX/zero-length-arrays.cpp
@@ -29,8 +29,6 @@ void testBar() {
   Bar b2(b);
 #if __cplusplus >= 201103L
 // expected-error@-2 {{call to implicitly-deleted copy constructor of 'Bar}}
-#else
-// expected-no-diagnostics
 #endif
   b = b2;
 }
@@ -48,3 +46,44 @@ void test () {
 }
 #endif
 }
+
+namespace GH173728 {
+#if __SIZEOF_SIZE_T__ == 8
+int reduced() {
+  int i;
+  return ({
+    struct T {
+    } s[-sizeof(0)][0 == sizeof(i < 0)]; // expected-error {{array is too 
large}}
+    0;
+  });
+}
+
+int original() {
+  int i = 0;
+  return 1 + ({
+    struct tree_el {
+      int val;
+      struct tree_el **right, *left;
+    } state_t[1 + -(sizeof(0x1c))][0 == sizeof(sizeof(i))]; // expected-error 
{{array is too large}}
+    0x97 < 10000;
+  });
+}
+
+int too_large() {
+  return 1 + ({ struct T {} s[(1ULL << 33) - 1][0]; 0x97 < 10000; });
+}
+
+signed char too_large_no_fold() {
+  return ({ struct T {} s[(1ULL << 33) - 1][0]; 1000; });
+}
+#endif
+
+int over_limit() {
+  return 1 + ({ struct T {} s[0xFFFFFFFFu][0]; 0x97 < 10000; });
+}
+
+void small() {
+  signed char a = ({ struct T {} s[4]; 1000; }); // expected-warning 
{{implicit conversion from 'int' to 'signed char' changes value from 1000 to 
-24}}
+  signed char b = ({ struct T {} s[4][0]; 1000; }); // expected-warning 
{{implicit conversion from 'int' to 'signed char' changes value from 1000 to 
-24}}
+}
+}

>From d61846b73bd709c2fff4eba830f8d8424a519d44 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Mon, 28 Sep 2026 23:52:40 +0530
Subject: [PATCH 2/3] Drop the constant evaluator changes

Keep this PR to the Sema check. The evaluator guard for huge arrays that
Sema still accepts will be a separate PR, together with the bytecode
interpreter side.
---
 clang/docs/ReleaseNotes.md                    |  8 ++--
 clang/lib/AST/ExprConstant.cpp                |  4 --
 clang/test/CodeGenCXX/stmtexpr.cpp            |  5 ---
 clang/test/SemaCXX/GH173728.cpp               | 21 +++++++++
 .../cxx2a-constexpr-dynalloc-limits.cpp       | 34 ---------------
 clang/test/SemaCXX/zero-length-arrays.cpp     | 43 +------------------
 6 files changed, 27 insertions(+), 88 deletions(-)
 create mode 100644 clang/test/SemaCXX/GH173728.cpp

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 9e1006db2c423..6074709fb11d2 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -792,10 +792,10 @@ features cannot lower the translation-unit ABI level;
   that was inherited from a different declarator, for example when
   ``__typeof__`` resolves to the type of another, already-processed
   declaration. (#GH217489)
-- Fixed a crash when constant-evaluating a default-constructed or copied local
-  array with a huge number of zero-sized elements, e.g. ``T s[N][0]``. Such
-  arrays are now also diagnosed as too large when their element count exceeds
-  the limit that already applies to their size in bytes. (#GH173728)
+- Fixed a crash on arrays of zero-sized elements with a huge element count,
+  e.g. ``T s[-sizeof(0)][0]``. Such arrays are now diagnosed as too large when
+  their element count exceeds the limit that already applies to their size in
+  bytes. (#GH173728)
 - Fixed an assertion failure when instantiating a block that captures
   `this` via a member access through a dependent base class.
 - Fixed `DiagnoseUnguardedAvailability::TraverseIfStmt` dereferencing a nullptr
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 5e3cfb6edba85..2df754dc9007f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -15860,8 +15860,6 @@ bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const 
ArrayInitLoopExpr *E) {
     return false;
 
   auto *CAT = cast<ConstantArrayType>(E->getType()->castAsArrayTypeUnsafe());
-  if (!CheckArraySize(Info, CAT, E->getExprLoc()))
-    return false;
 
   uint64_t Elements = CAT->getZExtSize();
   Result = APValue(APValue::UninitArray(), Elements, Elements);
@@ -15908,8 +15906,6 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const 
CXXConstructExpr *E,
   bool HadZeroInit = Value->hasValue();
 
   if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) {
-    if (!CheckArraySize(Info, CAT, E->getExprLoc()))
-      return false;
     unsigned FinalSize = CAT->getZExtSize();
 
     // Preserve the array filler if we had prior zero-initialization.
diff --git a/clang/test/CodeGenCXX/stmtexpr.cpp 
b/clang/test/CodeGenCXX/stmtexpr.cpp
index ff3802b417c1c..6e19ce864813f 100644
--- a/clang/test/CodeGenCXX/stmtexpr.cpp
+++ b/clang/test/CodeGenCXX/stmtexpr.cpp
@@ -78,11 +78,6 @@ int foo5(bool b) {
   G: return y;
 }
 
-// CHECK-LABEL: define{{.*}} i32 @gh173728()
-extern "C" int gh173728() {
-  return ({ struct T {} s[0xFFFFFFFFu][0]; 0; });
-}
-
 // When we emit a full expression with cleanups that contains branches out of
 // the full expression, the result of the inner expression (the call to
 // call_with_cleanups in this case) may not dominate the fallthrough 
destination
diff --git a/clang/test/SemaCXX/GH173728.cpp b/clang/test/SemaCXX/GH173728.cpp
new file mode 100644
index 0000000000000..023d82856b739
--- /dev/null
+++ b/clang/test/SemaCXX/GH173728.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify %s
+
+int main() {
+  int i;
+  return ({
+    struct T {
+    } s[-sizeof(0)][0 == sizeof(i < 0)]; // expected-error {{array is too 
large (18'446'744'073'709'551'612 elements)}}
+    0;
+  });
+}
+
+int original() {
+  int i = 0;
+  return 1 + ({
+    struct tree_el {
+      int val;
+      struct tree_el **right, *left;
+    } state_t[1 + -(sizeof(0x1c))][0 == sizeof(sizeof(i))]; // expected-error 
{{array is too large (18'446'744'073'709'551'613 elements)}}
+    0x97 < 10000;
+  });
+}
diff --git a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp 
b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
index 73ce6d14108f3..7537b47780aeb 100644
--- a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
+++ b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc-limits.cpp
@@ -99,37 +99,3 @@ void ohno() {
 }
 
 }
-
-namespace GH173728 {
-struct T {};
-
-template <auto N>
-constexpr int default_construct() {
-  T s[N][0]; // #gh173728-construct
-  return 0;
-}
-
-template <auto N>
-constexpr int capture_copy() {
-  T s[N][0] = {};
-  return [s] { return 0; }(); // #gh173728-capture
-}
-
-static_assert(default_construct<4>() == 0);
-static_assert(capture_copy<4>() == 0);
-
-static_assert(default_construct<1025>() == 0); // expected-error {{static 
assertion expression is not an integral constant expression}} \
-                                               // expected-note {{in call}}
-// expected-note@#gh173728-construct {{cannot allocate array; evaluated array 
bound 1025 exceeds the limit (1024)}}
-// expected-note@#gh173728-construct {{use -fconstexpr-steps}}
-
-#if __SIZEOF_SIZE_T__ == 8
-static_assert(default_construct<(1ULL << 33) - 1>() == 0); // expected-error 
{{static assertion expression is not an integral constant expression}} \
-                                                           // expected-note 
{{in call}}
-// expected-note@#gh173728-construct {{cannot allocate array; evaluated array 
bound 8589934591 is too large}}
-
-static_assert(capture_copy<(1ULL << 33) - 1>() == 0); // expected-error 
{{static assertion expression is not an integral constant expression}} \
-                                                      // expected-note {{in 
call}}
-// expected-note@#gh173728-capture {{cannot allocate array; evaluated array 
bound 8589934591 is too large}}
-#endif
-}
diff --git a/clang/test/SemaCXX/zero-length-arrays.cpp 
b/clang/test/SemaCXX/zero-length-arrays.cpp
index af1b61d4c0dd5..6bfc7a5fd2e35 100644
--- a/clang/test/SemaCXX/zero-length-arrays.cpp
+++ b/clang/test/SemaCXX/zero-length-arrays.cpp
@@ -29,6 +29,8 @@ void testBar() {
   Bar b2(b);
 #if __cplusplus >= 201103L
 // expected-error@-2 {{call to implicitly-deleted copy constructor of 'Bar}}
+#else
+// expected-no-diagnostics
 #endif
   b = b2;
 }
@@ -46,44 +48,3 @@ void test () {
 }
 #endif
 }
-
-namespace GH173728 {
-#if __SIZEOF_SIZE_T__ == 8
-int reduced() {
-  int i;
-  return ({
-    struct T {
-    } s[-sizeof(0)][0 == sizeof(i < 0)]; // expected-error {{array is too 
large}}
-    0;
-  });
-}
-
-int original() {
-  int i = 0;
-  return 1 + ({
-    struct tree_el {
-      int val;
-      struct tree_el **right, *left;
-    } state_t[1 + -(sizeof(0x1c))][0 == sizeof(sizeof(i))]; // expected-error 
{{array is too large}}
-    0x97 < 10000;
-  });
-}
-
-int too_large() {
-  return 1 + ({ struct T {} s[(1ULL << 33) - 1][0]; 0x97 < 10000; });
-}
-
-signed char too_large_no_fold() {
-  return ({ struct T {} s[(1ULL << 33) - 1][0]; 1000; });
-}
-#endif
-
-int over_limit() {
-  return 1 + ({ struct T {} s[0xFFFFFFFFu][0]; 0x97 < 10000; });
-}
-
-void small() {
-  signed char a = ({ struct T {} s[4]; 1000; }); // expected-warning 
{{implicit conversion from 'int' to 'signed char' changes value from 1000 to 
-24}}
-  signed char b = ({ struct T {} s[4][0]; 1000; }); // expected-warning 
{{implicit conversion from 'int' to 'signed char' changes value from 1000 to 
-24}}
-}
-}

>From 253061eff9d00d484e1d5e84ad7847e26ff5dd08 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Tue, 29 Sep 2026 22:16:46 +0530
Subject: [PATCH 3/3] Fix the crash in the constant evaluators instead of Sema

Revert the Sema array size change, which only rejected the reproducer's
wrapped-around count. Route array default construction and
ArrayInitLoopExpr through the existing CheckArraySize guard in
ExprConstant, and emit the matching CheckArraySize opcode on the same
paths in the bytecode compiler.
---
 clang/docs/ReleaseNotes.md                  |  8 ++--
 clang/lib/AST/ByteCode/Compiler.cpp         |  8 +++-
 clang/lib/AST/ExprConstant.cpp              |  4 ++
 clang/lib/Sema/SemaType.cpp                 | 14 +++----
 clang/test/AST/ByteCode/dynalloc-limits.cpp | 42 +++++++++++++++++++++
 clang/test/Sema/array-size-64.c             |  7 ----
 clang/test/SemaCXX/GH173728.cpp             | 21 -----------
 7 files changed, 62 insertions(+), 42 deletions(-)
 delete mode 100644 clang/test/SemaCXX/GH173728.cpp

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 6074709fb11d2..35dab3acbfa5b 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -792,10 +792,10 @@ features cannot lower the translation-unit ABI level;
   that was inherited from a different declarator, for example when
   ``__typeof__`` resolves to the type of another, already-processed
   declaration. (#GH217489)
-- Fixed a crash on arrays of zero-sized elements with a huge element count,
-  e.g. ``T s[-sizeof(0)][0]``. Such arrays are now diagnosed as too large when
-  their element count exceeds the limit that already applies to their size in
-  bytes. (#GH173728)
+- Fixed a crash when the constant evaluator default-constructed or copied a
+  very large array, such as a local ``T s[0xFFFFFFFF][0]`` of an empty class
+  ``T``. Such evaluations now fail once the element count exceeds the
+  ``-fconstexpr-steps`` limit, as they already did for ``new``. (#GH173728)
 - Fixed an assertion failure when instantiating a block that captures
   `this` via a member access through a dependent base class.
 - Fixed `DiagnoseUnguardedAvailability::TraverseIfStmt` dereferencing a nullptr
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp 
b/clang/lib/AST/ByteCode/Compiler.cpp
index 81c8fb0b9f17d..f204750afe84b 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -3033,6 +3033,8 @@ bool Compiler<Emitter>::VisitArrayInitLoopExpr(const 
ArrayInitLoopExpr *E) {
   const Expr *SubExpr = E->getSubExpr();
   OptPrimType SubExprT = classify(SubExpr);
   size_t Size = E->getArraySize().getZExtValue();
+  if (!this->emitCheckArraySize(Size, E))
+    return false;
 
   if (SubExprT) {
     // Unwrap the OpaqueValueExpr so we don't cache something we won't reuse.
@@ -4032,8 +4034,10 @@ bool Compiler<Emitter>::VisitCXXConstructExpr(const 
CXXConstructExpr *E) {
       if (!CAT)
         return false;
       QualType ElemTy = CAT->getElementType();
-      unsigned NumElems = CAT->getZExtSize();
-      for (size_t I = 0; I != NumElems; ++I) {
+      uint64_t NumElems = CAT->getZExtSize();
+      if (!this->emitCheckArraySize(NumElems, E))
+        return false;
+      for (uint64_t I = 0; I != NumElems; ++I) {
         if (!this->emitConstUint64(I, E))
           return false;
         if (!this->emitArrayElemPtrUint64(E))
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 2df754dc9007f..5e3cfb6edba85 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -15860,6 +15860,8 @@ bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const 
ArrayInitLoopExpr *E) {
     return false;
 
   auto *CAT = cast<ConstantArrayType>(E->getType()->castAsArrayTypeUnsafe());
+  if (!CheckArraySize(Info, CAT, E->getExprLoc()))
+    return false;
 
   uint64_t Elements = CAT->getZExtSize();
   Result = APValue(APValue::UninitArray(), Elements, Elements);
@@ -15906,6 +15908,8 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const 
CXXConstructExpr *E,
   bool HadZeroInit = Value->hasValue();
 
   if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) {
+    if (!CheckArraySize(Info, CAT, E->getExprLoc()))
+      return false;
     unsigned FinalSize = CAT->getZExtSize();
 
     // Preserve the array filler if we had prior zero-initialization.
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 85139ec4dd145..b5c71d72a23ff 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -2307,14 +2307,12 @@ QualType Sema::BuildArrayType(QualType T, 
ArraySizeModifier ASM,
           return QualType();
       }
 
-      // Is the array too large? Check the element count too, for zero-sized
-      // elements.
-      unsigned ActiveSizeBits = ConstVal.getActiveBits();
-      if (!T->isDependentType() && !T->isVariablyModifiedType() &&
-          !T->isIncompleteType() && !T->isUndeducedType())
-        ActiveSizeBits = std::max(
-            ActiveSizeBits,
-            ConstantArrayType::getNumAddressingBits(Context, T, ConstVal));
+      // Is the array too large?
+      unsigned ActiveSizeBits =
+          (!T->isDependentType() && !T->isVariablyModifiedType() &&
+           !T->isIncompleteType() && !T->isUndeducedType())
+              ? ConstantArrayType::getNumAddressingBits(Context, T, ConstVal)
+              : ConstVal.getActiveBits();
       if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context)) {
         Diag(ArraySize->getBeginLoc(), diag::err_array_too_large)
             << toString(ConstVal, 10, ConstVal.isSigned(),
diff --git a/clang/test/AST/ByteCode/dynalloc-limits.cpp 
b/clang/test/AST/ByteCode/dynalloc-limits.cpp
index 85d66ac88ee2c..304c3248a5aa4 100644
--- a/clang/test/AST/ByteCode/dynalloc-limits.cpp
+++ b/clang/test/AST/ByteCode/dynalloc-limits.cpp
@@ -73,3 +73,45 @@ int d = stack_array<1025>();
 constexpr int e = stack_array<1024>();
 constexpr int f = stack_array<1025>(); // both-error {{constexpr variable 'f' 
must be initialized by a constant expression}} \
                                        // both-note {{in call}}
+
+namespace GH173728 {
+struct T {};
+
+int stmt_expr() { return 1 + ({ T s[0xFFFFFFFFu][0]; 0x97 < 10000; }); }
+#if __SIZEOF_SIZE_T__ == 8
+int stmt_expr_truncated() {
+  return 1 + ({ T s[(1ULL << 33) - 1][0]; 0x97 < 10000; });
+}
+#endif
+
+template <auto N>
+constexpr int default_construct() {
+  T s[N][0]; // #gh173728-construct
+  return 0;
+}
+
+constexpr int construct_ok = default_construct<1024>();
+constexpr int construct_limit = default_construct<1025>(); // both-error 
{{constexpr variable 'construct_limit' must be initialized by a constant 
expression}} \
+                                                           // both-note {{in 
call}}
+// both-note@#gh173728-construct {{cannot allocate array; evaluated array 
bound 1025 exceeds the limit (1024)}}
+// both-note@#gh173728-construct {{use -fconstexpr-steps}}
+
+#if __SIZEOF_SIZE_T__ == 8
+constexpr int construct_huge = default_construct<(1ULL << 33) - 1>(); // 
both-error {{constexpr variable 'construct_huge' must be initialized by a 
constant expression}} \
+                                                                      // 
ref-note {{in call}}
+// ref-note@#gh173728-construct {{cannot allocate array; evaluated array bound 
8589934591 is too large}}
+#endif
+
+template <typename A>
+constexpr int capture_copy(const A &a) {
+  return [a] { return 0; }(); // #gh173728-capture
+}
+
+constexpr T src_ok[1024][0] = {};
+constexpr T src_limit[1025][0] = {};
+constexpr int capture_ok = capture_copy(src_ok);
+constexpr int capture_limit = capture_copy(src_limit); // both-error 
{{constexpr variable 'capture_limit' must be initialized by a constant 
expression}} \
+                                                       // both-note {{in call}}
+// both-note@#gh173728-capture {{cannot allocate array; evaluated array bound 
1025 exceeds the limit (1024)}}
+// both-note@#gh173728-capture {{use -fconstexpr-steps}}
+}
diff --git a/clang/test/Sema/array-size-64.c b/clang/test/Sema/array-size-64.c
index 1a0c1923ab3f5..3e6339bd6a640 100644
--- a/clang/test/Sema/array-size-64.c
+++ b/clang/test/Sema/array-size-64.c
@@ -10,10 +10,3 @@ void pr8256(void) {
   typedef char b[(long long)sizeof(a)-1];
 }
 
-void gh173728(void) {
-  struct S {} a[-sizeof(0)][0]; // expected-error {{array is too large}}
-  int b[1ULL << 61][0];         // expected-error {{array is too large}}
-  int c[(1ULL << 61) - 1][0];
-  int d[1ULL << 40][0];
-}
-
diff --git a/clang/test/SemaCXX/GH173728.cpp b/clang/test/SemaCXX/GH173728.cpp
deleted file mode 100644
index 023d82856b739..0000000000000
--- a/clang/test/SemaCXX/GH173728.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify %s
-
-int main() {
-  int i;
-  return ({
-    struct T {
-    } s[-sizeof(0)][0 == sizeof(i < 0)]; // expected-error {{array is too 
large (18'446'744'073'709'551'612 elements)}}
-    0;
-  });
-}
-
-int original() {
-  int i = 0;
-  return 1 + ({
-    struct tree_el {
-      int val;
-      struct tree_el **right, *left;
-    } state_t[1 + -(sizeof(0x1c))][0 == sizeof(sizeof(i))]; // expected-error 
{{array is too large (18'446'744'073'709'551'613 elements)}}
-    0x97 < 10000;
-  });
-}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to