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
