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; }; |
Eli Friedman | 9dd686d | 2012-10-24 20:28:18 +0000 | [diff] [blame] | 80 | [=]() { return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error {{no matching constructor for initialization of 'G'}} |
| 81 | (void)^{ return [=]{ const G* gg = &g; return gg->a; }(); }; // expected-error 2 {{no matching constructor for initialization of 'const 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 | |
Richard Smith | 5016a70 | 2012-10-20 01:38:33 +0000 | [diff] [blame] | 86 | // References can appear in constant expressions if they are initialized by |
| 87 | // reference constant expressions. |
| 88 | int i; |
| 89 | int &ref_i = i; // expected-note {{declared}} |
Richard Smith | 1658133 | 2012-03-02 04:14:40 +0000 | [diff] [blame] | 90 | [] { 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}} |
Richard Smith | 5016a70 | 2012-10-20 01:38:33 +0000 | [diff] [blame] | 91 | |
| 92 | static int j; |
| 93 | int &ref_j = j; |
| 94 | [] { return ref_j; }; // ok |
Eli Friedman | b942cb2 | 2012-02-03 22:47:37 +0000 | [diff] [blame] | 95 | } |
| 96 | } |
Douglas Gregor | b09ab8c | 2012-02-21 20:05:31 +0000 | [diff] [blame] | 97 | |
| 98 | namespace PR12031 { |
| 99 | struct X { |
| 100 | template<typename T> |
| 101 | X(const T&); |
| 102 | ~X(); |
| 103 | }; |
| 104 | |
| 105 | void f(int i, X x); |
| 106 | void g() { |
| 107 | const int v = 10; |
| 108 | f(v, [](){}); |
| 109 | } |
| 110 | } |
Richard Smith | 359c89d | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 111 | |
| 112 | namespace NullPtr { |
| 113 | int &f(int *p); |
| 114 | char &f(...); |
| 115 | void g() { |
| 116 | int n = 0; |
| 117 | [=] { |
| 118 | char &k = f(n); // not a null pointer constant |
| 119 | } (); |
| 120 | |
| 121 | const int m = 0; |
| 122 | [=] { |
David Blaikie | 50800fc | 2012-08-08 17:33:31 +0000 | [diff] [blame] | 123 | 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] | 124 | } (); |
| 125 | |
Richard Smith | 359c89d | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 126 | [=] () -> bool { |
David Blaikie | 50800fc | 2012-08-08 17:33:31 +0000 | [diff] [blame] | 127 | 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] | 128 | return &m == 0; |
Richard Smith | 359c89d | 2012-02-24 22:12:32 +0000 | [diff] [blame] | 129 | } (); |
| 130 | |
| 131 | [m] { |
David Blaikie | 50800fc | 2012-08-08 17:33:31 +0000 | [diff] [blame] | 132 | 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] | 133 | } (); |
| 134 | } |
| 135 | } |
Eli Friedman | 71930e0 | 2012-03-12 20:57:19 +0000 | [diff] [blame] | 136 | |
| 137 | void PR12248() |
| 138 | { |
| 139 | unsigned int result = 0; |
| 140 | auto l = [&]() { ++result; }; |
| 141 | } |
John McCall | 78dae24 | 2012-03-13 00:37:01 +0000 | [diff] [blame] | 142 | |
| 143 | namespace ModifyingCapture { |
| 144 | void test() { |
| 145 | int n = 0; |
| 146 | [=] { |
John McCall | 23dde82 | 2012-03-13 01:10:51 +0000 | [diff] [blame] | 147 | 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] | 148 | }; |
| 149 | } |
| 150 | } |
Richard Smith | 612409e | 2012-07-25 03:56:55 +0000 | [diff] [blame] | 151 | |
| 152 | namespace VariadicPackExpansion { |
| 153 | template<typename T, typename U> using Fst = T; |
| 154 | template<typename...Ts> bool g(Fst<bool, Ts> ...bools); |
| 155 | template<typename...Ts> bool f(Ts &&...ts) { |
| 156 | return g<Ts...>([&ts] { |
| 157 | if (!ts) |
| 158 | return false; |
| 159 | --ts; |
| 160 | return true; |
| 161 | } () ...); |
| 162 | } |
| 163 | void h() { |
| 164 | int a = 5, b = 2, c = 3; |
| 165 | while (f(a, b, c)) { |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | struct sink { |
| 170 | template<typename...Ts> sink(Ts &&...) {} |
| 171 | }; |
| 172 | |
| 173 | template<typename...Ts> void local_class() { |
| 174 | sink { |
| 175 | [] (Ts t) { |
| 176 | struct S : Ts { |
| 177 | void f(Ts t) { |
| 178 | Ts &that = *this; |
| 179 | that = t; |
| 180 | } |
| 181 | Ts g() { return *this; }; |
| 182 | }; |
| 183 | S s; |
| 184 | s.f(t); |
| 185 | return s; |
| 186 | } (Ts()).g() ... |
| 187 | }; |
| 188 | }; |
| 189 | struct X {}; struct Y {}; |
| 190 | template void local_class<X, Y>(); |
| 191 | |
| 192 | template<typename...Ts> void nested(Ts ...ts) { |
| 193 | f( |
| 194 | // Each expansion of this lambda implicitly captures all of 'ts', because |
| 195 | // the inner lambda also expands 'ts'. |
| 196 | [&] { |
| 197 | return ts + [&] { return f(ts...); } (); |
| 198 | } () ... |
| 199 | ); |
| 200 | } |
| 201 | template void nested(int, int, int); |
| 202 | |
| 203 | template<typename...Ts> void nested2(Ts ...ts) { // expected-note 2{{here}} |
| 204 | // Capture all 'ts', use only one. |
| 205 | f([&ts...] { return ts; } ()...); |
| 206 | // Capture each 'ts', use it. |
| 207 | f([&ts] { return ts; } ()...); |
| 208 | // Capture all 'ts', use all of them. |
| 209 | f([&ts...] { return (int)f(ts...); } ()); |
| 210 | // Capture each 'ts', use all of them. Ill-formed. In more detail: |
| 211 | // |
| 212 | // We instantiate two lambdas here; the first captures ts$0, the second |
| 213 | // captures ts$1. Both of them reference both ts parameters, so both are |
| 214 | // ill-formed because ts can't be implicitly captured. |
| 215 | // |
| 216 | // FIXME: This diagnostic does not explain what's happening. We should |
| 217 | // specify which 'ts' we're referring to in its diagnostic name. We should |
| 218 | // also say which slice of the pack expansion is being performed in the |
| 219 | // instantiation backtrace. |
| 220 | f([&ts] { return (int)f(ts...); } ()...); // \ |
| 221 | // expected-error 2{{'ts' cannot be implicitly captured}} \ |
| 222 | // expected-note 2{{lambda expression begins here}} |
| 223 | } |
| 224 | template void nested2(int); // ok |
| 225 | template void nested2(int, int); // expected-note {{in instantiation of}} |
| 226 | } |
Eli Friedman | 9cd5b24 | 2012-09-18 21:11:30 +0000 | [diff] [blame] | 227 | |
| 228 | namespace PR13860 { |
| 229 | void foo() { |
| 230 | auto x = PR13860UndeclaredIdentifier(); // expected-error {{use of undeclared identifier 'PR13860UndeclaredIdentifier'}} |
| 231 | auto y = [x]() { }; |
| 232 | static_assert(sizeof(y), ""); |
| 233 | } |
| 234 | } |
Eli Friedman | 7c3c6bc | 2012-09-20 01:40:23 +0000 | [diff] [blame] | 235 | |
| 236 | namespace PR13854 { |
| 237 | auto l = [](void){}; |
| 238 | } |
Benjamin Kramer | 4242740 | 2012-12-06 15:42:21 +0000 | [diff] [blame] | 239 | |
| 240 | namespace PR14518 { |
| 241 | auto f = [](void) { return __func__; }; // no-warning |
| 242 | } |