@@ -1856,8 +1856,12 @@ void CallStackFrame::describe(raw_ostream &Out) {
1856
1856
Out << ", ";
1857
1857
1858
1858
const ParmVarDecl *Param = *I;
1859
- const APValue &Arg = Arguments[ArgIndex];
1860
- Arg.printPretty(Out, Info.Ctx, Param->getType());
1859
+ if (Arguments) {
1860
+ const APValue &Arg = Arguments[ArgIndex];
1861
+ Arg.printPretty(Out, Info.Ctx, Param->getType());
1862
+ } else {
1863
+ Out << "<...>";
1864
+ }
1861
1865
1862
1866
if (ArgIndex == 0 && IsMemberCall)
1863
1867
Out << "->" << *Callee << '(';
@@ -5792,6 +5796,8 @@ typedef SmallVector<APValue, 8> ArgVector;
5792
5796
/// EvaluateArgs - Evaluate the arguments to a function call.
5793
5797
static bool EvaluateArgs(ArrayRef<const Expr *> Args, ArgVector &ArgValues,
5794
5798
EvalInfo &Info, const FunctionDecl *Callee) {
5799
+ ArgValues.resize(Args.size());
5800
+
5795
5801
bool Success = true;
5796
5802
llvm::SmallBitVector ForbiddenNullArgs;
5797
5803
if (Callee->hasAttr<NonNullAttr>()) {
@@ -5809,8 +5815,6 @@ static bool EvaluateArgs(ArrayRef<const Expr *> Args, ArgVector &ArgValues,
5809
5815
}
5810
5816
}
5811
5817
}
5812
- // FIXME: This is the wrong evaluation order for an assignment operator
5813
- // called via operator syntax.
5814
5818
for (unsigned Idx = 0; Idx < Args.size(); Idx++) {
5815
5819
if (!Evaluate(ArgValues[Idx], Info, Args[Idx])) {
5816
5820
// If we're checking for a potential constant expression, evaluate all
@@ -5834,17 +5838,13 @@ static bool EvaluateArgs(ArrayRef<const Expr *> Args, ArgVector &ArgValues,
5834
5838
/// Evaluate a function call.
5835
5839
static bool HandleFunctionCall(SourceLocation CallLoc,
5836
5840
const FunctionDecl *Callee, const LValue *This,
5837
- ArrayRef<const Expr*> Args, const Stmt *Body,
5838
- EvalInfo &Info, APValue &Result,
5839
- const LValue *ResultSlot) {
5840
- ArgVector ArgValues(Args.size());
5841
- if (!EvaluateArgs(Args, ArgValues, Info, Callee))
5842
- return false;
5843
-
5841
+ ArrayRef<const Expr *> Args, APValue *ArgValues,
5842
+ const Stmt *Body, EvalInfo &Info,
5843
+ APValue &Result, const LValue *ResultSlot) {
5844
5844
if (!Info.CheckCallLimit(CallLoc))
5845
5845
return false;
5846
5846
5847
- CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues.data() );
5847
+ CallStackFrame Frame(Info, CallLoc, Callee, This, ArgValues);
5848
5848
5849
5849
// For a trivial copy or move assignment, perform an APValue copy. This is
5850
5850
// essential for unions, where the operations performed by the assignment
@@ -7293,6 +7293,8 @@ class ExprEvaluatorBase
7293
7293
auto Args = llvm::makeArrayRef(E->getArgs(), E->getNumArgs());
7294
7294
bool HasQualifier = false;
7295
7295
7296
+ ArgVector ArgValues;
7297
+
7296
7298
// Extract function decl and 'this' pointer from the callee.
7297
7299
if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) {
7298
7300
const CXXMethodDecl *Member = nullptr;
@@ -7341,6 +7343,22 @@ class ExprEvaluatorBase
7341
7343
return Error(E);
7342
7344
}
7343
7345
7346
+ // For an (overloaded) assignment expression, evaluate the RHS before the
7347
+ // LHS.
7348
+ auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);
7349
+ if (OCE && OCE->isAssignmentOp()) {
7350
+ assert(Args.size() == 2 && "wrong number of arguments in assignment");
7351
+ if (isa<CXXMethodDecl>(FD)) {
7352
+ // Args[0] is the object argument.
7353
+ if (!EvaluateArgs({Args[1]}, ArgValues, Info, FD))
7354
+ return false;
7355
+ } else {
7356
+ if (!EvaluateArgs({Args[1], Args[0]}, ArgValues, Info, FD))
7357
+ return false;
7358
+ std::swap(ArgValues[0], ArgValues[1]);
7359
+ }
7360
+ }
7361
+
7344
7362
// Overloaded operator calls to member functions are represented as normal
7345
7363
// calls with '*this' as the first argument.
7346
7364
const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD);
@@ -7403,6 +7421,11 @@ class ExprEvaluatorBase
7403
7421
} else
7404
7422
return Error(E);
7405
7423
7424
+ // Evaluate the arguments now if we've not already done so.
7425
+ if (ArgValues.empty() && !Args.empty() &&
7426
+ !EvaluateArgs(Args, ArgValues, Info, FD))
7427
+ return false;
7428
+
7406
7429
SmallVector<QualType, 4> CovariantAdjustmentPath;
7407
7430
if (This) {
7408
7431
auto *NamedMember = dyn_cast<CXXMethodDecl>(FD);
@@ -7424,6 +7447,7 @@ class ExprEvaluatorBase
7424
7447
// Destructor calls are different enough that they have their own codepath.
7425
7448
if (auto *DD = dyn_cast<CXXDestructorDecl>(FD)) {
7426
7449
assert(This && "no 'this' pointer for destructor call");
7450
+ assert(ArgValues.empty() && "unexpected destructor arguments");
7427
7451
return HandleDestruction(Info, E, *This,
7428
7452
Info.Ctx.getRecordType(DD->getParent()));
7429
7453
}
@@ -7432,8 +7456,8 @@ class ExprEvaluatorBase
7432
7456
Stmt *Body = FD->getBody(Definition);
7433
7457
7434
7458
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body) ||
7435
- !HandleFunctionCall(E->getExprLoc(), Definition, This, Args, Body, Info,
7436
- Result, ResultSlot))
7459
+ !HandleFunctionCall(E->getExprLoc(), Definition, This, Args,
7460
+ ArgValues.data(), Body, Info, Result, ResultSlot))
7437
7461
return false;
7438
7462
7439
7463
if (!CovariantAdjustmentPath.empty() &&
@@ -8071,16 +8095,19 @@ bool LValueExprEvaluator::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
8071
8095
if (E->getBase()->getType()->isVectorType())
8072
8096
return Error(E);
8073
8097
8098
+ APSInt Index;
8074
8099
bool Success = true;
8075
- if (!evaluatePointer(E->getBase(), Result)) {
8076
- if (!Info.noteFailure())
8077
- return false;
8078
- Success = false;
8079
- }
8080
8100
8081
- APSInt Index;
8082
- if (!EvaluateInteger(E->getIdx(), Index, Info))
8083
- return false;
8101
+ // C++17's rules require us to evaluate the LHS first, regardless of which
8102
+ // side is the base.
8103
+ for (const Expr *SubExpr : {E->getLHS(), E->getRHS()}) {
8104
+ if (SubExpr == E->getBase() ? !evaluatePointer(SubExpr, Result)
8105
+ : !EvaluateInteger(SubExpr, Index, Info)) {
8106
+ if (!Info.noteFailure())
8107
+ return false;
8108
+ Success = false;
8109
+ }
8110
+ }
8084
8111
8085
8112
return Success &&
8086
8113
HandleLValueArrayAdjustment(Info, E, Result, E->getType(), Index);
@@ -8125,7 +8152,10 @@ bool LValueExprEvaluator::VisitCompoundAssignOperator(
8125
8152
if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure())
8126
8153
return Error(CAO);
8127
8154
8155
+ // C++17 onwards require that we evaluate the RHS first.
8128
8156
APValue RHS;
8157
+ if (!Evaluate(RHS, this->Info, CAO->getRHS()))
8158
+ return false;
8129
8159
8130
8160
// The overall lvalue result is the result of evaluating the LHS.
8131
8161
if (!this->Visit(CAO->getLHS())) {
@@ -8134,9 +8164,6 @@ bool LValueExprEvaluator::VisitCompoundAssignOperator(
8134
8164
return false;
8135
8165
}
8136
8166
8137
- if (!Evaluate(RHS, this->Info, CAO->getRHS()))
8138
- return false;
8139
-
8140
8167
return handleCompoundAssignment(
8141
8168
this->Info, CAO,
8142
8169
Result, CAO->getLHS()->getType(), CAO->getComputationLHSType(),
@@ -8147,17 +8174,17 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
8147
8174
if (!Info.getLangOpts().CPlusPlus14 && !Info.keepEvaluatingAfterFailure())
8148
8175
return Error(E);
8149
8176
8177
+ // C++17 onwards require that we evaluate the RHS first.
8150
8178
APValue NewVal;
8179
+ if (!Evaluate(NewVal, this->Info, E->getRHS()))
8180
+ return false;
8151
8181
8152
8182
if (!this->Visit(E->getLHS())) {
8153
8183
if (Info.noteFailure())
8154
8184
Evaluate(NewVal, this->Info, E->getRHS());
8155
8185
return false;
8156
8186
}
8157
8187
8158
- if (!Evaluate(NewVal, this->Info, E->getRHS()))
8159
- return false;
8160
-
8161
8188
if (Info.getLangOpts().CPlusPlus20 &&
8162
8189
!HandleUnionActiveMemberChange(Info, E->getLHS(), Result))
8163
8190
return false;
@@ -15270,7 +15297,8 @@ bool Expr::isPotentialConstantExpr(const FunctionDecl *FD,
15270
15297
} else {
15271
15298
SourceLocation Loc = FD->getLocation();
15272
15299
HandleFunctionCall(Loc, FD, (MD && MD->isInstance()) ? &This : nullptr,
15273
- Args, FD->getBody(), Info, Scratch, nullptr);
15300
+ Args, /*ArgValues*/ nullptr, FD->getBody(), Info,
15301
+ Scratch, nullptr);
15274
15302
}
15275
15303
15276
15304
return Diags.empty();
@@ -15292,13 +15320,8 @@ bool Expr::isPotentialConstantExprUnevaluated(Expr *E,
15292
15320
Info.CheckingPotentialConstantExpression = true;
15293
15321
15294
15322
// Fabricate a call stack frame to give the arguments a plausible cover story.
15295
- ArrayRef<const Expr*> Args;
15296
- ArgVector ArgValues(0);
15297
- bool Success = EvaluateArgs(Args, ArgValues, Info, FD);
15298
- (void)Success;
15299
- assert(Success &&
15300
- "Failed to set up arguments for potential constant evaluation");
15301
- CallStackFrame Frame(Info, SourceLocation(), FD, nullptr, ArgValues.data());
15323
+ CallStackFrame Frame(Info, SourceLocation(), FD, /*This*/ nullptr,
15324
+ /*ArgValues*/ nullptr);
15302
15325
15303
15326
APValue ResultScratch;
15304
15327
Evaluate(ResultScratch, Info, E);
0 commit comments