aboutsummaryrefslogtreecommitdiff
path: root/test/CXX/expr/expr.prim/expr.prim.lambda
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
commit999713eea940f4e087cc3ac878689c5c5c7a7225 (patch)
tree66586d880362aa3cbdd97551b9a9cb8b8d966ba5 /test/CXX/expr/expr.prim/expr.prim.lambda
parent68932845a432d2a1dbbc57a84fd85bbb37c90487 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150875 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CXX/expr/expr.prim/expr.prim.lambda')
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp22
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp27
-rw-r--r--test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp4
3 files changed, 48 insertions, 5 deletions
diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp
index 3301b29135..f6a8db23e9 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/blocks.cpp
+++ b/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/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
index 1723ee39fd..0cf01ade43 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/p16.cpp
+++ b/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/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
index e9356136c7..930a4b32fa 100644
--- a/test/CXX/expr/expr.prim/expr.prim.lambda/p18.cpp
+++ b/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&");
}();
}();