1087 lines · cpp
1// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -I %S/Inputs/loop-convert2 3#include "structures.h"4 5namespace Dependency {6 7void f() {8 const int N = 6;9 const int M = 8;10 int Arr[N][M];11 12 for (int I = 0; I < N; ++I) {13 int A = 0;14 int B = Arr[I][A];15 }16 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead17 // CHECK-FIXES: for (auto & I : Arr) {18 // CHECK-FIXES-NEXT: int A = 0;19 // CHECK-FIXES-NEXT: int B = I[A];20 21 for (int J = 0; J < M; ++J) {22 int A = 0;23 int B = Arr[A][J];24 }25}26 27} // namespace Dependency28 29namespace NamingAlias {30 31const int N = 10;32 33Val Arr[N];34dependent<Val> V;35dependent<Val> *Pv;36Val &func(Val &);37void sideEffect(int);38 39void aliasing() {40 // If the loop container is only used for a declaration of a temporary41 // variable to hold each element, we can name the new variable for the42 // converted range-based loop as the temporary variable's name.43 44 // In the following case, "T" is used as a temporary variable to hold each45 // element, and thus we consider the name "T" aliased to the loop.46 // The extra blank braces are left as a placeholder for after the variable47 // declaration is deleted.48 for (int I = 0; I < N; ++I) {49 Val &T = Arr[I];50 {}51 int Y = T.X;52 }53 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead54 // CHECK-FIXES: for (auto & T : Arr) {55 // CHECK-FIXES-NOT: Val &{{[a-z_]+}} =56 // CHECK-FIXES-NEXT: {}57 // CHECK-FIXES-NEXT: int Y = T.X;58 59 // The container was not only used to initialize a temporary loop variable for60 // the container's elements, so we do not alias the new loop variable.61 for (int I = 0; I < N; ++I) {62 Val &T = Arr[I];63 int Y = T.X;64 int Z = Arr[I].X + T.X;65 }66 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead67 // CHECK-FIXES: for (auto & I : Arr) {68 // CHECK-FIXES-NEXT: Val &T = I;69 // CHECK-FIXES-NEXT: int Y = T.X;70 // CHECK-FIXES-NEXT: int Z = I.X + T.X;71 72 for (int I = 0; I < N; ++I) {73 Val T = Arr[I];74 int Y = T.X;75 int Z = Arr[I].X + T.X;76 }77 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead78 // CHECK-FIXES: for (auto & I : Arr) {79 // CHECK-FIXES-NEXT: Val T = I;80 // CHECK-FIXES-NEXT: int Y = T.X;81 // CHECK-FIXES-NEXT: int Z = I.X + T.X;82 83 // The same for pseudo-arrays like std::vector<T> (or here dependent<Val>)84 // which provide a subscript operator[].85 for (int I = 0; I < V.size(); ++I) {86 Val &T = V[I];87 {}88 int Y = T.X;89 }90 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead91 // CHECK-FIXES: for (auto & T : V) {92 // CHECK-FIXES-NEXT: {}93 // CHECK-FIXES-NEXT: int Y = T.X;94 95 // The same with a call to at()96 for (int I = 0; I < Pv->size(); ++I) {97 Val &T = Pv->at(I);98 {}99 int Y = T.X;100 }101 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead102 // CHECK-FIXES: for (auto & T : *Pv) {103 // CHECK-FIXES-NEXT: {}104 // CHECK-FIXES-NEXT: int Y = T.X;105 106 for (int I = 0; I < N; ++I) {107 Val &T = func(Arr[I]);108 int Y = T.X;109 }110 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead111 // CHECK-FIXES: for (auto & I : Arr) {112 // CHECK-FIXES-NEXT: Val &T = func(I);113 // CHECK-FIXES-NEXT: int Y = T.X;114 115 int IntArr[N];116 for (unsigned I = 0; I < N; ++I) {117 if (int Alias = IntArr[I]) {118 sideEffect(Alias);119 }120 }121 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead122 // CHECK-FIXES: for (int Alias : IntArr) {123 // CHECK-FIXES-NEXT: if (Alias) {124 125 for (unsigned I = 0; I < N; ++I) {126 while (int Alias = IntArr[I]) {127 sideEffect(Alias);128 }129 }130 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead131 // CHECK-FIXES: for (int Alias : IntArr) {132 // CHECK-FIXES-NEXT: while (Alias) {133 134 for (unsigned I = 0; I < N; ++I) {135 switch (int Alias = IntArr[I]) {136 default:137 sideEffect(Alias);138 }139 }140 // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead141 // CHECK-FIXES: for (int Alias : IntArr) {142 // CHECK-FIXES-NEXT: switch (Alias) {143 144 for (unsigned I = 0; I < N; ++I) {145 for (int Alias = IntArr[I]; Alias < N; ++Alias) {146 sideEffect(Alias);147 }148 }149 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead150 // CHECK-FIXES: for (int Alias : IntArr) {151 // CHECK-FIXES-NEXT: for (; Alias < N; ++Alias) {152 153 for (unsigned I = 0; I < N; ++I) {154 for (unsigned J = 0; int Alias = IntArr[I]; ++J) {155 sideEffect(Alias);156 }157 }158 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead159 // CHECK-FIXES: for (int Alias : IntArr) {160 // CHECK-FIXES-NEXT: for (unsigned J = 0; Alias; ++J) {161 162 struct IntRef { IntRef(); IntRef(const int& i); operator int*(); };163 for (int I = 0; I < N; ++I) {164 IntRef Int(IntArr[I]);165 }166 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead167 // CHECK-FIXES: for (int I : IntArr) {168 // CHECK-FIXES-NEXT: IntRef Int(I);169 170 int *PtrArr[N];171 for (unsigned I = 0; I < N; ++I) {172 const int* const P = PtrArr[I];173 printf("%d\n", *P);174 }175 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead176 // CHECK-FIXES: for (auto P : PtrArr) {177 // CHECK-FIXES-NEXT: printf("%d\n", *P);178 179 IntRef Refs[N];180 for (unsigned I = 0; I < N; ++I) {181 int *P = Refs[I];182 printf("%d\n", *P);183 }184 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead185 // CHECK-FIXES: for (auto & Ref : Refs) {186 // CHECK-FIXES-NEXT: int *P = Ref;187 // CHECK-FIXES-NEXT: printf("%d\n", *P);188 189 // Ensure that removing the alias doesn't leave empty lines behind.190 for (int I = 0; I < N; ++I) {191 auto &X = IntArr[I];192 X = 0;193 }194 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead195 // CHECK-FIXES: for (int & X : IntArr) {196 // CHECK-FIXES-NEXT: {{^ X = 0;$}}197 // CHECK-FIXES-NEXT: {{^ }$}}198}199 200void refs_and_vals() {201 // The following tests check that the transform correctly preserves the202 // reference or value qualifiers of the aliased variable. That is, if the203 // variable was declared as a value, the loop variable will be declared as a204 // value and vice versa for references.205 206 S Ss;207 const S S_const = Ss;208 209 for (S::const_iterator It = S_const.begin(); It != S_const.end(); ++It) {210 MutableVal Alias = *It;211 {}212 Alias.X = 0;213 }214 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead215 // CHECK-FIXES: for (auto Alias : S_const) {216 // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =217 // CHECK-FIXES-NEXT: {}218 // CHECK-FIXES-NEXT: Alias.X = 0;219 220 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {221 MutableVal Alias = *It;222 {}223 Alias.X = 0;224 }225 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead226 // CHECK-FIXES: for (auto Alias : Ss) {227 // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =228 // CHECK-FIXES-NEXT: {}229 // CHECK-FIXES-NEXT: Alias.X = 0;230 231 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {232 MutableVal &Alias = *It;233 {}234 Alias.X = 0;235 }236 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead237 // CHECK-FIXES: for (auto & Alias : Ss) {238 // CHECK-FIXES-NOT: MutableVal &{{[a-z_]+}} =239 // CHECK-FIXES-NEXT: {}240 // CHECK-FIXES-NEXT: Alias.X = 0;241 242 dependent<int> Dep, Other;243 for (dependent<int>::iterator It = Dep.begin(), E = Dep.end(); It != E; ++It) {244 printf("%d\n", *It);245 const int& Idx = Other[0];246 unsigned Othersize = Other.size();247 }248 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead249 // CHECK-FIXES: for (int & It : Dep) {250 // CHECK-FIXES-NEXT: printf("%d\n", It);251 // CHECK-FIXES-NEXT: const int& Idx = Other[0];252 // CHECK-FIXES-NEXT: unsigned Othersize = Other.size();253 254 for (int i = 0; i < Other.size(); ++i) {255 Other.at(i);256 }257 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead258 // CHECK-FIXES: for (int & i : Other) {259 // CHECK-FIXES: i;260 261 for (int I = 0, E = Dep.size(); I != E; ++I) {262 int Idx = Other.at(I);263 Other.at(I, I); // Should not trigger assert failure.264 }265}266 267struct MemberNaming {268 const static int N = 10;269 int Ints[N], Ints_[N];270 dependent<int> DInts;271 void loops() {272 for (int I = 0; I < N; ++I) {273 printf("%d\n", Ints[I]);274 }275 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead276 // CHECK-FIXES: for (int Int : Ints) {277 // CHECK-FIXES-NEXT: printf("%d\n", Int);278 279 for (int I = 0; I < N; ++I) {280 printf("%d\n", Ints_[I]);281 }282 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead283 // CHECK-FIXES: for (int Int : Ints_) {284 // CHECK-FIXES-NEXT: printf("%d\n", Int);285 286 for (int I = 0; I < DInts.size(); ++I) {287 printf("%d\n", DInts[I]);288 }289 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead290 // CHECK-FIXES: for (int DInt : DInts) {291 // CHECK-FIXES-NEXT: printf("%d\n", DInt);292 }293 294 void outOfLine();295};296void MemberNaming::outOfLine() {297 for (int I = 0; I < N; ++I) {298 printf("%d\n", Ints[I]);299 }300 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead301 // CHECK-FIXES: for (int Int : Ints) {302 // CHECK-FIXES-NEXT: printf("%d\n", Int);303 304 for (int I = 0; I < N; ++I) {305 printf("%d\n", Ints_[I]);306 }307 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead308 // CHECK-FIXES: for (int Int : Ints_) {309 // CHECK-FIXES-NEXT: printf("%d\n", Int);310}311 312} // namespace NamingAlias313 314namespace NamingConlict {315 316#define MAX(a, b) (a > b) ? a : b317#define DEF 5318 319const int N = 10;320int Nums[N];321int Sum = 0;322 323namespace ns {324struct St {325 int X;326};327}328 329void sameNames() {330 int Num = 0;331 for (int I = 0; I < N; ++I) {332 printf("Fibonacci number is %d\n", Nums[I]);333 Sum += Nums[I] + 2 + Num;334 (void)Nums[I];335 }336 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead337 // CHECK-FIXES: for (int & I : Nums) {338 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);339 // CHECK-FIXES-NEXT: Sum += I + 2 + Num;340 // CHECK-FIXES-NEXT: (void)I;341 342 int Elem = 0;343 for (int I = 0; I < N; ++I) {344 printf("Fibonacci number is %d\n", Nums[I]);345 Sum += Nums[I] + 2 + Num + Elem;346 (void)Nums[I];347 }348 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead349 // CHECK-FIXES: for (int & I : Nums) {350 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);351 // CHECK-FIXES-NEXT: Sum += I + 2 + Num + Elem;352 // CHECK-FIXES-NEXT: (void)I;353}354 355void oldIndexConflict() {356 for (int Num = 0; Num < N; ++Num) {357 printf("Num: %d\n", Nums[Num]);358 }359 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead360 // CHECK-FIXES: for (int Num : Nums) {361 // CHECK-FIXES-NEXT: printf("Num: %d\n", Num);362 363 S Things;364 for (S::iterator Thing = Things.begin(), End = Things.end(); Thing != End; ++Thing) {365 printf("Thing: %d %d\n", Thing->X, (*Thing).X);366 }367 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead368 // CHECK-FIXES: for (auto & Thing : Things) {369 // CHECK-FIXES-NEXT: printf("Thing: %d %d\n", Thing.X, Thing.X);370}371 372void macroConflict() {373 S MAXs;374 for (S::iterator It = MAXs.begin(), E = MAXs.end(); It != E; ++It) {375 printf("s has value %d\n", (*It).X);376 printf("Max of 3 and 5: %d\n", MAX(3, 5));377 }378 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead379 // CHECK-FIXES: for (auto & It : MAXs) {380 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);381 // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));382 383 for (S::const_iterator It = MAXs.begin(), E = MAXs.end(); It != E; ++It) {384 printf("s has value %d\n", (*It).X);385 printf("Max of 3 and 5: %d\n", MAX(3, 5));386 }387 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead388 // CHECK-FIXES: for (auto It : MAXs) {389 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);390 // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));391 392 T DEFs;393 for (T::iterator It = DEFs.begin(), E = DEFs.end(); It != E; ++It) {394 if (*It == DEF) {395 printf("I found %d\n", *It);396 }397 }398 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead399 // CHECK-FIXES: for (int & It : DEFs) {400 // CHECK-FIXES-NEXT: if (It == DEF) {401 // CHECK-FIXES-NEXT: printf("I found %d\n", It);402}403 404void keywordConflict() {405 T ints;406 for (T::iterator It = ints.begin(), E = ints.end(); It != E; ++It) {407 *It = 5;408 }409 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead410 // CHECK-FIXES: for (int & It : ints) {411 // CHECK-FIXES-NEXT: It = 5;412 413 U __FUNCTION__s;414 for (U::iterator It = __FUNCTION__s.begin(), E = __FUNCTION__s.end();415 It != E; ++It) {416 int __FUNCTION__s_It = (*It).X + 2;417 }418 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead419 // CHECK-FIXES: for (auto & It : __FUNCTION__s) {420 // CHECK-FIXES-NEXT: int __FUNCTION__s_It = It.X + 2;421}422 423void typeConflict() {424 T Vals;425 // Using the name "Val", although it is the name of an existing struct, is426 // safe in this loop since it will only exist within this scope.427 for (T::iterator It = Vals.begin(), E = Vals.end(); It != E; ++It)428 (void) *It;429 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead430 // CHECK-FIXES: for (int & Val : Vals)431 432 // We cannot use the name "Val" in this loop since there is a reference to433 // it in the body of the loop.434 for (T::iterator It = Vals.begin(), E = Vals.end(); It != E; ++It) {435 *It = sizeof(Val);436 }437 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead438 // CHECK-FIXES: for (int & It : Vals) {439 // CHECK-FIXES-NEXT: It = sizeof(Val);440 441 typedef struct Val TD;442 U TDs;443 // Naming the variable "TD" within this loop is safe because the typedef444 // was never used within the loop.445 for (U::iterator It = TDs.begin(), E = TDs.end(); It != E; ++It)446 (void) *It;447 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead448 // CHECK-FIXES: for (auto & TD : TDs)449 450 // "TD" cannot be used in this loop since the typedef is being used.451 for (U::iterator It = TDs.begin(), E = TDs.end(); It != E; ++It) {452 TD V;453 V.X = 5;454 (void) *It;455 }456 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead457 // CHECK-FIXES: for (auto & It : TDs) {458 // CHECK-FIXES-NEXT: TD V;459 // CHECK-FIXES-NEXT: V.X = 5;460 461 using ns::St;462 T Sts;463 for (T::iterator It = Sts.begin(), E = Sts.end(); It != E; ++It) {464 *It = sizeof(St);465 }466 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead467 // CHECK-FIXES: for (int & It : Sts) {468 // CHECK-FIXES-NEXT: It = sizeof(St);469}470 471} // namespace NamingConflict472 473namespace FreeBeginEnd {474 475// FIXME: Loop Convert should detect free begin()/end() functions.476 477struct MyArray {478 unsigned size();479};480 481template <typename T>482struct MyContainer {483};484 485int *begin(const MyArray &Arr);486int *end(const MyArray &Arr);487 488template <typename T>489T *begin(const MyContainer<T> &C);490template <typename T>491T *end(const MyContainer<T> &C);492 493// The Loop Convert Transform doesn't detect free functions begin()/end() and494// so fails to transform these cases which it should.495void f() {496 MyArray Arr;497 for (unsigned I = 0, E = Arr.size(); I < E; ++I) {498 }499 500 MyContainer<int> C;501 for (int *I = begin(C), *E = end(C); I != E; ++I) {502 }503}504 505} // namespace FreeBeginEnd506 507namespace Nesting {508 509void g(S::iterator It);510void const_g(S::const_iterator It);511class Foo {512 public:513 void g(S::iterator It);514 void const_g(S::const_iterator It);515};516 517void f() {518 const int N = 10;519 const int M = 15;520 Val Arr[N];521 for (int I = 0; I < N; ++I) {522 for (int J = 0; J < N; ++J) {523 int K = Arr[I].X + Arr[J].X;524 // The repeat is there to allow FileCheck to make sure the two variable525 // names aren't the same.526 int L = Arr[I].X + Arr[J].X;527 }528 }529 // CHECK-MESSAGES: :[[@LINE-8]]:3: warning: use range-based for loop instead530 // CHECK-MESSAGES: :[[@LINE-8]]:5: warning: use range-based for loop instead531 // CHECK-FIXES: for (auto & I : Arr) {532 // CHECK-FIXES-NEXT: for (auto & J : Arr) {533 // CHECK-FIXES-NEXT: int K = I.X + J.X;534 // CHECK-FIXES-NOT: int L = I.X + I.X;535 536 // The inner loop is also convertible, but doesn't need to be converted537 // immediately. FIXME: update this test when that changes.538 Val Nest[N][M];539 for (int I = 0; I < N; ++I) {540 for (int J = 0; J < M; ++J) {541 printf("Got item %d", Nest[I][J].X);542 }543 }544 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead545 // CHECK-FIXES: for (auto & I : Nest) {546 // CHECK-FIXES-NEXT: for (int J = 0; J < M; ++J) {547 // CHECK-FIXES-NEXT: printf("Got item %d", I[J].X);548 549 // Note that the order of M and N are switched for this test.550 for (int J = 0; J < M; ++J) {551 for (int I = 0; I < N; ++I) {552 printf("Got item %d", Nest[I][J].X);553 }554 }555 // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop instead556 // CHECK-FIXES-NOT: for (auto & {{[a-zA-Z_]+}} : Nest[I])557 // CHECK-FIXES: for (int J = 0; J < M; ++J) {558 // CHECK-FIXES-NEXT: for (auto & I : Nest) {559 // CHECK-FIXES-NEXT: printf("Got item %d", I[J].X);560 561 // The inner loop is also convertible.562 Nested<T> NestT;563 for (Nested<T>::iterator I = NestT.begin(), E = NestT.end(); I != E; ++I) {564 for (T::iterator TI = (*I).begin(), TE = (*I).end(); TI != TE; ++TI) {565 printf("%d", *TI);566 }567 }568 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead569 // CHECK-FIXES: for (auto & I : NestT) {570 // CHECK-FIXES-NEXT: for (T::iterator TI = I.begin(), TE = I.end(); TI != TE; ++TI) {571 // CHECK-FIXES-NEXT: printf("%d", *TI);572 573 // The inner loop is also convertible.574 Nested<S> NestS;575 for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {576 for (S::const_iterator SI = (*I).begin(), SE = (*I).end(); SI != SE; ++SI) {577 printf("%d", *SI);578 }579 }580 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead581 // CHECK-FIXES: for (auto I : NestS) {582 // CHECK-FIXES-NEXT: for (S::const_iterator SI = I.begin(), SE = I.end(); SI != SE; ++SI) {583 // CHECK-FIXES-NEXT: printf("%d", *SI);584 585 for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {586 const S &Ss = *I;587 for (S::const_iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {588 printf("%d", *SI);589 const_g(SI);590 }591 }592 // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead593 // CHECK-FIXES: for (auto Ss : NestS) {594 595 for (Nested<S>::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {596 S &Ss = *I;597 for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {598 printf("%d", *SI);599 g(SI);600 }601 }602 // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead603 // CHECK-FIXES: for (auto & Ss : NestS) {604 605 Foo foo;606 for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {607 const S &Ss = *I;608 for (S::const_iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {609 printf("%d", *SI);610 foo.const_g(SI);611 }612 }613 // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead614 // CHECK-FIXES: for (auto Ss : NestS) {615 616 for (Nested<S>::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {617 S &Ss = *I;618 for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {619 printf("%d", *SI);620 foo.g(SI);621 }622 }623 // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead624 // CHECK-FIXES: for (auto & Ss : NestS) {625 626}627 628} // namespace Nesting629 630namespace SingleIterator {631 632void complexContainer() {633 X Exes[5];634 int Index = 0;635 636 for (S::iterator I = Exes[Index].getS().begin(), E = Exes[Index].getS().end(); I != E; ++I) {637 MutableVal K = *I;638 MutableVal J = *I;639 }640 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead641 // CHECK-FIXES: for (auto & I : Exes[Index].getS()) {642 // CHECK-FIXES-NEXT: MutableVal K = I;643 // CHECK-FIXES-NEXT: MutableVal J = I;644}645 646void f() {647 /// begin()/end() - based for loops here:648 T Tt;649 for (T::iterator It = Tt.begin(); It != Tt.end(); ++It) {650 printf("I found %d\n", *It);651 }652 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead653 // CHECK-FIXES: for (int & It : Tt) {654 // CHECK-FIXES-NEXT: printf("I found %d\n", It);655 656 T *Pt;657 for (T::iterator It = Pt->begin(); It != Pt->end(); ++It) {658 printf("I found %d\n", *It);659 }660 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead661 // CHECK-FIXES: for (int & It : *Pt) {662 // CHECK-FIXES-NEXT: printf("I found %d\n", It);663 664 S Ss;665 for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {666 printf("s has value %d\n", (*It).X);667 }668 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead669 // CHECK-FIXES: for (auto & It : Ss) {670 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);671 672 S *Ps;673 for (S::iterator It = Ps->begin(); It != Ps->end(); ++It) {674 printf("s has value %d\n", (*It).X);675 }676 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead677 // CHECK-FIXES: for (auto & P : *Ps) {678 // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);679 680 for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {681 printf("s has value %d\n", It->X);682 }683 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead684 // CHECK-FIXES: for (auto & It : Ss) {685 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);686 687 for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {688 It->X = 3;689 }690 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead691 // CHECK-FIXES: for (auto & It : Ss) {692 // CHECK-FIXES-NEXT: It.X = 3;693 694 for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {695 (*It).X = 3;696 }697 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead698 // CHECK-FIXES: for (auto & It : Ss) {699 // CHECK-FIXES-NEXT: It.X = 3;700 701 for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {702 It->nonConstFun(4, 5);703 }704 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead705 // CHECK-FIXES: for (auto & It : Ss) {706 // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);707 708 U Uu;709 for (U::iterator It = Uu.begin(); It != Uu.end(); ++It) {710 printf("s has value %d\n", It->X);711 }712 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead713 // CHECK-FIXES: for (auto & It : Uu) {714 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);715 716 for (U::iterator It = Uu.begin(); It != Uu.end(); ++It) {717 printf("s has value %d\n", (*It).X);718 }719 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead720 // CHECK-FIXES: for (auto & It : Uu) {721 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);722 723 U::iterator A;724 for (U::iterator I = Uu.begin(); I != Uu.end(); ++I)725 int K = A->X + I->X;726 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead727 // CHECK-FIXES: for (auto & I : Uu)728 // CHECK-FIXES-NEXT: int K = A->X + I.X;729 730 dependent<int> V;731 for (dependent<int>::iterator It = V.begin();732 It != V.end(); ++It) {733 printf("Fibonacci number is %d\n", *It);734 }735 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead736 // CHECK-FIXES: for (int & It : V) {737 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);738 739 for (dependent<int>::iterator It(V.begin());740 It != V.end(); ++It) {741 printf("Fibonacci number is %d\n", *It);742 }743 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead744 // CHECK-FIXES: for (int & It : V) {745 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);746 747 doublyDependent<int, int> intmap;748 for (doublyDependent<int, int>::iterator It = intmap.begin();749 It != intmap.end(); ++It) {750 printf("intmap[%d] = %d", It->first, It->second);751 }752 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead753 // CHECK-FIXES: for (auto & It : intmap) {754 // CHECK-FIXES-NEXT: printf("intmap[%d] = %d", It.first, It.second);755}756 757void different_type() {758 // Tests to verify the proper use of auto where the init variable type and the759 // initializer type differ or are mostly the same except for const qualifiers.760 761 // Ss.begin() returns a type 'iterator' which is just a non-const pointer and762 // differs from const_iterator only on the const qualification.763 S Ss;764 for (S::const_iterator It = Ss.begin(); It != Ss.end(); ++It) {765 printf("s has value %d\n", (*It).X);766 }767 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead768 // CHECK-FIXES: for (auto It : Ss) {769 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);770 771 S *Ps;772 for (S::const_iterator It = Ps->begin(); It != Ps->end(); ++It) {773 printf("s has value %d\n", (*It).X);774 }775 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead776 // CHECK-FIXES: for (auto P : *Ps) {777 // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);778 779 dependent<int> V;780 for (dependent<int>::const_iterator It = V.begin(); It != V.end(); ++It) {781 printf("Fibonacci number is %d\n", *It);782 }783 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead784 // CHECK-FIXES: for (int It : V) {785 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);786 787 for (dependent<int>::const_iterator It(V.begin()); It != V.end(); ++It) {788 printf("Fibonacci number is %d\n", *It);789 }790 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead791 // CHECK-FIXES: for (int It : V) {792 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);793}794 795} // namespace SingleIterator796 797 798namespace Macros {799 800#define TWO_PARAM(x, y) if (x == y) {}801#define THREE_PARAM(x, y, z) if (x == y) {z;}802 803const int N = 10;804int Arr[N];805 806void messing_with_macros() {807 for (int I = 0; I < N; ++I) {808 printf("Value: %d\n", Arr[I]);809 }810 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead811 // CHECK-FIXES: for (int I : Arr) {812 // CHECK-FIXES-NEXT: printf("Value: %d\n", I);813 814 for (int I = 0; I < N; ++I) {815 printf("Value: %d\n", CONT Arr[I]);816 }817 818 // Multiple macro arguments.819 for (int I = 0; I < N; ++I) {820 TWO_PARAM(Arr[I], Arr[I]);821 THREE_PARAM(Arr[I], Arr[I], Arr[I]);822 }823 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead824 // CHECK-FIXES: for (int & I : Arr) {825 // CHECK-FIXES-NEXT: TWO_PARAM(I, I);826 // CHECK-FIXES-NEXT: THREE_PARAM(I, I, I);827}828 829} // namespace Macros830 831namespace Templates {832 833template <class Container>834void set_union(Container &container) {835 for (typename Container::const_iterator SI = container.begin(),836 SE = container.end(); SI != SE; ++SI) {837 (void) *SI;838 }839 840 S Ss;841 for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI)842 (void) *SI;843 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead844 // CHECK-FIXES: for (auto & SI : Ss)845}846 847void template_instantiation() {848 S Ss;849 set_union(Ss);850}851 852} // namespace Templates853 854namespace Lambdas {855 856void capturesIndex() {857 const int N = 10;858 int Arr[N];859 // FIXME: the next four loops could be convertible, if the capture list is860 // also changed.861 862 for (int I = 0; I < N; ++I)863 auto F1 = [Arr, I]() { int R1 = Arr[I] + 1; };864 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead865 // CHECK-FIXES: for (int I : Arr)866 // CHECK-FIXES-NEXT: auto F1 = [Arr, &I]() { int R1 = I + 1; };867 868 for (int I = 0; I < N; ++I)869 auto F2 = [Arr, &I]() { int R2 = Arr[I] + 3; };870 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead871 // CHECK-FIXES: for (int I : Arr)872 // CHECK-FIXES-NEXT: auto F2 = [Arr, &I]() { int R2 = I + 3; };873 874 // FIXME: alias don't work if the index is captured.875 // Alias declared inside lambda (by value).876 for (int I = 0; I < N; ++I)877 auto F3 = [&Arr, I]() { int R3 = Arr[I]; };878 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead879 // CHECK-FIXES: for (int I : Arr)880 // CHECK-FIXES-NEXT: auto F3 = [&Arr, &I]() { int R3 = I; };881 882 883 for (int I = 0; I < N; ++I)884 auto F4 = [&Arr, &I]() { int R4 = Arr[I]; };885 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead886 // CHECK-FIXES: for (int I : Arr)887 // CHECK-FIXES-NEXT: auto F4 = [&Arr, &I]() { int R4 = I; };888 889 // Alias declared inside lambda (by reference).890 for (int I = 0; I < N; ++I)891 auto F5 = [&Arr, I]() { int &R5 = Arr[I]; };892 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead893 // CHECK-FIXES: for (int & I : Arr)894 // CHECK-FIXES-NEXT: auto F5 = [&Arr, &I]() { int &R5 = I; };895 896 897 for (int I = 0; I < N; ++I)898 auto F6 = [&Arr, &I]() { int &R6 = Arr[I]; };899 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead900 // CHECK-FIXES: for (int & I : Arr)901 // CHECK-FIXES-NEXT: auto F6 = [&Arr, &I]() { int &R6 = I; };902 903 for (int I = 0; I < N; ++I) {904 auto F = [Arr, I](int k) {905 printf("%d\n", Arr[I] + k);906 };907 F(Arr[I]);908 }909 // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead910 // CHECK-FIXES: for (int I : Arr) {911 // CHECK-FIXES-NEXT: auto F = [Arr, &I](int k) {912 // CHECK-FIXES-NEXT: printf("%d\n", I + k);913 // CHECK-FIXES-NEXT: };914 // CHECK-FIXES-NEXT: F(I);915}916 917void implicitCapture() {918 const int N = 10;919 int Arr[N];920 // Index is used, not convertible.921 for (int I = 0; I < N; ++I) {922 auto G1 = [&]() {923 int R = Arr[I];924 int J = I;925 };926 }927 928 for (int I = 0; I < N; ++I) {929 auto G2 = [=]() {930 int R = Arr[I];931 int J = I;932 };933 }934 935 // Convertible.936 for (int I = 0; I < N; ++I) {937 auto G3 = [&]() {938 int R3 = Arr[I];939 int J3 = Arr[I] + R3;940 };941 }942 // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead943 // CHECK-FIXES: for (int I : Arr) {944 // CHECK-FIXES-NEXT: auto G3 = [&]() {945 // CHECK-FIXES-NEXT: int R3 = I;946 // CHECK-FIXES-NEXT: int J3 = I + R3;947 948 for (int I = 0; I < N; ++I) {949 auto G4 = [=]() {950 int R4 = Arr[I] + 5;951 };952 }953 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead954 // CHECK-FIXES: for (int I : Arr) {955 // CHECK-FIXES-NEXT: auto G4 = [=]() {956 // CHECK-FIXES-NEXT: int R4 = I + 5;957 958 // Alias by value.959 for (int I = 0; I < N; ++I) {960 auto G5 = [&]() {961 int R5 = Arr[I];962 int J5 = 8 + R5;963 };964 }965 // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead966 // CHECK-FIXES: for (int R5 : Arr) {967 // CHECK-FIXES-NEXT: auto G5 = [&]() {968 // CHECK-FIXES-NEXT: int J5 = 8 + R5;969 970 // Alias by reference.971 for (int I = 0; I < N; ++I) {972 auto G6 = [&]() {973 int &R6 = Arr[I];974 int J6 = -1 + R6;975 };976 }977 // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead978 // CHECK-FIXES: for (int & R6 : Arr) {979 // CHECK-FIXES-NEXT: auto G6 = [&]() {980 // CHECK-FIXES-NEXT: int J6 = -1 + R6;981}982 983void iterators() {984 dependent<int> Dep;985 986 for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)987 auto H1 = [&I]() { int R = *I; };988 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead989 // CHECK-FIXES: for (int & I : Dep)990 // CHECK-FIXES-NEXT: auto H1 = [&I]() { int R = I; };991 992 for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)993 auto H2 = [&]() { int R = *I + 2; };994 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead995 // CHECK-FIXES: for (int & I : Dep)996 // CHECK-FIXES-NEXT: auto H2 = [&]() { int R = I + 2; };997 998 for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();999 I != E; ++I)1000 auto H3 = [I]() { int R = *I; };1001 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead1002 // CHECK-FIXES: for (int I : Dep)1003 // CHECK-FIXES-NEXT: auto H3 = [&I]() { int R = I; };1004 1005 for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();1006 I != E; ++I)1007 auto H4 = [&]() { int R = *I + 1; };1008 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead1009 // CHECK-FIXES: for (int I : Dep)1010 // CHECK-FIXES-NEXT: auto H4 = [&]() { int R = I + 1; };1011 1012 for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();1013 I != E; ++I)1014 auto H5 = [=]() { int R = *I; };1015 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead1016 // CHECK-FIXES: for (int R : Dep)1017 // CHECK-FIXES-NEXT: auto H5 = [=]() { };1018}1019 1020void captureByValue() {1021 // When the index is captured by value, we should replace this by a capture1022 // by reference. This avoids extra copies.1023 // FIXME: this could change semantics on array or pseudoarray loops if the1024 // container is captured by copy.1025 const int N = 10;1026 int Arr[N];1027 dependent<int> Dep;1028 1029 for (int I = 0; I < N; ++I) {1030 auto C1 = [&Arr, I]() { if (Arr[I] == 1); };1031 }1032 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead1033 // CHECK-FIXES: for (int I : Arr) {1034 // CHECK-FIXES-NEXT: auto C1 = [&Arr, &I]() { if (I == 1); };1035 1036 for (unsigned I = 0; I < Dep.size(); ++I) {1037 auto C2 = [&Dep, I]() { if (Dep[I] == 2); };1038 }1039 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead1040 // CHECK-FIXES: for (int I : Dep) {1041 // CHECK-FIXES-NEXT: auto C2 = [&Dep, &I]() { if (I == 2); };1042}1043 1044} // namespace Lambdas1045 1046namespace InitLists {1047 1048struct D { int Ii; };1049struct E { D Dd; };1050int g(int B);1051 1052void f() {1053 const unsigned N = 3;1054 int Array[N];1055 1056 // Subtrees of InitListExpr are visited twice. Test that we do not do repeated1057 // replacements.1058 for (unsigned I = 0; I < N; ++I) {1059 int A{ Array[I] };1060 int B{ g(Array[I]) };1061 int C{ g( { Array[I] } ) };1062 D Dd{ { g( { Array[I] } ) } };1063 E Ee{ { { g( { Array[I] } ) } } };1064 }1065 // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead1066 // CHECK-FIXES: for (int I : Array) {1067 // CHECK-FIXES-NEXT: int A{ I };1068 // CHECK-FIXES-NEXT: int B{ g(I) };1069 // CHECK-FIXES-NEXT: int C{ g( { I } ) };1070 // CHECK-FIXES-NEXT: D Dd{ { g( { I } ) } };1071 // CHECK-FIXES-NEXT: E Ee{ { { g( { I } ) } } };1072}1073 1074} // namespace InitLists1075 1076void bug28341() {1077 char v[5];1078 for(int i = 0; i < 5; ++i) {1079 unsigned char value = v[i];1080 if (value > 127)1081 ;1082 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead1083 // CHECK-FIXES: for(unsigned char value : v) {1084 // CHECK-FIXES-NEXT: if (value > 127)1085 }1086}1087