VarDecl *CapturedVar;
};
- /// Expression to initialize a field of the given type. This is only required
- /// if we are capturing ByVal and the variable's type has a non-trivial copy
- /// constructor.
- Expr *InitExpr = nullptr;
-
/// The source location at which the first capture occurred.
SourceLocation Loc;
enum IsThisCapture { ThisCapture };
Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
- QualType CaptureType, Expr *Cpy, const bool ByCopy, bool Invalid)
- : InitExpr(Cpy), Loc(Loc), CaptureType(CaptureType),
+ QualType CaptureType, const bool ByCopy, bool Invalid)
+ : Loc(Loc), CaptureType(CaptureType),
Kind(ByCopy ? Cap_ByCopy : Cap_ByRef), Nested(IsNested),
CapturesThis(true), ODRUsed(false), NonODRUsed(false),
Invalid(Invalid) {}
/// the type of the non-static data member in the lambda/block structure
/// that would store this capture.
QualType getCaptureType() const { return CaptureType; }
-
- Expr *getThisInitExpr() const {
- assert(isThisCapture() && "no 'this' init expression for non-this capture");
- return InitExpr;
- }
};
class CapturingScopeInfo : public FunctionScopeInfo {
}
void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType,
- Expr *Cpy, bool ByCopy);
+ bool ByCopy);
/// Determine whether the C++ 'this' is captured.
bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
Uses.push_back(WeakUseTy(E, IsRead));
}
-inline void
-CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc,
- QualType CaptureType, Expr *Cpy,
- const bool ByCopy) {
+inline void CapturingScopeInfo::addThisCapture(bool isNested,
+ SourceLocation Loc,
+ QualType CaptureType,
+ bool ByCopy) {
Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType,
- Cpy, ByCopy, /*Invalid*/ false));
+ ByCopy, /*Invalid*/ false));
CXXThisCaptureIndex = Captures.size();
}
const unsigned *const FunctionScopeIndexToStopAt = nullptr,
bool ByCopy = false);
+ /// Initialize the given 'this' capture with a suitable 'this' or '*this'
+ /// expression.
+ ExprResult performThisCaptureInitialization(const sema::Capture &Capture,
+ bool IsImplicit);
+
/// Determine whether the given type is the type of *this that is used
/// outside of the body of a member function for a type that is currently
/// being defined.
} else if (C.capturesThis()) {
LSI->addThisCapture(/*Nested*/ false, C.getLocation(), I->getType(),
- /*Expr*/ nullptr, C.getCaptureKind() == LCK_StarThis);
+ C.getCaptureKind() == LCK_StarThis);
} else {
LSI->addVLATypeCapture(C.getLocation(), I->getCapturedVLAType(),
I->getType());
}
}
-static Expr *captureThis(Sema &S, ASTContext &Context, RecordDecl *RD,
- QualType ThisTy, QualType CaptureType,
- SourceLocation Loc, const bool ByCopy) {
- Expr *This = new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/ true);
- if (ByCopy) {
- Expr *StarThis = S.CreateBuiltinUnaryOp(Loc, UO_Deref, This).get();
- InitializedEntity Entity =
- InitializedEntity::InitializeLambdaCapture(nullptr, CaptureType, Loc);
- InitializationKind InitKind =
- InitializationKind::CreateDirect(Loc, Loc, Loc);
- InitializationSequence Init(S, Entity, InitKind, StarThis);
- ExprResult ER = Init.Perform(S, Entity, InitKind, StarThis);
- if (ER.isInvalid()) return nullptr;
- return ER.get();
- }
- return This;
-}
-
bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt,
const bool ByCopy) {
dyn_cast<LambdaScopeInfo>(FunctionScopes[MaxFunctionScopesIndex])) &&
"Only a lambda can capture the enclosing object (referred to by "
"*this) by copy");
- // FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated
- // contexts.
QualType ThisTy = getCurrentThisType();
for (int idx = MaxFunctionScopesIndex; NumCapturingClosures;
--idx, --NumCapturingClosures) {
CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);
- Expr *ThisExpr = nullptr;
// The type of the corresponding data member (not a 'this' pointer if 'by
// copy').
CaptureType.removeLocalCVRQualifiers(Qualifiers::CVRMask);
}
- if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI)) {
- // For lambda expressions, build a field and an initializing expression,
- // and capture the *enclosing object* by copy only if this is the first
- // iteration.
- ThisExpr = captureThis(*this, Context, LSI->Lambda, ThisTy, CaptureType,
- Loc, ByCopy && idx == MaxFunctionScopesIndex);
-
- } else if (CapturedRegionScopeInfo *RSI
- = dyn_cast<CapturedRegionScopeInfo>(FunctionScopes[idx]))
- ThisExpr = captureThis(*this, Context, RSI->TheRecordDecl, ThisTy,
- CaptureType, Loc, false /*ByCopy*/);
-
bool isNested = NumCapturingClosures > 1;
- CSI->addThisCapture(isNested, Loc, CaptureType, ThisExpr, ByCopy);
+ CSI->addThisCapture(isNested, Loc, CaptureType, ByCopy);
}
return false;
}
Class->addDecl(Conversion);
}
+ExprResult Sema::performThisCaptureInitialization(const Capture &Cap,
+ bool IsImplicit) {
+ QualType ThisTy = getCurrentThisType();
+ SourceLocation Loc = Cap.getLocation();
+ Expr *This = BuildCXXThisExpr(Loc, ThisTy, IsImplicit);
+ if (Cap.isReferenceCapture())
+ return This;
+
+ // Capture (by copy) of '*this'.
+ Expr *StarThis = CreateBuiltinUnaryOp(Loc, UO_Deref, This).get();
+ InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture(
+ nullptr, Cap.getCaptureType(), Loc);
+ InitializationKind InitKind =
+ InitializationKind::CreateDirect(Loc, Loc, Loc);
+ InitializationSequence Init(*this, Entity, InitKind, StarThis);
+ return Init.Perform(*this, Entity, InitKind, StarThis);
+}
+
static ExprResult performLambdaVarCaptureInitialization(
Sema &S, const Capture &Capture, FieldDecl *Field,
SourceLocation ImplicitCaptureLoc, bool IsImplicitCapture) {
getLocForEndOfToken(CaptureDefaultLoc), ", this");
}
+ ExprResult Init = performThisCaptureInitialization(From, IsImplicit);
Captures.push_back(
LambdaCapture(From.getLocation(), IsImplicit,
From.isCopyCapture() ? LCK_StarThis : LCK_This));
- CaptureInits.push_back(From.getThisInitExpr());
+ CaptureInits.push_back(Init.get());
continue;
}
if (From.isVLATypeCapture()) {
? Var->getInit()
: performLambdaVarCaptureInitialization(
*this, From, Field, CaptureDefaultLoc, IsImplicit);
- if (Init.isInvalid())
- return ExprError();
CaptureInits.push_back(Init.get());
}
FieldDecl *Field = S.BuildCaptureField(RSI->TheRecordDecl, Cap);
if (Cap.isThisCapture()) {
+ ExprResult Init =
+ S.performThisCaptureInitialization(Cap, /*Implicit*/ true);
Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
CapturedStmt::VCK_This));
- CaptureInits.push_back(Cap.getThisInitExpr());
+ CaptureInits.push_back(Init.get());
continue;
} else if (Cap.isVLATypeCapture()) {
Captures.push_back(
// perform a copy here!
ExprResult Init = S.BuildDeclarationNameExpr(
CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var);
- if (Init.isInvalid())
- return true;
Captures.push_back(CapturedStmt::Capture(Loc,
Cap.isReferenceCapture()
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "V *"
// CHECK-NEXT: },
-// CHECK-NEXT: "valueCategory": "rvalue",
-// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: "valueCategory": "rvalue"
// CHECK-NEXT: },
// CHECK-NEXT: {
// CHECK-NEXT: "id": "0x{{.*}}",
// CHECK-NEXT: "type": {
// CHECK-NEXT: "qualType": "V *"
// CHECK-NEXT: },
-// CHECK-NEXT: "valueCategory": "rvalue",
-// CHECK-NEXT: "implicit": true
+// CHECK-NEXT: "valueCategory": "rvalue"
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: }
// CHECK-NEXT: CXXMethodDecl
// CHECK-NEXT: CompoundStmt
// CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'V *'
- // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} <col:8> 'V *' implicit this
+ // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} <col:8> 'V *' this
[*this]{};
// CHECK: LambdaExpr 0x{{[^ ]*}} <line:[[@LINE-1]]:7, col:15>
// CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <col:8> col:8 implicit 'V'
// CHECK-NEXT: ParenListExpr 0x{{[^ ]*}} <col:8> 'NULL TYPE'
// CHECK-NEXT: UnaryOperator 0x{{[^ ]*}} <col:8> '<dependent type>' prefix '*' cannot overflow
- // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} <col:8> 'V *' implicit this
+ // CHECK-NEXT: CXXThisExpr 0x{{[^ ]*}} <col:8> 'V *' this
}
};
a = static_cast<decltype(a)&&>(a); // expected-error {{copy assignment operator is implicitly deleted}}
}
struct P {
- P(const P&) = delete; // expected-note {{deleted here}}
+ P(const P&) = delete; // expected-note 2{{deleted here}}
};
struct Q {
~Q() = delete; // expected-note {{deleted here}}
R &operator=(R&&) = delete;
};
void g(P &p, Q &q, R &r) {
- auto pp = [p]{}; // expected-error {{deleted constructor}}
+ // FIXME: The note attached to the second error here is just amazingly bad.
+ auto pp = [p]{}; // expected-error {{deleted constructor}} expected-error {{deleted copy constructor of '(lambda}}
+ // expected-note@-1 {{copy constructor of '' is implicitly deleted because field '' has a deleted copy constructor}}
auto qq = [q]{}; // expected-error {{deleted function}} expected-note {{because}}
auto a = [r]{}; // expected-note 2{{here}}