r362182 - Defer building 'this' captures until we have left the capturing region

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Thu May 30 18:17:04 PDT 2019


Author: rsmith
Date: Thu May 30 18:17:04 2019
New Revision: 362182

URL: http://llvm.org/viewvc/llvm-project?rev=362182&view=rev
Log:
Defer building 'this' captures until we have left the capturing region
and returned to the context in which 'this' should be captured.

This means we now always mark 'this' referenced from the context in
which it's actually referenced, rather than potentially from some
context nested within that.

Modified:
    cfe/trunk/include/clang/Sema/ScopeInfo.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/test/AST/ast-dump-expr-json.cpp
    cfe/trunk/test/AST/ast-dump-expr.cpp
    cfe/trunk/test/SemaCXX/lambda-expressions.cpp

Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=362182&r1=362181&r2=362182&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Thu May 30 18:17:04 2019
@@ -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(
   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();
 }
 

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=362182&r1=362181&r2=362182&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu May 30 18:17:04 2019
@@ -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.

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=362182&r1=362181&r2=362182&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu May 30 18:17:04 2019
@@ -12943,7 +12943,7 @@ static void RebuildLambdaScopeInfo(CXXMe
 
     } 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());

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=362182&r1=362181&r2=362182&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu May 30 18:17:04 2019
@@ -1134,24 +1134,6 @@ Sema::CXXThisScopeRAII::~CXXThisScopeRAI
   }
 }
 
-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(SourceLoc
           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(SourceLoc
       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;
 }

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=362182&r1=362181&r2=362182&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Thu May 30 18:17:04 2019
@@ -1431,6 +1431,24 @@ static void addBlockPointerConversion(Se
   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(SourceL
                      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(SourceL
               ? Var->getInit()
               : performLambdaVarCaptureInitialization(
                     *this, From, Field, CaptureDefaultLoc, IsImplicit);
-      if (Init.isInvalid())
-        return ExprError();
       CaptureInits.push_back(Init.get());
     }
 

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=362182&r1=362181&r2=362182&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Thu May 30 18:17:04 2019
@@ -4235,9 +4235,11 @@ buildCapturedStmtCaptureList(Sema &S, Ca
     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, Ca
     // 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()

Modified: cfe/trunk/test/AST/ast-dump-expr-json.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/AST/ast-dump-expr-json.cpp?rev=362182&r1=362181&r2=362182&view=diff
==============================================================================
--- cfe/trunk/test/AST/ast-dump-expr-json.cpp (original)
+++ cfe/trunk/test/AST/ast-dump-expr-json.cpp Thu May 30 18:17:04 2019
@@ -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:                   }

Modified: cfe/trunk/test/AST/ast-dump-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/AST/ast-dump-expr.cpp?rev=362182&r1=362181&r2=362182&view=diff
==============================================================================
--- cfe/trunk/test/AST/ast-dump-expr.cpp (original)
+++ cfe/trunk/test/AST/ast-dump-expr.cpp Thu May 30 18:17:04 2019
@@ -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
     }
   };
 

Modified: cfe/trunk/test/SemaCXX/lambda-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=362182&r1=362181&r2=362182&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/lambda-expressions.cpp (original)
+++ cfe/trunk/test/SemaCXX/lambda-expressions.cpp Thu May 30 18:17:04 2019
@@ -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 at -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}}




More information about the cfe-commits mailing list