1 // RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -I %S/Inputs/loop-convert 2 3 #include "structures.h" 4 5 namespace Array { 6 7 const int N = 6; 8 const int NMinusOne = N - 1; 9 int Arr[N] = {1, 2, 3, 4, 5, 6}; 10 const int ConstArr[N] = {1, 2, 3, 4, 5, 6}; 11 int (*PArr)[N] = &Arr; 12 13 void f() { 14 int Sum = 0; 15 16 for (int I = 0; I < N; ++I) { 17 Sum += Arr[I]; 18 int K; 19 } 20 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead [modernize-loop-convert] 21 // CHECK-FIXES: for (int I : Arr) 22 // CHECK-FIXES-NEXT: Sum += I; 23 // CHECK-FIXES-NEXT: int K; 24 25 for (int I = 0; I < N; ++I) { 26 printf("Fibonacci number is %d\n", Arr[I]); 27 Sum += Arr[I] + 2; 28 } 29 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 30 // CHECK-FIXES: for (int I : Arr) 31 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); 32 // CHECK-FIXES-NEXT: Sum += I + 2; 33 34 for (int I = 0; I < N; ++I) { 35 int X = Arr[I]; 36 int Y = Arr[I] + 2; 37 } 38 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 39 // CHECK-FIXES: for (int I : Arr) 40 // CHECK-FIXES-NEXT: int X = I; 41 // CHECK-FIXES-NEXT: int Y = I + 2; 42 43 for (int I = 0; I < N; ++I) { 44 int X = N; 45 X = Arr[I]; 46 } 47 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 48 // CHECK-FIXES: for (int I : Arr) 49 // CHECK-FIXES-NEXT: int X = N; 50 // CHECK-FIXES-NEXT: X = I; 51 52 for (int I = 0; I < N; ++I) { 53 Arr[I] += 1; 54 } 55 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 56 // CHECK-FIXES: for (int & I : Arr) 57 // CHECK-FIXES-NEXT: I += 1; 58 59 for (int I = 0; I < N; ++I) { 60 int X = Arr[I] + 2; 61 Arr[I]++; 62 } 63 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 64 // CHECK-FIXES: for (int & I : Arr) 65 // CHECK-FIXES-NEXT: int X = I + 2; 66 // CHECK-FIXES-NEXT: I++; 67 68 for (int I = 0; I < N; ++I) { 69 Arr[I] = 4 + Arr[I]; 70 } 71 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 72 // CHECK-FIXES: for (int & I : Arr) 73 // CHECK-FIXES-NEXT: I = 4 + I; 74 75 for (int I = 0; I < NMinusOne + 1; ++I) { 76 Sum += Arr[I]; 77 } 78 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 79 // CHECK-FIXES: for (int I : Arr) 80 // CHECK-FIXES-NEXT: Sum += I; 81 82 for (int I = 0; I < N; ++I) { 83 printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]); 84 Sum += Arr[I] + 2; 85 } 86 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 87 // CHECK-FIXES: for (int & I : Arr) 88 // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I); 89 // CHECK-FIXES-NEXT: Sum += I + 2; 90 91 Val Teas[N]; 92 for (int I = 0; I < N; ++I) { 93 Teas[I].g(); 94 } 95 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 96 // CHECK-FIXES: for (auto & Tea : Teas) 97 // CHECK-FIXES-NEXT: Tea.g(); 98 99 for (int I = 0; N > I; ++I) { 100 printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]); 101 Sum += Arr[I] + 2; 102 } 103 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 104 // CHECK-FIXES: for (int & I : Arr) 105 // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I); 106 // CHECK-FIXES-NEXT: Sum += I + 2; 107 108 for (int I = 0; N != I; ++I) { 109 printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]); 110 Sum += Arr[I] + 2; 111 } 112 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 113 // CHECK-FIXES: for (int & I : Arr) 114 // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I); 115 // CHECK-FIXES-NEXT: Sum += I + 2; 116 117 for (int I = 0; I != N; ++I) { 118 printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]); 119 Sum += Arr[I] + 2; 120 } 121 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 122 // CHECK-FIXES: for (int & I : Arr) 123 // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I); 124 // CHECK-FIXES-NEXT: Sum += I + 2; 125 } 126 127 const int *constArray() { 128 for (int I = 0; I < N; ++I) { 129 printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]); 130 } 131 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 132 // CHECK-FIXES: for (int I : ConstArr) 133 // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I, I + I); 134 135 const NonTriviallyCopyable NonCopy[N]{}; 136 for (int I = 0; I < N; ++I) { 137 printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X); 138 } 139 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 140 // CHECK-FIXES: for (const auto & I : NonCopy) 141 // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X); 142 143 const TriviallyCopyableButBig Big[N]{}; 144 for (int I = 0; I < N; ++I) { 145 printf("2 * %d = %d\n", Big[I].X, Big[I].X + Big[I].X); 146 } 147 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 148 // CHECK-FIXES: for (const auto & I : Big) 149 // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X); 150 151 bool Something = false; 152 for (int I = 0; I < N; ++I) { 153 if (Something) 154 return &ConstArr[I]; 155 } 156 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 157 // CHECK-FIXES: for (const int & I : ConstArr) 158 // CHECK-FIXES-NEXT: if (Something) 159 // CHECK-FIXES-NEXT: return &I; 160 } 161 162 struct HasArr { 163 int Arr[N]; 164 Val ValArr[N]; 165 void implicitThis() { 166 for (int I = 0; I < N; ++I) { 167 printf("%d", Arr[I]); 168 } 169 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead 170 // CHECK-FIXES: for (int I : Arr) 171 // CHECK-FIXES-NEXT: printf("%d", I); 172 173 for (int I = 0; I < N; ++I) { 174 printf("%d", ValArr[I].X); 175 } 176 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead 177 // CHECK-FIXES: for (auto & I : ValArr) 178 // CHECK-FIXES-NEXT: printf("%d", I.X); 179 } 180 181 void explicitThis() { 182 for (int I = 0; I < N; ++I) { 183 printf("%d", this->Arr[I]); 184 } 185 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead 186 // CHECK-FIXES: for (int I : this->Arr) 187 // CHECK-FIXES-NEXT: printf("%d", I); 188 189 for (int I = 0; I < N; ++I) { 190 printf("%d", this->ValArr[I].X); 191 } 192 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead 193 // CHECK-FIXES: for (auto & I : this->ValArr) 194 // CHECK-FIXES-NEXT: printf("%d", I.X); 195 } 196 }; 197 198 struct HasIndirectArr { 199 HasArr HA; 200 void implicitThis() { 201 for (int I = 0; I < N; ++I) { 202 printf("%d", HA.Arr[I]); 203 } 204 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead 205 // CHECK-FIXES: for (int I : HA.Arr) 206 // CHECK-FIXES-NEXT: printf("%d", I); 207 208 for (int I = 0; I < N; ++I) { 209 printf("%d", HA.ValArr[I].X); 210 } 211 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead 212 // CHECK-FIXES: for (auto & I : HA.ValArr) 213 // CHECK-FIXES-NEXT: printf("%d", I.X); 214 } 215 216 void explicitThis() { 217 for (int I = 0; I < N; ++I) { 218 printf("%d", this->HA.Arr[I]); 219 } 220 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead 221 // CHECK-FIXES: for (int I : this->HA.Arr) 222 // CHECK-FIXES-NEXT: printf("%d", I); 223 224 for (int I = 0; I < N; ++I) { 225 printf("%d", this->HA.ValArr[I].X); 226 } 227 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead 228 // CHECK-FIXES: for (auto & I : this->HA.ValArr) 229 // CHECK-FIXES-NEXT: printf("%d", I.X); 230 } 231 }; 232 233 // Loops whose bounds are value-dependent should not be converted. 234 template <int N> 235 void dependentExprBound() { 236 for (int I = 0; I < N; ++I) 237 Arr[I] = 0; 238 } 239 template void dependentExprBound<20>(); 240 241 void memberFunctionPointer() { 242 Val V; 243 void (Val::*mfpArr[N])(void) = {&Val::g}; 244 for (int I = 0; I < N; ++I) 245 (V.*mfpArr[I])(); 246 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 247 // CHECK-FIXES: for (auto & I : mfpArr) 248 // CHECK-FIXES-NEXT: (V.*I)(); 249 250 struct Foo { 251 int (Val::*f)(); 252 } Foo[N]; 253 254 for (int I = 0; I < N; ++I) 255 int R = (V.*(Foo[I].f))(); 256 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 257 // CHECK-FIXES: for (auto & I : Foo) 258 // CHECK-FIXES-NEXT: int R = (V.*(I.f))(); 259 260 } 261 262 } // namespace Array 263 264 namespace Iterator { 265 266 void f() { 267 /// begin()/end() - based for loops here: 268 T Tt; 269 for (T::iterator It = Tt.begin(), E = Tt.end(); It != E; ++It) { 270 printf("I found %d\n", *It); 271 } 272 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 273 // CHECK-FIXES: for (int & It : Tt) 274 // CHECK-FIXES-NEXT: printf("I found %d\n", It); 275 276 // Do not crash because of Qq.begin() converting. Q::iterator converts with a 277 // conversion operator, which has no name, to Q::const_iterator. 278 Q Qq; 279 for (Q::const_iterator It = Qq.begin(), E = Qq.end(); It != E; ++It) { 280 printf("I found %d\n", *It); 281 } 282 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 283 // CHECK-FIXES: for (int & It : Qq) 284 // CHECK-FIXES-NEXT: printf("I found %d\n", It); 285 286 T *Pt; 287 for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) { 288 printf("I found %d\n", *It); 289 } 290 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 291 // CHECK-FIXES: for (int & It : *Pt) 292 // CHECK-FIXES-NEXT: printf("I found %d\n", It); 293 294 S Ss; 295 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { 296 printf("s has value %d\n", (*It).X); 297 } 298 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 299 // CHECK-FIXES: for (auto & It : Ss) 300 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); 301 302 S *Ps; 303 for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) { 304 printf("s has value %d\n", (*It).X); 305 } 306 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 307 // CHECK-FIXES: for (auto & P : *Ps) 308 // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X); 309 310 for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) { 311 printf("s has value %d\n", (*It).X); 312 } 313 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 314 // CHECK-FIXES: for (auto It : Ss) 315 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); 316 317 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { 318 printf("s has value %d\n", It->X); 319 } 320 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 321 // CHECK-FIXES: for (auto & It : Ss) 322 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); 323 324 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { 325 It->X = 3; 326 } 327 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 328 // CHECK-FIXES: for (auto & It : Ss) 329 // CHECK-FIXES-NEXT: It.X = 3; 330 331 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { 332 (*It).X = 3; 333 } 334 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 335 // CHECK-FIXES: for (auto & It : Ss) 336 // CHECK-FIXES-NEXT: It.X = 3; 337 338 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { 339 It->nonConstFun(4, 5); 340 } 341 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 342 // CHECK-FIXES: for (auto & It : Ss) 343 // CHECK-FIXES-NEXT: It.nonConstFun(4, 5); 344 345 U Uu; 346 for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) { 347 printf("s has value %d\n", It->X); 348 } 349 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 350 // CHECK-FIXES: for (auto & It : Uu) 351 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); 352 353 for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) { 354 printf("s has value %d\n", (*It).X); 355 } 356 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 357 // CHECK-FIXES: for (auto & It : Uu) 358 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); 359 360 for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) { 361 Val* a = It.operator->(); 362 } 363 364 U::iterator A; 365 for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I) 366 int K = A->X + I->X; 367 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 368 // CHECK-FIXES: for (auto & I : Uu) 369 // CHECK-FIXES-NEXT: int K = A->X + I.X; 370 371 dependent<int> V; 372 for (dependent<int>::iterator It = V.begin(), E = V.end(); 373 It != E; ++It) { 374 printf("Fibonacci number is %d\n", *It); 375 } 376 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 377 // CHECK-FIXES: for (int & It : V) 378 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It); 379 380 for (dependent<int>::iterator It(V.begin()), E = V.end(); 381 It != E; ++It) { 382 printf("Fibonacci number is %d\n", *It); 383 } 384 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 385 // CHECK-FIXES: for (int & It : V) 386 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It); 387 388 doublyDependent<int, int> Intmap; 389 for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end(); 390 It != E; ++It) { 391 printf("Intmap[%d] = %d", It->first, It->second); 392 } 393 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 394 // CHECK-FIXES: for (auto & It : Intmap) 395 // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second); 396 397 // PtrSet's iterator dereferences by value so auto & can't be used. 398 { 399 PtrSet<int *> Val_int_ptrs; 400 for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(), 401 E = Val_int_ptrs.end(); 402 I != E; ++I) { 403 (void) *I; 404 } 405 // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead 406 // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs) 407 } 408 409 // This container uses an iterator where the dereference type is a typedef of 410 // a reference type. Make sure non-const auto & is still used. A failure here 411 // means canonical types aren't being tested. 412 { 413 TypedefDerefContainer<int> Int_ptrs; 414 for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(), 415 E = Int_ptrs.end(); 416 I != E; ++I) { 417 (void) *I; 418 } 419 // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead 420 // CHECK-FIXES: for (int & Int_ptr : Int_ptrs) 421 } 422 423 { 424 // Iterators returning an rvalue reference should disqualify the loop from 425 // transformation. 426 RValueDerefContainer<int> Container; 427 for (RValueDerefContainer<int>::iterator I = Container.begin(), 428 E = Container.end(); 429 I != E; ++I) { 430 (void) *I; 431 } 432 } 433 434 dependent<Val *> Dpp; 435 for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) { 436 printf("%d\n", (**I).X); 437 } 438 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 439 // CHECK-FIXES: for (auto & I : Dpp) 440 // CHECK-FIXES-NEXT: printf("%d\n", (*I).X); 441 442 for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) { 443 printf("%d\n", (*I)->X); 444 } 445 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 446 // CHECK-FIXES: for (auto & I : Dpp) 447 // CHECK-FIXES-NEXT: printf("%d\n", I->X); 448 } 449 450 // Tests to verify the proper use of auto where the init variable type and the 451 // initializer type differ or are mostly the same except for const qualifiers. 452 void different_type() { 453 // Ss.begin() returns a type 'iterator' which is just a non-const pointer and 454 // differs from const_iterator only on the const qualification. 455 S Ss; 456 for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { 457 printf("s has value %d\n", (*It).X); 458 } 459 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 460 // CHECK-FIXES: for (auto It : Ss) 461 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); 462 463 S *Ps; 464 for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) { 465 printf("s has value %d\n", (*It).X); 466 } 467 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 468 // CHECK-FIXES: for (auto P : *Ps) 469 // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X); 470 471 dependent<int> V; 472 for (dependent<int>::const_iterator It = V.begin(), E = V.end(); 473 It != E; ++It) { 474 printf("Fibonacci number is %d\n", *It); 475 } 476 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 477 // CHECK-FIXES: for (int It : V) 478 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It); 479 480 for (dependent<int>::const_iterator It(V.begin()), E = V.end(); 481 It != E; ++It) { 482 printf("Fibonacci number is %d\n", *It); 483 } 484 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 485 // CHECK-FIXES: for (int It : V) 486 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It); 487 } 488 489 // Tests to ensure that an implicit 'this' is picked up as the container. 490 // If member calls are made to 'this' within the loop, the transform becomes 491 // risky as these calls may affect state that affects the loop. 492 class C { 493 public: 494 typedef MutableVal *iterator; 495 typedef const MutableVal *const_iterator; 496 497 iterator begin(); 498 iterator end(); 499 const_iterator begin() const; 500 const_iterator end() const; 501 502 void doSomething(); 503 void doSomething() const; 504 505 void doLoop() { 506 for (iterator I = begin(), E = end(); I != E; ++I) 507 (void) *I; 508 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead 509 // CHECK-FIXES: for (auto & I : *this) 510 511 for (iterator I = C::begin(), E = C::end(); I != E; ++I) 512 (void) *I; 513 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead 514 // CHECK-FIXES: for (auto & I : *this) 515 516 for (iterator I = begin(), E = end(); I != E; ++I) { 517 (void) *I; 518 doSomething(); 519 } 520 521 for (iterator I = begin(); I != end(); ++I) 522 (void) *I; 523 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead 524 // CHECK-FIXES: for (auto & I : *this) 525 526 for (iterator I = begin(); I != end(); ++I) { 527 (void) *I; 528 doSomething(); 529 } 530 } 531 532 void doLoop() const { 533 for (const_iterator I = begin(), E = end(); I != E; ++I) 534 (void) *I; 535 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead 536 // CHECK-FIXES: for (auto I : *this) 537 538 for (const_iterator I = C::begin(), E = C::end(); I != E; ++I) 539 (void) *I; 540 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead 541 // CHECK-FIXES: for (auto I : *this) 542 543 for (const_iterator I = begin(), E = end(); I != E; ++I) { 544 (void) *I; 545 doSomething(); 546 } 547 } 548 }; 549 550 class C2 { 551 public: 552 typedef MutableVal *iterator; 553 554 iterator begin() const; 555 iterator end() const; 556 557 void doLoop() { 558 // The implicit 'this' will have an Implicit cast to const C2* wrapped 559 // around it. Make sure the replacement still happens. 560 for (iterator I = begin(), E = end(); I != E; ++I) 561 (void) *I; 562 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead 563 // CHECK-FIXES: for (auto & I : *this) 564 } 565 }; 566 567 } // namespace Iterator 568 569 namespace PseudoArray { 570 571 const int N = 6; 572 dependent<int> V; 573 dependent<int> *Pv; 574 const dependent<NonTriviallyCopyable> Constv; 575 const dependent<NonTriviallyCopyable> *Pconstv; 576 577 transparent<dependent<int>> Cv; 578 dependent_derived<int> VD; 579 580 void f() { 581 int Sum = 0; 582 for (int I = 0, E = V.size(); I < E; ++I) { 583 printf("Fibonacci number is %d\n", V[I]); 584 Sum += V[I] + 2; 585 } 586 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 587 // CHECK-FIXES: for (int I : V) 588 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); 589 // CHECK-FIXES-NEXT: Sum += I + 2; 590 591 for (int I = 0, E = V.size(); I < E; ++I) { 592 printf("Fibonacci number is %d\n", V.at(I)); 593 Sum += V.at(I) + 2; 594 } 595 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 596 // CHECK-FIXES: for (int I : V) 597 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); 598 // CHECK-FIXES-NEXT: Sum += I + 2; 599 600 for (int I = 0, E = Pv->size(); I < E; ++I) { 601 printf("Fibonacci number is %d\n", Pv->at(I)); 602 Sum += Pv->at(I) + 2; 603 } 604 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 605 // CHECK-FIXES: for (int I : *Pv) 606 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); 607 // CHECK-FIXES-NEXT: Sum += I + 2; 608 609 // This test will fail if size() isn't called repeatedly, since it 610 // returns unsigned int, and 0 is deduced to be signed int. 611 // FIXME: Insert the necessary explicit conversion, or write out the types 612 // explicitly. 613 for (int I = 0; I < Pv->size(); ++I) { 614 printf("Fibonacci number is %d\n", (*Pv).at(I)); 615 Sum += (*Pv)[I] + 2; 616 } 617 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 618 // CHECK-FIXES: for (int I : *Pv) 619 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); 620 // CHECK-FIXES-NEXT: Sum += I + 2; 621 622 for (int I = 0; I < Cv->size(); ++I) { 623 printf("Fibonacci number is %d\n", Cv->at(I)); 624 Sum += Cv->at(I) + 2; 625 } 626 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 627 // CHECK-FIXES: for (int I : *Cv) 628 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); 629 // CHECK-FIXES-NEXT: Sum += I + 2; 630 631 for (int I = 0, E = V.size(); E > I; ++I) { 632 printf("Fibonacci number is %d\n", V[I]); 633 Sum += V[I] + 2; 634 } 635 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 636 // CHECK-FIXES: for (int I : V) 637 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); 638 // CHECK-FIXES-NEXT: Sum += I + 2; 639 640 for (int I = 0, E = V.size(); I != E; ++I) { 641 printf("Fibonacci number is %d\n", V[I]); 642 Sum += V[I] + 2; 643 } 644 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 645 // CHECK-FIXES: for (int I : V) 646 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); 647 // CHECK-FIXES-NEXT: Sum += I + 2; 648 649 for (int I = 0, E = V.size(); E != I; ++I) { 650 printf("Fibonacci number is %d\n", V[I]); 651 Sum += V[I] + 2; 652 } 653 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 654 // CHECK-FIXES: for (int I : V) 655 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); 656 // CHECK-FIXES-NEXT: Sum += I + 2; 657 658 for (int I = 0, E = VD.size(); E != I; ++I) { 659 printf("Fibonacci number is %d\n", VD[I]); 660 Sum += VD[I] + 2; 661 } 662 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 663 // CHECK-FIXES: for (int I : VD) 664 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); 665 // CHECK-FIXES-NEXT: Sum += I + 2; 666 } 667 668 // Ensure that 'const auto &' is used with containers of non-trivial types. 669 void constness() { 670 int Sum = 0; 671 for (int I = 0, E = Constv.size(); I < E; ++I) { 672 printf("Fibonacci number is %d\n", Constv[I].X); 673 Sum += Constv[I].X + 2; 674 } 675 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 676 // CHECK-FIXES: for (const auto & I : Constv) 677 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X); 678 // CHECK-FIXES-NEXT: Sum += I.X + 2; 679 680 for (int I = 0, E = Constv.size(); I < E; ++I) { 681 printf("Fibonacci number is %d\n", Constv.at(I).X); 682 Sum += Constv.at(I).X + 2; 683 } 684 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 685 // CHECK-FIXES: for (const auto & I : Constv) 686 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X); 687 // CHECK-FIXES-NEXT: Sum += I.X + 2; 688 689 for (int I = 0, E = Pconstv->size(); I < E; ++I) { 690 printf("Fibonacci number is %d\n", Pconstv->at(I).X); 691 Sum += Pconstv->at(I).X + 2; 692 } 693 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 694 // CHECK-FIXES: for (const auto & I : *Pconstv) 695 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X); 696 // CHECK-FIXES-NEXT: Sum += I.X + 2; 697 698 // This test will fail if size() isn't called repeatedly, since it 699 // returns unsigned int, and 0 is deduced to be signed int. 700 // FIXME: Insert the necessary explicit conversion, or write out the types 701 // explicitly. 702 for (int I = 0; I < Pconstv->size(); ++I) { 703 printf("Fibonacci number is %d\n", (*Pconstv).at(I).X); 704 Sum += (*Pconstv)[I].X + 2; 705 } 706 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 707 // CHECK-FIXES: for (const auto & I : *Pconstv) 708 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X); 709 // CHECK-FIXES-NEXT: Sum += I.X + 2; 710 } 711 712 void constRef(const dependent<int>& ConstVRef) { 713 int sum = 0; 714 // FIXME: This does not work with size_t (probably due to the implementation 715 // of dependent); make dependent work exactly like a std container type. 716 for (int I = 0; I < ConstVRef.size(); ++I) { 717 sum += ConstVRef[I]; 718 } 719 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 720 // CHECK-FIXES: for (int I : ConstVRef) 721 // CHECK-FIXES-NEXT: sum += I; 722 723 for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) { 724 sum += *I; 725 } 726 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 727 // CHECK-FIXES: for (int I : ConstVRef) 728 // CHECK-FIXES-NEXT: sum += I; 729 } 730 731 // Check for loops that don't mention containers. 732 void noContainer() { 733 for (auto I = 0; I < V.size(); ++I) { 734 } 735 736 for (auto I = 0; I < V.size(); ++I) 737 ; 738 } 739 740 struct NoBeginEnd { 741 unsigned size() const; 742 unsigned& operator[](int); 743 const unsigned& operator[](int) const; 744 }; 745 746 struct NoConstBeginEnd { 747 NoConstBeginEnd(); 748 unsigned size() const; 749 unsigned* begin(); 750 unsigned* end(); 751 unsigned& operator[](int); 752 const unsigned& operator[](int) const; 753 }; 754 755 struct ConstBeginEnd { 756 ConstBeginEnd(); 757 unsigned size() const; 758 unsigned* begin() const; 759 unsigned* end() const; 760 unsigned& operator[](int); 761 const unsigned& operator[](int) const; 762 }; 763 764 // Shouldn't transform pseudo-array uses if the container doesn't provide 765 // begin() and end() of the right const-ness. 766 void NoBeginEndTest() { 767 NoBeginEnd NBE; 768 for (unsigned I = 0, E = NBE.size(); I < E; ++I) 769 printf("%d\n", NBE[I]); 770 771 const NoConstBeginEnd Const_NCBE; 772 for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I) 773 printf("%d\n", Const_NCBE[I]); 774 775 ConstBeginEnd CBE; 776 for (unsigned I = 0, E = CBE.size(); I < E; ++I) 777 printf("%d\n", CBE[I]); 778 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 779 // CHECK-FIXES: for (unsigned int I : CBE) 780 // CHECK-FIXES-NEXT: printf("%d\n", I); 781 782 const ConstBeginEnd Const_CBE; 783 for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I) 784 printf("%d\n", Const_CBE[I]); 785 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 786 // CHECK-FIXES: for (unsigned int I : Const_CBE) 787 // CHECK-FIXES-NEXT: printf("%d\n", I); 788 } 789 790 struct DerefByValue { 791 DerefByValue(); 792 struct iter { unsigned operator*(); }; 793 unsigned size() const; 794 iter begin(); 795 iter end(); 796 unsigned operator[](int); 797 }; 798 799 void derefByValueTest() { 800 DerefByValue DBV; 801 for (unsigned I = 0, E = DBV.size(); I < E; ++I) { 802 printf("%d\n", DBV[I]); 803 } 804 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead 805 // CHECK-FIXES: for (unsigned int I : DBV) 806 // CHECK-FIXES-NEXT: printf("%d\n", I); 807 808 for (unsigned I = 0, E = DBV.size(); I < E; ++I) { 809 auto f = [DBV, I]() {}; 810 printf("%d\n", DBV[I]); 811 } 812 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead 813 // CHECK-FIXES: for (unsigned int I : DBV) 814 // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {}; 815 // CHECK-FIXES-NEXT: printf("%d\n", I); 816 } 817 818 void fundamentalTypesTest() { 819 const int N = 10; 820 bool Bools[N]; 821 for (int i = 0; i < N; ++i) 822 printf("%d", Bools[i]); 823 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 824 // CHECK-FIXES: for (bool Bool : Bools) 825 826 int Ints[N]; 827 unsigned short int Shorts[N]; 828 for (int i = 0; i < N; ++i) 829 printf("%d", Shorts[i]); 830 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 831 // CHECK-FIXES: for (unsigned short Short : Shorts) 832 833 signed long Longs[N]; 834 for (int i = 0; i < N; ++i) 835 printf("%d", Longs[i]); 836 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 837 // CHECK-FIXES: for (long Long : Longs) 838 839 long long int LongLongs[N]; 840 for (int i = 0; i < N; ++i) 841 printf("%d", LongLongs[i]); 842 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 843 // CHECK-FIXES: for (long long LongLong : LongLongs) 844 845 char Chars[N]; 846 for (int i = 0; i < N; ++i) 847 printf("%d", Chars[i]); 848 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 849 // CHECK-FIXES: for (char Char : Chars) 850 851 wchar_t WChars[N]; 852 for (int i = 0; i < N; ++i) 853 printf("%d", WChars[i]); 854 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 855 // CHECK-FIXES: for (wchar_t WChar : WChars) 856 857 float Floats[N]; 858 for (int i = 0; i < N; ++i) 859 printf("%d", Floats[i]); 860 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 861 // CHECK-FIXES: for (float Float : Floats) 862 863 double Doubles[N]; 864 for (int i = 0; i < N; ++i) 865 printf("%d", Doubles[i]); 866 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead 867 // CHECK-FIXES: for (double Double : Doubles) 868 } 869 870 } // namespace PseudoArray 871