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