summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2012-02-18 09:37:24 +0000
committerDouglas Gregor <dgregor@apple.com>2012-02-18 09:37:24 +0000
commitfdf598eaf31124a9fe60e2d9fdc434b4f69fe255 (patch)
treed135ba767c51439ed5eb015c0c8a95406650bcfa /clang/test
parent57d3aaed7876fe02c3451f8ea4e1eb8dd10dd8fd (diff)
downloadbcm5719-llvm-fdf598eaf31124a9fe60e2d9fdc434b4f69fe255.tar.gz
bcm5719-llvm-fdf598eaf31124a9fe60e2d9fdc434b4f69fe255.zip
Rewrite variable capture within lambda expressions and blocks,
eliminating a bunch of redundant code and properly modeling how the captures of outside blocks/lambdas affect the types seen by inner captures. This new scheme makes two passes over the capturing scope stack. The first pass goes up the stack (from innermost to outermost), assessing whether the capture looks feasible and stopping when it either hits the scope where the variable is declared or when it finds an existing capture. The second pass then walks down the stack (from outermost to innermost), capturing the variable at each step and updating the captured type and the type that an expression referring to that captured variable would see. It also checks type-specific restrictions, such as the inability to capture an array within a block. Note that only the first odr-use of each variable needs to do the full walk; subsequent uses will find the capture immediately, so multiple walks need not occur. The same routine that builds the captures can also compute the type of the captures without signaling errors and without actually performing the capture. This functionality is used to determine the type of declaration references as well as implementing the weird decltype((x)) rule within lambda expressions. The capture code now explicitly takes sides in the debate over C++ core issue 1249, which concerns the type of captures within nested lambdas. We opt to use the more permissive, more useful definition implemented by GCC rather than the one implemented by EDG. llvm-svn: 150875
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp22
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp27
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp4
-rw-r--r--clang/test/SemaCXX/lambda-expressions.cpp2
4 files changed, 49 insertions, 6 deletions
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp
index 3301b29135d..f6a8db23e9b 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp
@@ -33,3 +33,25 @@ void conversion_to_block_init(ConstCopyConstructorBoom<int> boom,
const auto& lambda2([=] { boom2.foo(); }); // expected-note{{in instantiation of member function}}
void (^block)(void) = lambda2;
}
+
+
+void nesting() {
+ int array[7]; // expected-note 2{{'array' declared here}}
+ [=] () mutable {
+ [&] {
+ ^ {
+ int i = array[2];
+ i += array[3];
+ }();
+ }();
+ }();
+
+ [&] {
+ [=] () mutable {
+ ^ {
+ int i = array[2]; // expected-error{{cannot refer to declaration with an array type inside block}}
+ i += array[3]; // expected-error{{cannot refer to declaration with an array type inside block}}
+ }();
+ }();
+ }();
+}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
index 1723ee39fd7..0cf01ade431 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
@@ -2,7 +2,7 @@
struct X {
- X(const X&) = delete; // expected-note{{explicitly marked deleted}}
+ X(const X&) = delete; // expected-note 2{{explicitly marked deleted}}
X(X&);
};
@@ -10,10 +10,31 @@ void test_capture(X x) {
[x] { }(); // okay: non-const copy ctor
[x] {
- [x] { // expected-error{{call to deleted constructor of 'const X'}}
+ [x] { // expected-error{{call to deleted constructor of 'X'}}
+ }();
+ }();
+
+ [x] {
+ [&x] {
+ [x] { // expected-error{{call to deleted constructor of 'const X'}}
+ }();
}();
}();
int a;
- [=]{ [&] { int&x = a; }(); }(); // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}}
+ [=]{
+ [&] {
+ int &x = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}}
+ int &x2 = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}}
+ }();
+ }();
+
+ [=]{
+ [&a] {
+ [&] {
+ int &x = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}}
+ int &x2 = a; // expected-error{{binding of reference to type 'int' to a value of type 'const int' drops qualifiers}}
+ }();
+ }();
+ }();
}
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
index e9356136c7b..930a4b32fa0 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
@@ -34,8 +34,8 @@ void f3() {
[=] {
[=] () mutable {
static_assert(is_same<decltype(x), float>::value, "should be float");
- static_assert(is_same<decltype((x)), const float&>::value,
- "should be const float&");
+ static_assert(is_same<decltype((x)), float&>::value,
+ "should be float&");
}();
}();
diff --git a/clang/test/SemaCXX/lambda-expressions.cpp b/clang/test/SemaCXX/lambda-expressions.cpp
index afbf9a1fffc..b54da37014b 100644
--- a/clang/test/SemaCXX/lambda-expressions.cpp
+++ b/clang/test/SemaCXX/lambda-expressions.cpp
@@ -78,7 +78,7 @@ namespace ImplicitCapture {
struct G { G(); G(G&); int a; }; // expected-note 6 {{not viable}}
G g;
[=]() { const G* gg = &g; return gg->a; }; // expected-warning{{omitted result type}}
- [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'const ImplicitCapture::G'}} \
+ [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'ImplicitCapture::G'}} \
// expected-warning{{omitted result type}}
(void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const ImplicitCapture::G'}} \
// expected-warning{{omitted result type}}
OpenPOWER on IntegriCloud