[lld][WebAssembly] Reinstate mistakenly disabled test. NFC
[llvm-project.git] / clang / test / SemaCXX / warn-range-loop-analysis.cpp
blob7fd7fcd69a5446d02638d5a48fcb78ee56284695
1 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wall -Wrange-loop-bind-reference -Wno-unused -verify %s
2 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wloop-analysis -verify %s
3 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wrange-loop-analysis -verify %s
4 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wloop-analysis -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
6 template <typename return_type>
7 struct Iterator {
8 return_type operator*();
9 Iterator operator++();
10 bool operator!=(const Iterator);
13 template <typename T>
14 struct Container {
15 typedef Iterator<T> I;
17 I begin();
18 I end();
21 struct Foo {};
22 struct Bar {
23 // Small trivially copyable types do not show a warning when copied in a
24 // range-based for loop. This size ensures the object is not considered
25 // small.
26 char s[128];
27 Bar(Foo);
28 Bar(int);
29 operator int();
32 // Testing notes:
33 // test0 checks that the full text of the warnings and notes is correct. The
34 // rest of the tests checks a smaller portion of the text.
35 // test1-6 are set in pairs, the odd numbers are the non-reference returning
36 // versions of the even numbers.
37 // test7-9 use an array instead of a range object
38 // tests use all four versions of the loop variable, const &T, const T, T&, and
39 // T. Versions producing errors and are commented out.
41 // Conversion chart:
42 // double <=> int
43 // int <=> Bar
44 // double => Bar
45 // Foo => Bar
47 // Conversions during tests:
48 // test1-2
49 // int => int
50 // int => double
51 // int => Bar
52 // test3-4
53 // Bar => Bar
54 // Bar => int
55 // test5-6
56 // Foo => Bar
57 // test7
58 // double => double
59 // double => int
60 // double => Bar
61 // test8
62 // Foo => Foo
63 // Foo => Bar
64 // test9
65 // Bar => Bar
66 // Bar => int
68 void test0() {
69 Container<int> int_non_ref_container;
70 Container<int&> int_container;
71 Container<Bar&> bar_container;
73 for (const int &x : int_non_ref_container) {}
74 // expected-warning@-1 {{loop variable 'x' binds to a temporary value produced by a range of type 'Container<int>'}}
75 // expected-note@-2 {{use non-reference type 'int'}}
76 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
78 for (const double &x : int_container) {}
79 // expected-warning@-1 {{loop variable 'x' of type 'const double &' binds to a temporary constructed from type 'int &'}}
80 // expected-note@-2 {{use non-reference type 'double' to make construction explicit or type 'const int &' to prevent copying}}
81 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:21-[[@LINE-3]]:22}:""
83 for (const Bar x : bar_container) {}
84 // expected-warning@-1 {{loop variable 'x' creates a copy from type 'const Bar'}}
85 // expected-note@-2 {{use reference type 'const Bar &' to prevent copying}}
86 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:18}:"&"
89 void test1() {
90 Container<int> A;
92 for (const int &&x : A) {}
93 // No warning, rvalue-reference to the temporary
94 for (const int &x : A) {}
95 // expected-warning@-1 {{binds to a temporary value produced by a range}}
96 // expected-note@-2 {{'int'}}
97 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
98 for (const int x : A) {}
99 // No warning, non-reference type indicates copy is made
100 for (int&& x : A) {}
101 // No warning, rvalue-reference to the temporary
102 //for (int &x : A) {}
103 // Binding error
104 for (int x : A) {}
105 // No warning, non-reference type indicates copy is made
107 for (const double &&x : A) {}
108 // No warning, rvalue-reference to the temporary
109 for (const double &x : A) {}
110 // expected-warning@-1 {{binds to a temporary value produced by a range}}
111 // expected-note@-2 {{'double'}}
112 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:21-[[@LINE-3]]:22}:""
113 for (const double x : A) {}
114 // No warning, non-reference type indicates copy is made
115 for (double &&x : A) {}
116 // No warning, rvalue-reference to the temporary
117 //for (double &x : A) {}
118 // Binding error
119 for (double x : A) {}
120 // No warning, non-reference type indicates copy is made
122 for (const Bar &&x : A) {}
123 // No warning, rvalue-reference to the temporary
124 for (const Bar &x : A) {}
125 // expected-warning@-1 {{binds to a temporary value produced by a range}}
126 // expected-note@-2 {{'Bar'}}
127 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
128 for (const Bar x : A) {}
129 // No warning, non-reference type indicates copy is made
130 for (Bar &&x : A) {}
131 // No warning, rvalue-reference to the temporary
132 //for (Bar &x : A) {}
133 // Binding error
134 for (Bar x : A) {}
135 // No warning, non-reference type indicates copy is made
138 void test2() {
139 Container<int&> B;
141 //for (const int &&x : B) {}
142 // Binding error
143 for (const int &x : B) {}
144 // No warning, this reference is not a temporary
145 for (const int x : B) {}
146 // No warning on POD copy
147 //for (int &x : B) {}
148 // Binding error
149 for (int &x : B) {}
150 // No warning
151 for (int x : B) {}
152 // No warning
154 for (const double &&x : B) {}
155 // expected-warning@-1 {{binds to a temporary constructed from}}
156 // expected-note-re@-2 {{'double'{{.*}}'const int &'}}
157 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:21-[[@LINE-3]]:23}:""
158 for (const double &x : B) {}
159 // expected-warning@-1 {{binds to a temporary constructed from}}
160 // expected-note-re@-2 {{'double'{{.*}}'const int &'}}
161 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:21-[[@LINE-3]]:22}:""
162 for (const double x : B) {}
163 for (double &&x : B) {}
164 // expected-warning@-1 {{binds to a temporary constructed from}}
165 // expected-note-re@-2 {{'double'{{.*}}'const int &'}}
166 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:15-[[@LINE-3]]:17}:""
167 //for (double &x : B) {}
168 // Binding error
169 for (double x : B) {}
170 // No warning
172 for (const Bar &&x : B) {}
173 // expected-warning@-1 {{binds to a temporary constructed from}}
174 // expected-note@-2 {{'Bar'}}
175 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:20}:""
176 for (const Bar &x : B) {}
177 // expected-warning@-1 {{binds to a temporary constructed from}}
178 // expected-note@-2 {{'Bar'}}
179 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
180 for (const Bar x : B) {}
181 for (Bar &&x : B) {}
182 // expected-warning@-1 {{binds to a temporary constructed from}}
183 // expected-note@-2 {{'Bar'}}
184 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:""
185 //for (Bar &x : B) {}
186 // Binding error
187 for (Bar x : B) {}
188 // No warning
191 void test3() {
192 Container<Bar> C;
194 for (const Bar &&x : C) {}
195 // No warning, rvalue-reference to the temporary
196 for (const Bar &x : C) {}
197 // expected-warning@-1 {{binds to a temporary value produced by a range}}
198 // expected-note@-2 {{'Bar'}}
199 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
200 for (const Bar x : C) {}
201 // No warning, non-reference type indicates copy is made
202 for (Bar &&x : C) {}
203 // No warning, rvalue-reference to the temporary
204 //for (Bar &x : C) {}
205 // Binding error
206 for (Bar x : C) {}
207 // No warning, non-reference type indicates copy is made
209 for (const int &&x : C) {}
210 // No warning, rvalue-reference to the temporary
211 for (const int &x : C) {}
212 // expected-warning@-1 {{binds to a temporary value produced by a range}}
213 // expected-note@-2 {{'int'}}
214 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
215 for (const int x : C) {}
216 // No warning, copy made
217 for (int &&x : C) {}
218 // No warning, rvalue-reference to the temporary
219 //for (int &x : C) {}
220 // Binding error
221 for (int x : C) {}
222 // No warning, copy made
225 void test4() {
226 Container<Bar&> D;
228 //for (const Bar &&x : D) {}
229 // Binding error
230 for (const Bar &x : D) {}
231 // No warning, this reference is not a temporary
232 for (const Bar x : D) {}
233 // expected-warning@-1 {{creates a copy}}
234 // expected-note@-2 {{'const Bar &'}}
235 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:18}:"&"
236 //for (Bar &&x : D) {}
237 // Binding error
238 for (Bar &x : D) {}
239 // No warning
240 for (Bar x : D) {}
241 // No warning
243 for (const int &&x : D) {}
244 // expected-warning@-1 {{binds to a temporary constructed from}}
245 // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}}
246 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:20}:""
247 for (const int &x : D) {}
248 // expected-warning@-1 {{binds to a temporary constructed from}}
249 // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}}
250 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
251 for (const int x : D) {}
252 // No warning
253 for (int &&x : D) {}
254 // expected-warning@-1 {{binds to a temporary constructed from}}
255 // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}}
256 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:""
257 //for (int &x : D) {}
258 // Binding error
259 for (int x : D) {}
260 // No warning
263 void test5() {
264 Container<Foo> E;
266 for (const Bar &&x : E) {}
267 // No warning, rvalue-reference to the temporary
268 for (const Bar &x : E) {}
269 // expected-warning@-1 {{binds to a temporary value produced by a range}}
270 // expected-note@-2 {{'Bar'}}
271 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
272 for (const Bar x : E) {}
273 // No warning, non-reference type indicates copy is made
274 for (Bar &&x : E) {}
275 // No warning, rvalue-reference to the temporary
276 //for (Bar &x : E) {}
277 // Binding error
278 for (Bar x : E) {}
279 // No warning, non-reference type indicates copy is made
282 void test6() {
283 Container<Foo&> F;
285 for (const Bar &&x : F) {}
286 // expected-warning@-1 {{binds to a temporary constructed from}}
287 // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}}
288 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:20}:""
289 for (const Bar &x : F) {}
290 // expected-warning@-1 {{binds to a temporary constructed from}}
291 // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}}
292 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
293 for (const Bar x : F) {}
294 // No warning.
295 for (Bar &&x : F) {}
296 // expected-warning@-1 {{binds to a temporary constructed from}}
297 // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}}
298 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:""
299 //for (Bar &x : F) {}
300 // Binding error
301 for (Bar x : F) {}
302 // No warning
305 void test7() {
306 double G[2];
308 //for (const double &&x : G) {}
309 // Binding error
310 for (const double &x : G) {}
311 // No warning
312 for (const double x : G) {}
313 // No warning on POD copy
314 //for (double &&x : G) {}
315 // Binding error
316 for (double &x : G) {}
317 // No warning
318 for (double x : G) {}
319 // No warning
321 for (const int &&x : G) {}
322 // expected-warning@-1 {{binds to a temporary constructed from}}
323 // expected-note-re@-2 {{'int'{{.*}}'const double &'}}
324 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:20}:""
325 for (const int &x : G) {}
326 // expected-warning@-1 {{binds to a temporary constructed from}}
327 // expected-note-re@-2 {{'int'{{.*}}'const double &'}}
328 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
329 for (const int x : G) {}
330 // No warning
331 for (int &&x : G) {}
332 // expected-warning@-1 {{binds to a temporary constructed from}}
333 // expected-note-re@-2 {{'int'{{.*}}'const double &'}}
334 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:""
335 //for (int &x : G) {}
336 // Binding error
337 for (int x : G) {}
338 // No warning
340 for (const Bar &&x : G) {}
341 // expected-warning@-1 {{binds to a temporary constructed from}}
342 // expected-note-re@-2 {{'Bar'{{.*}}'const double &'}}
343 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:20}:""
344 for (const Bar &x : G) {}
345 // expected-warning@-1 {{binds to a temporary constructed from}}
346 // expected-note-re@-2 {{'Bar'{{.*}}'const double &'}}
347 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
348 for (const Bar x : G) {}
349 // No warning
350 for (Bar &&x : G) {}
351 // expected-warning@-1 {{binds to a temporary constructed from}}
352 // expected-note-re@-2 {{'Bar'{{.*}}'const double &'}}
353 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:""
354 //for (Bar &x : G) {}
355 // Binding error
356 for (Bar x : G) {}
357 // No warning
360 void test8() {
361 Foo H[2];
363 //for (const Foo &&x : H) {}
364 // Binding error
365 for (const Foo &x : H) {}
366 // No warning
367 for (const Foo x : H) {}
368 // No warning on POD copy
369 //for (Foo &&x : H) {}
370 // Binding error
371 for (Foo &x : H) {}
372 // No warning
373 for (Foo x : H) {}
374 // No warning
376 for (const Bar &&x : H) {}
377 // expected-warning@-1 {{binds to a temporary constructed from}}
378 // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}}
379 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:20}:""
380 for (const Bar &x : H) {}
381 // expected-warning@-1 {{binds to a temporary constructed from}}
382 // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}}
383 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
384 for (const Bar x : H) {}
385 // No warning
386 for (Bar &&x: H) {}
387 // expected-warning@-1 {{binds to a temporary constructed from}}
388 // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}}
389 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:""
390 //for (Bar &x: H) {}
391 // Binding error
392 for (Bar x: H) {}
393 // No warning
396 void test9() {
397 Bar I[2] = {1,2};
399 //for (const Bar &&x : I) {}
400 // Binding error
401 for (const Bar &x : I) {}
402 // No warning
403 for (const Bar x : I) {}
404 // expected-warning@-1 {{creates a copy}}
405 // expected-note@-2 {{'const Bar &'}}
406 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:18}:"&"
407 //for (Bar &&x : I) {}
408 // Binding error
409 for (Bar &x : I) {}
410 // No warning
411 for (Bar x : I) {}
412 // No warning
414 for (const int &&x : I) {}
415 // expected-warning@-1 {{binds to a temporary constructed from}}
416 // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}}
417 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:20}:""
418 for (const int &x : I) {}
419 // expected-warning@-1 {{binds to a temporary constructed from}}
420 // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}}
421 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
422 for (const int x : I) {}
423 // No warning
424 for (int &&x : I) {}
425 // expected-warning@-1 {{binds to a temporary constructed from}}
426 // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}}
427 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:14}:""
428 //for (int &x : I) {}
429 // Binding error
430 for (int x : I) {}
431 // No warning
434 void test10() {
435 Container<Bar> C;
437 for (const Bar &x : C) {}
438 // expected-warning@-1 {{binds to a temporary value produced by a range}}
439 // expected-note@-2 {{'Bar'}}
440 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
442 for (const Bar& x : C) {}
443 // expected-warning@-1 {{binds to a temporary value produced by a range}}
444 // expected-note@-2 {{'Bar'}}
445 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:18}:""
447 for (const Bar & x : C) {}
448 // expected-warning@-1 {{binds to a temporary value produced by a range}}
449 // expected-note@-2 {{'Bar'}}
450 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:20}:""
452 for (const Bar&x : C) {}
453 // expected-warning@-1 {{binds to a temporary value produced by a range}}
454 // expected-note@-2 {{'Bar'}}
455 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:18}:" "
458 template <class T>
459 void test_template_function() {
460 // In a template instantiation the diagnostics should not be emitted for
461 // loops with dependent types.
462 Container<Bar> C;
463 for (const Bar &x : C) {}
464 // expected-warning@-1 {{binds to a temporary value produced by a range}}
465 // expected-note@-2 {{'Bar'}}
466 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:18-[[@LINE-3]]:19}:""
468 Container<T> Dependent;
469 for (const T &x : Dependent) {}
471 template void test_template_function<Bar>();
473 template <class T>
474 struct test_template_struct {
475 static void static_member() {
476 Container<Bar> C;
477 for (const Bar &x : C) {}
478 // expected-warning@-1 {{binds to a temporary value produced by a range}}
479 // expected-note@-2 {{'Bar'}}
480 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""
482 Container<T> Dependent;
483 for (const T &x : Dependent) {}
486 void member() {
487 Container<Bar> C;
488 for (const Bar &x : C) {}
489 // expected-warning@-1 {{binds to a temporary value produced by a range}}
490 // expected-note@-2 {{'Bar'}}
491 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""
493 Container<T> Dependent;
494 for (const T &x : Dependent) {}
497 template struct test_template_struct<Bar>;
499 struct test_struct_with_templated_member {
500 void member() {
501 Container<Bar> C;
502 for (const Bar &x : C) {}
503 // expected-warning@-1 {{binds to a temporary value produced by a range}}
504 // expected-note@-2 {{'Bar'}}
505 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""
508 template <class T>
509 void template_member() {
510 Container<Bar> C;
511 for (const Bar &x : C) {}
512 // expected-warning@-1 {{binds to a temporary value produced by a range}}
513 // expected-note@-2 {{'Bar'}}
514 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:20-[[@LINE-3]]:21}:""
516 Container<T> Dependent;
517 for (const T &x : Dependent) {}
520 template void test_struct_with_templated_member::template_member<Bar>();
522 #define TEST_MACRO \
523 void test_macro() { \
524 Container<Bar> C; \
525 for (const Bar &x : C) {} \
528 TEST_MACRO