@@ -6549,8 +6549,8 @@ static bool MaybeHandleUnionActiveMemberChange(EvalInfo &Info,
6549
6549
}
6550
6550
6551
6551
static bool EvaluateCallArg(const ParmVarDecl *PVD, const Expr *Arg,
6552
- CallRef Call, EvalInfo &Info,
6553
- bool NonNull = false ) {
6552
+ CallRef Call, EvalInfo &Info, bool NonNull = false,
6553
+ APValue **EvaluatedArg = nullptr ) {
6554
6554
LValue LV;
6555
6555
// Create the parameter slot and register its destruction. For a vararg
6556
6556
// argument, create a temporary.
@@ -6570,13 +6570,17 @@ static bool EvaluateCallArg(const ParmVarDecl *PVD, const Expr *Arg,
6570
6570
return false;
6571
6571
}
6572
6572
6573
+ if (EvaluatedArg)
6574
+ *EvaluatedArg = &V;
6575
+
6573
6576
return true;
6574
6577
}
6575
6578
6576
6579
/// Evaluate the arguments to a function call.
6577
6580
static bool EvaluateArgs(ArrayRef<const Expr *> Args, CallRef Call,
6578
6581
EvalInfo &Info, const FunctionDecl *Callee,
6579
- bool RightToLeft = false) {
6582
+ bool RightToLeft = false,
6583
+ LValue *ObjectArg = nullptr) {
6580
6584
bool Success = true;
6581
6585
llvm::SmallBitVector ForbiddenNullArgs;
6582
6586
if (Callee->hasAttr<NonNullAttr>()) {
@@ -6599,13 +6603,16 @@ static bool EvaluateArgs(ArrayRef<const Expr *> Args, CallRef Call,
6599
6603
const ParmVarDecl *PVD =
6600
6604
Idx < Callee->getNumParams() ? Callee->getParamDecl(Idx) : nullptr;
6601
6605
bool NonNull = !ForbiddenNullArgs.empty() && ForbiddenNullArgs[Idx];
6602
- if (!EvaluateCallArg(PVD, Args[Idx], Call, Info, NonNull)) {
6606
+ APValue *That = nullptr;
6607
+ if (!EvaluateCallArg(PVD, Args[Idx], Call, Info, NonNull, &That)) {
6603
6608
// If we're checking for a potential constant expression, evaluate all
6604
6609
// initializers even if some of them fail.
6605
6610
if (!Info.noteFailure())
6606
6611
return false;
6607
6612
Success = false;
6608
6613
}
6614
+ if (PVD && PVD->isExplicitObjectParameter() && That && That->isLValue())
6615
+ ObjectArg->setFrom(Info.Ctx, *That);
6609
6616
}
6610
6617
return Success;
6611
6618
}
@@ -6633,14 +6640,15 @@ static bool handleTrivialCopy(EvalInfo &Info, const ParmVarDecl *Param,
6633
6640
6634
6641
/// Evaluate a function call.
6635
6642
static bool HandleFunctionCall(SourceLocation CallLoc,
6636
- const FunctionDecl *Callee, const LValue *This,
6637
- const Expr *E, ArrayRef<const Expr *> Args,
6638
- CallRef Call, const Stmt *Body, EvalInfo &Info,
6643
+ const FunctionDecl *Callee,
6644
+ const LValue *ObjectArg, const Expr *E,
6645
+ ArrayRef<const Expr *> Args, CallRef Call,
6646
+ const Stmt *Body, EvalInfo &Info,
6639
6647
APValue &Result, const LValue *ResultSlot) {
6640
6648
if (!Info.CheckCallLimit(CallLoc))
6641
6649
return false;
6642
6650
6643
- CallStackFrame Frame(Info, E->getSourceRange(), Callee, This , E, Call);
6651
+ CallStackFrame Frame(Info, E->getSourceRange(), Callee, ObjectArg , E, Call);
6644
6652
6645
6653
// For a trivial copy or move assignment, perform an APValue copy. This is
6646
6654
// essential for unions, where the operations performed by the assignment
@@ -6653,16 +6661,20 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
6653
6661
(MD->getParent()->isUnion() ||
6654
6662
(MD->isTrivial() &&
6655
6663
isReadByLvalueToRvalueConversion(MD->getParent())))) {
6656
- assert(This &&
6664
+ unsigned ExplicitOffset = MD->isExplicitObjectMemberFunction() ? 1 : 0;
6665
+ assert(ObjectArg &&
6657
6666
(MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()));
6658
6667
APValue RHSValue;
6659
6668
if (!handleTrivialCopy(Info, MD->getParamDecl(0), Args[0], RHSValue,
6660
6669
MD->getParent()->isUnion()))
6661
6670
return false;
6662
- if (!handleAssignment(Info, Args[0], *This, MD->getThisType(),
6671
+
6672
+ LValue Obj;
6673
+ if (!handleAssignment(Info, Args[ExplicitOffset], *ObjectArg,
6674
+ MD->getFunctionObjectParameterReferenceType(),
6663
6675
RHSValue))
6664
6676
return false;
6665
- This ->moveInto(Result);
6677
+ ObjectArg ->moveInto(Result);
6666
6678
return true;
6667
6679
} else if (MD && isLambdaCallOperator(MD)) {
6668
6680
// We're in a lambda; determine the lambda capture field maps unless we're
@@ -8289,7 +8301,7 @@ class ExprEvaluatorBase
8289
8301
QualType CalleeType = Callee->getType();
8290
8302
8291
8303
const FunctionDecl *FD = nullptr;
8292
- LValue *This = nullptr, ThisVal ;
8304
+ LValue *This = nullptr, ObjectArg ;
8293
8305
auto Args = llvm::ArrayRef(E->getArgs(), E->getNumArgs());
8294
8306
bool HasQualifier = false;
8295
8307
@@ -8300,28 +8312,28 @@ class ExprEvaluatorBase
8300
8312
const CXXMethodDecl *Member = nullptr;
8301
8313
if (const MemberExpr *ME = dyn_cast<MemberExpr>(Callee)) {
8302
8314
// Explicit bound member calls, such as x.f() or p->g();
8303
- if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal ))
8315
+ if (!EvaluateObjectArgument(Info, ME->getBase(), ObjectArg ))
8304
8316
return false;
8305
8317
Member = dyn_cast<CXXMethodDecl>(ME->getMemberDecl());
8306
8318
if (!Member)
8307
8319
return Error(Callee);
8308
- This = &ThisVal ;
8320
+ This = &ObjectArg ;
8309
8321
HasQualifier = ME->hasQualifier();
8310
8322
} else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(Callee)) {
8311
8323
// Indirect bound member calls ('.*' or '->*').
8312
8324
const ValueDecl *D =
8313
- HandleMemberPointerAccess(Info, BE, ThisVal , false);
8325
+ HandleMemberPointerAccess(Info, BE, ObjectArg , false);
8314
8326
if (!D)
8315
8327
return false;
8316
8328
Member = dyn_cast<CXXMethodDecl>(D);
8317
8329
if (!Member)
8318
8330
return Error(Callee);
8319
- This = &ThisVal ;
8331
+ This = &ObjectArg ;
8320
8332
} else if (const auto *PDE = dyn_cast<CXXPseudoDestructorExpr>(Callee)) {
8321
8333
if (!Info.getLangOpts().CPlusPlus20)
8322
8334
Info.CCEDiag(PDE, diag::note_constexpr_pseudo_destructor);
8323
- return EvaluateObjectArgument(Info, PDE->getBase(), ThisVal ) &&
8324
- HandleDestruction(Info, PDE, ThisVal , PDE->getDestroyedType());
8335
+ return EvaluateObjectArgument(Info, PDE->getBase(), ObjectArg ) &&
8336
+ HandleDestruction(Info, PDE, ObjectArg , PDE->getDestroyedType());
8325
8337
} else
8326
8338
return Error(Callee);
8327
8339
FD = Member;
@@ -8358,7 +8370,7 @@ class ExprEvaluatorBase
8358
8370
if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
8359
8371
HasThis = MD->isImplicitObjectMemberFunction();
8360
8372
if (!EvaluateArgs(HasThis ? Args.slice(1) : Args, Call, Info, FD,
8361
- /*RightToLeft=*/true))
8373
+ /*RightToLeft=*/true, &ObjectArg ))
8362
8374
return false;
8363
8375
}
8364
8376
@@ -8373,20 +8385,20 @@ class ExprEvaluatorBase
8373
8385
if (Args.empty())
8374
8386
return Error(E);
8375
8387
8376
- if (!EvaluateObjectArgument(Info, Args[0], ThisVal ))
8388
+ if (!EvaluateObjectArgument(Info, Args[0], ObjectArg ))
8377
8389
return false;
8378
8390
8379
8391
// If we are calling a static operator, the 'this' argument needs to be
8380
8392
// ignored after being evaluated.
8381
8393
if (MD->isInstance())
8382
- This = &ThisVal ;
8394
+ This = &ObjectArg ;
8383
8395
8384
8396
// If this is syntactically a simple assignment using a trivial
8385
8397
// assignment operator, start the lifetimes of union members as needed,
8386
8398
// per C++20 [class.union]5.
8387
8399
if (Info.getLangOpts().CPlusPlus20 && OCE &&
8388
8400
OCE->getOperator() == OO_Equal && MD->isTrivial() &&
8389
- !MaybeHandleUnionActiveMemberChange(Info, Args[0], ThisVal ))
8401
+ !MaybeHandleUnionActiveMemberChange(Info, Args[0], ObjectArg ))
8390
8402
return false;
8391
8403
8392
8404
Args = Args.slice(1);
@@ -8441,7 +8453,8 @@ class ExprEvaluatorBase
8441
8453
// Evaluate the arguments now if we've not already done so.
8442
8454
if (!Call) {
8443
8455
Call = Info.CurrentCall->createCall(FD);
8444
- if (!EvaluateArgs(Args, Call, Info, FD))
8456
+ if (!EvaluateArgs(Args, Call, Info, FD, /*RightToLeft*/ false,
8457
+ &ObjectArg))
8445
8458
return false;
8446
8459
}
8447
8460
@@ -8475,6 +8488,11 @@ class ExprEvaluatorBase
8475
8488
Stmt *Body = FD->getBody(Definition);
8476
8489
SourceLocation Loc = E->getExprLoc();
8477
8490
8491
+ // Treat the object argument as `this` when evaluating defaulted
8492
+ // special menmber functions
8493
+ if (FD->hasCXXExplicitFunctionObjectParameter())
8494
+ This = &ObjectArg;
8495
+
8478
8496
if (!CheckConstexprFunction(Info, Loc, FD, Definition, Body) ||
8479
8497
!HandleFunctionCall(Loc, Definition, This, E, Args, Call, Body, Info,
8480
8498
Result, ResultSlot))
0 commit comments