1 // RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 -I %S/Inputs/modernize-loop-convert
2 
3 #include "structures.h"
4 
5 namespace Dependency {
6 
f()7 void 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 instead
17   // 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 Dependency
28 
29 namespace NamingAlias {
30 
31 const int N = 10;
32 
33 Val Arr[N];
34 dependent<Val> V;
35 dependent<Val> *Pv;
36 Val &func(Val &);
37 void sideEffect(int);
38 
aliasing()39 void aliasing() {
40   // If the loop container is only used for a declaration of a temporary
41   // variable to hold each element, we can name the new variable for the
42   // 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 each
45   // 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 variable
47   // 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 instead
54   // 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 for
60   // 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 instead
67   // 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 instead
78   // 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 instead
91   // 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 instead
102   // 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 instead
111   // 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 instead
122   // 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 instead
131   // 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 instead
141   // 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 instead
150   // 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 instead
159   // 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 instead
167   // 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 instead
176   // 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 instead
185   // 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 instead
195   // CHECK-FIXES: for (int & X : IntArr) {
196   // CHECK-FIXES-NEXT: {{^    X = 0;$}}
197   // CHECK-FIXES-NEXT: {{^  }$}}
198 }
199 
refs_and_vals()200 void refs_and_vals() {
201   // The following tests check that the transform correctly preserves the
202   // reference or value qualifiers of the aliased variable. That is, if the
203   // variable was declared as a value, the loop variable will be declared as a
204   // 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 instead
215   // 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 instead
226   // 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 instead
237   // 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 instead
249   // 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 instead
258   // 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 
267 struct MemberNaming {
268   const static int N = 10;
269   int Ints[N], Ints_[N];
270   dependent<int> DInts;
loopsNamingAlias::MemberNaming271   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 instead
276     // 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 instead
283     // 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 instead
290     // CHECK-FIXES: for (int DInt : DInts)
291     // CHECK-FIXES-NEXT: printf("%d\n", DInt);
292   }
293 
294   void outOfLine();
295 };
outOfLine()296 void 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 instead
301   // 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 instead
308   // CHECK-FIXES: for (int Int : Ints_)
309   // CHECK-FIXES-NEXT: printf("%d\n", Int);
310 }
311 
312 } // namespace NamingAlias
313 
314 namespace NamingConlict {
315 
316 #define MAX(a, b) (a > b) ? a : b
317 #define DEF 5
318 
319 const int N = 10;
320 int Nums[N];
321 int Sum = 0;
322 
323 namespace ns {
324 struct St {
325   int X;
326 };
327 }
328 
sameNames()329 void 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 instead
337   // 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 instead
349   // 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 
oldIndexConflict()355 void 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 instead
360   // 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 instead
368   // CHECK-FIXES: for (auto & Thing : Things)
369   // CHECK-FIXES-NEXT: printf("Thing: %d %d\n", Thing.X, Thing.X);
370 }
371 
macroConflict()372 void 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 instead
379   // 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 instead
388   // 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 instead
399   // 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 
keywordConflict()404 void 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 instead
410   // 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 instead
419   // CHECK-FIXES: for (auto & It : __FUNCTION__s)
420   // CHECK-FIXES-NEXT: int __FUNCTION__s_It = It.X + 2;
421 }
422 
typeConflict()423 void typeConflict() {
424   T Vals;
425   // Using the name "Val", although it is the name of an existing struct, is
426   // 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 instead
430   // CHECK-FIXES: for (int & Val : Vals)
431 
432   // We cannot use the name "Val" in this loop since there is a reference to
433   // 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 instead
438   // 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 typedef
444   // 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 instead
448   // 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 instead
457   // 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 instead
467   // CHECK-FIXES: for (int & It : Sts)
468   // CHECK-FIXES-NEXT: It = sizeof(St);
469 }
470 
471 } // namespace NamingConflict
472 
473 namespace FreeBeginEnd {
474 
475 // FIXME: Loop Convert should detect free begin()/end() functions.
476 
477 struct MyArray {
478   unsigned size();
479 };
480 
481 template <typename T>
482 struct MyContainer {
483 };
484 
485 int *begin(const MyArray &Arr);
486 int *end(const MyArray &Arr);
487 
488 template <typename T>
489 T *begin(const MyContainer<T> &C);
490 template <typename T>
491 T *end(const MyContainer<T> &C);
492 
493 // The Loop Convert Transform doesn't detect free functions begin()/end() and
494 // so fails to transform these cases which it should.
f()495 void 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 FreeBeginEnd
506 
507 namespace Nesting {
508 
509 void g(S::iterator It);
510 void const_g(S::const_iterator It);
511 class Foo {
512  public:
513   void g(S::iterator It);
514   void const_g(S::const_iterator It);
515 };
516 
f()517 void 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 variable
525       // 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 instead
530   // CHECK-MESSAGES: :[[@LINE-8]]:5: warning: use range-based for loop instead
531   // 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 converted
537   // 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 instead
545   // 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 instead
556   // 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 instead
569   // 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 instead
581   // 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 instead
593   // 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 instead
603   // 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 instead
614   // 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 instead
624   // CHECK-FIXES: for (auto & Ss : NestS)
625 
626 }
627 
628 } // namespace Nesting
629 
630 namespace SingleIterator {
631 
complexContainer()632 void 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 instead
641   // CHECK-FIXES: for (auto & I : Exes[Index].getS())
642   // CHECK-FIXES-NEXT: MutableVal K = I;
643   // CHECK-FIXES-NEXT: MutableVal J = I;
644 }
645 
f()646 void 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 instead
653   // 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 instead
661   // 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 instead
669   // 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 instead
677   // 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 instead
684   // 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 instead
691   // 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 instead
698   // 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 instead
705   // 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 instead
713   // 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 instead
720   // 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 instead
727   // 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 instead
736   // 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 instead
744   // 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 instead
753   // CHECK-FIXES: for (auto & It : intmap)
754   // CHECK-FIXES-NEXT: printf("intmap[%d] = %d", It.first, It.second);
755 }
756 
different_type()757 void different_type() {
758   // Tests to verify the proper use of auto where the init variable type and the
759   // 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 and
762   // 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 instead
768   // 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 instead
776   // CHECK-FIXES: for (auto P : *Ps)
777   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
778 
779   // V.begin() returns a user-defined type 'iterator' which, since it's
780   // different from const_iterator, disqualifies these loops from
781   // transformation.
782   dependent<int> V;
783   for (dependent<int>::const_iterator It = V.begin(); It != V.end(); ++It) {
784     printf("Fibonacci number is %d\n", *It);
785   }
786 
787   for (dependent<int>::const_iterator It(V.begin()); It != V.end(); ++It) {
788     printf("Fibonacci number is %d\n", *It);
789   }
790 }
791 
792 } // namespace SingleIterator
793 
794 
795 namespace Macros {
796 
797 #define TWO_PARAM(x, y) if (x == y) {}
798 #define THREE_PARAM(x, y, z) if (x == y) {z;}
799 
800 const int N = 10;
801 int Arr[N];
802 
messing_with_macros()803 void messing_with_macros() {
804   for (int I = 0; I < N; ++I) {
805     printf("Value: %d\n", Arr[I]);
806   }
807   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
808   // CHECK-FIXES: for (int I : Arr)
809   // CHECK-FIXES-NEXT:  printf("Value: %d\n", I);
810 
811   for (int I = 0; I < N; ++I) {
812     printf("Value: %d\n", CONT Arr[I]);
813   }
814 
815   // Multiple macro arguments.
816   for (int I = 0; I < N; ++I) {
817     TWO_PARAM(Arr[I], Arr[I]);
818     THREE_PARAM(Arr[I], Arr[I], Arr[I]);
819   }
820   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
821   // CHECK-FIXES: for (int & I : Arr)
822   // CHECK-FIXES-NEXT: TWO_PARAM(I, I);
823   // CHECK-FIXES-NEXT: THREE_PARAM(I, I, I);
824 }
825 
826 } // namespace Macros
827 
828 namespace Templates {
829 
830 template <class Container>
set_union(Container & container)831 void set_union(Container &container) {
832   for (typename Container::const_iterator SI = container.begin(),
833        SE = container.end(); SI != SE; ++SI) {
834     (void) *SI;
835   }
836 
837   S Ss;
838   for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI)
839     (void) *SI;
840   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
841   // CHECK-FIXES: for (auto & SI : Ss)
842 }
843 
template_instantiation()844 void template_instantiation() {
845   S Ss;
846   set_union(Ss);
847 }
848 
849 } // namespace Templates
850 
851 namespace Lambdas {
852 
capturesIndex()853 void capturesIndex() {
854   const int N = 10;
855   int Arr[N];
856   // FIXME: the next four loops could be convertible, if the capture list is
857   // also changed.
858 
859   for (int I = 0; I < N; ++I)
860     auto F1 = [Arr, I]() { int R1 = Arr[I] + 1; };
861   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
862   // CHECK-FIXES: for (int I : Arr)
863   // CHECK-FIXES-NEXT: auto F1 = [Arr, &I]() { int R1 = I + 1; };
864 
865   for (int I = 0; I < N; ++I)
866     auto F2 = [Arr, &I]() { int R2 = Arr[I] + 3; };
867   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
868   // CHECK-FIXES: for (int I : Arr)
869   // CHECK-FIXES-NEXT: auto F2 = [Arr, &I]() { int R2 = I + 3; };
870 
871   // FIXME: alias don't work if the index is captured.
872   // Alias declared inside lambda (by value).
873   for (int I = 0; I < N; ++I)
874     auto F3 = [&Arr, I]() { int R3 = Arr[I]; };
875   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
876   // CHECK-FIXES: for (int I : Arr)
877   // CHECK-FIXES-NEXT: auto F3 = [&Arr, &I]() { int R3 = I; };
878 
879 
880   for (int I = 0; I < N; ++I)
881     auto F4 = [&Arr, &I]() { int R4 = Arr[I]; };
882   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
883   // CHECK-FIXES: for (int I : Arr)
884   // CHECK-FIXES-NEXT: auto F4 = [&Arr, &I]() { int R4 = I; };
885 
886   // Alias declared inside lambda (by reference).
887   for (int I = 0; I < N; ++I)
888     auto F5 = [&Arr, I]() { int &R5 = Arr[I]; };
889   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
890   // CHECK-FIXES: for (int & I : Arr)
891   // CHECK-FIXES-NEXT: auto F5 = [&Arr, &I]() { int &R5 = I; };
892 
893 
894   for (int I = 0; I < N; ++I)
895     auto F6 = [&Arr, &I]() { int &R6 = Arr[I]; };
896   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
897   // CHECK-FIXES: for (int & I : Arr)
898   // CHECK-FIXES-NEXT: auto F6 = [&Arr, &I]() { int &R6 = I; };
899 
900   for (int I = 0; I < N; ++I) {
901     auto F = [Arr, I](int k) {
902       printf("%d\n", Arr[I] + k);
903     };
904     F(Arr[I]);
905   }
906   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
907   // CHECK-FIXES: for (int I : Arr)
908   // CHECK-FIXES-NEXT: auto F = [Arr, &I](int k)
909   // CHECK-FIXES-NEXT: printf("%d\n", I + k);
910   // CHECK-FIXES: F(I);
911 }
912 
implicitCapture()913 void implicitCapture() {
914   const int N = 10;
915   int Arr[N];
916   // Index is used, not convertible.
917   for (int I = 0; I < N; ++I) {
918     auto G1 = [&]() {
919       int R = Arr[I];
920       int J = I;
921     };
922   }
923 
924   for (int I = 0; I < N; ++I) {
925     auto G2 = [=]() {
926       int R = Arr[I];
927       int J = I;
928     };
929   }
930 
931   // Convertible.
932   for (int I = 0; I < N; ++I) {
933     auto G3 = [&]() {
934       int R3 = Arr[I];
935       int J3 = Arr[I] + R3;
936     };
937   }
938   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
939   // CHECK-FIXES: for (int I : Arr)
940   // CHECK-FIXES-NEXT: auto G3 = [&]()
941   // CHECK-FIXES-NEXT: int R3 = I;
942   // CHECK-FIXES-NEXT: int J3 = I + R3;
943 
944   for (int I = 0; I < N; ++I) {
945     auto G4 = [=]() {
946       int R4 = Arr[I] + 5;
947     };
948   }
949   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
950   // CHECK-FIXES: for (int I : Arr)
951   // CHECK-FIXES-NEXT: auto G4 = [=]()
952   // CHECK-FIXES-NEXT: int R4 = I + 5;
953 
954   // Alias by value.
955   for (int I = 0; I < N; ++I) {
956     auto G5 = [&]() {
957       int R5 = Arr[I];
958       int J5 = 8 + R5;
959     };
960   }
961   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
962   // CHECK-FIXES: for (int R5 : Arr)
963   // CHECK-FIXES-NEXT: auto G5 = [&]()
964   // CHECK-FIXES-NEXT: int J5 = 8 + R5;
965 
966   // Alias by reference.
967   for (int I = 0; I < N; ++I) {
968     auto G6 = [&]() {
969       int &R6 = Arr[I];
970       int J6 = -1 + R6;
971     };
972   }
973   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
974   // CHECK-FIXES: for (int & R6 : Arr)
975   // CHECK-FIXES-NEXT: auto G6 = [&]()
976   // CHECK-FIXES-NEXT: int J6 = -1 + R6;
977 }
978 
iterators()979 void iterators() {
980   dependent<int> Dep;
981 
982   for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)
983     auto H1 = [&I]() { int R = *I; };
984   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
985   // CHECK-FIXES: for (int & I : Dep)
986   // CHECK-FIXES-NEXT: auto H1 = [&I]() { int R = I; };
987 
988   for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)
989     auto H2 = [&]() { int R = *I + 2; };
990   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
991   // CHECK-FIXES: for (int & I : Dep)
992   // CHECK-FIXES-NEXT: auto H2 = [&]() { int R = I + 2; };
993 
994   // FIXME: It doesn't work with const iterators.
995   for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
996        I != E; ++I)
997     auto H3 = [I]() { int R = *I; };
998 
999   for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
1000        I != E; ++I)
1001     auto H4 = [&]() { int R = *I + 1; };
1002 
1003   for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
1004        I != E; ++I)
1005     auto H5 = [=]() { int R = *I; };
1006 }
1007 
captureByValue()1008 void captureByValue() {
1009   // When the index is captured by value, we should replace this by a capture
1010   // by reference. This avoids extra copies.
1011   // FIXME: this could change semantics on array or pseudoarray loops if the
1012   // container is captured by copy.
1013   const int N = 10;
1014   int Arr[N];
1015   dependent<int> Dep;
1016 
1017   for (int I = 0; I < N; ++I) {
1018     auto C1 = [&Arr, I]() { if (Arr[I] == 1); };
1019   }
1020   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1021   // CHECK-FIXES: for (int I : Arr)
1022   // CHECK-FIXES-NEXT: auto C1 = [&Arr, &I]() { if (I == 1); };
1023 
1024   for (unsigned I = 0; I < Dep.size(); ++I) {
1025     auto C2 = [&Dep, I]() { if (Dep[I] == 2); };
1026   }
1027   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1028   // CHECK-FIXES: for (int I : Dep)
1029   // CHECK-FIXES-NEXT: auto C2 = [&Dep, &I]() { if (I == 2); };
1030 }
1031 
1032 } // namespace Lambdas
1033 
1034 namespace InitLists {
1035 
1036 struct D { int Ii; };
1037 struct E { D Dd; };
1038 int g(int B);
1039 
f()1040 void f() {
1041   const unsigned N = 3;
1042   int Array[N];
1043 
1044   // Subtrees of InitListExpr are visited twice. Test that we do not do repeated
1045   // replacements.
1046   for (unsigned I = 0; I < N; ++I) {
1047     int A{ Array[I] };
1048     int B{ g(Array[I]) };
1049     int C{ g( { Array[I] } ) };
1050     D Dd{ { g( { Array[I] } ) } };
1051     E Ee{ { { g( { Array[I] } ) } } };
1052   }
1053   // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
1054   // CHECK-FIXES: for (int I : Array)
1055   // CHECK-FIXES-NEXT: int A{ I };
1056   // CHECK-FIXES-NEXT: int B{ g(I) };
1057   // CHECK-FIXES-NEXT: int C{ g( { I } ) };
1058   // CHECK-FIXES-NEXT: D Dd{ { g( { I } ) } };
1059   // CHECK-FIXES-NEXT: E Ee{ { { g( { I } ) } } };
1060 }
1061 
1062 } // namespace InitLists
1063 
bug28341()1064 void bug28341() {
1065   char v[5];
1066   for(int i = 0; i < 5; ++i) {
1067       unsigned char value = v[i];
1068       if (value > 127)
1069         ;
1070   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
1071   // CHECK-FIXES: for(unsigned char value : v)
1072   // CHECK-FIXES-NEXT: if (value > 127)
1073   }
1074 }
1075