brintos

brintos / llvm-project-archived public Read only

0
0
Text · 33.9 KiB · 161427c Raw
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