1 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wloop-analysis -verify %s 2 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -Wrange-loop-analysis -verify %s 3 4 template <typename return_type> 5 struct Iterator { 6 return_type operator*(); 7 Iterator operator++(); 8 bool operator!=(const Iterator); 9 }; 10 11 template <typename T> 12 struct Container { 13 typedef Iterator<T> I; 14 15 I begin(); 16 I end(); 17 }; 18 19 struct Foo {}; 20 struct Bar { 21 Bar(Foo); 22 Bar(int); 23 operator int(); 24 }; 25 26 // Testing notes: 27 // test0 checks that the full text of the warnings and notes is correct. The 28 // rest of the tests checks a smaller portion of the text. 29 // test1-6 are set in pairs, the odd numbers are the non-reference returning 30 // versions of the even numbers. 31 // test7-9 use an array instead of a range object 32 // tests use all four versions of the loop varaible, const &T, const T, T&, and 33 // T. Versions producing errors and are commented out. 34 // 35 // Conversion chart: 36 // double <=> int 37 // int <=> Bar 38 // double => Bar 39 // Foo => Bar 40 // 41 // Conversions during tests: 42 // test1-2 43 // int => int 44 // int => double 45 // int => Bar 46 // test3-4 47 // Bar => Bar 48 // Bar => int 49 // test5-6 50 // Foo => Bar 51 // test7 52 // double => double 53 // double => int 54 // double => Bar 55 // test8 56 // Foo => Foo 57 // Foo => Bar 58 // test9 59 // Bar => Bar 60 // Bar => int 61 62 void test0() { 63 Container<int> int_non_ref_container; 64 Container<int&> int_container; 65 Container<Bar&> bar_container; 66 67 for (const int &x : int_non_ref_container) {} 68 // expected-warning@-1 {{loop variable 'x' is always a copy because the range of type 'Container<int>' does not return a reference}} 69 // expected-note@-2 {{use non-reference type 'int'}} 70 71 for (const double &x : int_container) {} 72 // expected-warning@-1 {{loop variable 'x' has type 'const double &' but is initialized with type 'int' resulting in a copy}} 73 // expected-note@-2 {{use non-reference type 'double' to keep the copy or type 'const int &' to prevent copying}} 74 75 for (const Bar x : bar_container) {} 76 // expected-warning@-1 {{loop variable 'x' of type 'const Bar' creates a copy from type 'const Bar'}} 77 // expected-note@-2 {{use reference type 'const Bar &' to prevent copying}} 78 } 79 80 void test1() { 81 Container<int> A; 82 83 for (const int &x : A) {} 84 // expected-warning@-1 {{always a copy}} 85 // expected-note@-2 {{'int'}} 86 for (const int x : A) {} 87 // No warning, non-reference type indicates copy is made 88 //for (int &x : A) {} 89 // Binding error 90 for (int x : A) {} 91 // No warning, non-reference type indicates copy is made 92 93 for (const double &x : A) {} 94 // expected-warning@-1 {{always a copy}} 95 // expected-note@-2 {{'double'}} 96 for (const double x : A) {} 97 // No warning, non-reference type indicates copy is made 98 //for (double &x : A) {} 99 // Binding error 100 for (double x : A) {} 101 // No warning, non-reference type indicates copy is made 102 103 for (const Bar &x : A) {} 104 // expected-warning@-1 {{always a copy}} 105 // expected-note@-2 {{'Bar'}} 106 for (const Bar x : A) {} 107 // No warning, non-reference type indicates copy is made 108 //for (Bar &x : A) {} 109 // Binding error 110 for (Bar x : A) {} 111 // No warning, non-reference type indicates copy is made 112 } 113 114 void test2() { 115 Container<int&> B; 116 117 for (const int &x : B) {} 118 // No warning, this reference is not a temporary 119 for (const int x : B) {} 120 // No warning on POD copy 121 for (int &x : B) {} 122 // No warning 123 for (int x : B) {} 124 // No warning 125 126 for (const double &x : B) {} 127 // expected-warning@-1 {{resulting in a copy}} 128 // expected-note-re@-2 {{'double'{{.*}}'const int &'}} 129 for (const double x : B) {} 130 //for (double &x : B) {} 131 // Binding error 132 for (double x : B) {} 133 // No warning 134 135 for (const Bar &x : B) {} 136 // expected-warning@-1 {{resulting in a copy}} 137 // expected-note@-2 {{'Bar'}} 138 for (const Bar x : B) {} 139 //for (Bar &x : B) {} 140 // Binding error 141 for (Bar x : B) {} 142 // No warning 143 } 144 145 void test3() { 146 Container<Bar> C; 147 148 for (const Bar &x : C) {} 149 // expected-warning@-1 {{always a copy}} 150 // expected-note@-2 {{'Bar'}} 151 for (const Bar x : C) {} 152 // No warning, non-reference type indicates copy is made 153 //for (Bar &x : C) {} 154 // Binding error 155 for (Bar x : C) {} 156 // No warning, non-reference type indicates copy is made 157 158 for (const int &x : C) {} 159 // expected-warning@-1 {{always a copy}} 160 // expected-note@-2 {{'int'}} 161 for (const int x : C) {} 162 // No warning, copy made 163 //for (int &x : C) {} 164 // Binding error 165 for (int x : C) {} 166 // No warning, copy made 167 } 168 169 void test4() { 170 Container<Bar&> D; 171 172 for (const Bar &x : D) {} 173 // No warning, this reference is not a temporary 174 for (const Bar x : D) {} 175 // expected-warning@-1 {{creates a copy}} 176 // expected-note@-2 {{'const Bar &'}} 177 for (Bar &x : D) {} 178 // No warning 179 for (Bar x : D) {} 180 // No warning 181 182 for (const int &x : D) {} 183 // expected-warning@-1 {{resulting in a copy}} 184 // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}} 185 for (const int x : D) {} 186 // No warning 187 //for (int &x : D) {} 188 // Binding error 189 for (int x : D) {} 190 // No warning 191 } 192 193 void test5() { 194 Container<Foo> E; 195 196 for (const Bar &x : E) {} 197 // expected-warning@-1 {{always a copy}} 198 // expected-note@-2 {{'Bar'}} 199 for (const Bar x : E) {} 200 // No warning, non-reference type indicates copy is made 201 //for (Bar &x : E) {} 202 // Binding error 203 for (Bar x : E) {} 204 // No warning, non-reference type indicates copy is made 205 } 206 207 void test6() { 208 Container<Foo&> F; 209 210 for (const Bar &x : F) {} 211 // expected-warning@-1 {{resulting in a copy}} 212 // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}} 213 for (const Bar x : F) {} 214 // No warning. 215 //for (Bar &x : F) {} 216 // Binding error 217 for (Bar x : F) {} 218 // No warning 219 } 220 221 void test7() { 222 double G[2]; 223 224 for (const double &x : G) {} 225 // No warning 226 for (const double x : G) {} 227 // No warning on POD copy 228 for (double &x : G) {} 229 // No warning 230 for (double x : G) {} 231 // No warning 232 233 for (const int &x : G) {} 234 // expected-warning@-1 {{resulting in a copy}} 235 // expected-note-re@-2 {{'int'{{.*}}'const double &'}} 236 for (const int x : G) {} 237 // No warning 238 //for (int &x : G) {} 239 // Binding error 240 for (int x : G) {} 241 // No warning 242 243 for (const Bar &x : G) {} 244 // expected-warning@-1 {{resulting in a copy}} 245 // expected-note-re@-2 {{'Bar'{{.*}}'const double &'}} 246 for (const Bar x : G) {} 247 // No warning 248 //for (int &Bar : G) {} 249 // Binding error 250 for (int Bar : G) {} 251 // No warning 252 } 253 254 void test8() { 255 Foo H[2]; 256 257 for (const Foo &x : H) {} 258 // No warning 259 for (const Foo x : H) {} 260 // No warning on POD copy 261 for (Foo &x : H) {} 262 // No warning 263 for (Foo x : H) {} 264 // No warning 265 266 for (const Bar &x : H) {} 267 // expected-warning@-1 {{resulting in a copy}} 268 // expected-note-re@-2 {{'Bar'{{.*}}'const Foo &'}} 269 for (const Bar x : H) {} 270 // No warning 271 //for (Bar &x: H) {} 272 // Binding error 273 for (Bar x: H) {} 274 // No warning 275 } 276 277 void test9() { 278 Bar I[2] = {1,2}; 279 280 for (const Bar &x : I) {} 281 // No warning 282 for (const Bar x : I) {} 283 // expected-warning@-1 {{creates a copy}} 284 // expected-note@-2 {{'const Bar &'}} 285 for (Bar &x : I) {} 286 // No warning 287 for (Bar x : I) {} 288 // No warning 289 290 for (const int &x : I) {} 291 // expected-warning@-1 {{resulting in a copy}} 292 // expected-note-re@-2 {{'int'{{.*}}'const Bar &'}} 293 for (const int x : I) {} 294 // No warning 295 //for (int &x : I) {} 296 // Binding error 297 for (int x : I) {} 298 // No warning 299 } 300