1 // RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -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   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 instead
784   // 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 instead
791   // CHECK-FIXES: for (int It : V)
792   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
793 }
794 
795 } // namespace SingleIterator
796 
797 
798 namespace Macros {
799 
800 #define TWO_PARAM(x, y) if (x == y) {}
801 #define THREE_PARAM(x, y, z) if (x == y) {z;}
802 
803 const int N = 10;
804 int Arr[N];
805 
messing_with_macros()806 void 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 instead
811   // 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 instead
824   // 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 Macros
830 
831 namespace Templates {
832 
833 template <class Container>
set_union(Container & container)834 void 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 instead
844   // CHECK-FIXES: for (auto & SI : Ss)
845 }
846 
template_instantiation()847 void template_instantiation() {
848   S Ss;
849   set_union(Ss);
850 }
851 
852 } // namespace Templates
853 
854 namespace Lambdas {
855 
capturesIndex()856 void capturesIndex() {
857   const int N = 10;
858   int Arr[N];
859   // FIXME: the next four loops could be convertible, if the capture list is
860   // 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 instead
865   // 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 instead
871   // 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 instead
879   // 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 instead
886   // 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 instead
893   // 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 instead
900   // 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 instead
910   // 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: F(I);
914 }
915 
implicitCapture()916 void implicitCapture() {
917   const int N = 10;
918   int Arr[N];
919   // Index is used, not convertible.
920   for (int I = 0; I < N; ++I) {
921     auto G1 = [&]() {
922       int R = Arr[I];
923       int J = I;
924     };
925   }
926 
927   for (int I = 0; I < N; ++I) {
928     auto G2 = [=]() {
929       int R = Arr[I];
930       int J = I;
931     };
932   }
933 
934   // Convertible.
935   for (int I = 0; I < N; ++I) {
936     auto G3 = [&]() {
937       int R3 = Arr[I];
938       int J3 = Arr[I] + R3;
939     };
940   }
941   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
942   // CHECK-FIXES: for (int I : Arr)
943   // CHECK-FIXES-NEXT: auto G3 = [&]()
944   // CHECK-FIXES-NEXT: int R3 = I;
945   // CHECK-FIXES-NEXT: int J3 = I + R3;
946 
947   for (int I = 0; I < N; ++I) {
948     auto G4 = [=]() {
949       int R4 = Arr[I] + 5;
950     };
951   }
952   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
953   // CHECK-FIXES: for (int I : Arr)
954   // CHECK-FIXES-NEXT: auto G4 = [=]()
955   // CHECK-FIXES-NEXT: int R4 = I + 5;
956 
957   // Alias by value.
958   for (int I = 0; I < N; ++I) {
959     auto G5 = [&]() {
960       int R5 = Arr[I];
961       int J5 = 8 + R5;
962     };
963   }
964   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
965   // CHECK-FIXES: for (int R5 : Arr)
966   // CHECK-FIXES-NEXT: auto G5 = [&]()
967   // CHECK-FIXES-NEXT: int J5 = 8 + R5;
968 
969   // Alias by reference.
970   for (int I = 0; I < N; ++I) {
971     auto G6 = [&]() {
972       int &R6 = Arr[I];
973       int J6 = -1 + R6;
974     };
975   }
976   // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
977   // CHECK-FIXES: for (int & R6 : Arr)
978   // CHECK-FIXES-NEXT: auto G6 = [&]()
979   // CHECK-FIXES-NEXT: int J6 = -1 + R6;
980 }
981 
iterators()982 void iterators() {
983   dependent<int> Dep;
984 
985   for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)
986     auto H1 = [&I]() { int R = *I; };
987   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
988   // CHECK-FIXES: for (int & I : Dep)
989   // CHECK-FIXES-NEXT: auto H1 = [&I]() { int R = I; };
990 
991   for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)
992     auto H2 = [&]() { int R = *I + 2; };
993   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
994   // CHECK-FIXES: for (int & I : Dep)
995   // CHECK-FIXES-NEXT: auto H2 = [&]() { int R = I + 2; };
996 
997   for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
998        I != E; ++I)
999     auto H3 = [I]() { int R = *I; };
1000   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1001   // CHECK-FIXES: for (int I : Dep)
1002   // CHECK-FIXES-NEXT: auto H3 = [&I]() { int R = I; };
1003 
1004   for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
1005        I != E; ++I)
1006     auto H4 = [&]() { int R = *I + 1; };
1007   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1008   // CHECK-FIXES: for (int I : Dep)
1009   // CHECK-FIXES-NEXT: auto H4 = [&]() { int R = I + 1; };
1010 
1011   for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
1012        I != E; ++I)
1013     auto H5 = [=]() { int R = *I; };
1014   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1015   // CHECK-FIXES: for (int R : Dep)
1016   // CHECK-FIXES-NEXT: auto H5 = [=]() { };
1017 }
1018 
captureByValue()1019 void captureByValue() {
1020   // When the index is captured by value, we should replace this by a capture
1021   // by reference. This avoids extra copies.
1022   // FIXME: this could change semantics on array or pseudoarray loops if the
1023   // container is captured by copy.
1024   const int N = 10;
1025   int Arr[N];
1026   dependent<int> Dep;
1027 
1028   for (int I = 0; I < N; ++I) {
1029     auto C1 = [&Arr, I]() { if (Arr[I] == 1); };
1030   }
1031   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1032   // CHECK-FIXES: for (int I : Arr)
1033   // CHECK-FIXES-NEXT: auto C1 = [&Arr, &I]() { if (I == 1); };
1034 
1035   for (unsigned I = 0; I < Dep.size(); ++I) {
1036     auto C2 = [&Dep, I]() { if (Dep[I] == 2); };
1037   }
1038   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1039   // CHECK-FIXES: for (int I : Dep)
1040   // CHECK-FIXES-NEXT: auto C2 = [&Dep, &I]() { if (I == 2); };
1041 }
1042 
1043 } // namespace Lambdas
1044 
1045 namespace InitLists {
1046 
1047 struct D { int Ii; };
1048 struct E { D Dd; };
1049 int g(int B);
1050 
f()1051 void f() {
1052   const unsigned N = 3;
1053   int Array[N];
1054 
1055   // Subtrees of InitListExpr are visited twice. Test that we do not do repeated
1056   // replacements.
1057   for (unsigned I = 0; I < N; ++I) {
1058     int A{ Array[I] };
1059     int B{ g(Array[I]) };
1060     int C{ g( { Array[I] } ) };
1061     D Dd{ { g( { Array[I] } ) } };
1062     E Ee{ { { g( { Array[I] } ) } } };
1063   }
1064   // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
1065   // CHECK-FIXES: for (int I : Array)
1066   // CHECK-FIXES-NEXT: int A{ I };
1067   // CHECK-FIXES-NEXT: int B{ g(I) };
1068   // CHECK-FIXES-NEXT: int C{ g( { I } ) };
1069   // CHECK-FIXES-NEXT: D Dd{ { g( { I } ) } };
1070   // CHECK-FIXES-NEXT: E Ee{ { { g( { I } ) } } };
1071 }
1072 
1073 } // namespace InitLists
1074 
bug28341()1075 void bug28341() {
1076   char v[5];
1077   for(int i = 0; i < 5; ++i) {
1078       unsigned char value = v[i];
1079       if (value > 127)
1080         ;
1081   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
1082   // CHECK-FIXES: for(unsigned char value : v)
1083   // CHECK-FIXES-NEXT: if (value > 127)
1084   }
1085 }
1086