@@ -8519,6 +8519,53 @@ class LValueExprEvaluator
8519
8519
};
8520
8520
} // end anonymous namespace
8521
8521
8522
+ /// Get an lvalue to a field of a lambda's closure type.
8523
+ static bool HandleLambdaCapture(EvalInfo &Info, const Expr *E, LValue &Result,
8524
+ const CXXMethodDecl *MD, const FieldDecl *FD,
8525
+ bool LValueToRValueConversion) {
8526
+ // Static lambda function call operators can't have captures. We already
8527
+ // diagnosed this, so bail out here.
8528
+ if (MD->isStatic()) {
8529
+ assert(Info.CurrentCall->This == nullptr &&
8530
+ "This should not be set for a static call operator");
8531
+ return false;
8532
+ }
8533
+
8534
+ // Start with 'Result' referring to the complete closure object...
8535
+ if (MD->isExplicitObjectMemberFunction()) {
8536
+ // Self may be passed by reference or by value.
8537
+ const ParmVarDecl *Self = MD->getParamDecl(0);
8538
+ if (Self->getType()->isReferenceType()) {
8539
+ APValue *RefValue = Info.getParamSlot(Info.CurrentCall->Arguments, Self);
8540
+ Result.setFrom(Info.Ctx, *RefValue);
8541
+ } else {
8542
+ const ParmVarDecl *VD = Info.CurrentCall->Arguments.getOrigParam(Self);
8543
+ CallStackFrame *Frame =
8544
+ Info.getCallFrameAndDepth(Info.CurrentCall->Arguments.CallIndex)
8545
+ .first;
8546
+ unsigned Version = Info.CurrentCall->Arguments.Version;
8547
+ Result.set({VD, Frame->Index, Version});
8548
+ }
8549
+ } else
8550
+ Result = *Info.CurrentCall->This;
8551
+
8552
+ // ... then update it to refer to the field of the closure object
8553
+ // that represents the capture.
8554
+ if (!HandleLValueMember(Info, E, Result, FD))
8555
+ return false;
8556
+
8557
+ // And if the field is of reference type (or if we captured '*this' by
8558
+ // reference), update 'Result' to refer to what
8559
+ // the field refers to.
8560
+ if (LValueToRValueConversion) {
8561
+ APValue RVal;
8562
+ if (!handleLValueToRValueConversion(Info, E, FD->getType(), Result, RVal))
8563
+ return false;
8564
+ Result.setFrom(Info.Ctx, RVal);
8565
+ }
8566
+ return true;
8567
+ }
8568
+
8522
8569
/// Evaluate an expression as an lvalue. This can be legitimately called on
8523
8570
/// expressions which are not glvalues, in three cases:
8524
8571
/// * function designators in C, and
@@ -8563,37 +8610,8 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
8563
8610
8564
8611
if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) {
8565
8612
const auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee);
8566
-
8567
- // Static lambda function call operators can't have captures. We already
8568
- // diagnosed this, so bail out here.
8569
- if (MD->isStatic()) {
8570
- assert(Info.CurrentCall->This == nullptr &&
8571
- "This should not be set for a static call operator");
8572
- return false;
8573
- }
8574
-
8575
- // Start with 'Result' referring to the complete closure object...
8576
- if (MD->isExplicitObjectMemberFunction()) {
8577
- APValue *RefValue =
8578
- Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0));
8579
- Result.setFrom(Info.Ctx, *RefValue);
8580
- } else
8581
- Result = *Info.CurrentCall->This;
8582
-
8583
- // ... then update it to refer to the field of the closure object
8584
- // that represents the capture.
8585
- if (!HandleLValueMember(Info, E, Result, FD))
8586
- return false;
8587
- // And if the field is of reference type, update 'Result' to refer to what
8588
- // the field refers to.
8589
- if (FD->getType()->isReferenceType()) {
8590
- APValue RVal;
8591
- if (!handleLValueToRValueConversion(Info, E, FD->getType(), Result,
8592
- RVal))
8593
- return false;
8594
- Result.setFrom(Info.Ctx, RVal);
8595
- }
8596
- return true;
8613
+ return HandleLambdaCapture(Info, E, Result, MD, FD,
8614
+ FD->getType()->isReferenceType());
8597
8615
}
8598
8616
}
8599
8617
@@ -9071,45 +9089,46 @@ class PointerExprEvaluator
9071
9089
return Error(E);
9072
9090
}
9073
9091
bool VisitCXXThisExpr(const CXXThisExpr *E) {
9074
- // Can't look at 'this' when checking a potential constant expression.
9075
- if (Info.checkingPotentialConstantExpression())
9076
- return false;
9077
- if (!Info.CurrentCall->This) {
9092
+ auto DiagnoseInvalidUseOfThis = [&] {
9078
9093
if (Info.getLangOpts().CPlusPlus11)
9079
9094
Info.FFDiag(E, diag::note_constexpr_this) << E->isImplicit();
9080
9095
else
9081
9096
Info.FFDiag(E);
9097
+ };
9098
+
9099
+ // Can't look at 'this' when checking a potential constant expression.
9100
+ if (Info.checkingPotentialConstantExpression())
9082
9101
return false;
9102
+
9103
+ bool IsExplicitLambda =
9104
+ isLambdaCallWithExplicitObjectParameter(Info.CurrentCall->Callee);
9105
+ if (!IsExplicitLambda) {
9106
+ if (!Info.CurrentCall->This) {
9107
+ DiagnoseInvalidUseOfThis();
9108
+ return false;
9109
+ }
9110
+
9111
+ Result = *Info.CurrentCall->This;
9083
9112
}
9084
- Result = *Info.CurrentCall->This;
9085
9113
9086
9114
if (isLambdaCallOperator(Info.CurrentCall->Callee)) {
9087
9115
// Ensure we actually have captured 'this'. If something was wrong with
9088
9116
// 'this' capture, the error would have been previously reported.
9089
9117
// Otherwise we can be inside of a default initialization of an object
9090
9118
// declared by lambda's body, so no need to return false.
9091
- if (!Info.CurrentCall->LambdaThisCaptureField)
9092
- return true;
9093
-
9094
- // If we have captured 'this', the 'this' expression refers
9095
- // to the enclosing '*this' object (either by value or reference) which is
9096
- // either copied into the closure object's field that represents the
9097
- // '*this' or refers to '*this'.
9098
- // Update 'Result' to refer to the data member/field of the closure object
9099
- // that represents the '*this' capture.
9100
- if (!HandleLValueMember(Info, E, Result,
9101
- Info.CurrentCall->LambdaThisCaptureField))
9102
- return false;
9103
- // If we captured '*this' by reference, replace the field with its referent.
9104
- if (Info.CurrentCall->LambdaThisCaptureField->getType()
9105
- ->isPointerType()) {
9106
- APValue RVal;
9107
- if (!handleLValueToRValueConversion(Info, E, E->getType(), Result,
9108
- RVal))
9119
+ if (!Info.CurrentCall->LambdaThisCaptureField) {
9120
+ if (IsExplicitLambda && !Info.CurrentCall->This) {
9121
+ DiagnoseInvalidUseOfThis();
9109
9122
return false;
9123
+ }
9110
9124
9111
- Result.setFrom(Info.Ctx, RVal) ;
9125
+ return true ;
9112
9126
}
9127
+
9128
+ const auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee);
9129
+ return HandleLambdaCapture(
9130
+ Info, E, Result, MD, Info.CurrentCall->LambdaThisCaptureField,
9131
+ Info.CurrentCall->LambdaThisCaptureField->getType()->isPointerType());
9113
9132
}
9114
9133
return true;
9115
9134
}
0 commit comments