1 // RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -I %S/Inputs/modernize-loop-convert
2 
3 #include "structures.h"
4 
5 namespace Array {
6 
7 const int N = 6;
8 const int NMinusOne = N - 1;
9 int Arr[N] = {1, 2, 3, 4, 5, 6};
10 const int ConstArr[N] = {1, 2, 3, 4, 5, 6};
11 int (*PArr)[N] = &Arr;
12 
f()13 void f() {
14   int Sum = 0;
15 
16   for (int I = 0; I < N; ++I) {
17     Sum += Arr[I];
18     int K;
19   }
20   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead [modernize-loop-convert]
21   // CHECK-FIXES: for (int I : Arr)
22   // CHECK-FIXES-NEXT: Sum += I;
23   // CHECK-FIXES-NEXT: int K;
24 
25   for (int I = 0; I < N; ++I) {
26     printf("Fibonacci number is %d\n", Arr[I]);
27     Sum += Arr[I] + 2;
28   }
29   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
30   // CHECK-FIXES: for (int I : Arr)
31   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
32   // CHECK-FIXES-NEXT: Sum += I + 2;
33 
34   for (int I = 0; I < N; ++I) {
35     int X = Arr[I];
36     int Y = Arr[I] + 2;
37   }
38   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
39   // CHECK-FIXES: for (int I : Arr)
40   // CHECK-FIXES-NEXT: int X = I;
41   // CHECK-FIXES-NEXT: int Y = I + 2;
42 
43   for (int I = 0; I < N; ++I) {
44     int X = N;
45     X = Arr[I];
46   }
47   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
48   // CHECK-FIXES: for (int I : Arr)
49   // CHECK-FIXES-NEXT: int X = N;
50   // CHECK-FIXES-NEXT: X = I;
51 
52   for (int I = 0; I < N; ++I) {
53     Arr[I] += 1;
54   }
55   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
56   // CHECK-FIXES: for (int & I : Arr)
57   // CHECK-FIXES-NEXT: I += 1;
58 
59   for (int I = 0; I < N; ++I) {
60     int X = Arr[I] + 2;
61     Arr[I]++;
62   }
63   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
64   // CHECK-FIXES: for (int & I : Arr)
65   // CHECK-FIXES-NEXT: int X = I + 2;
66   // CHECK-FIXES-NEXT: I++;
67 
68   for (int I = 0; I < N; ++I) {
69     Arr[I] = 4 + Arr[I];
70   }
71   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
72   // CHECK-FIXES: for (int & I : Arr)
73   // CHECK-FIXES-NEXT: I = 4 + I;
74 
75   for (int I = 0; I < NMinusOne + 1; ++I) {
76     Sum += Arr[I];
77   }
78   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
79   // CHECK-FIXES: for (int I : Arr)
80   // CHECK-FIXES-NEXT: Sum += I;
81 
82   for (int I = 0; I < N; ++I) {
83     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
84     Sum += Arr[I] + 2;
85   }
86   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
87   // CHECK-FIXES: for (int & I : Arr)
88   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
89   // CHECK-FIXES-NEXT: Sum += I + 2;
90 
91   Val Teas[N];
92   for (int I = 0; I < N; ++I) {
93     Teas[I].g();
94   }
95   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
96   // CHECK-FIXES: for (auto & Tea : Teas)
97   // CHECK-FIXES-NEXT: Tea.g();
98 
99   for (int I = 0; N > I; ++I) {
100     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
101     Sum += Arr[I] + 2;
102   }
103   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
104   // CHECK-FIXES: for (int & I : Arr)
105   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
106   // CHECK-FIXES-NEXT: Sum += I + 2;
107 
108   for (int I = 0; N != I; ++I) {
109     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
110     Sum += Arr[I] + 2;
111   }
112   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
113   // CHECK-FIXES: for (int & I : Arr)
114   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
115   // CHECK-FIXES-NEXT: Sum += I + 2;
116 
117   for (int I = 0; I != N; ++I) {
118     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
119     Sum += Arr[I] + 2;
120   }
121   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
122   // CHECK-FIXES: for (int & I : Arr)
123   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
124   // CHECK-FIXES-NEXT: Sum += I + 2;
125 }
126 
constArray()127 const int *constArray() {
128   for (int I = 0; I < N; ++I) {
129     printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
130   }
131   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
132   // CHECK-FIXES: for (int I : ConstArr)
133   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I, I + I);
134 
135   const NonTriviallyCopyable NonCopy[N]{};
136   for (int I = 0; I < N; ++I) {
137     printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);
138   }
139   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
140   // CHECK-FIXES: for (const auto & I : NonCopy)
141   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
142 
143   const TriviallyCopyableButBig Big[N]{};
144   for (int I = 0; I < N; ++I) {
145     printf("2 * %d = %d\n", Big[I].X, Big[I].X + Big[I].X);
146   }
147   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
148   // CHECK-FIXES: for (const auto & I : Big)
149   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
150 
151   bool Something = false;
152   for (int I = 0; I < N; ++I) {
153     if (Something)
154       return &ConstArr[I];
155   }
156   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
157   // CHECK-FIXES: for (const int & I : ConstArr)
158   // CHECK-FIXES-NEXT: if (Something)
159   // CHECK-FIXES-NEXT: return &I;
160 }
161 
162 struct HasArr {
163   int Arr[N];
164   Val ValArr[N];
implicitThisArray::HasArr165   void implicitThis() {
166     for (int I = 0; I < N; ++I) {
167       printf("%d", Arr[I]);
168     }
169     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
170     // CHECK-FIXES: for (int I : Arr)
171     // CHECK-FIXES-NEXT: printf("%d", I);
172 
173     for (int I = 0; I < N; ++I) {
174       printf("%d", ValArr[I].X);
175     }
176     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
177     // CHECK-FIXES: for (auto & I : ValArr)
178     // CHECK-FIXES-NEXT: printf("%d", I.X);
179   }
180 
explicitThisArray::HasArr181   void explicitThis() {
182     for (int I = 0; I < N; ++I) {
183       printf("%d", this->Arr[I]);
184     }
185     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
186     // CHECK-FIXES: for (int I : this->Arr)
187     // CHECK-FIXES-NEXT: printf("%d", I);
188 
189     for (int I = 0; I < N; ++I) {
190       printf("%d", this->ValArr[I].X);
191     }
192     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
193     // CHECK-FIXES: for (auto & I : this->ValArr)
194     // CHECK-FIXES-NEXT: printf("%d", I.X);
195   }
196 };
197 
198 struct HasIndirectArr {
199   HasArr HA;
implicitThisArray::HasIndirectArr200   void implicitThis() {
201     for (int I = 0; I < N; ++I) {
202       printf("%d", HA.Arr[I]);
203     }
204     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
205     // CHECK-FIXES: for (int I : HA.Arr)
206     // CHECK-FIXES-NEXT: printf("%d", I);
207 
208     for (int I = 0; I < N; ++I) {
209       printf("%d", HA.ValArr[I].X);
210     }
211     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
212     // CHECK-FIXES: for (auto & I : HA.ValArr)
213     // CHECK-FIXES-NEXT: printf("%d", I.X);
214   }
215 
explicitThisArray::HasIndirectArr216   void explicitThis() {
217     for (int I = 0; I < N; ++I) {
218       printf("%d", this->HA.Arr[I]);
219     }
220     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
221     // CHECK-FIXES: for (int I : this->HA.Arr)
222     // CHECK-FIXES-NEXT: printf("%d", I);
223 
224     for (int I = 0; I < N; ++I) {
225       printf("%d", this->HA.ValArr[I].X);
226     }
227     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
228     // CHECK-FIXES: for (auto & I : this->HA.ValArr)
229     // CHECK-FIXES-NEXT: printf("%d", I.X);
230   }
231 };
232 
233 // Loops whose bounds are value-dependent should not be converted.
234 template <int N>
dependentExprBound()235 void dependentExprBound() {
236   for (int I = 0; I < N; ++I)
237     Arr[I] = 0;
238 }
239 template void dependentExprBound<20>();
240 
memberFunctionPointer()241 void memberFunctionPointer() {
242   Val V;
243   void (Val::*mfpArr[N])(void) = {&Val::g};
244   for (int I = 0; I < N; ++I)
245     (V.*mfpArr[I])();
246   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
247   // CHECK-FIXES: for (auto & I : mfpArr)
248   // CHECK-FIXES-NEXT: (V.*I)();
249 
250   struct Foo {
251     int (Val::*f)();
252   } Foo[N];
253 
254   for (int I = 0; I < N; ++I)
255     int R = (V.*(Foo[I].f))();
256   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
257   // CHECK-FIXES: for (auto & I : Foo)
258   // CHECK-FIXES-NEXT: int R = (V.*(I.f))();
259 
260 }
261 
262 } // namespace Array
263 
264 namespace Iterator {
265 
f()266 void f() {
267   /// begin()/end() - based for loops here:
268   T Tt;
269   for (T::iterator It = Tt.begin(), E = Tt.end(); It != E; ++It) {
270     printf("I found %d\n", *It);
271   }
272   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
273   // CHECK-FIXES: for (int & It : Tt)
274   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
275 
276   T *Pt;
277   for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {
278     printf("I found %d\n", *It);
279   }
280   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
281   // CHECK-FIXES: for (int & It : *Pt)
282   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
283 
284   S Ss;
285   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
286     printf("s has value %d\n", (*It).X);
287   }
288   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
289   // CHECK-FIXES: for (auto & It : Ss)
290   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
291 
292   S *Ps;
293   for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
294     printf("s has value %d\n", (*It).X);
295   }
296   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
297   // CHECK-FIXES: for (auto & P : *Ps)
298   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
299 
300   for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
301     printf("s has value %d\n", (*It).X);
302   }
303   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
304   // CHECK-FIXES: for (auto It : Ss)
305   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
306 
307   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
308     printf("s has value %d\n", It->X);
309   }
310   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
311   // CHECK-FIXES: for (auto & It : Ss)
312   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
313 
314   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
315     It->X = 3;
316   }
317   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
318   // CHECK-FIXES: for (auto & It : Ss)
319   // CHECK-FIXES-NEXT: It.X = 3;
320 
321   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
322     (*It).X = 3;
323   }
324   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
325   // CHECK-FIXES: for (auto & It : Ss)
326   // CHECK-FIXES-NEXT: It.X = 3;
327 
328   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
329     It->nonConstFun(4, 5);
330   }
331   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
332   // CHECK-FIXES: for (auto & It : Ss)
333   // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
334 
335   U Uu;
336   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
337     printf("s has value %d\n", It->X);
338   }
339   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
340   // CHECK-FIXES: for (auto & It : Uu)
341   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
342 
343   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
344     printf("s has value %d\n", (*It).X);
345   }
346   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
347   // CHECK-FIXES: for (auto & It : Uu)
348   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
349 
350   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
351     Val* a = It.operator->();
352   }
353 
354   U::iterator A;
355   for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I)
356     int K = A->X + I->X;
357   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
358   // CHECK-FIXES: for (auto & I : Uu)
359   // CHECK-FIXES-NEXT: int K = A->X + I.X;
360 
361   dependent<int> V;
362   for (dependent<int>::iterator It = V.begin(), E = V.end();
363        It != E; ++It) {
364     printf("Fibonacci number is %d\n", *It);
365   }
366   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
367   // CHECK-FIXES: for (int & It : V)
368   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
369 
370   for (dependent<int>::iterator It(V.begin()), E = V.end();
371        It != E; ++It) {
372     printf("Fibonacci number is %d\n", *It);
373   }
374   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
375   // CHECK-FIXES: for (int & It : V)
376   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
377 
378   doublyDependent<int, int> Intmap;
379   for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end();
380        It != E; ++It) {
381     printf("Intmap[%d] = %d", It->first, It->second);
382   }
383   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
384   // CHECK-FIXES: for (auto & It : Intmap)
385   // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second);
386 
387   // PtrSet's iterator dereferences by value so auto & can't be used.
388   {
389     PtrSet<int *> Val_int_ptrs;
390     for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(),
391                                  E = Val_int_ptrs.end();
392          I != E; ++I) {
393       (void) *I;
394     }
395     // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
396     // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
397   }
398 
399   // This container uses an iterator where the dereference type is a typedef of
400   // a reference type. Make sure non-const auto & is still used. A failure here
401   // means canonical types aren't being tested.
402   {
403     TypedefDerefContainer<int> Int_ptrs;
404     for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(),
405                                               E = Int_ptrs.end();
406          I != E; ++I) {
407       (void) *I;
408     }
409     // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
410     // CHECK-FIXES: for (int & Int_ptr : Int_ptrs)
411   }
412 
413   {
414     // Iterators returning an rvalue reference should disqualify the loop from
415     // transformation.
416     RValueDerefContainer<int> Container;
417     for (RValueDerefContainer<int>::iterator I = Container.begin(),
418                                              E = Container.end();
419          I != E; ++I) {
420       (void) *I;
421     }
422   }
423 
424   dependent<Val *> Dpp;
425   for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
426     printf("%d\n", (**I).X);
427   }
428   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
429   // CHECK-FIXES: for (auto & I : Dpp)
430   // CHECK-FIXES-NEXT: printf("%d\n", (*I).X);
431 
432   for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
433     printf("%d\n", (*I)->X);
434   }
435   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
436   // CHECK-FIXES: for (auto & I : Dpp)
437   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
438 }
439 
440 // Tests to verify the proper use of auto where the init variable type and the
441 // initializer type differ or are mostly the same except for const qualifiers.
different_type()442 void different_type() {
443   // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
444   // differs from const_iterator only on the const qualification.
445   S Ss;
446   for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
447     printf("s has value %d\n", (*It).X);
448   }
449   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
450   // CHECK-FIXES: for (auto It : Ss)
451   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
452 
453   S *Ps;
454   for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
455     printf("s has value %d\n", (*It).X);
456   }
457   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
458   // CHECK-FIXES: for (auto P : *Ps)
459   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
460 
461   dependent<int> V;
462   for (dependent<int>::const_iterator It = V.begin(), E = V.end();
463        It != E; ++It) {
464     printf("Fibonacci number is %d\n", *It);
465   }
466   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
467   // CHECK-FIXES: for (int It : V)
468   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
469 
470   for (dependent<int>::const_iterator It(V.begin()), E = V.end();
471        It != E; ++It) {
472     printf("Fibonacci number is %d\n", *It);
473   }
474   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
475   // CHECK-FIXES: for (int It : V)
476   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
477 }
478 
479 // Tests to ensure that an implicit 'this' is picked up as the container.
480 // If member calls are made to 'this' within the loop, the transform becomes
481 // risky as these calls may affect state that affects the loop.
482 class C {
483 public:
484   typedef MutableVal *iterator;
485   typedef const MutableVal *const_iterator;
486 
487   iterator begin();
488   iterator end();
489   const_iterator begin() const;
490   const_iterator end() const;
491 
492   void doSomething();
493   void doSomething() const;
494 
doLoop()495   void doLoop() {
496     for (iterator I = begin(), E = end(); I != E; ++I)
497       (void) *I;
498     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
499     // CHECK-FIXES: for (auto & I : *this)
500 
501     for (iterator I = C::begin(), E = C::end(); I != E; ++I)
502       (void) *I;
503     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
504     // CHECK-FIXES: for (auto & I : *this)
505 
506     for (iterator I = begin(), E = end(); I != E; ++I) {
507       (void) *I;
508       doSomething();
509     }
510 
511     for (iterator I = begin(); I != end(); ++I)
512       (void) *I;
513     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
514     // CHECK-FIXES: for (auto & I : *this)
515 
516     for (iterator I = begin(); I != end(); ++I) {
517       (void) *I;
518       doSomething();
519     }
520   }
521 
doLoop() const522   void doLoop() const {
523     for (const_iterator I = begin(), E = end(); I != E; ++I)
524       (void) *I;
525     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
526     // CHECK-FIXES: for (auto I : *this)
527 
528     for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
529       (void) *I;
530     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
531     // CHECK-FIXES: for (auto I : *this)
532 
533     for (const_iterator I = begin(), E = end(); I != E; ++I) {
534       (void) *I;
535       doSomething();
536     }
537   }
538 };
539 
540 class C2 {
541 public:
542   typedef MutableVal *iterator;
543 
544   iterator begin() const;
545   iterator end() const;
546 
doLoop()547   void doLoop() {
548     // The implicit 'this' will have an Implicit cast to const C2* wrapped
549     // around it. Make sure the replacement still happens.
550     for (iterator I = begin(), E = end(); I != E; ++I)
551       (void) *I;
552     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
553     // CHECK-FIXES: for (auto & I : *this)
554   }
555 };
556 
557 } // namespace Iterator
558 
559 namespace PseudoArray {
560 
561 const int N = 6;
562 dependent<int> V;
563 dependent<int> *Pv;
564 const dependent<NonTriviallyCopyable> Constv;
565 const dependent<NonTriviallyCopyable> *Pconstv;
566 
567 transparent<dependent<int>> Cv;
568 
f()569 void f() {
570   int Sum = 0;
571   for (int I = 0, E = V.size(); I < E; ++I) {
572     printf("Fibonacci number is %d\n", V[I]);
573     Sum += V[I] + 2;
574   }
575   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
576   // CHECK-FIXES: for (int I : V)
577   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
578   // CHECK-FIXES-NEXT: Sum += I + 2;
579 
580   for (int I = 0, E = V.size(); I < E; ++I) {
581     printf("Fibonacci number is %d\n", V.at(I));
582     Sum += V.at(I) + 2;
583   }
584   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
585   // CHECK-FIXES: for (int I : V)
586   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
587   // CHECK-FIXES-NEXT: Sum += I + 2;
588 
589   for (int I = 0, E = Pv->size(); I < E; ++I) {
590     printf("Fibonacci number is %d\n", Pv->at(I));
591     Sum += Pv->at(I) + 2;
592   }
593   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
594   // CHECK-FIXES: for (int I : *Pv)
595   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
596   // CHECK-FIXES-NEXT: Sum += I + 2;
597 
598   // This test will fail if size() isn't called repeatedly, since it
599   // returns unsigned int, and 0 is deduced to be signed int.
600   // FIXME: Insert the necessary explicit conversion, or write out the types
601   // explicitly.
602   for (int I = 0; I < Pv->size(); ++I) {
603     printf("Fibonacci number is %d\n", (*Pv).at(I));
604     Sum += (*Pv)[I] + 2;
605   }
606   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
607   // CHECK-FIXES: for (int I : *Pv)
608   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
609   // CHECK-FIXES-NEXT: Sum += I + 2;
610 
611   for (int I = 0; I < Cv->size(); ++I) {
612     printf("Fibonacci number is %d\n", Cv->at(I));
613     Sum += Cv->at(I) + 2;
614   }
615   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
616   // CHECK-FIXES: for (int I : *Cv)
617   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
618   // CHECK-FIXES-NEXT: Sum += I + 2;
619 
620   for (int I = 0, E = V.size(); E > I; ++I) {
621     printf("Fibonacci number is %d\n", V[I]);
622     Sum += V[I] + 2;
623   }
624   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
625   // CHECK-FIXES: for (int I : V)
626   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
627   // CHECK-FIXES-NEXT: Sum += I + 2;
628 
629   for (int I = 0, E = V.size(); I != E; ++I) {
630     printf("Fibonacci number is %d\n", V[I]);
631     Sum += V[I] + 2;
632   }
633   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
634   // CHECK-FIXES: for (int I : V)
635   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
636   // CHECK-FIXES-NEXT: Sum += I + 2;
637 
638   for (int I = 0, E = V.size(); E != I; ++I) {
639     printf("Fibonacci number is %d\n", V[I]);
640     Sum += V[I] + 2;
641   }
642   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
643   // CHECK-FIXES: for (int I : V)
644   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
645   // CHECK-FIXES-NEXT: Sum += I + 2;
646 }
647 
648 // Ensure that 'const auto &' is used with containers of non-trivial types.
constness()649 void constness() {
650   int Sum = 0;
651   for (int I = 0, E = Constv.size(); I < E; ++I) {
652     printf("Fibonacci number is %d\n", Constv[I].X);
653     Sum += Constv[I].X + 2;
654   }
655   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
656   // CHECK-FIXES: for (const auto & I : Constv)
657   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
658   // CHECK-FIXES-NEXT: Sum += I.X + 2;
659 
660   for (int I = 0, E = Constv.size(); I < E; ++I) {
661     printf("Fibonacci number is %d\n", Constv.at(I).X);
662     Sum += Constv.at(I).X + 2;
663   }
664   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
665   // CHECK-FIXES: for (const auto & I : Constv)
666   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
667   // CHECK-FIXES-NEXT: Sum += I.X + 2;
668 
669   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
670     printf("Fibonacci number is %d\n", Pconstv->at(I).X);
671     Sum += Pconstv->at(I).X + 2;
672   }
673   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
674   // CHECK-FIXES: for (const auto & I : *Pconstv)
675   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
676   // CHECK-FIXES-NEXT: Sum += I.X + 2;
677 
678   // This test will fail if size() isn't called repeatedly, since it
679   // returns unsigned int, and 0 is deduced to be signed int.
680   // FIXME: Insert the necessary explicit conversion, or write out the types
681   // explicitly.
682   for (int I = 0; I < Pconstv->size(); ++I) {
683     printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
684     Sum += (*Pconstv)[I].X + 2;
685   }
686   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
687   // CHECK-FIXES: for (const auto & I : *Pconstv)
688   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
689   // CHECK-FIXES-NEXT: Sum += I.X + 2;
690 }
691 
constRef(const dependent<int> & ConstVRef)692 void constRef(const dependent<int>& ConstVRef) {
693   int sum = 0;
694   // FIXME: This does not work with size_t (probably due to the implementation
695   // of dependent); make dependent work exactly like a std container type.
696   for (int I = 0; I < ConstVRef.size(); ++I) {
697     sum += ConstVRef[I];
698   }
699   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
700   // CHECK-FIXES: for (int I : ConstVRef)
701   // CHECK-FIXES-NEXT: sum += I;
702 
703   for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
704     sum += *I;
705   }
706   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
707   // CHECK-FIXES: for (int I : ConstVRef)
708   // CHECK-FIXES-NEXT: sum += I;
709 }
710 
711 // Check for loops that don't mention containers.
noContainer()712 void noContainer() {
713   for (auto I = 0; I < V.size(); ++I) {
714   }
715 
716   for (auto I = 0; I < V.size(); ++I)
717     ;
718 }
719 
720 struct NoBeginEnd {
721   unsigned size() const;
722   unsigned& operator[](int);
723   const unsigned& operator[](int) const;
724 };
725 
726 struct NoConstBeginEnd {
727   NoConstBeginEnd();
728   unsigned size() const;
729   unsigned* begin();
730   unsigned* end();
731   unsigned& operator[](int);
732   const unsigned& operator[](int) const;
733 };
734 
735 struct ConstBeginEnd {
736   ConstBeginEnd();
737   unsigned size() const;
738   unsigned* begin() const;
739   unsigned* end() const;
740   unsigned& operator[](int);
741   const unsigned& operator[](int) const;
742 };
743 
744 // Shouldn't transform pseudo-array uses if the container doesn't provide
745 // begin() and end() of the right const-ness.
NoBeginEndTest()746 void NoBeginEndTest() {
747   NoBeginEnd NBE;
748   for (unsigned I = 0, E = NBE.size(); I < E; ++I)
749     printf("%d\n", NBE[I]);
750 
751   const NoConstBeginEnd Const_NCBE;
752   for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
753     printf("%d\n", Const_NCBE[I]);
754 
755   ConstBeginEnd CBE;
756   for (unsigned I = 0, E = CBE.size(); I < E; ++I)
757     printf("%d\n", CBE[I]);
758   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
759   // CHECK-FIXES: for (unsigned int I : CBE)
760   // CHECK-FIXES-NEXT: printf("%d\n", I);
761 
762   const ConstBeginEnd Const_CBE;
763   for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
764     printf("%d\n", Const_CBE[I]);
765   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
766   // CHECK-FIXES: for (unsigned int I : Const_CBE)
767   // CHECK-FIXES-NEXT: printf("%d\n", I);
768 }
769 
770 struct DerefByValue {
771   DerefByValue();
772   struct iter { unsigned operator*(); };
773   unsigned size() const;
774   iter begin();
775   iter end();
776   unsigned operator[](int);
777 };
778 
derefByValueTest()779 void derefByValueTest() {
780   DerefByValue DBV;
781   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
782     printf("%d\n", DBV[I]);
783   }
784   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
785   // CHECK-FIXES: for (unsigned int I : DBV)
786   // CHECK-FIXES-NEXT: printf("%d\n", I);
787 
788   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
789     auto f = [DBV, I]() {};
790     printf("%d\n", DBV[I]);
791   }
792   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
793   // CHECK-FIXES: for (unsigned int I : DBV)
794   // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
795   // CHECK-FIXES-NEXT: printf("%d\n", I);
796 }
797 
fundamentalTypesTest()798 void fundamentalTypesTest() {
799   const int N = 10;
800   bool Bools[N];
801   for (int i = 0; i < N; ++i)
802     printf("%d", Bools[i]);
803   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
804   // CHECK-FIXES: for (bool Bool : Bools)
805 
806   int Ints[N];
807   unsigned short int Shorts[N];
808   for (int i = 0; i < N; ++i)
809     printf("%d", Shorts[i]);
810   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
811   // CHECK-FIXES: for (unsigned short Short : Shorts)
812 
813   signed long Longs[N];
814   for (int i = 0; i < N; ++i)
815     printf("%d", Longs[i]);
816   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
817   // CHECK-FIXES: for (long Long : Longs)
818 
819   long long int LongLongs[N];
820   for (int i = 0; i < N; ++i)
821     printf("%d", LongLongs[i]);
822   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
823   // CHECK-FIXES: for (long long LongLong : LongLongs)
824 
825   char Chars[N];
826   for (int i = 0; i < N; ++i)
827     printf("%d", Chars[i]);
828   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
829   // CHECK-FIXES: for (char Char : Chars)
830 
831   wchar_t WChars[N];
832   for (int i = 0; i < N; ++i)
833     printf("%d", WChars[i]);
834   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
835   // CHECK-FIXES: for (wchar_t WChar : WChars)
836 
837   float Floats[N];
838   for (int i = 0; i < N; ++i)
839     printf("%d", Floats[i]);
840   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
841   // CHECK-FIXES: for (float Float : Floats)
842 
843   double Doubles[N];
844   for (int i = 0; i < N; ++i)
845     printf("%d", Doubles[i]);
846   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
847   // CHECK-FIXES: for (double Double : Doubles)
848 }
849 
850 } // namespace PseudoArray
851