diff options
Diffstat (limited to 'test/SemaCXX/warn-range-loop-analysis.cpp')
-rw-r--r-- | test/SemaCXX/warn-range-loop-analysis.cpp | 299 |
1 files changed, 299 insertions, 0 deletions
diff --git a/test/SemaCXX/warn-range-loop-analysis.cpp b/test/SemaCXX/warn-range-loop-analysis.cpp new file mode 100644 index 0000000..91756b9 --- /dev/null +++ b/test/SemaCXX/warn-range-loop-analysis.cpp @@ -0,0 +1,299 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wloop-analysis -verify %s +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wrange-loop-analysis -verify %s + +template <typename return_type> +struct Iterator { + return_type operator*(); + Iterator operator++(); + bool operator!=(const Iterator); +}; + +template <typename T> +struct Container { + typedef Iterator<T> I; + + I begin(); + I end(); +}; + +struct Foo {}; +struct Bar { + Bar(Foo); + Bar(int); + operator int(); +}; + +// Testing notes: +// test0 checks that the full text of the warnings and notes is correct. The +// rest of the tests checks a smaller portion of the text. +// test1-6 are set in pairs, the odd numbers are the non-reference returning +// versions of the even numbers. +// test7-9 use an array instead of a range object +// tests use all four versions of the loop varaible, const &T, const T, T&, and +// T. Versions producing errors and are commented out. +// +// Conversion chart: +// double <=> int +// int <=> Bar +// double => Bar +// Foo => Bar +// +// Conversions during tests: +// test1-2 +// int => int +// int => double +// int => Bar +// test3-4 +// Bar => Bar +// Bar => int +// test5-6 +// Foo => Bar +// test7 +// double => double +// double => int +// double => Bar +// test8 +// Foo => Foo +// Foo => Bar +// test9 +// Bar => Bar +// Bar => int + +void test0() { + Container<int> int_non_ref_container; + Container<int&> int_container; + Container<Bar&> bar_container; + + for (const int &x : int_non_ref_container) {} + // expected-warning@-1 {{loop variable 'x' is always a copy because the range of type 'Container<int>' does not return a reference}} + // expected-note@-2 {{use non-reference type 'int'}} + + for (const double &x : int_container) {} + // expected-warning@-1 {{loop variable 'x' has type 'const double &' but is initialized with type 'int' resulting in a copy}} + // expected-note@-2 {{use non-reference type 'double' to keep the copy or type 'const int &' to prevent copying}} + + for (const Bar x : bar_container) {} + // expected-warning@-1 {{loop variable 'x' of type 'const Bar' creates a copy from type 'const Bar'}} + // expected-note@-2 {{use reference type 'const Bar &' to prevent copying}} +} + +void test1() { + Container<int> A; + + for (const int &x : A) {} + // expected-warning@-1 {{always a copy}} + // expected-note@-2 {{'int'}} + for (const int x : A) {} + // No warning, non-reference type indicates copy is made + //for (int &x : A) {} + // Binding error + for (int x : A) {} + // No warning, non-reference type indicates copy is made + + for (const double &x : A) {} + // expected-warning@-1 {{always a copy}} + // expected-note@-2 {{'double'}} + for (const double x : A) {} + // No warning, non-reference type indicates copy is made + //for (double &x : A) {} + // Binding error + for (double x : A) {} + // No warning, non-reference type indicates copy is made + + for (const Bar &x : A) {} + // expected-warning@-1 {{always a copy}} + // expected-note@-2 {{'Bar'}} + for (const Bar x : A) {} + // No warning, non-reference type indicates copy is made + //for (Bar &x : A) {} + // Binding error + for (Bar x : A) {} + // No warning, non-reference type indicates copy is made +} + +void test2() { + Container<int&> B; + + for (const int &x : B) {} + // No warning, this reference is not a temporary + for (const int x : B) {} + // No warning on POD copy + for (int &x : B) {} + // No warning + for (int x : B) {} + // No warning + + for (const double &x : B) {} + // expected-warning@-1 {{resulting in a copy}} + // expected-note-re@-2 {{'double'{{.*}}'const int &'}} + for (const double x : B) {} + //for (double &x : B) {} + // Binding error + for (double x : B) {} + // No warning + + for (const Bar &x : B) {} + // expected-warning@-1 {{resulting in a copy}} + // expected-note@-2 {{'Bar'}} + for (const Bar x : B) {} + //for (Bar &x : B) {} + // Binding error + for (Bar x : B) {} + // No warning +} + +void test3() { + Container<Bar> C; + + for (const Bar &x : C) {} + // expected-warning@-1 {{always a copy}} + // expected-note@-2 {{'Bar'}} + for (const Bar x : C) {} + // No warning, non-reference type indicates copy is made + //for (Bar &x : C) {} + // Binding error + for (Bar x : C) {} + // No warning, non-reference type indicates copy is made + + for (const int &x : C) {} + // expected-warning@-1 {{always a copy}} + // expected-note@-2 {{'int'}} + for (const int x : C) {} + // No warning, copy made + //for (int &x : C) {} + // Binding error + for (int x : C) {} + // No warning, copy made +} + +void test4() { + Container<Bar&> D; + + for (const Bar &x : D) {} + // No warning, this reference is not a temporary + for (const Bar x : D) {} + // expected-warning@-1 {{creates a copy}} + // expected-note@-2 {{'const Bar &'}} + for (Bar &x : D) {} + // No warning + for (Bar x : D) {} + // No warning + + for (const int &x : D) {} + // expected-warning@-1 {{resulting in a copy}} + // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}} + for (const int x : D) {} + // No warning + //for (int &x : D) {} + // Binding error + for (int x : D) {} + // No warning +} + +void test5() { + Container<Foo> E; + + for (const Bar &x : E) {} + // expected-warning@-1 {{always a copy}} + // expected-note@-2 {{'Bar'}} + for (const Bar x : E) {} + // No warning, non-reference type indicates copy is made + //for (Bar &x : E) {} + // Binding error + for (Bar x : E) {} + // No warning, non-reference type indicates copy is made +} + +void test6() { + Container<Foo&> F; + + for (const Bar &x : F) {} + // expected-warning@-1 {{resulting in a copy}} + // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}} + for (const Bar x : F) {} + // No warning. + //for (Bar &x : F) {} + // Binding error + for (Bar x : F) {} + // No warning +} + +void test7() { + double G[2]; + + for (const double &x : G) {} + // No warning + for (const double x : G) {} + // No warning on POD copy + for (double &x : G) {} + // No warning + for (double x : G) {} + // No warning + + for (const int &x : G) {} + // expected-warning@-1 {{resulting in a copy}} + // expected-note-re@-2 {{'int'{{.*}}'const double &'}} + for (const int x : G) {} + // No warning + //for (int &x : G) {} + // Binding error + for (int x : G) {} + // No warning + + for (const Bar &x : G) {} + // expected-warning@-1 {{resulting in a copy}} + // expected-note-re@-2 {{'Bar'{{.*}}'const double &'}} + for (const Bar x : G) {} + // No warning + //for (int &Bar : G) {} + // Binding error + for (int Bar : G) {} + // No warning +} + +void test8() { + Foo H[2]; + + for (const Foo &x : H) {} + // No warning + for (const Foo x : H) {} + // No warning on POD copy + for (Foo &x : H) {} + // No warning + for (Foo x : H) {} + // No warning + + for (const Bar &x : H) {} + // expected-warning@-1 {{resulting in a copy}} + // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}} + for (const Bar x : H) {} + // No warning + //for (Bar &x: H) {} + // Binding error + for (Bar x: H) {} + // No warning +} + +void test9() { + Bar I[2] = {1,2}; + + for (const Bar &x : I) {} + // No warning + for (const Bar x : I) {} + // expected-warning@-1 {{creates a copy}} + // expected-note@-2 {{'const Bar &'}} + for (Bar &x : I) {} + // No warning + for (Bar x : I) {} + // No warning + + for (const int &x : I) {} + // expected-warning@-1 {{resulting in a copy}} + // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}} + for (const int x : I) {} + // No warning + //for (int &x : I) {} + // Binding error + for (int x : I) {} + // No warning +} |