Author: Richard Smith Date: 2020-03-29T19:33:56-07:00 New Revision: 9a7eda1bece887ca9af085d79fe6e4fb8826dcda
URL: https://github.com/llvm/llvm-project/commit/9a7eda1bece887ca9af085d79fe6e4fb8826dcda DIFF: https://github.com/llvm/llvm-project/commit/9a7eda1bece887ca9af085d79fe6e4fb8826dcda.diff LOG: PR45350: Handle unsized array CXXConstructExprs in constant evaluation of array new expressions with runtime bound. Added: Modified: clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/constant-expression-cxx2a.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 06f4885e47d6..53e168a81bc3 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8677,6 +8677,10 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This, APValue &Result, const InitListExpr *ILE, QualType AllocType); +static bool EvaluateArrayNewConstructExpr(EvalInfo &Info, LValue &This, + APValue &Result, + const CXXConstructExpr *CCE, + QualType AllocType); bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { if (!Info.getLangOpts().CPlusPlus2a) @@ -8726,6 +8730,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { const Expr *Init = E->getInitializer(); const InitListExpr *ResizedArrayILE = nullptr; + const CXXConstructExpr *ResizedArrayCCE = nullptr; QualType AllocType = E->getAllocatedType(); if (Optional<const Expr*> ArraySize = E->getArraySize()) { @@ -8769,7 +8774,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { // -- the new-initializer is a braced-init-list and the number of // array elements for which initializers are provided [...] // exceeds the number of elements to initialize - if (Init) { + if (Init && !isa<CXXConstructExpr>(Init)) { auto *CAT = Info.Ctx.getAsConstantArrayType(Init->getType()); assert(CAT && "unexpected type for array initializer"); @@ -8792,6 +8797,8 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { // special handling for this case when we initialize. if (InitBound != AllocBound) ResizedArrayILE = cast<InitListExpr>(Init); + } else if (Init) { + ResizedArrayCCE = cast<CXXConstructExpr>(Init); } AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound, nullptr, @@ -8856,6 +8863,10 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { if (!EvaluateArrayNewInitList(Info, Result, *Val, ResizedArrayILE, AllocType)) return false; + } else if (ResizedArrayCCE) { + if (!EvaluateArrayNewConstructExpr(Info, Result, *Val, ResizedArrayCCE, + AllocType)) + return false; } else if (Init) { if (!EvaluateInPlace(*Val, Info, Result, Init)) return false; @@ -9683,6 +9694,16 @@ static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This, .VisitInitListExpr(ILE, AllocType); } +static bool EvaluateArrayNewConstructExpr(EvalInfo &Info, LValue &This, + APValue &Result, + const CXXConstructExpr *CCE, + QualType AllocType) { + assert(CCE->isRValue() && CCE->getType()->isArrayType() && + "not an array rvalue"); + return ArrayExprEvaluator(Info, This, Result) + .VisitCXXConstructExpr(CCE, This, &Result, AllocType); +} + // Return true iff the given array filler may depend on the element index. static bool MaybeElementDependentArrayFiller(const Expr *FillerExpr) { // For now, just whitelist non-class value-initialization and initialization diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index 42d7300c5fde..f66f380b635f 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -1381,3 +1381,23 @@ namespace PR45133 { constinit V v2 = X<2>(); constinit V v3 = X<3>(); // expected-error {{constant init}} expected-note {{constinit}} expected-note {{in call}} } + +namespace PR45350 { + int q; + struct V { int n; int *p = &n; constexpr ~V() { *p = *p * 10 + n; }}; + constexpr int f(int n) { + int k = 0; + V *p = new V[n]; + for (int i = 0; i != n; ++i) { + if (p[i].p != &p[i].n) return -1; + p[i].n = i; + p[i].p = &k; + } + delete[] p; + return k; + } + // [expr.delete]p6: + // In the case of an array, the elements will be destroyed in order of + // decreasing address + static_assert(f(6) == 543210); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits