529 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wall -Wrange-loop-bind-reference -Wno-unused -verify %s2// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wloop-analysis -verify %s3// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wrange-loop-analysis -verify %s4// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wloop-analysis -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s5 6template <typename return_type>7struct Iterator {8 return_type operator*();9 Iterator operator++();10 bool operator!=(const Iterator);11};12 13template <typename T>14struct Container {15 typedef Iterator<T> I;16 17 I begin();18 I end();19};20 21struct Foo {};22struct Bar {23 // Small trivially copyable types do not show a warning when copied in a24 // range-based for loop. This size ensures the object is not considered25 // small.26 char s[128];27 Bar(Foo);28 Bar(int);29 operator int();30};31 32// Testing notes:33// test0 checks that the full text of the warnings and notes is correct. The34// 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 returning36// versions of the even numbers.37// test7-9 use an array instead of a range object38// tests use all four versions of the loop variable, const &T, const T, T&, and39// T. Versions producing errors and are commented out.40//41// Conversion chart:42// double <=> int43// int <=> Bar44// double => Bar45// Foo => Bar46//47// Conversions during tests:48// test1-249// int => int50// int => double51// int => Bar52// test3-453// Bar => Bar54// Bar => int55// test5-656// Foo => Bar57// test758// double => double59// double => int60// double => Bar61// test862// Foo => Foo63// Foo => Bar64// test965// Bar => Bar66// Bar => int67 68void test0() {69 Container<int> int_non_ref_container;70 Container<int&> int_container;71 Container<Bar&> bar_container;72 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}:""77 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}:""82 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}:"&"87}88 89void test1() {90 Container<int> A;91 92 for (const int &&x : A) {}93 // No warning, rvalue-reference to the temporary94 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 made100 for (int&& x : A) {}101 // No warning, rvalue-reference to the temporary102 //for (int &x : A) {}103 // Binding error104 for (int x : A) {}105 // No warning, non-reference type indicates copy is made106 107 for (const double &&x : A) {}108 // No warning, rvalue-reference to the temporary109 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 made115 for (double &&x : A) {}116 // No warning, rvalue-reference to the temporary117 //for (double &x : A) {}118 // Binding error119 for (double x : A) {}120 // No warning, non-reference type indicates copy is made121 122 for (const Bar &&x : A) {}123 // No warning, rvalue-reference to the temporary124 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 made130 for (Bar &&x : A) {}131 // No warning, rvalue-reference to the temporary132 //for (Bar &x : A) {}133 // Binding error134 for (Bar x : A) {}135 // No warning, non-reference type indicates copy is made136}137 138void test2() {139 Container<int&> B;140 141 //for (const int &&x : B) {}142 // Binding error143 for (const int &x : B) {}144 // No warning, this reference is not a temporary145 for (const int x : B) {}146 // No warning on POD copy147 //for (int &x : B) {}148 // Binding error149 for (int &x : B) {}150 // No warning151 for (int x : B) {}152 // No warning153 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 error169 for (double x : B) {}170 // No warning171 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 error187 for (Bar x : B) {}188 // No warning189}190 191void test3() {192 Container<Bar> C;193 194 for (const Bar &&x : C) {}195 // No warning, rvalue-reference to the temporary196 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 made202 for (Bar &&x : C) {}203 // No warning, rvalue-reference to the temporary204 //for (Bar &x : C) {}205 // Binding error206 for (Bar x : C) {}207 // No warning, non-reference type indicates copy is made208 209 for (const int &&x : C) {}210 // No warning, rvalue-reference to the temporary211 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 made217 for (int &&x : C) {}218 // No warning, rvalue-reference to the temporary219 //for (int &x : C) {}220 // Binding error221 for (int x : C) {}222 // No warning, copy made223}224 225void test4() {226 Container<Bar&> D;227 228 //for (const Bar &&x : D) {}229 // Binding error230 for (const Bar &x : D) {}231 // No warning, this reference is not a temporary232 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 error238 for (Bar &x : D) {}239 // No warning240 for (Bar x : D) {}241 // No warning242 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 warning253 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 error259 for (int x : D) {}260 // No warning261}262 263void test5() {264 Container<Foo> E;265 266 for (const Bar &&x : E) {}267 // No warning, rvalue-reference to the temporary268 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 made274 for (Bar &&x : E) {}275 // No warning, rvalue-reference to the temporary276 //for (Bar &x : E) {}277 // Binding error278 for (Bar x : E) {}279 // No warning, non-reference type indicates copy is made280}281 282void test6() {283 Container<Foo&> F;284 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 error301 for (Bar x : F) {}302 // No warning303}304 305void test7() {306 double G[2];307 308 //for (const double &&x : G) {}309 // Binding error310 for (const double &x : G) {}311 // No warning312 for (const double x : G) {}313 // No warning on POD copy314 //for (double &&x : G) {}315 // Binding error316 for (double &x : G) {}317 // No warning318 for (double x : G) {}319 // No warning320 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 warning331 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 error337 for (int x : G) {}338 // No warning339 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 warning350 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 error356 for (Bar x : G) {}357 // No warning358}359 360void test8() {361 Foo H[2];362 363 //for (const Foo &&x : H) {}364 // Binding error365 for (const Foo &x : H) {}366 // No warning367 for (const Foo x : H) {}368 // No warning on POD copy369 //for (Foo &&x : H) {}370 // Binding error371 for (Foo &x : H) {}372 // No warning373 for (Foo x : H) {}374 // No warning375 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 warning386 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 error392 for (Bar x: H) {}393 // No warning394}395 396void test9() {397 Bar I[2] = {1,2};398 399 //for (const Bar &&x : I) {}400 // Binding error401 for (const Bar &x : I) {}402 // No warning403 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 error409 for (Bar &x : I) {}410 // No warning411 for (Bar x : I) {}412 // No warning413 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 warning424 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 error430 for (int x : I) {}431 // No warning432}433 434void test10() {435 Container<Bar> C;436 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}:""441 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}:""446 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}:""451 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}:" "456}457 458template <class T>459void test_template_function() {460 // In a template instantiation the diagnostics should not be emitted for461 // 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}:""467 468 Container<T> Dependent;469 for (const T &x : Dependent) {}470}471template void test_template_function<Bar>();472 473template <class T>474struct 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}:""481 482 Container<T> Dependent;483 for (const T &x : Dependent) {}484 }485 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}:""492 493 Container<T> Dependent;494 for (const T &x : Dependent) {}495 }496};497template struct test_template_struct<Bar>;498 499struct 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}:""506 }507 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}:""515 516 Container<T> Dependent;517 for (const T &x : Dependent) {}518 }519};520template void test_struct_with_templated_member::template_member<Bar>();521 522#define TEST_MACRO \523 void test_macro() { \524 Container<Bar> C; \525 for (const Bar &x : C) {} \526 }527 528TEST_MACRO529