]> granicus.if.org Git - clang/commitdiff
Replace the broken LambdaCapture::isInitCapture API.
authorJames Dennett <jdennett@google.com>
Thu, 7 May 2015 18:48:18 +0000 (18:48 +0000)
committerJames Dennett <jdennett@google.com>
Thu, 7 May 2015 18:48:18 +0000 (18:48 +0000)
A LambdaCapture does not have sufficient information
to correctly determine whether it is an init-capture or not.
Doing so requires knowledge held in the LambdaExpr itself.

It the case of a nested capture of an init-capture it is not
sufficient to check (as LambdaCapture::isInitCapture did)
whether the associated VarDecl was from an init-capture.

This patch moves isInitCapture to LambdaExpr and updates
Capture->isInitCapture() to Lambda->isInitCapture(Capture).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@236760 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DataRecursiveASTVisitor.h
include/clang/AST/ExprCXX.h
include/clang/AST/LambdaCapture.h
include/clang/AST/RecursiveASTVisitor.h
lib/AST/ExprCXX.cpp
lib/AST/StmtPrinter.cpp
lib/Sema/TreeTransform.h
test/SemaCXX/cxx1y-init-captures.cpp

index d3dde6803fb559939bc781c3db57b6ac836b1c73..9b5b0233bb2c8fb6bd3af289ae4b9a3b07860e0e 100644 (file)
@@ -791,7 +791,7 @@ template <typename Derived>
 bool
 RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
                                                     const LambdaCapture *C) {
-  if (C->isInitCapture())
+  if (LE->isInitCapture(C))
     TRY_TO(TraverseDecl(C->getCapturedVar()));
   return true;
 }
index d1a6063b6b9f2dc0d7dd20245904b23dbb305e9a..1dbf5743c12454004689af3f63a9b04af8f755f7 100644 (file)
@@ -1452,6 +1452,9 @@ public:
     return CaptureDefaultLoc;
   }
 
+  /// \brief Determine whether one of this lambda's captures is an init-capture.
+  bool isInitCapture(const LambdaCapture *Capture) const;
+
   /// \brief An iterator that walks over the captures of the lambda,
   /// both implicit and explicit.
   typedef const Capture *capture_iterator;
index a7468a0fd53f45cbc11cae146454dc8963ccf51a..ddefa88a6b697d1e95247d6df43dacda7c923f77 100644 (file)
@@ -85,11 +85,6 @@ public:
            (DeclAndBits.getInt() & Capture_ByCopy);
   }
 
-  /// \brief Determine whether this is an init-capture.
-  bool isInitCapture() const {
-    return capturesVariable() && getCapturedVar()->isInitCapture();
-  }
-
   /// \brief Retrieve the declaration of the local variable being
   /// captured.
   ///
index 235023d374e7f26b9c79c06366c59f9a72bcc319..129c2b5fe0465086c4572a4e06b3368af4bba31f 100644 (file)
@@ -857,7 +857,7 @@ template <typename Derived>
 bool
 RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr *LE,
                                                     const LambdaCapture *C) {
-  if (C->isInitCapture())
+  if (LE->isInitCapture(C))
     TRY_TO(TraverseDecl(C->getCapturedVar()));
   return true;
 }
index f23b3eb79cea5aef0109884916753cbef922ca3c..d6f2ce63a0a57a3f2ea685bee61e0640b857ce96 100644 (file)
@@ -1027,6 +1027,11 @@ LambdaExpr *LambdaExpr::CreateDeserialized(const ASTContext &C,
   return new (Mem) LambdaExpr(EmptyShell(), NumCaptures, NumArrayIndexVars > 0);
 }
 
+bool LambdaExpr::isInitCapture(const LambdaCapture *C) const {
+  return (C->capturesVariable() && C->getCapturedVar()->isInitCapture() &&
+          (getCallOperator() == C->getCapturedVar()->getDeclContext()));
+}
+
 LambdaExpr::capture_iterator LambdaExpr::capture_begin() const {
   return getLambdaClass()->getLambdaData().Captures;
 }
index b68f3a3a26edb9e7b43ed48ddca07c1a03b6e647..dc4f9964c7a6f665757f553f61fc77293ef820bd 100644 (file)
@@ -1758,7 +1758,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
       break;
 
     case LCK_ByRef:
-      if (Node->getCaptureDefault() != LCD_ByRef || C->isInitCapture())
+      if (Node->getCaptureDefault() != LCD_ByRef || Node->isInitCapture(C))
         OS << '&';
       OS << C->getCapturedVar()->getName();
       break;
@@ -1770,7 +1770,7 @@ void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
       llvm_unreachable("VLA type in explicit captures.");
     }
 
-    if (C->isInitCapture())
+    if (Node->isInitCapture(C))
       PrintExpr(C->getCapturedVar()->getInit());
   }
   OS << ']';
index 704cef36d4473a84b41716d54079fca9c18205c1..f5249fdeb017fd117dfb35705ba0797ad0a692b4 100644 (file)
@@ -9133,7 +9133,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
   for (LambdaExpr::capture_iterator C = E->capture_begin(),
                                     CEnd = E->capture_end();
        C != CEnd; ++C) {
-    if (!C->isInitCapture())
+    if (!E->isInitCapture(C))
       continue;
     EnterExpressionEvaluationContext EEEC(getSema(),
                                           Sema::PotentiallyEvaluated);
@@ -9245,7 +9245,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
       continue;
 
     // Rebuild init-captures, including the implied field declaration.
-    if (C->isInitCapture()) {
+    if (E->isInitCapture(C)) {
       InitCaptureInfoTy InitExprTypePair = 
           InitCaptureExprsAndTypes[C - E->capture_begin()];
       ExprResult Init = InitExprTypePair.first;
index 64fe50a70e7847ffa4eeb537a623b59c8fda4c49..203e28d7c3f9d1bd9cd358acf688a8e7af7fc992 100644 (file)
@@ -166,4 +166,27 @@ int test(T t = T{}) {
 
 int run = test(); //expected-note {{instantiation}}
 
-}
\ No newline at end of file
+}
+
+namespace classification_of_captures_of_init_captures {
+
+template <typename T>
+void f() {
+  [a = 24] () mutable {
+    [&a] { a = 3; }();
+  }();
+}
+
+template <typename T>
+void h() {
+  [a = 24] (auto param) mutable {
+    [&a] { a = 3; }();
+  }(42);
+}
+
+int run() {
+  f<int>();
+  h<int>();
+}
+
+}