@@ -6549,8 +6549,8 @@ static bool MaybeHandleUnionActiveMemberChange(EvalInfo &Info,
65496549}
65506550
65516551static 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 ) {
65546554 LValue LV;
65556555 // Create the parameter slot and register its destruction. For a vararg
65566556 // argument, create a temporary.
@@ -6570,13 +6570,17 @@ static bool EvaluateCallArg(const ParmVarDecl *PVD, const Expr *Arg,
65706570 return false;
65716571 }
65726572
6573+ if (EvaluatedArg)
6574+ *EvaluatedArg = &V;
6575+
65736576 return true;
65746577}
65756578
65766579/// Evaluate the arguments to a function call.
65776580static bool EvaluateArgs(ArrayRef<const Expr *> Args, CallRef Call,
65786581 EvalInfo &Info, const FunctionDecl *Callee,
6579- bool RightToLeft = false) {
6582+ bool RightToLeft = false,
6583+ LValue *ObjectArg = nullptr) {
65806584 bool Success = true;
65816585 llvm::SmallBitVector ForbiddenNullArgs;
65826586 if (Callee->hasAttr<NonNullAttr>()) {
@@ -6599,13 +6603,16 @@ static bool EvaluateArgs(ArrayRef<const Expr *> Args, CallRef Call,
65996603 const ParmVarDecl *PVD =
66006604 Idx < Callee->getNumParams() ? Callee->getParamDecl(Idx) : nullptr;
66016605 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)) {
66036608 // If we're checking for a potential constant expression, evaluate all
66046609 // initializers even if some of them fail.
66056610 if (!Info.noteFailure())
66066611 return false;
66076612 Success = false;
66086613 }
6614+ if (PVD && PVD->isExplicitObjectParameter() && That && That->isLValue())
6615+ ObjectArg->setFrom(Info.Ctx, *That);
66096616 }
66106617 return Success;
66116618}
@@ -6633,14 +6640,15 @@ static bool handleTrivialCopy(EvalInfo &Info, const ParmVarDecl *Param,
66336640
66346641/// Evaluate a function call.
66356642static 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,
66396647 APValue &Result, const LValue *ResultSlot) {
66406648 if (!Info.CheckCallLimit(CallLoc))
66416649 return false;
66426650
6643- CallStackFrame Frame(Info, E->getSourceRange(), Callee, This , E, Call);
6651+ CallStackFrame Frame(Info, E->getSourceRange(), Callee, ObjectArg , E, Call);
66446652
66456653 // For a trivial copy or move assignment, perform an APValue copy. This is
66466654 // essential for unions, where the operations performed by the assignment
@@ -6653,16 +6661,20 @@ static bool HandleFunctionCall(SourceLocation CallLoc,
66536661 (MD->getParent()->isUnion() ||
66546662 (MD->isTrivial() &&
66556663 isReadByLvalueToRvalueConversion(MD->getParent())))) {
6656- assert(This &&
6664+ unsigned ExplicitOffset = MD->isExplicitObjectMemberFunction() ? 1 : 0;
6665+ assert(ObjectArg &&
66576666 (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()));
66586667 APValue RHSValue;
66596668 if (!handleTrivialCopy(Info, MD->getParamDecl(0), Args[0], RHSValue,
66606669 MD->getParent()->isUnion()))
66616670 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(),
66636675 RHSValue))
66646676 return false;
6665- This ->moveInto(Result);
6677+ ObjectArg ->moveInto(Result);
66666678 return true;
66676679 } else if (MD && isLambdaCallOperator(MD)) {
66686680 // We're in a lambda; determine the lambda capture field maps unless we're
@@ -8289,7 +8301,7 @@ class ExprEvaluatorBase
82898301 QualType CalleeType = Callee->getType();
82908302
82918303 const FunctionDecl *FD = nullptr;
8292- LValue *This = nullptr, ThisVal ;
8304+ LValue *This = nullptr, ObjectArg ;
82938305 auto Args = llvm::ArrayRef(E->getArgs(), E->getNumArgs());
82948306 bool HasQualifier = false;
82958307
@@ -8300,28 +8312,28 @@ class ExprEvaluatorBase
83008312 const CXXMethodDecl *Member = nullptr;
83018313 if (const MemberExpr *ME = dyn_cast<MemberExpr>(Callee)) {
83028314 // 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 ))
83048316 return false;
83058317 Member = dyn_cast<CXXMethodDecl>(ME->getMemberDecl());
83068318 if (!Member)
83078319 return Error(Callee);
8308- This = &ThisVal ;
8320+ This = &ObjectArg ;
83098321 HasQualifier = ME->hasQualifier();
83108322 } else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(Callee)) {
83118323 // Indirect bound member calls ('.*' or '->*').
83128324 const ValueDecl *D =
8313- HandleMemberPointerAccess(Info, BE, ThisVal , false);
8325+ HandleMemberPointerAccess(Info, BE, ObjectArg , false);
83148326 if (!D)
83158327 return false;
83168328 Member = dyn_cast<CXXMethodDecl>(D);
83178329 if (!Member)
83188330 return Error(Callee);
8319- This = &ThisVal ;
8331+ This = &ObjectArg ;
83208332 } else if (const auto *PDE = dyn_cast<CXXPseudoDestructorExpr>(Callee)) {
83218333 if (!Info.getLangOpts().CPlusPlus20)
83228334 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());
83258337 } else
83268338 return Error(Callee);
83278339 FD = Member;
@@ -8358,7 +8370,7 @@ class ExprEvaluatorBase
83588370 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
83598371 HasThis = MD->isImplicitObjectMemberFunction();
83608372 if (!EvaluateArgs(HasThis ? Args.slice(1) : Args, Call, Info, FD,
8361- /*RightToLeft=*/true))
8373+ /*RightToLeft=*/true, &ObjectArg ))
83628374 return false;
83638375 }
83648376
@@ -8373,20 +8385,20 @@ class ExprEvaluatorBase
83738385 if (Args.empty())
83748386 return Error(E);
83758387
8376- if (!EvaluateObjectArgument(Info, Args[0], ThisVal ))
8388+ if (!EvaluateObjectArgument(Info, Args[0], ObjectArg ))
83778389 return false;
83788390
83798391 // If we are calling a static operator, the 'this' argument needs to be
83808392 // ignored after being evaluated.
83818393 if (MD->isInstance())
8382- This = &ThisVal ;
8394+ This = &ObjectArg ;
83838395
83848396 // If this is syntactically a simple assignment using a trivial
83858397 // assignment operator, start the lifetimes of union members as needed,
83868398 // per C++20 [class.union]5.
83878399 if (Info.getLangOpts().CPlusPlus20 && OCE &&
83888400 OCE->getOperator() == OO_Equal && MD->isTrivial() &&
8389- !MaybeHandleUnionActiveMemberChange(Info, Args[0], ThisVal ))
8401+ !MaybeHandleUnionActiveMemberChange(Info, Args[0], ObjectArg ))
83908402 return false;
83918403
83928404 Args = Args.slice(1);
@@ -8441,7 +8453,8 @@ class ExprEvaluatorBase
84418453 // Evaluate the arguments now if we've not already done so.
84428454 if (!Call) {
84438455 Call = Info.CurrentCall->createCall(FD);
8444- if (!EvaluateArgs(Args, Call, Info, FD))
8456+ if (!EvaluateArgs(Args, Call, Info, FD, /*RightToLeft*/ false,
8457+ &ObjectArg))
84458458 return false;
84468459 }
84478460
@@ -8475,6 +8488,11 @@ class ExprEvaluatorBase
84758488 Stmt *Body = FD->getBody(Definition);
84768489 SourceLocation Loc = E->getExprLoc();
84778490
8491+ // Treat the object argument as `this` when evaluating defaulted
8492+ // special menmber functions
8493+ if (FD->hasCXXExplicitFunctionObjectParameter())
8494+ This = &ObjectArg;
8495+
84788496 if (!CheckConstexprFunction(Info, Loc, FD, Definition, Body) ||
84798497 !HandleFunctionCall(Loc, Definition, This, E, Args, Call, Body, Info,
84808498 Result, ResultSlot))
0 commit comments