aboutsummaryrefslogtreecommitdiff
path: root/clang/test
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2013-12-05 05:25:04 +0000
committerBill Wendling <isanbard@gmail.com>2013-12-05 05:25:04 +0000
commite4bf668c153e3a5cd1b939226bc766a7dac9d16f (patch)
treefee5e1d7a8ad98229d8ca96bf3d0760a989bdb8b /clang/test
parent1be84437a23cd121a3804849a1825c1570c7bcdb (diff)
downloadllvm-e4bf668c153e3a5cd1b939226bc766a7dac9d16f.zip
llvm-e4bf668c153e3a5cd1b939226bc766a7dac9d16f.tar.gz
llvm-e4bf668c153e3a5cd1b939226bc766a7dac9d16f.tar.bz2
Merging r196454:
------------------------------------------------------------------------ r196454 | faisalv | 2013-12-04 17:40:41 -0800 (Wed, 04 Dec 2013) | 43 lines Fix init-captures for generic lambdas. For an init capture, process the initialization expression right away. For lambda init-captures such as the following: const int x = 10; auto L = [i = x+1](int a) { return [j = x+2, &k = x](char b) { }; }; keep in mind that each lambda init-capture has to have: - its initialization expression executed in the context of the enclosing/parent decl-context. - but the variable itself has to be 'injected' into the decl-context of its lambda's call-operator (which has not yet been created). Each init-expression is a full-expression that has to get Sema-analyzed (for capturing etc.) before its lambda's call-operator's decl-context, scope & scopeinfo are pushed on their respective stacks. Thus if any variable is odr-used in the init-capture it will correctly get captured in the enclosing lambda, if one exists. The init-variables above are created later once the lambdascope and call-operators decl-context is pushed onto its respective stack. Since the lambda init-capture's initializer expression occurs in the context of the enclosing function or lambda, therefore we can not wait till a lambda scope has been pushed on before deciding whether the variable needs to be captured. We also need to process all lvalue-to-rvalue conversions and discarded-value conversions, so that we can avoid capturing certain constant variables. For e.g., void test() { const int x = 10; auto L = [&z = x](char a) { <-- don't capture by the current lambda return [y = x](int i) { <-- don't capture by enclosing lambda return y; } }; If x was not const, the second use would require 'L' to capture, and that would be an error. Make sure TranformLambdaExpr is also aware of this. Patch approved by Richard (Thanks!!) http://llvm-reviews.chandlerc.com/D2092 ------------------------------------------------------------------------ llvm-svn: 196470
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/SemaCXX/cxx1y-init-captures.cpp167
1 files changed, 161 insertions, 6 deletions
diff --git a/clang/test/SemaCXX/cxx1y-init-captures.cpp b/clang/test/SemaCXX/cxx1y-init-captures.cpp
index d737a4a..2cb4d31 100644
--- a/clang/test/SemaCXX/cxx1y-init-captures.cpp
+++ b/clang/test/SemaCXX/cxx1y-init-captures.cpp
@@ -1,14 +1,169 @@
-// RUN: %clang_cc1 -std=c++1y %s -verify
+// RUN: %clang_cc1 -std=c++1y %s -verify -emit-llvm-only
-// expected-no-diagnostics
namespace variadic_expansion {
- void f(int &, char &);
-
- template <typename ... T> void g(T &... t) {
+ int f(int &, char &) { return 0; }
+ template<class ... Ts> char fv(Ts ... ts) { return 0; }
+ // FIXME: why do we get 2 error messages
+ template <typename ... T> void g(T &... t) { //expected-note3{{declared here}}
f([&a(t)]()->decltype(auto) {
return a;
}() ...);
+
+ auto L = [x = f([&a(t)]()->decltype(auto) { return a; }()...)]() { return x; };
+ const int y = 10;
+ auto M = [x = y,
+ &z = y](T& ... t) { };
+ auto N = [x = y,
+ &z = y, n = f(t...),
+ o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...), t...](T& ... s) {
+ fv([&a(t)]()->decltype(auto) {
+ return a;
+ }() ...);
+ };
+ auto N2 = [x = y, //expected-note3{{begins here}}
+ &z = y, n = f(t...),
+ o = f([&a(t)](T& ... t)->decltype(auto) { return a; }(t...)...)](T& ... s) {
+ fv([&a(t)]()->decltype(auto) { //expected-error 3{{captured}}
+ return a;
+ }() ...);
+ };
+
+ }
+
+ void h(int i, char c) { g(i, c); } //expected-note{{in instantiation}}
+}
+
+namespace odr_use_within_init_capture {
+
+int test() {
+
+ { // no captures
+ const int x = 10;
+ auto L = [z = x + 2](int a) {
+ auto M = [y = x - 2](char b) {
+ return y;
+ };
+ return M;
+ };
+
+ }
+ { // should not capture
+ const int x = 10;
+ auto L = [&z = x](int a) {
+ return a;;
+ };
+
+ }
+ {
+ const int x = 10;
+ auto L = [k = x](char a) { //expected-note {{declared}}
+ return [](int b) { //expected-note {{begins}}
+ return [j = k](int c) { //expected-error {{cannot be implicitly captured}}
+ return c;
+ };
+ };
+ };
+ }
+ {
+ const int x = 10;
+ auto L = [k = x](char a) {
+ return [=](int b) {
+ return [j = k](int c) {
+ return c;
+ };
+ };
+ };
}
+ {
+ const int x = 10;
+ auto L = [k = x](char a) {
+ return [k](int b) {
+ return [j = k](int c) {
+ return c;
+ };
+ };
+ };
+ }
+
+ return 0;
+}
- void h(int i, char c) { g(i, c); }
+int run = test();
+
+}
+
+namespace odr_use_within_init_capture_template {
+
+template<class T = int>
+int test(T t = T{}) {
+
+ { // no captures
+ const T x = 10;
+ auto L = [z = x](char a) {
+ auto M = [y = x](T b) {
+ return y;
+ };
+ return M;
+ };
+
+ }
+ { // should not capture
+ const T x = 10;
+ auto L = [&z = x](T a) {
+ return a;;
+ };
+
+ }
+ { // will need to capture x in outer lambda
+ const T x = 10; //expected-note {{declared}}
+ auto L = [z = x](char a) { //expected-note {{begins}}
+ auto M = [&y = x](T b) { //expected-error {{cannot be implicitly captured}}
+ return y;
+ };
+ return M;
+ };
+
+ }
+ { // will need to capture x in outer lambda
+ const T x = 10;
+ auto L = [=,z = x](char a) {
+ auto M = [&y = x](T b) {
+ return y;
+ };
+ return M;
+ };
+
+ }
+ { // will need to capture x in outer lambda
+ const T x = 10;
+ auto L = [x, z = x](char a) {
+ auto M = [&y = x](T b) {
+ return y;
+ };
+ return M;
+ };
+ }
+ { // will need to capture x in outer lambda
+ const int x = 10; //expected-note 2{{declared}}
+ auto L = [z = x](char a) { //expected-note 2{{begins}}
+ auto M = [&y = x](T b) { //expected-error 2{{cannot be implicitly captured}}
+ return y;
+ };
+ return M;
+ };
+ }
+ {
+ // no captures
+ const T x = 10;
+ auto L = [z =
+ [z = x, &y = x](char a) { return z + y; }('a')](char a)
+ { return z; };
+
+ }
+
+ return 0;
}
+
+int run = test(); //expected-note {{instantiation}}
+
+} \ No newline at end of file