1012 lines · cpp
1// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -I %S/Inputs/loop-convert2 3#include "structures.h"4 5namespace Array {6 7const int N = 6;8const int NMinusOne = N - 1;9int Arr[N] = {1, 2, 3, 4, 5, 6};10const int ConstArr[N] = {1, 2, 3, 4, 5, 6};11int (*PArr)[N] = &Arr;12 13void 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 instead30 // 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 instead39 // 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 instead48 // 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 instead56 // 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 instead64 // 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 instead72 // 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 instead79 // 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 instead87 // 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 int Matrix[N][12];92 unsigned size = 0;93 for (int I = 0; I < N; ++I) {94 size += sizeof(Matrix[I]);95 size += sizeof Matrix[I];96 size += sizeof((Matrix[I]));97 }98 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead99 // CHECK-FIXES: for (auto & I : Matrix) {100 // CHECK-FIXES-NEXT: size += sizeof(I);101 // CHECK-FIXES-NEXT: size += sizeof I;102 // CHECK-FIXES-NEXT: size += sizeof(I);103 104 Val Teas[N];105 for (int I = 0; I < N; ++I) {106 Teas[I].g();107 }108 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead109 // CHECK-FIXES: for (auto & Tea : Teas) {110 // CHECK-FIXES-NEXT: Tea.g();111 112 for (int I = 0; N > I; ++I) {113 printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);114 Sum += Arr[I] + 2;115 }116 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead117 // CHECK-FIXES: for (int & I : Arr) {118 // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);119 // CHECK-FIXES-NEXT: Sum += I + 2;120 121 for (int I = 0; N != I; ++I) {122 printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);123 Sum += Arr[I] + 2;124 }125 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead126 // CHECK-FIXES: for (int & I : Arr) {127 // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);128 // CHECK-FIXES-NEXT: Sum += I + 2;129 130 for (int I = 0; I != N; ++I) {131 printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);132 Sum += Arr[I] + 2;133 }134 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead135 // CHECK-FIXES: for (int & I : Arr) {136 // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);137 // CHECK-FIXES-NEXT: Sum += I + 2;138}139 140const int *constArray() {141 for (int I = 0; I < N; ++I) {142 printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);143 }144 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead145 // CHECK-FIXES: for (int I : ConstArr) {146 // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I, I + I);147 148 const NonTriviallyCopyable NonCopy[N]{};149 for (int I = 0; I < N; ++I) {150 printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);151 }152 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead153 // CHECK-FIXES: for (const auto & I : NonCopy) {154 // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);155 156 const TriviallyCopyableButBig Big[N]{};157 for (int I = 0; I < N; ++I) {158 printf("2 * %d = %d\n", Big[I].X, Big[I].X + Big[I].X);159 }160 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead161 // CHECK-FIXES: for (const auto & I : Big) {162 // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);163 164 bool Something = false;165 for (int I = 0; I < N; ++I) {166 if (Something)167 return &ConstArr[I];168 }169 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead170 // CHECK-FIXES: for (const int & I : ConstArr) {171 // CHECK-FIXES-NEXT: if (Something)172 // CHECK-FIXES-NEXT: return &I;173 174 return nullptr;175}176 177struct HasArr {178 int Arr[N];179 Val ValArr[N];180 void implicitThis() {181 for (int I = 0; I < N; ++I) {182 printf("%d", Arr[I]);183 }184 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead185 // CHECK-FIXES: for (int I : Arr) {186 // CHECK-FIXES-NEXT: printf("%d", I);187 188 for (int I = 0; I < N; ++I) {189 printf("%d", ValArr[I].X);190 }191 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead192 // CHECK-FIXES: for (auto & I : ValArr) {193 // CHECK-FIXES-NEXT: printf("%d", I.X);194 }195 196 void explicitThis() {197 for (int I = 0; I < N; ++I) {198 printf("%d", this->Arr[I]);199 }200 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead201 // CHECK-FIXES: for (int I : this->Arr) {202 // CHECK-FIXES-NEXT: printf("%d", I);203 204 for (int I = 0; I < N; ++I) {205 printf("%d", this->ValArr[I].X);206 }207 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead208 // CHECK-FIXES: for (auto & I : this->ValArr) {209 // CHECK-FIXES-NEXT: printf("%d", I.X);210 }211};212 213struct HasIndirectArr {214 HasArr HA;215 void implicitThis() {216 for (int I = 0; I < N; ++I) {217 printf("%d", HA.Arr[I]);218 }219 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead220 // CHECK-FIXES: for (int I : HA.Arr) {221 // CHECK-FIXES-NEXT: printf("%d", I);222 223 for (int I = 0; I < N; ++I) {224 printf("%d", HA.ValArr[I].X);225 }226 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead227 // CHECK-FIXES: for (auto & I : HA.ValArr) {228 // CHECK-FIXES-NEXT: printf("%d", I.X);229 }230 231 void explicitThis() {232 for (int I = 0; I < N; ++I) {233 printf("%d", this->HA.Arr[I]);234 }235 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead236 // CHECK-FIXES: for (int I : this->HA.Arr) {237 // CHECK-FIXES-NEXT: printf("%d", I);238 239 for (int I = 0; I < N; ++I) {240 printf("%d", this->HA.ValArr[I].X);241 }242 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead243 // CHECK-FIXES: for (auto & I : this->HA.ValArr) {244 // CHECK-FIXES-NEXT: printf("%d", I.X);245 }246};247 248// Loops whose bounds are value-dependent should not be converted.249template <int N>250void dependentExprBound() {251 for (int I = 0; I < N; ++I)252 Arr[I] = 0;253}254template void dependentExprBound<20>();255 256void memberFunctionPointer() {257 Val V;258 void (Val::*mfpArr[N])(void) = {&Val::g};259 for (int I = 0; I < N; ++I)260 (V.*mfpArr[I])();261 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead262 // CHECK-FIXES: for (auto & I : mfpArr)263 // CHECK-FIXES-NEXT: (V.*I)();264 265 struct Foo {266 int (Val::*f)();267 } Foo[N];268 269 for (int I = 0; I < N; ++I)270 int R = (V.*(Foo[I].f))();271 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead272 // CHECK-FIXES: for (auto & I : Foo)273 // CHECK-FIXES-NEXT: int R = (V.*(I.f))();274 275}276 277} // namespace Array278 279namespace Iterator {280 281void f() {282 /// begin()/end() - based for loops here:283 T Tt;284 for (T::iterator It = Tt.begin(), E = Tt.end(); It != E; ++It) {285 printf("I found %d\n", *It);286 }287 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead288 // CHECK-FIXES: for (int & It : Tt) {289 // CHECK-FIXES-NEXT: printf("I found %d\n", It);290 291 // Do not crash because of Qq.begin() converting. Q::iterator converts with a292 // conversion operator, which has no name, to Q::const_iterator.293 Q Qq;294 for (Q::const_iterator It = Qq.begin(), E = Qq.end(); It != E; ++It) {295 printf("I found %d\n", *It);296 }297 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead298 // CHECK-FIXES: for (int & It : Qq) {299 // CHECK-FIXES-NEXT: printf("I found %d\n", It);300 301 T *Pt;302 for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {303 printf("I found %d\n", *It);304 }305 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead306 // CHECK-FIXES: for (int & It : *Pt) {307 // CHECK-FIXES-NEXT: printf("I found %d\n", It);308 309 S Ss;310 for (S::iterator It = Ss.begin(), E = Ss.end(); 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 instead314 // CHECK-FIXES: for (auto & It : Ss) {315 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);316 317 S *Ps;318 for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {319 printf("s has value %d\n", (*It).X);320 }321 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead322 // CHECK-FIXES: for (auto & P : *Ps) {323 // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);324 325 for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {326 printf("s has value %d\n", (*It).X);327 }328 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead329 // CHECK-FIXES: for (auto It : Ss) {330 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);331 332 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {333 printf("s has value %d\n", It->X);334 }335 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead336 // CHECK-FIXES: for (auto & It : Ss) {337 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);338 339 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {340 It->X = 3;341 }342 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead343 // CHECK-FIXES: for (auto & It : Ss) {344 // CHECK-FIXES-NEXT: It.X = 3;345 346 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {347 (*It).X = 3;348 }349 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead350 // CHECK-FIXES: for (auto & It : Ss) {351 // CHECK-FIXES-NEXT: It.X = 3;352 353 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {354 It->nonConstFun(4, 5);355 }356 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead357 // CHECK-FIXES: for (auto & It : Ss) {358 // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);359 360 U Uu;361 for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {362 printf("s has value %d\n", It->X);363 }364 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead365 // CHECK-FIXES: for (auto & It : Uu) {366 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);367 368 for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {369 printf("s has value %d\n", (*It).X);370 }371 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead372 // CHECK-FIXES: for (auto & It : Uu) {373 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);374 375 for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {376 Val* a = It.operator->();377 }378 379 U::iterator A;380 for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I)381 int K = A->X + I->X;382 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead383 // CHECK-FIXES: for (auto & I : Uu)384 // CHECK-FIXES-NEXT: int K = A->X + I.X;385 386 dependent<int> V;387 for (dependent<int>::iterator It = V.begin(), E = V.end();388 It != E; ++It) {389 printf("Fibonacci number is %d\n", *It);390 }391 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead392 // CHECK-FIXES: for (int & It : V) {393 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);394 395 for (dependent<int>::iterator It(V.begin()), E = V.end();396 It != E; ++It) {397 printf("Fibonacci number is %d\n", *It);398 }399 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead400 // CHECK-FIXES: for (int & It : V) {401 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);402 403 doublyDependent<int, int> Intmap;404 for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end();405 It != E; ++It) {406 printf("Intmap[%d] = %d", It->first, It->second);407 }408 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead409 // CHECK-FIXES: for (auto & It : Intmap) {410 // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second);411 412 // PtrSet's iterator dereferences by value so auto & can't be used.413 {414 PtrSet<int *> Val_int_ptrs;415 for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(),416 E = Val_int_ptrs.end();417 I != E; ++I) {418 (void) *I;419 }420 // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead421 // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs) {422 }423 424 // This container uses an iterator where the dereference type is a typedef of425 // a reference type. Make sure non-const auto & is still used. A failure here426 // means canonical types aren't being tested.427 {428 TypedefDerefContainer<int> Int_ptrs;429 for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(),430 E = Int_ptrs.end();431 I != E; ++I) {432 (void) *I;433 }434 // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead435 // CHECK-FIXES: for (int & Int_ptr : Int_ptrs) {436 }437 438 {439 // Iterators returning an rvalue reference should disqualify the loop from440 // transformation.441 RValueDerefContainer<int> Container;442 for (RValueDerefContainer<int>::iterator I = Container.begin(),443 E = Container.end();444 I != E; ++I) {445 (void) *I;446 }447 }448 449 dependent<Val *> Dpp;450 for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {451 printf("%d\n", (**I).X);452 }453 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead454 // CHECK-FIXES: for (auto & I : Dpp) {455 // CHECK-FIXES-NEXT: printf("%d\n", (*I).X);456 457 for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {458 printf("%d\n", (*I)->X);459 }460 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead461 // CHECK-FIXES: for (auto & I : Dpp) {462 // CHECK-FIXES-NEXT: printf("%d\n", I->X);463 464 for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {465 printf("s0 has value %d\n", (*It).X);466 }467 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead468 // CHECK-FIXES: for (auto & It : Ss) {469 // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);470 471 for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {472 printf("s1 has value %d\n", (*It).X);473 }474 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead475 // CHECK-FIXES: for (auto & It : Ss) {476 // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);477 478 for (S::iterator It = begin(*Ps), E = end(*Ps); It != E; ++It) {479 printf("s2 has value %d\n", (*It).X);480 }481 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead482 // CHECK-FIXES: for (auto & It : *Ps) {483 // CHECK-FIXES-NEXT: printf("s2 has value %d\n", It.X);484 485 for (S::iterator It = begin(*Ps); It != end(*Ps); ++It) {486 printf("s3 has value %d\n", (*It).X);487 }488 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead489 // CHECK-FIXES: for (auto & It : *Ps) {490 // CHECK-FIXES-NEXT: printf("s3 has value %d\n", It.X);491 492 for (S::const_iterator It = cbegin(Ss), E = cend(Ss); It != E; ++It) {493 printf("s4 has value %d\n", (*It).X);494 }495 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead496 // CHECK-FIXES: for (auto It : Ss) {497 // CHECK-FIXES-NEXT: printf("s4 has value %d\n", It.X);498}499 500// Tests to verify the proper use of auto where the init variable type and the501// initializer type differ or are mostly the same except for const qualifiers.502void different_type() {503 // Ss.begin() returns a type 'iterator' which is just a non-const pointer and504 // differs from const_iterator only on the const qualification.505 S Ss;506 for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {507 printf("s has value %d\n", (*It).X);508 }509 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead510 // CHECK-FIXES: for (auto It : Ss) {511 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);512 513 S *Ps;514 for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {515 printf("s has value %d\n", (*It).X);516 }517 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead518 // CHECK-FIXES: for (auto P : *Ps) {519 // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);520 521 dependent<int> V;522 for (dependent<int>::const_iterator It = V.begin(), E = V.end();523 It != E; ++It) {524 printf("Fibonacci number is %d\n", *It);525 }526 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead527 // CHECK-FIXES: for (int It : V) {528 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);529 530 for (dependent<int>::const_iterator It(V.begin()), E = V.end();531 It != E; ++It) {532 printf("Fibonacci number is %d\n", *It);533 }534 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead535 // CHECK-FIXES: for (int It : V) {536 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);537}538 539// Tests to ensure that an implicit 'this' is picked up as the container.540// If member calls are made to 'this' within the loop, the transform becomes541// risky as these calls may affect state that affects the loop.542class C {543public:544 typedef MutableVal *iterator;545 typedef const MutableVal *const_iterator;546 547 iterator begin();548 iterator end();549 const_iterator begin() const;550 const_iterator end() const;551 552 void doSomething();553 void doSomething() const;554 555 void doLoop() {556 for (iterator I = begin(), E = end(); I != E; ++I)557 (void) *I;558 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead559 // CHECK-FIXES: for (auto & I : *this)560 561 for (iterator I = C::begin(), E = C::end(); I != E; ++I)562 (void) *I;563 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead564 // CHECK-FIXES: for (auto & I : *this)565 566 for (iterator I = begin(), E = end(); I != E; ++I) {567 (void) *I;568 doSomething();569 }570 571 for (iterator I = begin(); I != end(); ++I)572 (void) *I;573 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead574 // CHECK-FIXES: for (auto & I : *this)575 576 for (iterator I = begin(); I != end(); ++I) {577 (void) *I;578 doSomething();579 }580 }581 582 void doLoop() const {583 for (const_iterator I = begin(), E = end(); I != E; ++I)584 (void) *I;585 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead586 // CHECK-FIXES: for (auto I : *this)587 588 for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)589 (void) *I;590 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead591 // CHECK-FIXES: for (auto I : *this)592 593 for (const_iterator I = begin(), E = end(); I != E; ++I) {594 (void) *I;595 doSomething();596 }597 }598};599 600class C2 {601public:602 typedef MutableVal *iterator;603 604 iterator begin() const;605 iterator end() const;606 607 void doLoop() {608 // The implicit 'this' will have an Implicit cast to const C2* wrapped609 // around it. Make sure the replacement still happens.610 for (iterator I = begin(), E = end(); I != E; ++I)611 (void) *I;612 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead613 // CHECK-FIXES: for (auto & I : *this)614 }615};616 617} // namespace Iterator618 619namespace PseudoArray {620 621const int N = 6;622dependent<int> V;623dependent<int> *Pv;624const dependent<NonTriviallyCopyable> Constv;625const dependent<NonTriviallyCopyable> *Pconstv;626 627transparent<dependent<int>> Cv;628dependent_derived<int> VD;629 630void f() {631 int Sum = 0;632 for (int I = 0, E = V.size(); I < E; ++I) {633 printf("Fibonacci number is %d\n", V[I]);634 Sum += V[I] + 2;635 }636 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead637 // CHECK-FIXES: for (int I : V) {638 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);639 // CHECK-FIXES-NEXT: Sum += I + 2;640 641 for (int I = 0, E = V.size(); I < E; ++I) {642 printf("Fibonacci number is %d\n", V.at(I));643 Sum += V.at(I) + 2;644 }645 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead646 // CHECK-FIXES: for (int I : V) {647 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);648 // CHECK-FIXES-NEXT: Sum += I + 2;649 650 for (int I = 0, E = Pv->size(); I < E; ++I) {651 printf("Fibonacci number is %d\n", Pv->at(I));652 Sum += Pv->at(I) + 2;653 }654 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead655 // CHECK-FIXES: for (int I : *Pv) {656 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);657 // CHECK-FIXES-NEXT: Sum += I + 2;658 659 // This test will fail if size() isn't called repeatedly, since it660 // returns unsigned int, and 0 is deduced to be signed int.661 // FIXME: Insert the necessary explicit conversion, or write out the types662 // explicitly.663 for (int I = 0; I < Pv->size(); ++I) {664 printf("Fibonacci number is %d\n", (*Pv).at(I));665 Sum += (*Pv)[I] + 2;666 }667 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead668 // CHECK-FIXES: for (int I : *Pv) {669 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);670 // CHECK-FIXES-NEXT: Sum += I + 2;671 672 for (int I = 0; I < Cv->size(); ++I) {673 printf("Fibonacci number is %d\n", Cv->at(I));674 Sum += Cv->at(I) + 2;675 }676 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead677 // CHECK-FIXES: for (int I : *Cv) {678 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);679 // CHECK-FIXES-NEXT: Sum += I + 2;680 681 for (int I = 0, E = V.size(); E > I; ++I) {682 printf("Fibonacci number is %d\n", V[I]);683 Sum += V[I] + 2;684 }685 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead686 // CHECK-FIXES: for (int I : V) {687 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);688 // CHECK-FIXES-NEXT: Sum += I + 2;689 690 for (int I = 0, E = V.size(); I != E; ++I) {691 printf("Fibonacci number is %d\n", V[I]);692 Sum += V[I] + 2;693 }694 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead695 // CHECK-FIXES: for (int I : V) {696 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);697 // CHECK-FIXES-NEXT: Sum += I + 2;698 699 for (int I = 0, E = V.size(); E != I; ++I) {700 printf("Fibonacci number is %d\n", V[I]);701 Sum += V[I] + 2;702 }703 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead704 // CHECK-FIXES: for (int I : V) {705 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);706 // CHECK-FIXES-NEXT: Sum += I + 2;707 708 for (int I = 0, E = VD.size(); E != I; ++I) {709 printf("Fibonacci number is %d\n", VD[I]);710 Sum += VD[I] + 2;711 }712 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead713 // CHECK-FIXES: for (int I : VD) {714 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);715 // CHECK-FIXES-NEXT: Sum += I + 2;716 717 for (int I = 0, E = size(V); E != I; ++I) {718 printf("Fibonacci number is %d\n", V[I]);719 Sum += V[I] + 2;720 }721 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead722 // CHECK-FIXES: for (int I : V) {723 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);724 // CHECK-FIXES-NEXT: Sum += I + 2;725 726 for (int I = 0, E = size(V); E != I; ++I) {727 V[I] = 0;728 }729 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead730 // CHECK-FIXES: for (int & I : V) {731 // CHECK-FIXES-NEXT: I = 0;732 733 for (int I = 0, E = std::size(V); E != I; ++I) {734 V[I] = 0;735 }736 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead737 // CHECK-FIXES: for (int & I : V) {738 // CHECK-FIXES-NEXT: I = 0;739 740 // Although 'length' might be a valid free function, only size() is standardized741 for (int I = 0, E = length(V); E != I; ++I) {742 printf("Fibonacci number is %d\n", V[I]);743 Sum += V[I] + 2;744 }745 746 dependent<Val> Vals;747 for (int I = 0, E = size(Vals); E != I; ++I) {748 Sum += Vals[I].X;749 }750 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead751 // CHECK-FIXES: for (auto & Val : Vals) {752 // CHECK-FIXES-NEXT: Sum += Val.X;753}754 755// Ensure that 'const auto &' is used with containers of non-trivial types.756void constness() {757 int Sum = 0;758 for (int I = 0, E = Constv.size(); I < E; ++I) {759 printf("Fibonacci number is %d\n", Constv[I].X);760 Sum += Constv[I].X + 2;761 }762 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead763 // CHECK-FIXES: for (const auto & I : Constv) {764 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);765 // CHECK-FIXES-NEXT: Sum += I.X + 2;766 767 for (int I = 0, E = Constv.size(); I < E; ++I) {768 printf("Fibonacci number is %d\n", Constv.at(I).X);769 Sum += Constv.at(I).X + 2;770 }771 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead772 // CHECK-FIXES: for (const auto & I : Constv) {773 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);774 // CHECK-FIXES-NEXT: Sum += I.X + 2;775 776 for (int I = 0, E = Pconstv->size(); I < E; ++I) {777 printf("Fibonacci number is %d\n", Pconstv->at(I).X);778 Sum += Pconstv->at(I).X + 2;779 }780 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead781 // CHECK-FIXES: for (const auto & I : *Pconstv) {782 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);783 // CHECK-FIXES-NEXT: Sum += I.X + 2;784 785 // This test will fail if size() isn't called repeatedly, since it786 // returns unsigned int, and 0 is deduced to be signed int.787 // FIXME: Insert the necessary explicit conversion, or write out the types788 // explicitly.789 for (int I = 0; I < Pconstv->size(); ++I) {790 printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);791 Sum += (*Pconstv)[I].X + 2;792 }793 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead794 // CHECK-FIXES: for (const auto & I : *Pconstv) {795 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);796 // CHECK-FIXES-NEXT: Sum += I.X + 2;797}798 799void constRef(const dependent<int>& ConstVRef) {800 int sum = 0;801 // FIXME: This does not work with size_t (probably due to the implementation802 // of dependent); make dependent work exactly like a std container type.803 for (int I = 0; I < ConstVRef.size(); ++I) {804 sum += ConstVRef[I];805 }806 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead807 // CHECK-FIXES: for (int I : ConstVRef) {808 // CHECK-FIXES-NEXT: sum += I;809 810 for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {811 sum += *I;812 }813 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead814 // CHECK-FIXES: for (int I : ConstVRef) {815 // CHECK-FIXES-NEXT: sum += I;816}817 818// Check for loops that don't mention containers.819void noContainer() {820 for (auto I = 0; I < V.size(); ++I) {821 }822 823 for (auto I = 0; I < V.size(); ++I)824 ;825}826 827struct NoBeginEnd {828 unsigned size() const;829 unsigned& operator[](int);830 const unsigned& operator[](int) const;831};832 833struct NoConstBeginEnd {834 NoConstBeginEnd();835 unsigned size() const;836 unsigned* begin();837 unsigned* end();838 unsigned& operator[](int);839 const unsigned& operator[](int) const;840};841 842struct ConstBeginEnd {843 ConstBeginEnd();844 unsigned size() const;845 unsigned* begin() const;846 unsigned* end() const;847 unsigned& operator[](int);848 const unsigned& operator[](int) const;849};850 851// Shouldn't transform pseudo-array uses if the container doesn't provide852// begin() and end() of the right const-ness.853void NoBeginEndTest() {854 NoBeginEnd NBE;855 for (unsigned I = 0, E = NBE.size(); I < E; ++I)856 printf("%d\n", NBE[I]);857 858 const NoConstBeginEnd Const_NCBE;859 for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)860 printf("%d\n", Const_NCBE[I]);861 862 ConstBeginEnd CBE;863 for (unsigned I = 0, E = CBE.size(); I < E; ++I)864 printf("%d\n", CBE[I]);865 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead866 // CHECK-FIXES: for (unsigned int I : CBE)867 // CHECK-FIXES-NEXT: printf("%d\n", I);868 869 const ConstBeginEnd Const_CBE;870 for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)871 printf("%d\n", Const_CBE[I]);872 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead873 // CHECK-FIXES: for (unsigned int I : Const_CBE)874 // CHECK-FIXES-NEXT: printf("%d\n", I);875}876 877struct DerefByValue {878 DerefByValue();879 struct iter { unsigned operator*(); };880 unsigned size() const;881 iter begin();882 iter end();883 unsigned operator[](int);884};885 886void derefByValueTest() {887 DerefByValue DBV;888 for (unsigned I = 0, E = DBV.size(); I < E; ++I) {889 printf("%d\n", DBV[I]);890 }891 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead892 // CHECK-FIXES: for (unsigned int I : DBV) {893 // CHECK-FIXES-NEXT: printf("%d\n", I);894 895 for (unsigned I = 0, E = DBV.size(); I < E; ++I) {896 auto f = [DBV, I]() {};897 printf("%d\n", DBV[I]);898 }899 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead900 // CHECK-FIXES: for (unsigned int I : DBV) {901 // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};902 // CHECK-FIXES-NEXT: printf("%d\n", I);903}904 905void fundamentalTypesTest() {906 const int N = 10;907 bool Bools[N];908 for (int i = 0; i < N; ++i)909 printf("%d", Bools[i]);910 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead911 // CHECK-FIXES: for (bool Bool : Bools)912 913 int Ints[N];914 unsigned short int Shorts[N];915 for (int i = 0; i < N; ++i)916 printf("%d", Shorts[i]);917 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead918 // CHECK-FIXES: for (unsigned short Short : Shorts)919 920 signed long Longs[N];921 for (int i = 0; i < N; ++i)922 printf("%d", Longs[i]);923 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead924 // CHECK-FIXES: for (long Long : Longs)925 926 long long int LongLongs[N];927 for (int i = 0; i < N; ++i)928 printf("%d", LongLongs[i]);929 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead930 // CHECK-FIXES: for (long long LongLong : LongLongs)931 932 char Chars[N];933 for (int i = 0; i < N; ++i)934 printf("%d", Chars[i]);935 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead936 // CHECK-FIXES: for (char Char : Chars)937 938 wchar_t WChars[N];939 for (int i = 0; i < N; ++i)940 printf("%d", WChars[i]);941 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead942 // CHECK-FIXES: for (wchar_t WChar : WChars)943 944 float Floats[N];945 for (int i = 0; i < N; ++i)946 printf("%d", Floats[i]);947 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead948 // CHECK-FIXES: for (float Float : Floats)949 950 double Doubles[N];951 for (int i = 0; i < N; ++i)952 printf("%d", Doubles[i]);953 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead954 // CHECK-FIXES: for (double Double : Doubles)955}956 957template <unsigned p> void _dependenceArrayTest() {958 unsigned test[3][p];959 for (unsigned i = 0; i < p; ++i)960 for (unsigned j = 0; j < 3; ++j)961 printf("%d", test[j][i]);962 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead963 // CHECK-FIXES: for (auto & j : test)964 // CHECK-FIXES: printf("%d", j[i]);965}966void dependenceArrayTest() {967 _dependenceArrayTest<1>();968 _dependenceArrayTest<2>();969}970 971} // namespace PseudoArray972 973namespace PR78381 {974 struct blocked_range {975 int begin() const;976 int end() const;977 };978 979 void test() {980 blocked_range r;981 for (auto i = r.begin(); i!=r.end(); ++i) {982 }983 }984}985 986namespace GH109083 {987void test() {988 const int N = 6;989 int Arr[N] = {1, 2, 3, 4, 5, 6};990 991 for (int I = 0; I < N; ++I) {992 auto V = [T = Arr[I]]() {};993 }994 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]995 // CHECK-FIXES: for (int I : Arr) {996 // CHECK-FIXES-NEXT: auto V = [T = I]() {};997 for (int I = 0; I < N; ++I) {998 auto V = [T = 10 + Arr[I]]() {};999 }1000 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]1001 // CHECK-FIXES: for (int I : Arr) {1002 // CHECK-FIXES-NEXT: auto V = [T = 10 + I]() {};1003 1004 for (int I = 0; I < N; ++I) {1005 auto V = [T = I]() {};1006 }1007 for (int I = 0; I < N; ++I) {1008 auto V = [T = I + 10]() {};1009 }1010}1011} // namespace GH1090831012