r200948 - PR18128: a lambda capture-default is not permitted for a non-local lambda

Richard Smith richard-llvm at metafoo.co.uk
Thu Feb 6 13:49:09 PST 2014


Author: rsmith
Date: Thu Feb  6 15:49:08 2014
New Revision: 200948

URL: http://llvm.org/viewvc/llvm-project?rev=200948&view=rev
Log:
PR18128: a lambda capture-default is not permitted for a non-local lambda
expression.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/test/SemaCXX/lambda-expressions.cpp
    cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=200948&r1=200947&r2=200948&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Feb  6 15:49:08 2014
@@ -952,6 +952,8 @@ def err_capture_of_abstract_type : Error
   "by-copy capture of value of abstract type %0">;
 def err_capture_of_incomplete_type : Error<
   "by-copy capture of variable %0 with incomplete type %1">;
+def err_capture_default_non_local : Error<
+  "non-local lambda expression cannot have a capture-default">;
 
 def err_multiple_final_overriders : Error<
   "virtual function %q0 has more than one final overrider in %1">; 

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=200948&r1=200947&r2=200948&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Thu Feb  6 15:49:08 2014
@@ -256,7 +256,7 @@ CXXRecordDecl *Sema::createLambdaClosure
                                                      IsGenericLambda, 
                                                      CaptureDefault);
   DC->addDecl(Class);
-  
+
   return Class;
 }
 
@@ -935,6 +935,23 @@ void Sema::ActOnStartOfLambdaDefinition(
                        ExplicitResultType,
                        !Method->isConst());
 
+  // C++11 [expr.prim.lambda]p9:
+  //   A lambda-expression whose smallest enclosing scope is a block scope is a
+  //   local lambda expression; any other lambda expression shall not have a
+  //   capture-default or simple-capture in its lambda-introducer.
+  //
+  // For simple-captures, this is covered by the check below that any named
+  // entity is a variable that can be captured.
+  //
+  // For DR1632, we also allow a capture-default in any context where we can
+  // odr-use 'this' (in particular, in a default initializer for a non-static
+  // data member).
+  if (Intro.Default != LCD_None && !Class->getParent()->isFunctionOrMethod() &&
+      (getCurrentThisType().isNull() ||
+       CheckCXXThisCapture(SourceLocation(), /*Explicit*/true,
+                           /*BuildAndDiagnose*/false)))
+    Diag(Intro.DefaultLoc, diag::err_capture_default_non_local);
+
   // Distinct capture names, for diagnostics.
   llvm::SmallSet<IdentifierInfo*, 8> CaptureNames;
 

Modified: cfe/trunk/test/SemaCXX/lambda-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/lambda-expressions.cpp?rev=200948&r1=200947&r2=200948&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/lambda-expressions.cpp (original)
+++ cfe/trunk/test/SemaCXX/lambda-expressions.cpp Thu Feb  6 15:49:08 2014
@@ -291,7 +291,7 @@ namespace NSDMIs_in_lambdas {
   void f() { []() { S<int> s; }; }
 
   auto x = []{ struct S { int n, m = n; }; };
-  auto y = [&]{ struct S { int n, m = n; }; };
+  auto y = [&]{ struct S { int n, m = n; }; }; // expected-error {{non-local lambda expression cannot have a capture-default}}
   void g() { auto z = [&]{ struct S { int n, m = n; }; }; }
 }
 
@@ -324,3 +324,23 @@ namespace CaptureAbstract {
     [=] { return s.n; }; // expected-error {{abstract}}
   }
 }
+
+namespace PR18128 {
+  auto l = [=]{}; // expected-error {{non-local lambda expression cannot have a capture-default}}
+
+  struct S {
+    int n;
+    int (*f())[true ? 1 : ([=]{ return n; }(), 0)];
+    // expected-error at -1 {{non-local lambda expression cannot have a capture-default}}
+    // expected-error at -2 {{invalid use of non-static data member 'n'}}
+    // expected-error at -3 {{a lambda expression may not appear inside of a constant expression}}
+    int g(int k = ([=]{ return n; }(), 0));
+    // expected-error at -1 {{non-local lambda expression cannot have a capture-default}}
+    // expected-error at -2 {{invalid use of non-static data member 'n'}}
+
+    int a = [=]{ return n; }(); // ok
+    int b = [=]{ return [=]{ return n; }(); }(); // ok
+    int c = []{ int k = 0; return [=]{ return k; }(); }(); // ok
+    int d = []{ return [=]{ return n; }(); }(); // expected-error {{'this' cannot be implicitly captured in this context}}
+  };
+}

Modified: cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp?rev=200948&r1=200947&r2=200948&view=diff
==============================================================================
--- cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp (original)
+++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTest.cpp Thu Feb  6 15:49:08 2014
@@ -1000,7 +1000,7 @@ TEST(Matcher, Call) {
 }
 
 TEST(Matcher, Lambda) {
-  EXPECT_TRUE(matches("auto f = [&] (int i) { return i; };",
+  EXPECT_TRUE(matches("auto f = [] (int i) { return i; };",
                       lambdaExpr()));
 }
 





More information about the cfe-commits mailing list