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