[llvm-branch-commits] [clang] 964da81 - PR45350: Handle unsized array CXXConstructExprs in constant evaluation
Tom Stellard via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon May 18 18:41:56 PDT 2020
Author: Richard Smith
Date: 2020-05-18T18:40:31-07:00
New Revision: 964da8185568aa86e6ddbd8f2fadf1faf22df7d2
URL: https://github.com/llvm/llvm-project/commit/964da8185568aa86e6ddbd8f2fadf1faf22df7d2
DIFF: https://github.com/llvm/llvm-project/commit/964da8185568aa86e6ddbd8f2fadf1faf22df7d2.diff
LOG: PR45350: Handle unsized array CXXConstructExprs in constant evaluation
of array new expressions with runtime bound.
(cherry picked from commit 9a7eda1bece887ca9af085d79fe6e4fb8826dcda)
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 c79973507323..7af1edb9565a 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8593,6 +8593,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)
@@ -8642,6 +8646,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()) {
@@ -8685,7 +8690,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");
@@ -8708,6 +8713,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,
@@ -8772,6 +8779,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;
@@ -9597,6 +9608,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 9012f377e1bc..b4a50aa6df4f 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -1279,3 +1279,23 @@ namespace value_dependent_init {
A a = T();
}
}
+
+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);
+}
More information about the llvm-branch-commits
mailing list