1 | // RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only %s |
2 | // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING |
3 | // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS |
4 | // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING |
5 | |
6 | constexpr int ODRUSE_SZ = sizeof(char); |
7 | |
8 | template<class T, int N> |
9 | void f(T, const int (&)[N]) { } |
10 | |
11 | template<class T> |
12 | void f(const T&, const int (&)[ODRUSE_SZ]) { } |
13 | |
14 | #define DEFINE_SELECTOR(x) \ |
15 | int selector_ ## x[sizeof(x) == ODRUSE_SZ ? ODRUSE_SZ : ODRUSE_SZ + 5] |
16 | |
17 | #define F_CALL(x, a) f(x, selector_ ## a) |
18 | |
19 | // This is a risky assumption, because if an empty class gets captured by value |
20 | // the lambda's size will still be '1' |
21 | #define ASSERT_NO_CAPTURES(L) static_assert(sizeof(L) == 1, "size of closure with no captures must be 1") |
22 | #define ASSERT_CLOSURE_SIZE_EXACT(L, N) static_assert(sizeof(L) == (N), "size of closure must be " #N) |
23 | #define ASSERT_CLOSURE_SIZE(L, N) static_assert(sizeof(L) >= (N), "size of closure must be >=" #N) |
24 | |
25 | |
26 | namespace sample { |
27 | struct X { |
28 | int i; |
29 | X(int i) : i(i) { } |
30 | }; |
31 | } |
32 | |
33 | namespace test_transformations_in_templates { |
34 | template<class T> void foo(T t) { |
35 | auto L = [](auto a) { return a; }; |
36 | } |
37 | template<class T> void foo2(T t) { |
38 | auto L = [](auto a) -> void { |
39 | auto M = [](char b) -> void { |
40 | auto N = [](auto c) -> void { |
41 | int selector[sizeof(c) == 1 ? |
42 | (sizeof(b) == 1 ? 1 : 2) |
43 | : 2 |
44 | ]{}; |
45 | }; |
46 | N('a'); |
47 | }; |
48 | }; |
49 | L(3.14); |
50 | } |
51 | |
52 | void doit() { |
53 | foo(3); |
54 | foo('a'); |
55 | foo2('A'); |
56 | } |
57 | } |
58 | |
59 | namespace test_return_type_deduction { |
60 | |
61 | void doit() { |
62 | |
63 | auto L = [](auto a, auto b) { |
64 | if ( a > b ) return a; |
65 | return b; |
66 | }; |
67 | L(2, 4); |
68 | { |
69 | auto L2 = [](auto a, int i) { |
70 | return a + i; |
71 | }; |
72 | L2(3.14, 2); |
73 | } |
74 | { |
75 | int a; //expected-note{{declared here}} |
76 | auto B = []() { return ^{ return a; }; }; //expected-error{{cannot be implicitly capture}}\ |
77 | //expected-note{{begins here}} |
78 | //[](){ return ({int b = 5; return 'c'; 'x';}); }; |
79 | |
80 | //auto X = ^{ return a; }; |
81 | |
82 | //auto Y = []() -> auto { return 3; return 'c'; }; |
83 | |
84 | } |
85 | } |
86 | } |
87 | |
88 | |
89 | namespace test_no_capture{ |
90 | void doit() { |
91 | const int x = 10; //expected-note{{declared here}} |
92 | { |
93 | // should not capture 'x' - variable undergoes lvalue-to-rvalue |
94 | auto L = [=](auto a) { |
95 | int y = x; |
96 | return a + y; |
97 | }; |
98 | ASSERT_NO_CAPTURES(L); |
99 | } |
100 | { |
101 | // should not capture 'x' - even though certain instantiations require |
102 | auto L = [](auto a) { //expected-note{{begins here}} |
103 | DEFINE_SELECTOR(a); |
104 | F_CALL(x, a); //expected-error{{'x' cannot be implicitly captured}} |
105 | }; |
106 | ASSERT_NO_CAPTURES(L); |
107 | L('s'); //expected-note{{in instantiation of}} |
108 | } |
109 | { |
110 | // Does not capture because no default capture in inner most lambda 'b' |
111 | auto L = [=](auto a) { |
112 | return [=](int p) { |
113 | return [](auto b) { |
114 | DEFINE_SELECTOR(a); |
115 | F_CALL(x, a); |
116 | return 0; |
117 | }; |
118 | }; |
119 | }; |
120 | ASSERT_NO_CAPTURES(L); |
121 | } |
122 | } // doit |
123 | } // namespace |
124 | |
125 | namespace test_capture_of_potentially_evaluated_expression { |
126 | void doit() { |
127 | const int x = 5; |
128 | { |
129 | auto L = [=](auto a) { |
130 | DEFINE_SELECTOR(a); |
131 | F_CALL(x, a); |
132 | }; |
133 | static_assert(sizeof(L) == 4, "Must be captured"); |
134 | } |
135 | { |
136 | int j = 0; //expected-note{{declared}} |
137 | auto L = [](auto a) { //expected-note{{begins here}} |
138 | return j + 1; //expected-error{{cannot be implicitly captured}} |
139 | }; |
140 | } |
141 | { |
142 | const int x = 10; |
143 | auto L = [](auto a) { |
144 | //const int y = 20; |
145 | return [](int p) { |
146 | return [](auto b) { |
147 | DEFINE_SELECTOR(a); |
148 | F_CALL(x, a); |
149 | return 0; |
150 | }; |
151 | }; |
152 | }; |
153 | auto M = L(3); |
154 | auto N = M(5); |
155 | |
156 | } |
157 | |
158 | { // if the nested capture does not implicitly or explicitly allow any captures |
159 | // nothing should capture - and instantiations will create errors if needed. |
160 | const int x = 0; |
161 | auto L = [=](auto a) { // <-- #A |
162 | const int y = 0; |
163 | return [](auto b) { // <-- #B |
164 | int c[sizeof(b)]; |
165 | f(x, c); |
166 | f(y, c); |
167 | int i = x; |
168 | }; |
169 | }; |
170 | ASSERT_NO_CAPTURES(L); |
171 | auto M_int = L(2); |
172 | ASSERT_NO_CAPTURES(M_int); |
173 | } |
174 | { // Permutations of this example must be thoroughly tested! |
175 | const int x = 0; |
176 | sample::X cx{5}; |
177 | auto L = [=](auto a) { |
178 | const int z = 3; |
179 | return [&,a](auto b) { |
180 | const int y = 5; |
181 | return [=](auto c) { |
182 | int d[sizeof(a) == sizeof(c) || sizeof(c) == sizeof(b) ? 2 : 1]; |
183 | f(x, d); |
184 | f(y, d); |
185 | f(z, d); |
186 | decltype(a) A = a; |
187 | decltype(b) B = b; |
188 | const int &i = cx.i; |
189 | }; |
190 | }; |
191 | }; |
192 | auto M = L(3)(3.5); |
193 | M(3.14); |
194 | } |
195 | } |
196 | namespace Test_no_capture_of_clearly_no_odr_use { |
197 | auto foo() { |
198 | const int x = 10; |
199 | auto L = [=](auto a) { |
200 | return [=](auto b) { |
201 | return [=](auto c) { |
202 | int A = x; |
203 | return A; |
204 | }; |
205 | }; |
206 | }; |
207 | auto M = L(1); |
208 | auto N = M(2.14); |
209 | ASSERT_NO_CAPTURES(L); |
210 | ASSERT_NO_CAPTURES(N); |
211 | |
212 | return 0; |
213 | } |
214 | } |
215 | |
216 | namespace Test_capture_of_odr_use_var { |
217 | auto foo() { |
218 | const int x = 10; |
219 | auto L = [=](auto a) { |
220 | return [=](auto b) { |
221 | return [=](auto c) { |
222 | int A = x; |
223 | const int &i = x; |
224 | decltype(a) A2 = a; |
225 | return A; |
226 | }; |
227 | }; |
228 | }; |
229 | auto M_int = L(1); |
230 | auto N_int_int = M_int(2); |
231 | ASSERT_CLOSURE_SIZE_EXACT(L, sizeof(x)); |
232 | // M_int captures both a & x |
233 | ASSERT_CLOSURE_SIZE_EXACT(M_int, sizeof(x) + sizeof(int)); |
234 | // N_int_int captures both a & x |
235 | ASSERT_CLOSURE_SIZE_EXACT(N_int_int, sizeof(x) + sizeof(int)); |
236 | auto M_double = L(3.14); |
237 | ASSERT_CLOSURE_SIZE(M_double, sizeof(x) + sizeof(double)); |
238 | |
239 | return 0; |
240 | } |
241 | auto run = foo(); |
242 | } |
243 | |
244 | } |
245 | namespace more_nested_captures_1 { |
246 | template<class T> struct Y { |
247 | static void f(int, double, ...) { } |
248 | template<class R> |
249 | static void f(const int&, R, ...) { } |
250 | template<class R> |
251 | void foo(R t) { |
252 | const int x = 10; //expected-note{{declared here}} |
253 | auto L = [](auto a) { |
254 | return [=](auto b) { |
255 | return [=](auto c) { |
256 | f(x, c, b, a); //expected-error{{reference to local variable 'x'}} |
257 | return 0; |
258 | }; |
259 | }; |
260 | }; |
261 | auto M = L(t); |
262 | auto N = M('b'); |
263 | N(3.14); |
264 | N(5); //expected-note{{in instantiation of}} |
265 | } |
266 | }; |
267 | Y<int> yi; |
268 | int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}} |
269 | } |
270 | |
271 | |
272 | namespace more_nested_captures_1_1 { |
273 | template<class T> struct Y { |
274 | static void f(int, double, ...) { } |
275 | template<class R> |
276 | static void f(const int&, R, ...) { } |
277 | template<class R> |
278 | void foo(R t) { |
279 | const int x = 10; //expected-note{{declared here}} |
280 | auto L = [](auto a) { |
281 | return [=](char b) { |
282 | return [=](auto c) { |
283 | f(x, c, b, a); //expected-error{{reference to local variable 'x'}} |
284 | return 0; |
285 | }; |
286 | }; |
287 | }; |
288 | auto M = L(t); |
289 | auto N = M('b'); |
290 | N(3.14); |
291 | N(5); //expected-note{{in instantiation of}} |
292 | } |
293 | }; |
294 | Y<int> yi; |
295 | int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}} |
296 | } |
297 | namespace more_nested_captures_1_2 { |
298 | template<class T> struct Y { |
299 | static void f(int, double, ...) { } |
300 | template<class R> |
301 | static void f(const int&, R, ...) { } |
302 | template<class R> |
303 | void foo(R t) { |
304 | const int x = 10; |
305 | auto L = [=](auto a) { |
306 | return [=](char b) { |
307 | return [=](auto c) { |
308 | f(x, c, b, a); |
309 | return 0; |
310 | }; |
311 | }; |
312 | }; |
313 | auto M = L(t); |
314 | auto N = M('b'); |
315 | N(3.14); |
316 | N(5); |
317 | } |
318 | }; |
319 | Y<int> yi; |
320 | int run = (yi.foo(3.14), 0); |
321 | } |
322 | |
323 | namespace more_nested_captures_1_3 { |
324 | template<class T> struct Y { |
325 | static void f(int, double, ...) { } |
326 | template<class R> |
327 | static void f(const int&, R, ...) { } |
328 | template<class R> |
329 | void foo(R t) { |
330 | const int x = 10; //expected-note{{declared here}} |
331 | auto L = [=](auto a) { |
332 | return [](auto b) { |
333 | const int y = 0; |
334 | return [=](auto c) { |
335 | f(x, c, b); //expected-error{{reference to local variable 'x'}} |
336 | f(y, b, c); |
337 | return 0; |
338 | }; |
339 | }; |
340 | }; |
341 | auto M = L(t); |
342 | auto N = M('b'); |
343 | N(3.14); |
344 | N(5); //expected-note{{in instantiation of}} |
345 | } |
346 | }; |
347 | Y<int> yi; |
348 | int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}} |
349 | } |
350 | |
351 | |
352 | namespace more_nested_captures_1_4 { |
353 | template<class T> struct Y { |
354 | static void f(int, double, ...) { } |
355 | template<class R> |
356 | static void f(const int&, R, ...) { } |
357 | template<class R> |
358 | void foo(R t) { |
359 | const int x = 10; //expected-note{{declared here}} |
360 | auto L = [=](auto a) { |
361 | T t2{t}; |
362 | return [](auto b) { |
363 | const int y = 0; //expected-note{{declared here}} |
364 | return [](auto c) { //expected-note 2{{lambda expression begins here}} |
365 | f(x, c); //expected-error{{variable 'x'}} |
366 | f(y, c); //expected-error{{variable 'y'}} |
367 | return 0; |
368 | }; |
369 | }; |
370 | }; |
371 | auto M = L(t); |
372 | auto N_char = M('b'); |
373 | N_char(3.14); |
374 | auto N_double = M(3.14); |
375 | N_double(3.14); |
376 | N_char(3); //expected-note{{in instantiation of}} |
377 | } |
378 | }; |
379 | Y<int> yi; |
380 | int run = (yi.foo('a'), 0); //expected-note{{in instantiation of}} |
381 | } |
382 | |
383 | |
384 | namespace more_nested_captures_2 { |
385 | template<class T> struct Y { |
386 | static void f(int, double) { } |
387 | template<class R> |
388 | static void f(const int&, R) { } |
389 | template<class R> |
390 | void foo(R t) { |
391 | const int x = 10; |
392 | auto L = [=](auto a) { |
393 | return [=](auto b) { |
394 | return [=](auto c) { |
395 | f(x, c); |
396 | return 0; |
397 | }; |
398 | }; |
399 | }; |
400 | auto M = L(t); |
401 | auto N = M('b'); |
402 | N(3); |
403 | N(3.14); |
404 | } |
405 | }; |
406 | Y<int> yi; |
407 | int run = (yi.foo(3.14), 0); |
408 | |
409 | } |
410 | |
411 | namespace more_nested_captures_3 { |
412 | template<class T> struct Y { |
413 | static void f(int, double) { } |
414 | template<class R> |
415 | static void f(const int&, R) { } |
416 | template<class R> |
417 | void foo(R t) { |
418 | const int x = 10; //expected-note{{declared here}} |
419 | auto L = [](auto a) { |
420 | return [=](auto b) { |
421 | return [=](auto c) { |
422 | f(x, c); //expected-error{{reference to local variable 'x'}} |
423 | return 0; |
424 | }; |
425 | }; |
426 | }; |
427 | auto M = L(t); |
428 | auto N = M('b'); |
429 | N(3); //expected-note{{in instantiation of}} |
430 | N(3.14); |
431 | } |
432 | }; |
433 | Y<int> yi; |
434 | int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}} |
435 | |
436 | } |
437 | |
438 | namespace more_nested_captures_4 { |
439 | template<class T> struct Y { |
440 | static void f(int, double) { } |
441 | template<class R> |
442 | static void f(const int&, R) { } |
443 | template<class R> |
444 | void foo(R t) { |
445 | const int x = 10; //expected-note{{'x' declared here}} |
446 | auto L = [](auto a) { |
447 | return [=](char b) { |
448 | return [=](auto c) { |
449 | f(x, c); //expected-error{{reference to local variable 'x'}} |
450 | return 0; |
451 | }; |
452 | }; |
453 | }; |
454 | auto M = L(t); |
455 | auto N = M('b'); |
456 | N(3); //expected-note{{in instantiation of}} |
457 | N(3.14); |
458 | } |
459 | }; |
460 | Y<int> yi; |
461 | int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}} |
462 | |
463 | } |
464 | |
465 | namespace more_nested_captures_5 { |
466 | template<class T> struct Y { |
467 | static void f(int, double) { } |
468 | template<class R> |
469 | static void f(const int&, R) { } |
470 | template<class R> |
471 | void foo(R t) { |
472 | const int x = 10; |
473 | auto L = [=](auto a) { |
474 | return [=](char b) { |
475 | return [=](auto c) { |
476 | f(x, c); |
477 | return 0; |
478 | }; |
479 | }; |
480 | }; |
481 | auto M = L(t); |
482 | auto N = M('b'); |
483 | N(3); |
484 | N(3.14); |
485 | } |
486 | }; |
487 | Y<int> yi; |
488 | int run = (yi.foo(3.14), 0); |
489 | |
490 | } |
491 | |
492 | namespace lambdas_in_NSDMIs { |
493 | template<class T> |
494 | struct L { |
495 | T t{}; |
496 | T t2 = ([](auto a) { return [](auto b) { return b; };})(t)(t); |
497 | T t3 = ([](auto a) { return a; })(t); |
498 | }; |
499 | L<int> l; |
500 | int run = l.t2; |
501 | } |
502 | namespace test_nested_decltypes_in_trailing_return_types { |
503 | int foo() { |
504 | auto L = [](auto a) { |
505 | return [](auto b, decltype(a) b2) -> decltype(a) { |
506 | return decltype(a){}; |
507 | }; |
508 | }; |
509 | auto M = L(3.14); |
510 | M('a', 6.26); |
511 | return 0; |
512 | } |
513 | } |
514 | |
515 | namespace more_this_capture_1 { |
516 | struct X { |
517 | void f(int) { } |
518 | static void f(double) { } |
519 | void foo() { |
520 | { |
521 | auto L = [=](auto a) { |
522 | f(a); |
523 | }; |
524 | L(3); |
525 | L(3.13); |
526 | } |
527 | { |
528 | auto L = [](auto a) { |
529 | f(a); //expected-error{{this}} |
530 | }; |
531 | L(3.13); |
532 | L(2); //expected-note{{in instantiation}} |
533 | } |
534 | } |
535 | |
536 | int g() { |
537 | auto L = [=](auto a) { |
538 | return [](int i) { |
539 | return [=](auto b) { |
540 | f(b); |
541 | int x = i; |
542 | }; |
543 | }; |
544 | }; |
545 | auto M = L(0.0); |
546 | auto N = M(3); |
547 | N(5.32); // OK |
548 | return 0; |
549 | } |
550 | }; |
551 | int run = X{}.g(); |
552 | } |
553 | namespace more_this_capture_1_1 { |
554 | struct X { |
555 | void f(int) { } |
556 | static void f(double) { } |
557 | |
558 | int g() { |
559 | auto L = [=](auto a) { |
560 | return [](int i) { |
561 | return [=](auto b) { |
562 | f(decltype(a){}); //expected-error{{this}} |
563 | int x = i; |
564 | }; |
565 | }; |
566 | }; |
567 | auto M = L(0.0); |
568 | auto N = M(3); |
569 | N(5.32); // OK |
570 | L(3); // expected-note{{instantiation}} |
571 | return 0; |
572 | } |
573 | }; |
574 | int run = X{}.g(); |
575 | } |
576 | |
577 | namespace more_this_capture_1_1_1 { |
578 | struct X { |
579 | void f(int) { } |
580 | static void f(double) { } |
581 | |
582 | int g() { |
583 | auto L = [=](auto a) { |
584 | return [](auto b) { |
585 | return [=](int i) { |
586 | f(b); |
587 | f(decltype(a){}); //expected-error{{this}} |
588 | }; |
589 | }; |
590 | }; |
591 | auto M = L(0.0); // OK |
592 | auto N = M(3.3); //OK |
593 | auto M_int = L(0); //expected-note{{instantiation}} |
594 | return 0; |
595 | } |
596 | }; |
597 | int run = X{}.g(); |
598 | } |
599 | |
600 | |
601 | namespace more_this_capture_1_1_1_1 { |
602 | struct X { |
603 | void f(int) { } |
604 | static void f(double) { } |
605 | |
606 | int g() { |
607 | auto L = [=](auto a) { |
608 | return [](auto b) { |
609 | return [=](int i) { |
610 | f(b); //expected-error{{this}} |
611 | f(decltype(a){}); |
612 | }; |
613 | }; |
614 | }; |
615 | auto M_double = L(0.0); // OK |
616 | auto N = M_double(3); //expected-note{{instantiation}} |
617 | |
618 | return 0; |
619 | } |
620 | }; |
621 | int run = X{}.g(); |
622 | } |
623 | |
624 | namespace more_this_capture_2 { |
625 | struct X { |
626 | void f(int) { } |
627 | static void f(double) { } |
628 | |
629 | int g() { |
630 | auto L = [=](auto a) { |
631 | return [](int i) { |
632 | return [=](auto b) { |
633 | f(b); //expected-error{{'this' cannot}} |
634 | int x = i; |
635 | }; |
636 | }; |
637 | }; |
638 | auto M = L(0.0); |
639 | auto N = M(3); |
640 | N(5); // NOT OK expected-note{{in instantiation of}} |
641 | return 0; |
642 | } |
643 | }; |
644 | int run = X{}.g(); |
645 | } |
646 | namespace diagnose_errors_early_in_generic_lambdas { |
647 | |
648 | int foo() |
649 | { |
650 | |
651 | { // This variable is used and must be caught early, do not need instantiation |
652 | const int x = 0; //expected-note{{declared}} |
653 | auto L = [](auto a) { //expected-note{{begins}} |
654 | const int &r = x; //expected-error{{variable}} |
655 | }; |
656 | } |
657 | { // This variable is not used |
658 | const int x = 0; |
659 | auto L = [](auto a) { |
660 | int i = x; |
661 | }; |
662 | } |
663 | { |
664 | |
665 | const int x = 0; //expected-note{{declared}} |
666 | auto L = [=](auto a) { // <-- #A |
667 | const int y = 0; |
668 | return [](auto b) { //expected-note{{begins}} |
669 | int c[sizeof(b)]; |
670 | f(x, c); |
671 | f(y, c); |
672 | int i = x; |
673 | // This use will always be an error regardless of instantatiation |
674 | // so diagnose this early. |
675 | const int &r = x; //expected-error{{variable}} |
676 | }; |
677 | }; |
678 | |
679 | } |
680 | return 0; |
681 | } |
682 | |
683 | int run = foo(); |
684 | } |
685 | |
686 | namespace generic_nongenerics_interleaved_1 { |
687 | int foo() { |
688 | { |
689 | auto L = [](int a) { |
690 | int y = 10; |
691 | return [=](auto b) { |
692 | return a + y; |
693 | }; |
694 | }; |
695 | auto M = L(3); |
696 | M(5); |
697 | } |
698 | { |
699 | int x; |
700 | auto L = [](int a) { |
701 | int y = 10; |
702 | return [=](auto b) { |
703 | return a + y; |
704 | }; |
705 | }; |
706 | auto M = L(3); |
707 | M(5); |
708 | } |
709 | { |
710 | // FIXME: why are there 2 error messages here? |
711 | int x; |
712 | auto L = [](auto a) { //expected-note {{declared here}} |
713 | int y = 10; //expected-note {{declared here}} |
714 | return [](int b) { //expected-note 2{{expression begins here}} |
715 | return [=] (auto c) { |
716 | return a + y; //expected-error 2{{cannot be implicitly captured}} |
717 | }; |
718 | }; |
719 | }; |
720 | } |
721 | { |
722 | int x; |
723 | auto L = [](auto a) { |
724 | int y = 10; |
725 | return [=](int b) { |
726 | return [=] (auto c) { |
727 | return a + y; |
728 | }; |
729 | }; |
730 | }; |
731 | } |
732 | return 1; |
733 | } |
734 | |
735 | int run = foo(); |
736 | } |
737 | namespace dont_capture_refs_if_initialized_with_constant_expressions { |
738 | |
739 | auto foo(int i) { |
740 | // This is surprisingly not odr-used within the lambda! |
741 | static int j; |
742 | j = i; |
743 | int &ref_j = j; |
744 | return [](auto a) { return ref_j; }; // ok |
745 | } |
746 | |
747 | template<class T> |
748 | auto foo2(T t) { |
749 | // This is surprisingly not odr-used within the lambda! |
750 | static T j; |
751 | j = t; |
752 | T &ref_j = j; |
753 | return [](auto a) { return ref_j; }; // ok |
754 | } |
755 | |
756 | int do_test() { |
757 | auto L = foo(3); |
758 | auto L_int = L(3); |
759 | auto L_char = L('a'); |
760 | auto L1 = foo2(3.14); |
761 | auto L1_int = L1(3); |
762 | auto L1_char = L1('a'); |
763 | return 0; |
764 | } |
765 | |
766 | } // dont_capture_refs_if_initialized_with_constant_expressions |
767 | |
768 | namespace test_conversion_to_fptr { |
769 | |
770 | template<class T> struct X { |
771 | |
772 | T (*fp)(T) = [](auto a) { return a; }; |
773 | |
774 | }; |
775 | |
776 | X<int> xi; |
777 | |
778 | template<class T> |
779 | void fooT(T t, T (*fp)(T) = [](auto a) { return a; }) { |
780 | fp(t); |
781 | } |
782 | |
783 | int test() { |
784 | { |
785 | auto L = [](auto a) { return a; }; |
786 | int (*fp)(int) = L; |
787 | fp(5); |
788 | L(3); |
789 | char (*fc)(char) = L; |
790 | fc('b'); |
791 | L('c'); |
792 | double (*fd)(double) = L; |
793 | fd(3.14); |
794 | fd(6.26); |
795 | L(4.25); |
796 | } |
797 | { |
798 | auto L = [](auto a) ->int { return a; }; //expected-note 2{{candidate template ignored}} |
799 | int (*fp)(int) = L; |
800 | char (*fc)(char) = L; //expected-error{{no viable conversion}} |
801 | double (*fd)(double) = L; //expected-error{{no viable conversion}} |
802 | } |
803 | { |
804 | int x = 5; |
805 | auto L = [=](auto b, char c = 'x') { |
806 | int i = x; |
807 | return [](auto a) ->decltype(a) { return a; }; |
808 | }; |
809 | int (*fp)(int) = L(8); |
810 | fp(5); |
811 | L(3); |
812 | char (*fc)(char) = L('a'); |
813 | fc('b'); |
814 | L('c'); |
815 | double (*fd)(double) = L(3.14); |
816 | fd(3.14); |
817 | fd(6.26); |
818 | |
819 | } |
820 | { |
821 | auto L = [=](auto b) { |
822 | return [](auto a) ->decltype(b)* { return (decltype(b)*)0; }; |
823 | }; |
824 | int* (*fp)(int) = L(8); |
825 | fp(5); |
826 | L(3); |
827 | char* (*fc)(char) = L('a'); |
828 | fc('b'); |
829 | L('c'); |
830 | double* (*fd)(double) = L(3.14); |
831 | fd(3.14); |
832 | fd(6.26); |
833 | } |
834 | { |
835 | auto L = [=](auto b) { |
836 | return [](auto a) ->decltype(b)* { return (decltype(b)*)0; }; //expected-note{{candidate template ignored}} |
837 | }; |
838 | char* (*fp)(int) = L('8'); |
839 | fp(5); |
840 | char* (*fc)(char) = L('a'); |
841 | fc('b'); |
842 | double* (*fi)(int) = L(3.14); |
843 | fi(5); |
844 | int* (*fi2)(int) = L(3.14); //expected-error{{no viable conversion}} |
845 | } |
846 | |
847 | { |
848 | auto L = [=](auto b) { |
849 | return [](auto a) { |
850 | return [=](auto c) { |
851 | return [](auto d) ->decltype(a + b + c + d) { return d; }; |
852 | }; |
853 | }; |
854 | }; |
855 | int (*fp)(int) = L('8')(3)(short{}); |
856 | double (*fs)(char) = L(3.14)(short{})('4'); |
857 | } |
858 | |
859 | fooT(3); |
860 | fooT('a'); |
861 | fooT(3.14); |
862 | fooT("abcdefg"); |
863 | return 0; |
864 | } |
865 | int run2 = test(); |
866 | |
867 | } |
868 | |
869 | |
870 | namespace this_capture { |
871 | void f(char, int) { } |
872 | template<class T> |
873 | void f(T, const int&) { } |
874 | |
875 | struct X { |
876 | int x = 0; |
877 | void foo() { |
878 | auto L = [=](auto a) { |
879 | return [=](auto b) { |
880 | //f(a, x++); |
881 | x++; |
882 | }; |
883 | }; |
884 | L('a')(5); |
885 | L('b')(4); |
886 | L(3.14)('3'); |
887 | |
888 | } |
889 | |
890 | }; |
891 | |
892 | int run = (X{}.foo(), 0); |
893 | |
894 | namespace this_capture_unresolvable { |
895 | struct X { |
896 | void f(int) { } |
897 | static void f(double) { } |
898 | |
899 | int g() { |
900 | auto lam = [=](auto a) { f(a); }; // captures 'this' |
901 | lam(0); // ok. |
902 | lam(0.0); // ok. |
903 | return 0; |
904 | } |
905 | int g2() { |
906 | auto lam = [](auto a) { f(a); }; // expected-error{{'this'}} |
907 | lam(0); // expected-note{{in instantiation of}} |
908 | lam(0.0); // ok. |
909 | return 0; |
910 | } |
911 | double (*fd)(double) = [](auto a) { f(a); return a; }; |
912 | |
913 | }; |
914 | |
915 | int run = X{}.g(); |
916 | |
917 | } |
918 | |
919 | namespace check_nsdmi_and_this_capture_of_member_functions { |
920 | |
921 | struct FunctorDouble { |
922 | template<class T> FunctorDouble(T t) { t(2.14); }; |
923 | }; |
924 | struct FunctorInt { |
925 | template<class T> FunctorInt(T t) { t(2); }; //expected-note{{in instantiation of}} |
926 | }; |
927 | |
928 | template<class T> struct YUnresolvable { |
929 | void f(int) { } |
930 | static void f(double) { } |
931 | |
932 | T t = [](auto a) { f(a); return a; }; |
933 | T t2 = [=](auto b) { f(b); return b; }; |
934 | }; |
935 | |
936 | template<class T> struct YUnresolvable2 { |
937 | void f(int) { } |
938 | static void f(double) { } |
939 | |
940 | T t = [](auto a) { f(a); return a; }; //expected-error{{'this'}} \ |
941 | //expected-note{{in instantiation of}} |
942 | T t2 = [=](auto b) { f(b); return b; }; |
943 | }; |
944 | |
945 | |
946 | YUnresolvable<FunctorDouble> yud; |
947 | // This will cause an error since it call's with an int and calls a member function. |
948 | YUnresolvable2<FunctorInt> yui; |
949 | |
950 | |
951 | template<class T> struct YOnlyStatic { |
952 | static void f(double) { } |
953 | |
954 | T t = [](auto a) { f(a); return a; }; |
955 | }; |
956 | YOnlyStatic<FunctorDouble> yos; |
957 | template<class T> struct YOnlyNonStatic { |
958 | void f(int) { } |
959 | |
960 | T t = [](auto a) { f(a); return a; }; //expected-error{{'this'}} |
961 | }; |
962 | |
963 | |
964 | } |
965 | |
966 | |
967 | namespace check_nsdmi_and_this_capture_of_data_members { |
968 | |
969 | struct FunctorDouble { |
970 | template<class T> FunctorDouble(T t) { t(2.14); }; |
971 | }; |
972 | struct FunctorInt { |
973 | template<class T> FunctorInt(T t) { t(2); }; |
974 | }; |
975 | |
976 | template<class T> struct YThisCapture { |
977 | const int x = 10; |
978 | static double d; |
979 | T t = [](auto a) { return x; }; //expected-error{{'this'}} |
980 | T t2 = [](auto b) { return d; }; |
981 | T t3 = [this](auto a) { |
982 | return [=](auto b) { |
983 | return x; |
984 | }; |
985 | }; |
986 | T t4 = [=](auto a) { |
987 | return [=](auto b) { |
988 | return x; |
989 | }; |
990 | }; |
991 | T t5 = [](auto a) { |
992 | return [=](auto b) { |
993 | return x; //expected-error{{'this'}} |
994 | }; |
995 | }; |
996 | }; |
997 | |
998 | template<class T> double YThisCapture<T>::d = 3.14; |
999 | |
1000 | |
1001 | } |
1002 | |
1003 | |
1004 | #ifdef DELAYED_TEMPLATE_PARSING |
1005 | template<class T> void foo_no_error(T t) { |
1006 | auto L = []() |
1007 | { return t; }; |
1008 | } |
1009 | template<class T> void foo(T t) { //expected-note 2{{declared here}} |
1010 | auto L = []() //expected-note 2{{begins here}} |
1011 | { return t; }; //expected-error 2{{cannot be implicitly captured}} |
1012 | } |
1013 | template void foo(int); //expected-note{{in instantiation of}} |
1014 | |
1015 | #else |
1016 | |
1017 | template<class T> void foo(T t) { //expected-note{{declared here}} |
1018 | auto L = []() //expected-note{{begins here}} |
1019 | { return t; }; //expected-error{{cannot be implicitly captured}} |
1020 | } |
1021 | |
1022 | #endif |
1023 | } |
1024 | |
1025 | namespace no_this_capture_for_static { |
1026 | |
1027 | struct X { |
1028 | static void f(double) { } |
1029 | |
1030 | int g() { |
1031 | auto lam = [=](auto a) { f(a); }; |
1032 | lam(0); // ok. |
1033 | ASSERT_NO_CAPTURES(lam); |
1034 | return 0; |
1035 | } |
1036 | }; |
1037 | |
1038 | int run = X{}.g(); |
1039 | } |
1040 | |
1041 | namespace this_capture_for_non_static { |
1042 | |
1043 | struct X { |
1044 | void f(double) { } |
1045 | |
1046 | int g() { |
1047 | auto L = [=](auto a) { f(a); }; |
1048 | L(0); |
1049 | auto L2 = [](auto a) { f(a); }; //expected-error {{cannot be implicitly captured}} |
1050 | return 0; |
1051 | } |
1052 | }; |
1053 | |
1054 | int run = X{}.g(); |
1055 | } |
1056 | |
1057 | namespace this_captures_with_num_args_disambiguation { |
1058 | |
1059 | struct X { |
1060 | void f(int) { } |
1061 | static void f(double, int i) { } |
1062 | int g() { |
1063 | auto lam = [](auto a) { f(a, a); }; |
1064 | lam(0); |
1065 | return 0; |
1066 | } |
1067 | }; |
1068 | |
1069 | int run = X{}.g(); |
1070 | } |
1071 | namespace enclosing_function_is_template_this_capture { |
1072 | // Only error if the instantiation tries to use the member function. |
1073 | struct X { |
1074 | void f(int) { } |
1075 | static void f(double) { } |
1076 | template<class T> |
1077 | int g(T t) { |
1078 | auto L = [](auto a) { f(a); }; //expected-error{{'this'}} |
1079 | L(t); // expected-note{{in instantiation of}} |
1080 | return 0; |
1081 | } |
1082 | }; |
1083 | |
1084 | int run = X{}.g(0.0); // OK. |
1085 | int run2 = X{}.g(0); // expected-note{{in instantiation of}} |
1086 | |
1087 | |
1088 | } |
1089 | |
1090 | namespace enclosing_function_is_template_this_capture_2 { |
1091 | // This should error, even if not instantiated, since |
1092 | // this would need to be captured. |
1093 | struct X { |
1094 | void f(int) { } |
1095 | template<class T> |
1096 | int g(T t) { |
1097 | auto L = [](auto a) { f(a); }; //expected-error{{'this'}} |
1098 | L(t); |
1099 | return 0; |
1100 | } |
1101 | }; |
1102 | |
1103 | } |
1104 | |
1105 | |
1106 | namespace enclosing_function_is_template_this_capture_3 { |
1107 | // This should not error, this does not need to be captured. |
1108 | struct X { |
1109 | static void f(int) { } |
1110 | template<class T> |
1111 | int g(T t) { |
1112 | auto L = [](auto a) { f(a); }; |
1113 | L(t); |
1114 | return 0; |
1115 | } |
1116 | }; |
1117 | |
1118 | int run = X{}.g(0.0); // OK. |
1119 | int run2 = X{}.g(0); // OK. |
1120 | |
1121 | } |
1122 | |
1123 | namespace nested_this_capture_1 { |
1124 | struct X { |
1125 | void f(int) { } |
1126 | static void f(double) { } |
1127 | |
1128 | int g() { |
1129 | auto L = [=](auto a) { |
1130 | return [this]() { |
1131 | return [=](auto b) { |
1132 | f(b); |
1133 | }; |
1134 | }; |
1135 | }; |
1136 | auto M = L(0); |
1137 | auto N = M(); |
1138 | N(5); |
1139 | return 0; |
1140 | } |
1141 | }; |
1142 | |
1143 | int run = X{}.g(); |
1144 | |
1145 | } |
1146 | |
1147 | |
1148 | namespace nested_this_capture_2 { |
1149 | struct X { |
1150 | void f(int) { } |
1151 | static void f(double) { } |
1152 | |
1153 | int g() { |
1154 | auto L = [=](auto a) { |
1155 | return [&]() { |
1156 | return [=](auto b) { |
1157 | f(b); |
1158 | }; |
1159 | }; |
1160 | }; |
1161 | auto M = L(0); |
1162 | auto N = M(); |
1163 | N(5); |
1164 | N(3.14); |
1165 | return 0; |
1166 | } |
1167 | }; |
1168 | |
1169 | int run = X{}.g(); |
1170 | |
1171 | } |
1172 | |
1173 | namespace nested_this_capture_3_1 { |
1174 | struct X { |
1175 | template<class T> |
1176 | void f(int, T t) { } |
1177 | template<class T> |
1178 | static void f(double, T t) { } |
1179 | |
1180 | int g() { |
1181 | auto L = [=](auto a) { |
1182 | return [&](auto c) { |
1183 | return [=](auto b) { |
1184 | f(b, c); |
1185 | }; |
1186 | }; |
1187 | }; |
1188 | auto M = L(0); |
1189 | auto N = M('a'); |
1190 | N(5); |
1191 | N(3.14); |
1192 | return 0; |
1193 | } |
1194 | }; |
1195 | |
1196 | int run = X{}.g(); |
1197 | |
1198 | } |
1199 | |
1200 | |
1201 | namespace nested_this_capture_3_2 { |
1202 | struct X { |
1203 | void f(int) { } |
1204 | static void f(double) { } |
1205 | |
1206 | int g() { |
1207 | auto L = [=](auto a) { |
1208 | return [](int i) { |
1209 | return [=](auto b) { |
1210 | f(b); //expected-error {{'this' cannot}} |
1211 | int x = i; |
1212 | }; |
1213 | }; |
1214 | }; |
1215 | auto M = L(0.0); |
1216 | auto N = M(3); |
1217 | N(5); //expected-note {{in instantiation of}} |
1218 | N(3.14); // OK. |
1219 | return 0; |
1220 | } |
1221 | }; |
1222 | |
1223 | int run = X{}.g(); |
1224 | |
1225 | } |
1226 | |
1227 | namespace nested_this_capture_4 { |
1228 | struct X { |
1229 | void f(int) { } |
1230 | static void f(double) { } |
1231 | |
1232 | int g() { |
1233 | auto L = [](auto a) { |
1234 | return [=](auto i) { |
1235 | return [=](auto b) { |
1236 | f(b); //expected-error {{'this' cannot}} |
1237 | int x = i; |
1238 | }; |
1239 | }; |
1240 | }; |
1241 | auto M = L(0.0); |
1242 | auto N = M(3); |
1243 | N(5); //expected-note {{in instantiation of}} |
1244 | N(3.14); // OK. |
1245 | return 0; |
1246 | } |
1247 | }; |
1248 | |
1249 | int run = X{}.g(); |
1250 | |
1251 | } |
1252 | namespace capture_enclosing_function_parameters { |
1253 | |
1254 | |
1255 | inline auto foo(int x) { |
1256 | int i = 10; |
1257 | auto lambda = [=](auto z) { return x + z; }; |
1258 | return lambda; |
1259 | } |
1260 | |
1261 | int foo2() { |
1262 | auto L = foo(3); |
1263 | L(4); |
1264 | L('a'); |
1265 | L(3.14); |
1266 | return 0; |
1267 | } |
1268 | |
1269 | inline auto foo3(int x) { |
1270 | int local = 1; |
1271 | auto L = [=](auto a) { |
1272 | int i = a[local]; |
1273 | return [=](auto b) mutable { |
1274 | auto n = b; |
1275 | return [&, n](auto c) mutable { |
1276 | ++local; |
1277 | return ++x; |
1278 | }; |
1279 | }; |
1280 | }; |
1281 | auto M = L("foo-abc"); |
1282 | auto N = M("foo-def"); |
1283 | auto O = N("foo-ghi"); |
1284 | |
1285 | return L; |
1286 | } |
1287 | |
1288 | int main() { |
1289 | auto L3 = foo3(3); |
1290 | auto M3 = L3("L3-1"); |
1291 | auto N3 = M3("M3-1"); |
1292 | auto O3 = N3("N3-1"); |
1293 | N3("N3-2"); |
1294 | M3("M3-2"); |
1295 | M3("M3-3"); |
1296 | L3("L3-2"); |
1297 | } |
1298 | } // end ns |
1299 | |
1300 | namespace capture_arrays { |
1301 | |
1302 | inline int sum_array(int n) { |
1303 | int array2[5] = { 1, 2, 3, 4, 5}; |
1304 | |
1305 | auto L = [=](auto N) -> int { |
1306 | int sum = 0; |
1307 | int array[5] = { 1, 2, 3, 4, 5 }; |
1308 | sum += array2[sum]; |
1309 | sum += array2[N]; |
1310 | return 0; |
1311 | }; |
1312 | L(2); |
1313 | return L(n); |
1314 | } |
1315 | } |
1316 | |
1317 | namespace capture_non_odr_used_variable_because_named_in_instantiation_dependent_expressions { |
1318 | |
1319 | // even though 'x' is not odr-used, it should be captured. |
1320 | |
1321 | int test() { |
1322 | const int x = 10; |
1323 | auto L = [=](auto a) { |
1324 | (void) +x + a; |
1325 | }; |
1326 | ASSERT_CLOSURE_SIZE_EXACT(L, sizeof(x)); |
1327 | } |
1328 | |
1329 | } //end ns |
1330 | #ifdef MS_EXTENSIONS |
1331 | namespace explicit_spec { |
1332 | template<class R> struct X { |
1333 | template<class T> int foo(T t) { |
1334 | auto L = [](auto a) { return a; }; |
1335 | L(&t); |
1336 | return 0; |
1337 | } |
1338 | |
1339 | template<> int foo<char>(char c) { //expected-warning{{explicit specialization}} |
1340 | const int x = 10; |
1341 | auto LC = [](auto a) { return a; }; |
1342 | R r; |
1343 | LC(&r); |
1344 | auto L = [=](auto a) { |
1345 | return [=](auto b) { |
1346 | int d[sizeof(a)]; |
1347 | f(x, d); |
1348 | }; |
1349 | }; |
1350 | auto M = L(1); |
1351 | |
1352 | ASSERT_NO_CAPTURES(M); |
1353 | return 0; |
1354 | } |
1355 | |
1356 | }; |
1357 | |
1358 | int run_char = X<int>{}.foo('a'); |
1359 | int run_int = X<double>{}.foo(4); |
1360 | } |
1361 | #endif // MS_EXTENSIONS |
1362 | |
1363 | namespace nsdmi_capturing_this { |
1364 | struct X { |
1365 | int m = 10; |
1366 | int n = [this](auto) { return m; }(20); |
1367 | }; |
1368 | |
1369 | template<class T> |
1370 | struct XT { |
1371 | T m = 10; |
1372 | T n = [this](auto) { return m; }(20); |
1373 | }; |
1374 | |
1375 | XT<int> xt{}; |
1376 | |
1377 | |
1378 | } |
1379 | |
1380 | void PR33318(int i) { |
1381 | [&](auto) { static_assert(&i != nullptr, ""); }(0); // expected-warning 2{{always true}} expected-note {{instantiation}} |
1382 | } |
1383 | |
1384 | // Check to make sure that we don't capture when member-calls are made to members that are not of 'this' class. |
1385 | namespace PR34266 { |
1386 | // https://bugs.llvm.org/show_bug.cgi?id=34266 |
1387 | namespace ns1 { |
1388 | struct A { |
1389 | static void bar(int) { } |
1390 | static void bar(double) { } |
1391 | }; |
1392 | |
1393 | struct B |
1394 | { |
1395 | template<class T> |
1396 | auto f() { |
1397 | auto L = [=] { |
1398 | T{}.bar(3.0); |
1399 | T::bar(3); |
1400 | |
1401 | }; |
1402 | ASSERT_NO_CAPTURES(L); |
1403 | return L; |
1404 | }; |
1405 | }; |
1406 | |
1407 | void test() { |
1408 | B{}.f<A>(); |
1409 | } |
1410 | } // end ns1 |
1411 | |
1412 | namespace ns2 { |
1413 | struct A { |
1414 | static void bar(int) { } |
1415 | static void bar(double) { } |
1416 | }; |
1417 | |
1418 | struct B |
1419 | { |
1420 | using T = A; |
1421 | auto f() { |
1422 | auto L = [=](auto a) { |
1423 | T{}.bar(a); |
1424 | T::bar(a); |
1425 | |
1426 | }; |
1427 | ASSERT_NO_CAPTURES(L); |
1428 | return L; |
1429 | }; |
1430 | }; |
1431 | |
1432 | void test() { |
1433 | B{}.f()(3.0); |
1434 | B{}.f()(3); |
1435 | } |
1436 | } // end ns2 |
1437 | |
1438 | namespace ns3 { |
1439 | struct A { |
1440 | void bar(int) { } |
1441 | static void bar(double) { } |
1442 | }; |
1443 | |
1444 | struct B |
1445 | { |
1446 | using T = A; |
1447 | auto f() { |
1448 | auto L = [=](auto a) { |
1449 | T{}.bar(a); |
1450 | T::bar(a); // This call ignores the instance member function because the implicit object argument fails to convert. |
1451 | |
1452 | }; |
1453 | ASSERT_NO_CAPTURES(L); |
1454 | return L; |
1455 | }; |
1456 | }; |
1457 | |
1458 | void test() { |
1459 | B{}.f()(3.0); |
1460 | B{}.f()(3); |
1461 | } |
1462 | |
1463 | } // end ns3 |
1464 | |
1465 | |
1466 | namespace ns4 { |
1467 | struct A { |
1468 | void bar(int) { } |
1469 | static void bar(double) { } |
1470 | }; |
1471 | |
1472 | struct B : A |
1473 | { |
1474 | using T = A; |
1475 | auto f() { |
1476 | auto L = [=](auto a) { |
1477 | T{}.bar(a); |
1478 | T::bar(a); |
1479 | |
1480 | }; |
1481 | // just check to see if the size if >= 2 bytes (which should be the case if we capture anything) |
1482 | ASSERT_CLOSURE_SIZE(L, 2); |
1483 | return L; |
1484 | }; |
1485 | }; |
1486 | |
1487 | void test() { |
1488 | B{}.f()(3.0); |
1489 | B{}.f()(3); |
1490 | } |
1491 | |
1492 | } // end ns4 |
1493 | |
1494 | namespace ns5 { |
1495 | struct A { |
1496 | void bar(int) { } |
1497 | static void bar(double) { } |
1498 | }; |
1499 | |
1500 | struct B |
1501 | { |
1502 | template<class T> |
1503 | auto f() { |
1504 | auto L = [&](auto a) { |
1505 | T{}.bar(a); |
1506 | T::bar(a); |
1507 | |
1508 | }; |
1509 | |
1510 | ASSERT_NO_CAPTURES(L); |
1511 | return L; |
1512 | }; |
1513 | }; |
1514 | |
1515 | void test() { |
1516 | B{}.f<A>()(3.0); |
1517 | B{}.f<A>()(3); |
1518 | } |
1519 | |
1520 | } // end ns5 |
1521 | |
1522 | |
1523 | |
1524 | } // end PR34266 |
1525 | |