| Douglas Gregor | 503384f | 2012-02-09 00:47:04 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -std=c++0x -Wno-unused-value -fsyntax-only -verify -fblocks %s |
| Eli Friedman | e81d7e9 | 2012-01-07 01:08:17 +0000 | [diff] [blame] | 2 | |
| Eli Friedman | 72899c3 | 2012-01-07 04:59:52 +0000 | [diff] [blame] | 3 | namespace std { class type_info; }; |
| 4 | |
| Eli Friedman | e81d7e9 | 2012-01-07 01:08:17 +0000 | [diff] [blame] | 5 | namespace ExplicitCapture { |
| Eli Friedman | e81d7e9 | 2012-01-07 01:08:17 +0000 | [diff] [blame] | 6 | class C { |
| Eli Friedman | 72899c3 | 2012-01-07 04:59:52 +0000 | [diff] [blame] | 7 | int Member; |
| Eli Friedman | e81d7e9 | 2012-01-07 01:08:17 +0000 | [diff] [blame] | 8 | |
| Eli Friedman | 72899c3 | 2012-01-07 04:59:52 +0000 | [diff] [blame] | 9 | static void Overload(int); |
| 10 | void Overload(); |
| 11 | virtual C& Overload(float); |
| 12 | |
| Eli Friedman | 72899c3 | 2012-01-07 04:59:52 +0000 | [diff] [blame] | 13 | void ImplicitThisCapture() { |
| Douglas Gregor | b326ca8 | 2012-02-09 08:26:42 +0000 | [diff] [blame] | 14 | [](){(void)Member;}; // expected-error {{'this' cannot be implicitly captured in this context}} |
| 15 | [&](){(void)Member;}; |
| 16 | |
| 17 | [this](){(void)Member;}; |
| 18 | [this]{[this]{};}; |
| 19 | []{[this]{};};// expected-error {{'this' cannot be implicitly captured in this context}} |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 20 | []{Overload(3);}; |
| 21 | []{Overload();}; // expected-error {{'this' cannot be implicitly captured in this context}} |
| Douglas Gregor | b326ca8 | 2012-02-09 08:26:42 +0000 | [diff] [blame] | 22 | []{(void)typeid(Overload());}; |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 23 | []{(void)typeid(Overload(.5f));};// expected-error {{'this' cannot be implicitly captured in this context}} |
| Eli Friedman | 72899c3 | 2012-01-07 04:59:52 +0000 | [diff] [blame] | 24 | } |
| Eli Friedman | e81d7e9 | 2012-01-07 01:08:17 +0000 | [diff] [blame] | 25 | }; |
| 26 | |
| 27 | void f() { |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 28 | [this] () {}; // expected-error {{'this' cannot be captured in this context}} |
| Eli Friedman | e81d7e9 | 2012-01-07 01:08:17 +0000 | [diff] [blame] | 29 | } |
| 30 | } |
| Eli Friedman | 84b007f | 2012-01-26 03:00:14 +0000 | [diff] [blame] | 31 | |
| 32 | namespace ReturnDeduction { |
| 33 | void test() { |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 34 | [](){ return 1; }; |
| 35 | [](){ return 1; }; |
| 36 | [](){ return ({return 1; 1;}); }; |
| 37 | [](){ return ({return 'c'; 1;}); }; // expected-error {{must match previous return type}} |
| 38 | []()->int{ return 'c'; return 1; }; |
| Douglas Gregor | b326ca8 | 2012-02-09 08:26:42 +0000 | [diff] [blame] | 39 | [](){ return 'c'; return 1; }; // expected-error {{must match previous return type}} |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 40 | []() { return; return (void)0; }; |
| 41 | [](){ return 1; return 1; }; |
| Eli Friedman | 84b007f | 2012-01-26 03:00:14 +0000 | [diff] [blame] | 42 | } |
| 43 | } |
| Eli Friedman | b942cb2 | 2012-02-03 22:47:37 +0000 | [diff] [blame] | 44 | |
| 45 | namespace ImplicitCapture { |
| 46 | void test() { |
| Eli Friedman | cefc7b2 | 2012-02-03 23:06:43 +0000 | [diff] [blame] | 47 | int a = 0; // expected-note 5 {{declared}} |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 48 | []() { return a; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{begins here}} |
| 49 | [&]() { return a; }; |
| 50 | [=]() { return a; }; |
| 51 | [=]() { int* b = &a; }; // expected-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const int *'}} |
| Douglas Gregor | b326ca8 | 2012-02-09 08:26:42 +0000 | [diff] [blame] | 52 | [=]() { return [&]() { return a; }; }; |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 53 | []() { return [&]() { return a; }; }; // expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} |
| 54 | []() { return ^{ return a; }; };// expected-error {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} |
| 55 | []() { return [&a] { return a; }; }; // expected-error 2 {{variable 'a' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note 2 {{lambda expression begins here}} |
| 56 | [=]() { return [&a] { return a; }; }; // |
| Eli Friedman | b942cb2 | 2012-02-03 22:47:37 +0000 | [diff] [blame] | 57 | |
| 58 | const int b = 2; |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 59 | []() { return b; }; |
| Eli Friedman | b942cb2 | 2012-02-03 22:47:37 +0000 | [diff] [blame] | 60 | |
| 61 | union { // expected-note {{declared}} |
| 62 | int c; |
| 63 | float d; |
| 64 | }; |
| 65 | d = 3; |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 66 | [=]() { return c; }; // expected-error {{unnamed variable cannot be implicitly captured in a lambda expression}} |
| Eli Friedman | b942cb2 | 2012-02-03 22:47:37 +0000 | [diff] [blame] | 67 | |
| Eli Friedman | cefc7b2 | 2012-02-03 23:06:43 +0000 | [diff] [blame] | 68 | __block int e; // expected-note 3 {{declared}} |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 69 | [&]() { return e; }; // expected-error {{__block variable 'e' cannot be captured in a lambda expression}} |
| 70 | [&e]() { return e; }; // expected-error 2 {{__block variable 'e' cannot be captured in a lambda expression}} |
| Eli Friedman | b942cb2 | 2012-02-03 22:47:37 +0000 | [diff] [blame] | 71 | |
| 72 | int f[10]; // expected-note {{declared}} |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 73 | [&]() { return f[2]; }; |
| Douglas Gregor | f8af982 | 2012-02-12 18:42:33 +0000 | [diff] [blame] | 74 | (void) ^{ return []() { return f[2]; }; }; // expected-error {{variable 'f' cannot be implicitly captured in a lambda with no capture-default specified}} \ |
| 75 | // expected-note{{lambda expression begins here}} |
| Eli Friedman | b942cb2 | 2012-02-03 22:47:37 +0000 | [diff] [blame] | 76 | |
| 77 | struct G { G(); G(G&); int a; }; // expected-note 6 {{not viable}} |
| 78 | G g; |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 79 | [=]() { const G* gg = &g; return gg->a; }; |
| 80 | [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'ImplicitCapture::G'}} |
| 81 | (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const ImplicitCapture::G'}} |
| Eli Friedman | 210386e | 2012-02-06 21:50:18 +0000 | [diff] [blame] | 82 | |
| 83 | const int h = a; // expected-note {{declared}} |
| Aaron Ballman | 2876983 | 2012-06-04 20:07:46 +0000 | [diff] [blame] | 84 | []() { return h; }; // expected-error {{variable 'h' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} |
| Richard Smith | 1658133 | 2012-03-02 04:14:40 +0000 | [diff] [blame] | 85 | |
| 86 | // The exemption for variables which can appear in constant expressions |
| 87 | // applies only to objects (and not to references). |
| 88 | // FIXME: This might be a bug in the standard. |
| 89 | static int i; |
| 90 | constexpr int &ref_i = i; // expected-note {{declared}} |
| 91 | [] { return ref_i; }; // expected-error {{variable 'ref_i' cannot be implicitly captured in a lambda with no capture-default specified}} expected-note {{lambda expression begins here}} |
| Eli Friedman | b942cb2 | 2012-02-03 22:47:37 +0000 | [diff] [blame] | 92 | } |
| 93 | } |
| Douglas Gregor | b09ab8c | 2012-02-21 20:05:31 +0000 | [diff] [blame] | 94 | |
| 95 | namespace PR12031 { |
| 96 | struct X { |
| 97 | template<typename T> |
| 98 | X(const T&); |
| 99 | ~X(); |
| 100 | }; |
| 101 | |
| 102 | void f(int i, X x); |
| 103 | void g() { |
| 104 | const int v = 10; |
| 105 | f(v, [](){}); |
| 106 | } |
| 107 | } |
| Richard Smith | 359c89d | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 108 | |
| 109 | namespace NullPtr { |
| 110 | int &f(int *p); |
| 111 | char &f(...); |
| 112 | void g() { |
| 113 | int n = 0; |
| 114 | [=] { |
| 115 | char &k = f(n); // not a null pointer constant |
| 116 | } (); |
| 117 | |
| 118 | const int m = 0; |
| 119 | [=] { |
| David Blaikie | 50800fc | 2012-08-08 17:33:31 +0000 | [diff] [blame^] | 120 | int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}} |
| Richard Smith | 359c89d | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 121 | } (); |
| 122 | |
| Richard Smith | 359c89d | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 123 | [=] () -> bool { |
| David Blaikie | 50800fc | 2012-08-08 17:33:31 +0000 | [diff] [blame^] | 124 | int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}} |
| Richard Smith | 61dab36 | 2012-02-24 23:21:24 +0000 | [diff] [blame] | 125 | return &m == 0; |
| Richard Smith | 359c89d | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 126 | } (); |
| 127 | |
| 128 | [m] { |
| David Blaikie | 50800fc | 2012-08-08 17:33:31 +0000 | [diff] [blame^] | 129 | int &k = f(m); // expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}} |
| Richard Smith | 359c89d | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 130 | } (); |
| 131 | } |
| 132 | } |
| Eli Friedman | 71930e0 | 2012-03-12 20:57:19 +0000 | [diff] [blame] | 133 | |
| 134 | void PR12248() |
| 135 | { |
| 136 | unsigned int result = 0; |
| 137 | auto l = [&]() { ++result; }; |
| 138 | } |
| John McCall | 78dae24 | 2012-03-13 00:37:01 +0000 | [diff] [blame] | 139 | |
| 140 | namespace ModifyingCapture { |
| 141 | void test() { |
| 142 | int n = 0; |
| 143 | [=] { |
| John McCall | 23dde82 | 2012-03-13 01:10:51 +0000 | [diff] [blame] | 144 | n = 1; // expected-error {{cannot assign to a variable captured by copy in a non-mutable lambda}} |
| John McCall | 78dae24 | 2012-03-13 00:37:01 +0000 | [diff] [blame] | 145 | }; |
| 146 | } |
| 147 | } |
| Richard Smith | 612409e | 2012-07-25 03:56:55 +0000 | [diff] [blame] | 148 | |
| 149 | namespace VariadicPackExpansion { |
| 150 | template<typename T, typename U> using Fst = T; |
| 151 | template<typename...Ts> bool g(Fst<bool, Ts> ...bools); |
| 152 | template<typename...Ts> bool f(Ts &&...ts) { |
| 153 | return g<Ts...>([&ts] { |
| 154 | if (!ts) |
| 155 | return false; |
| 156 | --ts; |
| 157 | return true; |
| 158 | } () ...); |
| 159 | } |
| 160 | void h() { |
| 161 | int a = 5, b = 2, c = 3; |
| 162 | while (f(a, b, c)) { |
| 163 | } |
| 164 | } |
| 165 | |
| 166 | struct sink { |
| 167 | template<typename...Ts> sink(Ts &&...) {} |
| 168 | }; |
| 169 | |
| 170 | template<typename...Ts> void local_class() { |
| 171 | sink { |
| 172 | [] (Ts t) { |
| 173 | struct S : Ts { |
| 174 | void f(Ts t) { |
| 175 | Ts &that = *this; |
| 176 | that = t; |
| 177 | } |
| 178 | Ts g() { return *this; }; |
| 179 | }; |
| 180 | S s; |
| 181 | s.f(t); |
| 182 | return s; |
| 183 | } (Ts()).g() ... |
| 184 | }; |
| 185 | }; |
| 186 | struct X {}; struct Y {}; |
| 187 | template void local_class<X, Y>(); |
| 188 | |
| 189 | template<typename...Ts> void nested(Ts ...ts) { |
| 190 | f( |
| 191 | // Each expansion of this lambda implicitly captures all of 'ts', because |
| 192 | // the inner lambda also expands 'ts'. |
| 193 | [&] { |
| 194 | return ts + [&] { return f(ts...); } (); |
| 195 | } () ... |
| 196 | ); |
| 197 | } |
| 198 | template void nested(int, int, int); |
| 199 | |
| 200 | template<typename...Ts> void nested2(Ts ...ts) { // expected-note 2{{here}} |
| 201 | // Capture all 'ts', use only one. |
| 202 | f([&ts...] { return ts; } ()...); |
| 203 | // Capture each 'ts', use it. |
| 204 | f([&ts] { return ts; } ()...); |
| 205 | // Capture all 'ts', use all of them. |
| 206 | f([&ts...] { return (int)f(ts...); } ()); |
| 207 | // Capture each 'ts', use all of them. Ill-formed. In more detail: |
| 208 | // |
| 209 | // We instantiate two lambdas here; the first captures ts$0, the second |
| 210 | // captures ts$1. Both of them reference both ts parameters, so both are |
| 211 | // ill-formed because ts can't be implicitly captured. |
| 212 | // |
| 213 | // FIXME: This diagnostic does not explain what's happening. We should |
| 214 | // specify which 'ts' we're referring to in its diagnostic name. We should |
| 215 | // also say which slice of the pack expansion is being performed in the |
| 216 | // instantiation backtrace. |
| 217 | f([&ts] { return (int)f(ts...); } ()...); // \ |
| 218 | // expected-error 2{{'ts' cannot be implicitly captured}} \ |
| 219 | // expected-note 2{{lambda expression begins here}} |
| 220 | } |
| 221 | template void nested2(int); // ok |
| 222 | template void nested2(int, int); // expected-note {{in instantiation of}} |
| 223 | } |