faisalv created this revision.
faisalv added a reviewer: rsmith.
faisalv added a subscriber: cfe-commits.

Implement lambda capture of *this.

struct A {
  int d = 10;
  auto foo() { return [*this] (auto a) mutable { d+=a; return d; }; }
};
auto L = A{}.foo(); // A{}'s lifetime is gone.

// Below is still ok, because *this was captured by value.
assert(L(10) == 20);
assert(L(100) == 120);




http://reviews.llvm.org/D18139

Files:
  README.txt
  include/clang/AST/LambdaCapture.h
  include/clang/Basic/Lambda.h
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/AST/ExprCXX.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/StmtProfile.cpp
  lib/CodeGen/CodeGenFunction.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderDecl.cpp
  lib/Serialization/ASTWriter.cpp
  test/CodeGenCXX/cxx1z-lambda-star-this.cpp
  test/SemaCXX/cxx1z-lambda-star-this.cpp

Index: test/SemaCXX/cxx1z-lambda-star-this.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/cxx1z-lambda-star-this.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -emit-llvm-only %s
+// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS
+// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING
+
+
+namespace test_star_this {
+namespace ns1 {
+class A {
+  int x = 345;
+  auto foo() {
+    (void) [*this, this] { };  //expected-error{{'this' can appear only once}}
+    (void) [this] { ++x; };
+    (void) [*this] { ++x; };  //expected-error{{read-only variable}}
+    (void) [*this] () mutable { ++x; };
+    (void) [=] { return x; };
+    (void) [&, this] { return x; };
+    (void) [=, *this] { return x; };
+    (void) [&, *this] { return x; };
+  }
+};
+} // end ns1
+
+namespace ns2 {
+  class B {
+    B(const B&) = delete; //expected-note{{deleted here}}
+    int *x = (int *) 456;
+    void foo() {
+      (void)[this] { return x; };
+      (void)[*this] { return x; }; //expected-error{{call to deleted}}
+    }
+  };
+} // end ns2
+namespace ns3 {
+  class B {
+    B(const B&) = delete; //expected-note2{{deleted here}}
+    
+    int *x = (int *) 456;
+    public: 
+    template<class T = int>
+    void foo() {
+      (void)[this] { return x; };
+      (void)[*this] { return x; }; //expected-error2{{call to deleted}}
+    }
+    
+    B() = default;
+  } b;
+  B *c = (b.foo(), nullptr); //expected-note{{in instantiation}}
+} // end ns3
+
+namespace ns4 {
+template<class U>
+class B {
+  B(const B&) = delete; //expected-note{{deleted here}}
+  double d = 3.14;
+  public: 
+  template<class T = int>
+  auto foo() {
+    const auto &L = [*this] (auto a) mutable { //expected-error{{call to deleted}}
+      d += a; 
+      return [this] (auto b) { return d +=b; }; 
+    }; 
+  }
+  
+  B() = default;
+};
+void main() {
+  B<int*> b;
+  b.foo(); //expected-note{{in instantiation}}
+} // end main  
+} // end ns4
+} //end ns test_star_this
Index: test/CodeGenCXX/cxx1z-lambda-star-this.cpp
===================================================================
--- /dev/null
+++ test/CodeGenCXX/cxx1z-lambda-star-this.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -std=c++1y -triple i686-pc-windows-msvc -emit-llvm %s -o - | FileCheck %s
+//CHECK: %[[A_LAMBDA:.*]] = type { %struct.A }
+//CHECK: %[[B_LAMBDA:.*]] = type { %struct.B* }
+struct A {
+  double a = 111;
+  auto foo() { return [*this] { return a; }; }
+};
+
+namespace ns1 {
+int X = A{}.foo()();
+} //end ns1
+
+//CHECK: @"\01?foo@A@@QAE?A?<auto>@@XZ"(%struct.A* %this, %class.anon* noalias sret %[[A_LAMBDA_RETVAL:.*]])
+// get the first object with the closure type, which is of type 'struct.A'
+//CHECK: %0 = getelementptr inbounds %[[A_LAMBDA]], %[[A_LAMBDA]]* %[[A_LAMBDA_RETVAL]], i32 0, i32 0
+//CHECK: %1 = bitcast %struct.A* %0 to i8*
+//CHECK: %2 = bitcast %struct.A* %this1 to i8*
+// copy the contents ...
+//CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* %1, i8* %2, i32 8, i32 8, i1 false)
+
+struct B {
+  double b = 222;
+  auto bar() { return [this] { return b; }; };
+};
+
+namespace ns2 {
+int X = B{}.bar()();
+}
+//CHECK: @"\01?bar@B@@QAE?A?<auto>@@XZ"(%struct.B* %this, %class.anon.0* noalias sret %agg.result)
+//CHECK: %0 = getelementptr inbounds %class.anon.0, %class.anon.0* %agg.result, i32 0, i32 0
+//CHECK: store %struct.B* %this1, %struct.B** %0, align 4
\ No newline at end of file
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -5631,6 +5631,7 @@
       Record.push_back(Capture.isImplicit());
       Record.push_back(Capture.getCaptureKind());
       switch (Capture.getCaptureKind()) {
+      case LCK_StarThis:
       case LCK_This:
       case LCK_VLAType:
         break;
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp
+++ lib/Serialization/ASTReaderDecl.cpp
@@ -1497,10 +1497,12 @@
       bool IsImplicit = Record[Idx++];
       LambdaCaptureKind Kind = static_cast<LambdaCaptureKind>(Record[Idx++]);
       switch (Kind) {
+      case LCK_StarThis: 
       case LCK_This:
       case LCK_VLAType:
         *ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation());
         break;
+      
       case LCK_ByCopy:
       case LCK_ByRef:
         VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx);
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -10060,7 +10060,9 @@
 
     // Capturing 'this' is trivial.
     if (C->capturesThis()) {
-      getSema().CheckCXXThisCapture(C->getLocation(), C->isExplicit());
+      getSema().CheckCXXThisCapture(C->getLocation(), C->isExplicit(),
+                                    /*BuildAndDiagnose*/ true, nullptr,
+                                    C->capturesStarThis());
       continue;
     }
     // Captured expression will be recaptured during captured variables
Index: lib/Sema/SemaLambda.cpp
===================================================================
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -924,7 +924,7 @@
     = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
   for (auto C = Intro.Captures.begin(), E = Intro.Captures.end(); C != E;
        PrevCaptureLoc = C->Loc, ++C) {
-    if (C->Kind == LCK_This) {
+    if (C->Kind == LCK_This || C->Kind == LCK_StarThis) {
       // C++11 [expr.prim.lambda]p8:
       //   An identifier or this shall not appear more than once in a 
       //   lambda-capture.
@@ -935,11 +935,11 @@
                    SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
         continue;
       }
-
+      // FIXME: Fix this comment from the wording for lambda '*this' wording.
       // C++11 [expr.prim.lambda]p8:
       //   If a lambda-capture includes a capture-default that is =, the 
       //   lambda-capture shall not contain this [...].
-      if (Intro.Default == LCD_ByCopy) {
+      if (Intro.Default == LCD_ByCopy && C->Kind != LCK_StarThis) {
         Diag(C->Loc, diag::err_this_capture_with_copy_default)
             << FixItHint::CreateRemoval(
                 SourceRange(getLocForEndOfToken(PrevCaptureLoc), C->Loc));
@@ -955,7 +955,9 @@
         continue;
       }
       
-      CheckCXXThisCapture(C->Loc, /*Explicit=*/true);
+      CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true,
+                          /*FunctionScopeIndexToStopAtPtr*/ nullptr,
+                          C->Kind == LCK_StarThis);
       continue;
     }
 
@@ -1529,10 +1531,9 @@
       // Handle 'this' capture.
       if (From.isThisCapture()) {
         Captures.push_back(
-            LambdaCapture(From.getLocation(), IsImplicit, LCK_This));
-        CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(),
-                                                         getCurrentThisType(),
-                                                         /*isImplicit=*/true));
+            LambdaCapture(From.getLocation(), IsImplicit,
+                          From.isStarThisCapture() ? LCK_StarThis : LCK_This));
+        CaptureInits.push_back(From.getInitExpr());
         ArrayIndexStarts.push_back(ArrayIndexVars.size());
         continue;
       }
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -849,7 +849,21 @@
           cast<CXXRecordDecl>(CurContext->getParent()->getParent()));
       // There are no cv-qualifiers for 'this' within default initializers, 
       // per [expr.prim.general]p4.
-      return Context.getPointerType(ClassTy);
+      ThisTy = Context.getPointerType(ClassTy);
+    }
+  }
+   // Add const for '* this' capture if not mutable.
+  if (isLambdaCallOperator(CurContext)) {
+    LambdaScopeInfo *LSI = getCurLambda();
+    assert(LSI);
+    if (LSI->isCXXThisCaptured()) {
+      auto C = LSI->getCXXThisCapture();
+      QualType BaseType = ThisTy->getPointeeType();
+      if (C.isStarThisCapture() && LSI->CallOperator->isConst() &&
+          !BaseType.isConstQualified()) {
+        BaseType.addConst();
+        ThisTy = Context.getPointerType(BaseType);
+      }
     }
   }
   return ThisTy;
@@ -884,20 +898,37 @@
   }
 }
 
-static Expr *captureThis(ASTContext &Context, RecordDecl *RD,
-                         QualType ThisTy, SourceLocation Loc) {
+static Expr *captureThis(Sema &S, ASTContext &Context, RecordDecl *RD,
+                         QualType ThisTy, SourceLocation Loc,
+                         const bool ByCopy) {
+  QualType CaptureThisTy = ByCopy ? ThisTy->getPointeeType() : ThisTy;
+ 
   FieldDecl *Field
-    = FieldDecl::Create(Context, RD, Loc, Loc, nullptr, ThisTy,
-                        Context.getTrivialTypeSourceInfo(ThisTy, Loc),
+       = FieldDecl::Create(Context, RD, Loc, Loc, nullptr, CaptureThisTy,
+                       Context.getTrivialTypeSourceInfo(CaptureThisTy, Loc),
                         nullptr, false, ICIS_NoInit);
   Field->setImplicit(true);
   Field->setAccess(AS_private);
   RD->addDecl(Field);
-  return new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/true);
+  Expr *This = new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/true);
+  if (ByCopy) {
+    Expr *StarThis =  S.CreateBuiltinUnaryOp(Loc,
+                                      UO_Deref,
+                                      This).get();
+    InitializedEntity Entity = InitializedEntity::InitializeLambdaCapture(
+      &S.Context.Idents.get("*this"), CaptureThisTy, 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, bool Explicit, 
-    bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt) {
+    bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt,
+    const bool ByCopy) {
   // We don't need to capture this in an unevaluated context.
   if (isUnevaluatedContext() && !Explicit)
     return true;
@@ -948,13 +979,15 @@
     QualType ThisTy = getCurrentThisType();
     if (LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI))
       // For lambda expressions, build a field and an initializing expression.
-      ThisExpr = captureThis(Context, LSI->Lambda, ThisTy, Loc);
+      ThisExpr = captureThis(*this, Context, LSI->Lambda, ThisTy, Loc, ByCopy);
     else if (CapturedRegionScopeInfo *RSI
         = dyn_cast<CapturedRegionScopeInfo>(FunctionScopes[idx]))
-      ThisExpr = captureThis(Context, RSI->TheRecordDecl, ThisTy, Loc);
+      ThisExpr =
+          captureThis(*this, Context, RSI->TheRecordDecl, ThisTy, Loc,
+                      false/*ByCopy*/);
 
     bool isNested = NumClosures > 1;
-    CSI->addThisCapture(isNested, Loc, ThisTy, ThisExpr);
+    CSI->addThisCapture(isNested, Loc, ThisTy, ThisExpr, ByCopy);
   }
   return false;
 }
@@ -968,6 +1001,7 @@
   if (ThisTy.isNull()) return Diag(Loc, diag::err_invalid_this_use);
 
   CheckCXXThisCapture(Loc);
+ 
   return new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit=*/false);
 }
 
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -13253,7 +13253,7 @@
 
 /// \brief Create a field within the lambda class for the variable
 /// being captured.
-static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI, VarDecl *Var,
+static void addAsFieldToClosureType(Sema &S, LambdaScopeInfo *LSI, VarDecl *,
                                     QualType FieldType, QualType DeclRefType,
                                     SourceLocation Loc,
                                     bool RefersToCapturedVariable) {
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -10990,7 +10990,8 @@
 
     } else if (C.capturesThis()) {
       LSI->addThisCapture(/*Nested*/ false, C.getLocation(), 
-                              S.getCurrentThisType(), /*Expr*/ nullptr);
+                              S.getCurrentThisType(), /*Expr*/ nullptr,
+                              !I->getType()->isPointerType());
     } else {
       LSI->addVLATypeCapture(C.getLocation(), I->getType());
     }
Index: lib/Parse/ParseExprCXX.cpp
===================================================================
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -846,8 +846,13 @@
     IdentifierInfo *Id = nullptr;
     SourceLocation EllipsisLoc;
     ExprResult Init;
-    
-    if (Tok.is(tok::kw_this)) {
+
+    if (Tok.is(tok::star) && NextToken().is(tok::kw_this)) {
+      Kind = LCK_StarThis;
+      // FIXME: We should store our location for '*' for better diagnostic messages;
+      ConsumeToken(); // Consume '*'
+      Loc = ConsumeToken();
+    } else if (Tok.is(tok::kw_this)) {
       Kind = LCK_This;
       Loc = ConsumeToken();
     } else {
Index: lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- lib/CodeGen/CodeGenFunction.cpp
+++ lib/CodeGen/CodeGenFunction.cpp
@@ -826,9 +826,16 @@
                                         LambdaThisCaptureField);
       if (LambdaThisCaptureField) {
         // If this lambda captures this, load it.
-        LValue ThisLValue = EmitLValueForLambdaField(LambdaThisCaptureField);
-        CXXThisValue = EmitLoadOfLValue(ThisLValue,
+        if (!LambdaThisCaptureField->getType()->isPointerType()) {
+          QualType LambdaTagType = getContext().getTagDeclType(LambdaThisCaptureField->getParent());
+          LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue, LambdaTagType);
+          LValue ThisLValue = EmitLValueForField(LambdaLV, LambdaThisCaptureField);
+          CXXThisValue = ThisLValue.getAddress().getPointer();
+        } else {
+          LValue ThisLValue = EmitLValueForLambdaField(LambdaThisCaptureField);
+          CXXThisValue = EmitLoadOfLValue(ThisLValue,
                                         SourceLocation()).getScalarVal();
+        }
       }
       for (auto *FD : MD->getParent()->fields()) {
         if (FD->hasCapturedVLAType()) {
Index: lib/AST/StmtProfile.cpp
===================================================================
--- lib/AST/StmtProfile.cpp
+++ lib/AST/StmtProfile.cpp
@@ -1257,6 +1257,7 @@
        C != CEnd; ++C) {
     ID.AddInteger(C->getCaptureKind());
     switch (C->getCaptureKind()) {
+    case LCK_StarThis:
     case LCK_This:
       break;
     case LCK_ByRef:
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp
+++ lib/AST/StmtPrinter.cpp
@@ -2008,7 +2008,9 @@
     case LCK_This:
       OS << "this";
       break;
-
+    case LCK_StarThis:
+      OS << "*this";
+      break;
     case LCK_ByRef:
       if (Node->getCaptureDefault() != LCD_ByRef || Node->isInitCapture(C))
         OS << '&';
Index: lib/AST/ExprCXX.cpp
===================================================================
--- lib/AST/ExprCXX.cpp
+++ lib/AST/ExprCXX.cpp
@@ -882,17 +882,19 @@
 LambdaCapture::LambdaCapture(SourceLocation Loc, bool Implicit,
                              LambdaCaptureKind Kind, VarDecl *Var,
                              SourceLocation EllipsisLoc)
-  : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc)
+  : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc), IsStarThis(false)
 {
   unsigned Bits = 0;
   if (Implicit)
     Bits |= Capture_Implicit;
   
   switch (Kind) {
+  case LCK_StarThis:
+    IsStarThis = true;
   case LCK_This:
     assert(!Var && "'this' capture cannot have a variable!");
     break;
-
+  
   case LCK_ByCopy:
     Bits |= Capture_ByCopy;
     // Fall through 
@@ -909,9 +911,11 @@
 
 LambdaCaptureKind LambdaCapture::getCaptureKind() const {
   Decl *D = DeclAndBits.getPointer();
-  bool CapByCopy = DeclAndBits.getInt() & Capture_ByCopy;
+  unsigned Bits = DeclAndBits.getInt();
+  bool CapByCopy = Bits & Capture_ByCopy;
   if (!D)
-    return CapByCopy ? LCK_VLAType : LCK_This;
+    return CapByCopy ? LCK_VLAType
+                     : (IsStarThis ? LCK_StarThis : LCK_This);
 
   return CapByCopy ? LCK_ByCopy : LCK_ByRef;
 }
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -4619,7 +4619,8 @@
   /// \return returns 'true' if failed, 'false' if success.
   bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false, 
       bool BuildAndDiagnose = true,
-      const unsigned *const FunctionScopeIndexToStopAt = nullptr);
+      const unsigned *const FunctionScopeIndexToStopAt = nullptr,
+      bool ByCopy = false);
 
   /// \brief 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
Index: include/clang/Sema/ScopeInfo.h
===================================================================
--- include/clang/Sema/ScopeInfo.h
+++ include/clang/Sema/ScopeInfo.h
@@ -414,7 +414,7 @@
     enum CaptureKind {
       Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_This
     };
-
+    bool IsStarThis = false;
     /// The variable being captured (if we are not capturing 'this') and whether
     /// this is a nested capture.
     llvm::PointerIntPair<VarDecl*, 1, bool> VarAndNested;
@@ -446,20 +446,25 @@
 
     enum IsThisCapture { ThisCapture };
     Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
-            QualType CaptureType, Expr *Cpy)
+            QualType CaptureType, Expr *Cpy, const bool ByCopy)
         : VarAndNested(nullptr, IsNested),
           InitExprAndCaptureKind(Cpy, Cap_This),
-          Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {}
+          Loc(Loc), EllipsisLoc(), CaptureType(CaptureType),
+          IsStarThis(ByCopy) {}
 
     bool isThisCapture() const {
       return InitExprAndCaptureKind.getInt() == Cap_This;
     }
+    bool isStarThisCapture() const {
+      return IsStarThis;
+    }
     bool isVariableCapture() const {
-      return InitExprAndCaptureKind.getInt() != Cap_This && !isVLATypeCapture();
+      return !isThisCapture() && !isVLATypeCapture();
     }
     bool isCopyCapture() const {
-      return InitExprAndCaptureKind.getInt() == Cap_ByCopy &&
-             !isVLATypeCapture();
+      return (InitExprAndCaptureKind.getInt() == Cap_ByCopy &&
+              !isVLATypeCapture()) ||
+             IsStarThis;
     }
     bool isReferenceCapture() const {
       return InitExprAndCaptureKind.getInt() == Cap_ByRef;
@@ -534,7 +539,7 @@
   }
 
   void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType,
-                      Expr *Cpy);
+                      Expr *Cpy, bool ByCopy);
 
   /// \brief Determine whether the C++ 'this' is captured.
   bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
@@ -854,9 +859,10 @@
 
 inline void
 CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc,
-                                   QualType CaptureType, Expr *Cpy) {
+                                   QualType CaptureType, Expr *Cpy,
+                                   const bool ByCopy) {
   Captures.push_back(Capture(Capture::ThisCapture, isNested, Loc, CaptureType,
-                             Cpy));
+                             Cpy, ByCopy));
   CXXThisCaptureIndex = Captures.size();
 }
 
Index: include/clang/Basic/Lambda.h
===================================================================
--- include/clang/Basic/Lambda.h
+++ include/clang/Basic/Lambda.h
@@ -33,6 +33,7 @@
 /// is an expression.
 enum LambdaCaptureKind {
   LCK_This,   ///< Capturing the \c this pointer
+  LCK_StarThis, /// < Capturing the \c *this object by value
   LCK_ByCopy, ///< Capturing by copy (a.k.a., by value)
   LCK_ByRef,  ///< Capturing by reference
   LCK_VLAType ///< Capturing variable-length array type
Index: include/clang/AST/LambdaCapture.h
===================================================================
--- include/clang/AST/LambdaCapture.h
+++ include/clang/AST/LambdaCapture.h
@@ -35,11 +35,10 @@
     /// This includes the case of a non-reference init-capture.
     Capture_ByCopy = 0x02
   };
-
   llvm::PointerIntPair<Decl *, 2> DeclAndBits;
   SourceLocation Loc;
   SourceLocation EllipsisLoc;
-
+  bool IsStarThis : 1;
   friend class ASTStmtReader;
   friend class ASTStmtWriter;
 
@@ -69,8 +68,12 @@
   /// \brief Determine whether this capture handles the C++ \c this
   /// pointer.
   bool capturesThis() const {
-    return (DeclAndBits.getPointer() == nullptr) &&
-           !(DeclAndBits.getInt() & Capture_ByCopy);
+    return ((DeclAndBits.getPointer() == nullptr) &&
+           !(DeclAndBits.getInt() & Capture_ByCopy)) 
+           || IsStarThis;
+  }
+  bool capturesStarThis() const {
+    return capturesThis() && IsStarThis;
   }
 
   /// \brief Determine whether this capture handles a variable.
Index: README.txt
===================================================================
--- README.txt
+++ README.txt
@@ -24,3 +24,5 @@
 
 If you find a bug in Clang, please file it in the LLVM bug tracker:
   http://llvm.org/bugs/
+
+use llvm svn-revision 262784
\ No newline at end of file
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to