forked from OSchip/llvm-project
Add various tests for captures and the reaching scope of the lambda
expression. Implement C++11 [expr.prim.lambda]p12's requirement that capturing a variable will odr-use it. llvm-svn: 150237
This commit is contained in:
parent
12695101ec
commit
f02455e5ee
|
@ -9624,8 +9624,12 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
|
|||
// to be re-"exported" from the lambda expression itself.
|
||||
S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
|
||||
|
||||
// C++ [expr.prim.labda]p12:
|
||||
// An entity captured by a lambda-expression is odr-used (3.2) in
|
||||
// the scope containing the lambda-expression.
|
||||
Expr *Ref = new (S.Context) DeclRefExpr(Var, Type.getNonReferenceType(),
|
||||
VK_LValue, Loc);
|
||||
Var->setUsed(true);
|
||||
|
||||
// When the field has array type, create index variables for each
|
||||
// dimension of the array. We use these index variables to subscript
|
||||
|
@ -9999,7 +10003,7 @@ void Sema::MarkMemberReferenced(MemberExpr *E) {
|
|||
MarkExprReferenced(*this, E->getMemberLoc(), E->getMemberDecl(), E);
|
||||
}
|
||||
|
||||
/// \brief Perform marking for a reference to an aribitrary declaration. It
|
||||
/// \brief Perform marking for a reference to an arbitrary declaration. It
|
||||
/// marks the declaration referenced, and performs odr-use checking for functions
|
||||
/// and variables. This method should not be used when building an normal
|
||||
/// expression which refers to a variable.
|
||||
|
|
|
@ -23,3 +23,18 @@ class X0 {
|
|||
(void)[&Variable] () {}; // expected-error {{use of undeclared identifier 'Variable'; did you mean 'variable'}}
|
||||
}
|
||||
};
|
||||
|
||||
void test_reaching_scope() {
|
||||
int local; // expected-note{{declared here}}
|
||||
static int local_static; // expected-note{{'local_static' declared here}}
|
||||
(void)[=]() {
|
||||
struct InnerLocal {
|
||||
void member() {
|
||||
(void)[local, // expected-error{{reference to local variable 'local' declared in enclosing function 'test_reaching_scope'}}
|
||||
local_static]() { // expected-error{{'local_static' cannot be captured because it does not have automatic storage duration}}
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// RUN: %clang_cc1 -std=c++11 %s -verify
|
||||
|
||||
void test_reaching_scope() {
|
||||
int local; // expected-note{{declared here}}
|
||||
static int local_static;
|
||||
(void)[=]() {
|
||||
struct InnerLocal {
|
||||
void member() {
|
||||
(void)[=]() {
|
||||
return local + // expected-error{{reference to local variable 'local' declared in enclosing function 'test_reaching_scope'}}
|
||||
local_static;
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// RUN: %clang_cc1 -std=c++11 %s -Wunused -verify
|
||||
|
||||
void odr_used() {
|
||||
int i = 17;
|
||||
[i]{}();
|
||||
}
|
||||
|
||||
struct ReachingThis {
|
||||
static void static_foo() {
|
||||
(void)[this](){}; // expected-error{{'this' cannot be captured in this context}}
|
||||
|
||||
struct Local {
|
||||
int i;
|
||||
|
||||
void bar() {
|
||||
(void)[this](){};
|
||||
(void)[&](){i = 7; };
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void foo() {
|
||||
(void)[this](){};
|
||||
|
||||
struct Local {
|
||||
int i;
|
||||
|
||||
static void static_bar() {
|
||||
(void)[this](){}; // expected-error{{'this' cannot be captured in this context}}
|
||||
(void)[&](){i = 7; }; // expected-error{{invalid use of nonstatic data member 'i'}}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
void immediately_enclosing(int i) { // expected-note{{'i' declared here}}
|
||||
[i]() {
|
||||
[i] {}();
|
||||
}();
|
||||
|
||||
[=]() {
|
||||
[i] {}();
|
||||
}();
|
||||
|
||||
[]() { // expected-note{{lambda expression begins here}}
|
||||
[i] {}(); // expected-error{{variable 'i' cannot be implicitly captured in a lambda with no capture-default specified}}
|
||||
}();
|
||||
}
|
Loading…
Reference in New Issue