From 5f43a81a63bbaf78fa6aefa20b70929a0584c494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= Date: Tue, 6 May 2025 12:36:24 +0200 Subject: [PATCH 1/2] [clang][ExprConst] Check for array size of initlists Fixes #138653 --- clang/lib/AST/ExprConstant.cpp | 8 ++++ .../SemaCXX/constant-expression-cxx2a.cpp | 42 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index e5950f461e4b2..dfffd9c9beb8c 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -11788,6 +11788,11 @@ bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr( LLVM_DEBUG(llvm::dbgs() << "The number of elements to initialize: " << NumEltsToInit << ".\n"); + if (!Info.CheckArraySize(ExprToVisit->getExprLoc(), + CAT->getNumAddressingBits(Info.Ctx), NumEltsToInit, + /*Diag=*/true)) + return false; + Result = APValue(APValue::UninitArray(), NumEltsToInit, NumElts); // If the array was previously zero-initialized, preserve the @@ -11919,6 +11924,9 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E, if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) { unsigned FinalSize = CAT->getZExtSize(); + if (!CheckArraySize(Info, CAT, E->getExprLoc())) + return false; + // Preserve the array filler if we had prior zero-initialization. APValue Filler = HadZeroInit && Value->hasArrayFiller() ? Value->getArrayFiller() diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index 85720606fe9de..b9cf35a4f1d77 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -1497,3 +1497,45 @@ namespace GH67317 { // expected-note {{subobject of type 'const unsigned char' is not initialized}} __builtin_bit_cast(unsigned char, *new char[3][1]); }; + +namespace LargeArrays { + constexpr unsigned kNumberOfIterations = 2000000; + constexpr unsigned kThreadsNumber = 2 * 8 * 1024; + + /// Large array initialized by Paren/InitListExpr. + template + struct array1 { + using AT = T[S]; + AT Data{}; + constexpr array1() : Data(T()) {} // expected-note {{cannot allocate array}} + }; + + /// And initialized by a CXXConstructExpr. + template + struct array2 { + using AT = T[S]; + AT Data; + constexpr array2() {} // expected-note {{cannot allocate array}} + }; + + template + class A{}; + int main() { + array1, kThreadsNumber * kNumberOfIterations> futures1{}; + array2, kThreadsNumber * kNumberOfIterations> futures2{}; + } + + constexpr int CE1() { + array1, kThreadsNumber * kNumberOfIterations> futures1{}; // expected-note {{in call to}} + return 1; + } + static_assert(CE1() == 1); // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to}} + + constexpr int CE2() { + array2, kThreadsNumber * kNumberOfIterations> futures2{}; // expected-note {{in call to}} + return 1; + } + static_assert(CE2() == 1); // expected-error {{not an integral constant expression}} \ + // expected-note {{in call to}} +} From 92a4d685e05a8a7b20a6abab6360fa799839f5ca Mon Sep 17 00:00:00 2001 From: Timm Baeder Date: Thu, 8 May 2025 05:24:59 +0200 Subject: [PATCH 2/2] Update constant-expression-cxx2a.cpp --- clang/test/SemaCXX/constant-expression-cxx2a.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index b9cf35a4f1d77..3b58ebc6aaa1e 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -1498,7 +1498,7 @@ namespace GH67317 { __builtin_bit_cast(unsigned char, *new char[3][1]); }; -namespace LargeArrays { +namespace GH138653 { constexpr unsigned kNumberOfIterations = 2000000; constexpr unsigned kThreadsNumber = 2 * 8 * 1024;