diff options
-rw-r--r-- | clang/include/clang/Sema/ScopeInfo.h | 26 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 35 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 23 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 6 | ||||
-rw-r--r-- | clang/test/AST/ast-dump-expr-json.cpp | 6 | ||||
-rw-r--r-- | clang/test/AST/ast-dump-expr.cpp | 4 | ||||
-rw-r--r-- | clang/test/SemaCXX/lambda-expressions.cpp | 6 |
9 files changed, 46 insertions, 67 deletions
diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h index 215025c62d2..177c88d7e84 100644 --- a/clang/include/clang/Sema/ScopeInfo.h +++ b/clang/include/clang/Sema/ScopeInfo.h @@ -517,11 +517,6 @@ class Capture { 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; @@ -566,8 +561,8 @@ public: 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) {} @@ -626,11 +621,6 @@ public: /// 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 { @@ -681,7 +671,7 @@ public: } 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; } @@ -1025,12 +1015,12 @@ void FunctionScopeInfo::recordUseOfWeak(const ExprT *E, bool IsRead) { 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(); } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7ec9f4737b2..3e128df7fba 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5291,6 +5291,11 @@ public: 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. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 759eb531c50..6bd7b4e0711 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12943,7 +12943,7 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, } 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()); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 6e67968929a..ac050fa1ef5 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1134,24 +1134,6 @@ Sema::CXXThisScopeRAII::~CXXThisScopeRAII() { } } -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) { @@ -1241,13 +1223,10 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, 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'). @@ -1261,20 +1240,8 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit, 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; } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index a17a3da67fd..d3f3b60926f 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1431,6 +1431,24 @@ static void addBlockPointerConversion(Sema &S, 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) { @@ -1680,10 +1698,11 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, 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()) { @@ -1703,8 +1722,6 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, ? Var->getInit() : performLambdaVarCaptureInitialization( *this, From, Field, CaptureDefaultLoc, IsImplicit); - if (Init.isInvalid()) - return ExprError(); CaptureInits.push_back(Init.get()); } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 7a9a801b188..3a7acd20274 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -4235,9 +4235,11 @@ buildCapturedStmtCaptureList(Sema &S, CapturedRegionScopeInfo *RSI, 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( @@ -4256,8 +4258,6 @@ buildCapturedStmtCaptureList(Sema &S, CapturedRegionScopeInfo *RSI, // 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() diff --git a/clang/test/AST/ast-dump-expr-json.cpp b/clang/test/AST/ast-dump-expr-json.cpp index 90a3bb07342..3a8e745e50f 100644 --- a/clang/test/AST/ast-dump-expr-json.cpp +++ b/clang/test/AST/ast-dump-expr-json.cpp @@ -3941,8 +3941,7 @@ void TestNonADLCall3() { // 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{{.*}}", @@ -4173,8 +4172,7 @@ void TestNonADLCall3() { // 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: } diff --git a/clang/test/AST/ast-dump-expr.cpp b/clang/test/AST/ast-dump-expr.cpp index 693dd573079..47f69a882ec 100644 --- a/clang/test/AST/ast-dump-expr.cpp +++ b/clang/test/AST/ast-dump-expr.cpp @@ -255,7 +255,7 @@ void PrimaryExpressions(Ts... a) { // 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> @@ -272,7 +272,7 @@ void PrimaryExpressions(Ts... a) { // 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 } }; diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp index 8b0b83078b0..311def9147f 100644 --- a/clang/test/SemaCXX/lambda-expressions.cpp +++ b/clang/test/SemaCXX/lambda-expressions.cpp @@ -105,7 +105,7 @@ namespace SpecialMembers { 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}} @@ -117,7 +117,9 @@ namespace SpecialMembers { 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}} |