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

expression.

llvm-svn: 200948
This commit is contained in:
Richard Smith 2014-02-06 21:49:08 +00:00
parent 3a4bf0405e
commit 3d584b0ced
4 changed files with 42 additions and 3 deletions

View 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">;

View 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;

View 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}}
};
}

View 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()));
}