Skip to content

Commit 964da81

Browse files
zygoloidtstellar
authored andcommitted
PR45350: Handle unsized array CXXConstructExprs in constant evaluation
of array new expressions with runtime bound. (cherry picked from commit 9a7eda1)
1 parent aba4e3f commit 964da81

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8593,6 +8593,10 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
85938593
static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This,
85948594
APValue &Result, const InitListExpr *ILE,
85958595
QualType AllocType);
8596+
static bool EvaluateArrayNewConstructExpr(EvalInfo &Info, LValue &This,
8597+
APValue &Result,
8598+
const CXXConstructExpr *CCE,
8599+
QualType AllocType);
85968600

85978601
bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
85988602
if (!Info.getLangOpts().CPlusPlus2a)
@@ -8642,6 +8646,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
86428646

86438647
const Expr *Init = E->getInitializer();
86448648
const InitListExpr *ResizedArrayILE = nullptr;
8649+
const CXXConstructExpr *ResizedArrayCCE = nullptr;
86458650

86468651
QualType AllocType = E->getAllocatedType();
86478652
if (Optional<const Expr*> ArraySize = E->getArraySize()) {
@@ -8685,7 +8690,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
86858690
// -- the new-initializer is a braced-init-list and the number of
86868691
// array elements for which initializers are provided [...]
86878692
// exceeds the number of elements to initialize
8688-
if (Init) {
8693+
if (Init && !isa<CXXConstructExpr>(Init)) {
86898694
auto *CAT = Info.Ctx.getAsConstantArrayType(Init->getType());
86908695
assert(CAT && "unexpected type for array initializer");
86918696

@@ -8708,6 +8713,8 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
87088713
// special handling for this case when we initialize.
87098714
if (InitBound != AllocBound)
87108715
ResizedArrayILE = cast<InitListExpr>(Init);
8716+
} else if (Init) {
8717+
ResizedArrayCCE = cast<CXXConstructExpr>(Init);
87118718
}
87128719

87138720
AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound, nullptr,
@@ -8772,6 +8779,10 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
87728779
if (!EvaluateArrayNewInitList(Info, Result, *Val, ResizedArrayILE,
87738780
AllocType))
87748781
return false;
8782+
} else if (ResizedArrayCCE) {
8783+
if (!EvaluateArrayNewConstructExpr(Info, Result, *Val, ResizedArrayCCE,
8784+
AllocType))
8785+
return false;
87758786
} else if (Init) {
87768787
if (!EvaluateInPlace(*Val, Info, Result, Init))
87778788
return false;
@@ -9597,6 +9608,16 @@ static bool EvaluateArrayNewInitList(EvalInfo &Info, LValue &This,
95979608
.VisitInitListExpr(ILE, AllocType);
95989609
}
95999610

9611+
static bool EvaluateArrayNewConstructExpr(EvalInfo &Info, LValue &This,
9612+
APValue &Result,
9613+
const CXXConstructExpr *CCE,
9614+
QualType AllocType) {
9615+
assert(CCE->isRValue() && CCE->getType()->isArrayType() &&
9616+
"not an array rvalue");
9617+
return ArrayExprEvaluator(Info, This, Result)
9618+
.VisitCXXConstructExpr(CCE, This, &Result, AllocType);
9619+
}
9620+
96009621
// Return true iff the given array filler may depend on the element index.
96019622
static bool MaybeElementDependentArrayFiller(const Expr *FillerExpr) {
96029623
// For now, just whitelist non-class value-initialization and initialization

clang/test/SemaCXX/constant-expression-cxx2a.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,3 +1279,23 @@ namespace value_dependent_init {
12791279
A a = T();
12801280
}
12811281
}
1282+
1283+
namespace PR45350 {
1284+
int q;
1285+
struct V { int n; int *p = &n; constexpr ~V() { *p = *p * 10 + n; }};
1286+
constexpr int f(int n) {
1287+
int k = 0;
1288+
V *p = new V[n];
1289+
for (int i = 0; i != n; ++i) {
1290+
if (p[i].p != &p[i].n) return -1;
1291+
p[i].n = i;
1292+
p[i].p = &k;
1293+
}
1294+
delete[] p;
1295+
return k;
1296+
}
1297+
// [expr.delete]p6:
1298+
// In the case of an array, the elements will be destroyed in order of
1299+
// decreasing address
1300+
static_assert(f(6) == 543210);
1301+
}

0 commit comments

Comments
 (0)