Skip to content

Commit

Permalink
PR45350: Handle unsized array CXXConstructExprs in constant evaluation
Browse files Browse the repository at this point in the history
of array new expressions with runtime bound.
  • Loading branch information
zygoloid committed Mar 30, 2020
1 parent 31a1d85 commit 9a7eda1
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 1 deletion.
23 changes: 22 additions & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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");

Expand All @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
20 changes: 20 additions & 0 deletions clang/test/SemaCXX/constant-expression-cxx2a.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

0 comments on commit 9a7eda1

Please sign in to comment.