]> granicus.if.org Git - clang/commitdiff
Make explicit captures which cause implicit captures work correctly.
authorEli Friedman <eli.friedman@gmail.com>
Fri, 3 Feb 2012 23:06:43 +0000 (23:06 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Fri, 3 Feb 2012 23:06:43 +0000 (23:06 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149719 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp
test/SemaCXX/lambda-expressions.cpp

index efa57cb8a569b225c500e7a6a94b22d9e6ea5609..6a9384daec934728eb8db7ded565badec86f096a 100644 (file)
@@ -2284,7 +2284,11 @@ public:
   void UpdateMarkingForLValueToRValue(Expr *E);
   void CleanupVarDeclMarking();
 
-  void TryCaptureVar(VarDecl *var, SourceLocation loc);
+  enum TryCaptureKind {
+    TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef
+  };
+  void TryCaptureVar(VarDecl *var, SourceLocation loc,
+                     TryCaptureKind Kind = TryCapture_Implicit);
 
   void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T);
   void MarkDeclarationsReferencedInExpr(Expr *E);
index 8e196fbfe215dfbbb052cc85cb0f002246a0f9cb..8c49c537c5f582d1ec9df84dfef32d4b642a4004 100644 (file)
@@ -9453,7 +9453,8 @@ static bool shouldAddConstForScope(CapturingScopeInfo *CSI, VarDecl *VD) {
 // Check if the variable needs to be captured; if so, try to perform
 // the capture.
 // FIXME: Add support for explicit captures.
-void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc) {
+void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc,
+                         TryCaptureKind Kind) {
   DeclContext *DC = CurContext;
   if (var->getDeclContext() == DC) return;
   if (!var->hasLocalStorage()) return;
@@ -9536,7 +9537,12 @@ void Sema::TryCaptureVar(VarDecl *var, SourceLocation loc) {
     }
 
     bool byRef;
-    if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) {
+    bool isInnermostCapture = (i == e - 1);
+    if (isInnermostCapture && Kind == TryCapture_ExplicitByVal) {
+      byRef = false;
+    } else if (isInnermostCapture && Kind == TryCapture_ExplicitByRef) {
+      byRef = true;
+    } else if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) {
       // No capture-default
       Diag(loc, diag::err_lambda_impcap) << var->getDeclName();
       Diag(var->getLocation(), diag::note_previous_decl) << var->getDeclName();
index 3dd271bb8affb8e8650f5d21a1386597944093ab..b35ea802e56bd8521beb57646c67567cf5fb86c1 100644 (file)
@@ -5030,12 +5030,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
       Diag(Var->getLocation(), diag::note_previous_decl) << C->Id;
       continue;
     }
-    
-    if (Var->hasAttr<BlocksAttr>()) {
-      Diag(C->Loc, diag::err_lambda_capture_block) << C->Id;
-      Diag(Var->getLocation(), diag::note_previous_decl) << C->Id;
-      continue;
-    }
 
     // C++11 [expr.prim.lambda]p8:
     //   An identifier or this shall not appear more than once in a 
@@ -5046,13 +5040,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
         << SourceRange(LSI->getCapture(Var).getLocation());
       continue;
     }
-    
-    // FIXME: If this is capture by copy, make sure that we can in fact copy
-    // the variable.
-    // FIXME: Unify with normal capture path, so we get all of the necessary
-    // nested captures.
-    LSI->AddCapture(Var, /*isBlock*/false, C->Kind == LCK_ByRef,
-                    /*isNested=*/false, C->Loc, 0);
+
+    TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
+                                                 TryCapture_ExplicitByVal;
+    TryCaptureVar(Var, C->Loc, Kind);
   }
   LSI->finishedExplicitCaptures();
 
index 0f7d5484a8a88a44e660c0f0c2fd2e6f5417f901..05aba53dbbacf93f6202521d135655391c421130 100644 (file)
@@ -45,7 +45,7 @@ namespace ReturnDeduction {
 
 namespace ImplicitCapture {
   void test() {
-    int a = 0; // expected-note 3 {{declared}}
+    int a = 0; // expected-note 5 {{declared}}
     []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}} expected-error {{not supported yet}} 
     [&]() { return a; }; // expected-error {{not supported yet}}
     [=]() { return a; }; // expected-error {{not supported yet}}
@@ -53,6 +53,8 @@ namespace ImplicitCapture {
     [=]() { return [&]() { return a; }; }; // expected-error 2 {{not supported yet}}
     []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} expected-error 2 {{not supported yet}}
     []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} expected-error {{not supported yet}}
+    []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}} expected-error 2 {{not supported yet}}
+    [=]() { return [&a] { return a; }; }; // expected-error 2 {{not supported yet}}
 
     const int b = 2;
     []() { return b; }; // expected-error {{not supported yet}}
@@ -64,8 +66,9 @@ namespace ImplicitCapture {
     d = 3;
     [=]() { return c; }; // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}} expected-error {{not supported yet}}
 
-    __block int e; // expected-note {{declared}}
+    __block int e; // expected-note {{declared}}
     [&]() { return e; }; // expected-error {{__block variable 'e' cannot be captured in a lambda expression}} expected-error {{not supported yet}}
+    [&e]() { return e; }; // expected-error 2 {{__block variable 'e' cannot be captured in a lambda expression}} expected-error {{not supported yet}}
 
     int f[10]; // expected-note {{declared}}
     [&]() { return f[2]; };  // expected-error {{not supported yet}}