]> granicus.if.org Git - clang/commitdiff
PR18128: a lambda capture-default is not permitted for a non-local lambda
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 6 Feb 2014 21:49:08 +0000 (21:49 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 6 Feb 2014 21:49:08 +0000 (21:49 +0000)
expression.

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

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

index 550e9c11b4163c2291b73bb2820fa0ffe51504da..c06a086eafe315a5868b21489e144aa0706a673a 100644 (file)
@@ -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">; 
index 5d282cb6fc5ed46851904c6a5fcb70c379e05d84..8c1b57fd0faf4d3f978cb03a3b56225ca7991277 100644 (file)
@@ -256,7 +256,7 @@ CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange,
                                                      IsGenericLambda, 
                                                      CaptureDefault);
   DC->addDecl(Class);
-  
+
   return Class;
 }
 
@@ -935,6 +935,23 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
                        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;
 
index 28a2a744f505dc54cbd915ea5ef97818116692ca..018df002dbf29b56ee438e6fafea0bc2a7c2e7f7 100644 (file)
@@ -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@-1 {{non-local lambda expression cannot have a capture-default}}
+    // expected-error@-2 {{invalid use of non-static data member 'n'}}
+    // expected-error@-3 {{a lambda expression may not appear inside of a constant expression}}
+    int g(int k = ([=]{ return n; }(), 0));
+    // expected-error@-1 {{non-local lambda expression cannot have a capture-default}}
+    // expected-error@-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}}
+  };
+}
index a76903fc4af6d98d79658327bcc4ee576865462d..8825174c4999f9766c701760ce37ae0e2994157d 100644 (file)
@@ -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()));
 }