xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp (revision 89a1d03e2b379e325daa5249411e414bbd995b5e)
1 // RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -I %S/Inputs/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 
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 
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];
165   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 
181   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;
200   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 
216   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>
235 void dependentExprBound() {
236   for (int I = 0; I < N; ++I)
237     Arr[I] = 0;
238 }
239 template void dependentExprBound<20>();
240 
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 
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   // Do not crash because of Qq.begin() converting. Q::iterator converts with a
277   // conversion operator, which has no name, to Q::const_iterator.
278   Q Qq;
279   for (Q::const_iterator It = Qq.begin(), E = Qq.end(); It != E; ++It) {
280     printf("I found %d\n", *It);
281   }
282   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
283   // CHECK-FIXES: for (int & It : Qq)
284   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
285 
286   T *Pt;
287   for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {
288     printf("I found %d\n", *It);
289   }
290   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
291   // CHECK-FIXES: for (int & It : *Pt)
292   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
293 
294   S Ss;
295   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
296     printf("s has value %d\n", (*It).X);
297   }
298   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
299   // CHECK-FIXES: for (auto & It : Ss)
300   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
301 
302   S *Ps;
303   for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
304     printf("s has value %d\n", (*It).X);
305   }
306   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
307   // CHECK-FIXES: for (auto & P : *Ps)
308   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
309 
310   for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
311     printf("s has value %d\n", (*It).X);
312   }
313   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
314   // CHECK-FIXES: for (auto It : Ss)
315   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
316 
317   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
318     printf("s has value %d\n", It->X);
319   }
320   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
321   // CHECK-FIXES: for (auto & It : Ss)
322   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
323 
324   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
325     It->X = 3;
326   }
327   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
328   // CHECK-FIXES: for (auto & It : Ss)
329   // CHECK-FIXES-NEXT: It.X = 3;
330 
331   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
332     (*It).X = 3;
333   }
334   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
335   // CHECK-FIXES: for (auto & It : Ss)
336   // CHECK-FIXES-NEXT: It.X = 3;
337 
338   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
339     It->nonConstFun(4, 5);
340   }
341   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
342   // CHECK-FIXES: for (auto & It : Ss)
343   // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
344 
345   U Uu;
346   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
347     printf("s has value %d\n", It->X);
348   }
349   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
350   // CHECK-FIXES: for (auto & It : Uu)
351   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
352 
353   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
354     printf("s has value %d\n", (*It).X);
355   }
356   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
357   // CHECK-FIXES: for (auto & It : Uu)
358   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
359 
360   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
361     Val* a = It.operator->();
362   }
363 
364   U::iterator A;
365   for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I)
366     int K = A->X + I->X;
367   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
368   // CHECK-FIXES: for (auto & I : Uu)
369   // CHECK-FIXES-NEXT: int K = A->X + I.X;
370 
371   dependent<int> V;
372   for (dependent<int>::iterator It = V.begin(), E = V.end();
373        It != E; ++It) {
374     printf("Fibonacci number is %d\n", *It);
375   }
376   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
377   // CHECK-FIXES: for (int & It : V)
378   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
379 
380   for (dependent<int>::iterator It(V.begin()), E = V.end();
381        It != E; ++It) {
382     printf("Fibonacci number is %d\n", *It);
383   }
384   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
385   // CHECK-FIXES: for (int & It : V)
386   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
387 
388   doublyDependent<int, int> Intmap;
389   for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end();
390        It != E; ++It) {
391     printf("Intmap[%d] = %d", It->first, It->second);
392   }
393   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
394   // CHECK-FIXES: for (auto & It : Intmap)
395   // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second);
396 
397   // PtrSet's iterator dereferences by value so auto & can't be used.
398   {
399     PtrSet<int *> Val_int_ptrs;
400     for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(),
401                                  E = Val_int_ptrs.end();
402          I != E; ++I) {
403       (void) *I;
404     }
405     // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
406     // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
407   }
408 
409   // This container uses an iterator where the dereference type is a typedef of
410   // a reference type. Make sure non-const auto & is still used. A failure here
411   // means canonical types aren't being tested.
412   {
413     TypedefDerefContainer<int> Int_ptrs;
414     for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(),
415                                               E = Int_ptrs.end();
416          I != E; ++I) {
417       (void) *I;
418     }
419     // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
420     // CHECK-FIXES: for (int & Int_ptr : Int_ptrs)
421   }
422 
423   {
424     // Iterators returning an rvalue reference should disqualify the loop from
425     // transformation.
426     RValueDerefContainer<int> Container;
427     for (RValueDerefContainer<int>::iterator I = Container.begin(),
428                                              E = Container.end();
429          I != E; ++I) {
430       (void) *I;
431     }
432   }
433 
434   dependent<Val *> Dpp;
435   for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
436     printf("%d\n", (**I).X);
437   }
438   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
439   // CHECK-FIXES: for (auto & I : Dpp)
440   // CHECK-FIXES-NEXT: printf("%d\n", (*I).X);
441 
442   for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
443     printf("%d\n", (*I)->X);
444   }
445   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
446   // CHECK-FIXES: for (auto & I : Dpp)
447   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
448 }
449 
450 // Tests to verify the proper use of auto where the init variable type and the
451 // initializer type differ or are mostly the same except for const qualifiers.
452 void different_type() {
453   // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
454   // differs from const_iterator only on the const qualification.
455   S Ss;
456   for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
457     printf("s has value %d\n", (*It).X);
458   }
459   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
460   // CHECK-FIXES: for (auto It : Ss)
461   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
462 
463   S *Ps;
464   for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
465     printf("s has value %d\n", (*It).X);
466   }
467   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
468   // CHECK-FIXES: for (auto P : *Ps)
469   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
470 
471   dependent<int> V;
472   for (dependent<int>::const_iterator It = V.begin(), E = V.end();
473        It != E; ++It) {
474     printf("Fibonacci number is %d\n", *It);
475   }
476   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
477   // CHECK-FIXES: for (int It : V)
478   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
479 
480   for (dependent<int>::const_iterator It(V.begin()), E = V.end();
481        It != E; ++It) {
482     printf("Fibonacci number is %d\n", *It);
483   }
484   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
485   // CHECK-FIXES: for (int It : V)
486   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
487 }
488 
489 // Tests to ensure that an implicit 'this' is picked up as the container.
490 // If member calls are made to 'this' within the loop, the transform becomes
491 // risky as these calls may affect state that affects the loop.
492 class C {
493 public:
494   typedef MutableVal *iterator;
495   typedef const MutableVal *const_iterator;
496 
497   iterator begin();
498   iterator end();
499   const_iterator begin() const;
500   const_iterator end() const;
501 
502   void doSomething();
503   void doSomething() const;
504 
505   void doLoop() {
506     for (iterator I = begin(), E = end(); I != E; ++I)
507       (void) *I;
508     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
509     // CHECK-FIXES: for (auto & I : *this)
510 
511     for (iterator I = C::begin(), E = C::end(); I != E; ++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(), E = end(); I != E; ++I) {
517       (void) *I;
518       doSomething();
519     }
520 
521     for (iterator I = begin(); I != end(); ++I)
522       (void) *I;
523     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
524     // CHECK-FIXES: for (auto & I : *this)
525 
526     for (iterator I = begin(); I != end(); ++I) {
527       (void) *I;
528       doSomething();
529     }
530   }
531 
532   void doLoop() const {
533     for (const_iterator I = begin(), E = end(); I != E; ++I)
534       (void) *I;
535     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
536     // CHECK-FIXES: for (auto I : *this)
537 
538     for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
539       (void) *I;
540     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
541     // CHECK-FIXES: for (auto I : *this)
542 
543     for (const_iterator I = begin(), E = end(); I != E; ++I) {
544       (void) *I;
545       doSomething();
546     }
547   }
548 };
549 
550 class C2 {
551 public:
552   typedef MutableVal *iterator;
553 
554   iterator begin() const;
555   iterator end() const;
556 
557   void doLoop() {
558     // The implicit 'this' will have an Implicit cast to const C2* wrapped
559     // around it. Make sure the replacement still happens.
560     for (iterator I = begin(), E = end(); I != E; ++I)
561       (void) *I;
562     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
563     // CHECK-FIXES: for (auto & I : *this)
564   }
565 };
566 
567 } // namespace Iterator
568 
569 namespace PseudoArray {
570 
571 const int N = 6;
572 dependent<int> V;
573 dependent<int> *Pv;
574 const dependent<NonTriviallyCopyable> Constv;
575 const dependent<NonTriviallyCopyable> *Pconstv;
576 
577 transparent<dependent<int>> Cv;
578 
579 void f() {
580   int Sum = 0;
581   for (int I = 0, E = V.size(); I < E; ++I) {
582     printf("Fibonacci number is %d\n", V[I]);
583     Sum += V[I] + 2;
584   }
585   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
586   // CHECK-FIXES: for (int I : V)
587   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
588   // CHECK-FIXES-NEXT: Sum += I + 2;
589 
590   for (int I = 0, E = V.size(); I < E; ++I) {
591     printf("Fibonacci number is %d\n", V.at(I));
592     Sum += V.at(I) + 2;
593   }
594   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
595   // CHECK-FIXES: for (int I : V)
596   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
597   // CHECK-FIXES-NEXT: Sum += I + 2;
598 
599   for (int I = 0, E = Pv->size(); I < E; ++I) {
600     printf("Fibonacci number is %d\n", Pv->at(I));
601     Sum += Pv->at(I) + 2;
602   }
603   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
604   // CHECK-FIXES: for (int I : *Pv)
605   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
606   // CHECK-FIXES-NEXT: Sum += I + 2;
607 
608   // This test will fail if size() isn't called repeatedly, since it
609   // returns unsigned int, and 0 is deduced to be signed int.
610   // FIXME: Insert the necessary explicit conversion, or write out the types
611   // explicitly.
612   for (int I = 0; I < Pv->size(); ++I) {
613     printf("Fibonacci number is %d\n", (*Pv).at(I));
614     Sum += (*Pv)[I] + 2;
615   }
616   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
617   // CHECK-FIXES: for (int I : *Pv)
618   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
619   // CHECK-FIXES-NEXT: Sum += I + 2;
620 
621   for (int I = 0; I < Cv->size(); ++I) {
622     printf("Fibonacci number is %d\n", Cv->at(I));
623     Sum += Cv->at(I) + 2;
624   }
625   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
626   // CHECK-FIXES: for (int I : *Cv)
627   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
628   // CHECK-FIXES-NEXT: Sum += I + 2;
629 
630   for (int I = 0, E = V.size(); E > I; ++I) {
631     printf("Fibonacci number is %d\n", V[I]);
632     Sum += V[I] + 2;
633   }
634   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
635   // CHECK-FIXES: for (int I : V)
636   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
637   // CHECK-FIXES-NEXT: Sum += I + 2;
638 
639   for (int I = 0, E = V.size(); I != E; ++I) {
640     printf("Fibonacci number is %d\n", V[I]);
641     Sum += V[I] + 2;
642   }
643   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
644   // CHECK-FIXES: for (int I : V)
645   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
646   // CHECK-FIXES-NEXT: Sum += I + 2;
647 
648   for (int I = 0, E = V.size(); E != I; ++I) {
649     printf("Fibonacci number is %d\n", V[I]);
650     Sum += V[I] + 2;
651   }
652   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
653   // CHECK-FIXES: for (int I : V)
654   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
655   // CHECK-FIXES-NEXT: Sum += I + 2;
656 }
657 
658 // Ensure that 'const auto &' is used with containers of non-trivial types.
659 void constness() {
660   int Sum = 0;
661   for (int I = 0, E = Constv.size(); I < E; ++I) {
662     printf("Fibonacci number is %d\n", Constv[I].X);
663     Sum += Constv[I].X + 2;
664   }
665   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
666   // CHECK-FIXES: for (const auto & I : Constv)
667   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
668   // CHECK-FIXES-NEXT: Sum += I.X + 2;
669 
670   for (int I = 0, E = Constv.size(); I < E; ++I) {
671     printf("Fibonacci number is %d\n", Constv.at(I).X);
672     Sum += Constv.at(I).X + 2;
673   }
674   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
675   // CHECK-FIXES: for (const auto & I : Constv)
676   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
677   // CHECK-FIXES-NEXT: Sum += I.X + 2;
678 
679   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
680     printf("Fibonacci number is %d\n", Pconstv->at(I).X);
681     Sum += Pconstv->at(I).X + 2;
682   }
683   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
684   // CHECK-FIXES: for (const auto & I : *Pconstv)
685   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
686   // CHECK-FIXES-NEXT: Sum += I.X + 2;
687 
688   // This test will fail if size() isn't called repeatedly, since it
689   // returns unsigned int, and 0 is deduced to be signed int.
690   // FIXME: Insert the necessary explicit conversion, or write out the types
691   // explicitly.
692   for (int I = 0; I < Pconstv->size(); ++I) {
693     printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
694     Sum += (*Pconstv)[I].X + 2;
695   }
696   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
697   // CHECK-FIXES: for (const auto & I : *Pconstv)
698   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
699   // CHECK-FIXES-NEXT: Sum += I.X + 2;
700 }
701 
702 void constRef(const dependent<int>& ConstVRef) {
703   int sum = 0;
704   // FIXME: This does not work with size_t (probably due to the implementation
705   // of dependent); make dependent work exactly like a std container type.
706   for (int I = 0; I < ConstVRef.size(); ++I) {
707     sum += ConstVRef[I];
708   }
709   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
710   // CHECK-FIXES: for (int I : ConstVRef)
711   // CHECK-FIXES-NEXT: sum += I;
712 
713   for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
714     sum += *I;
715   }
716   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
717   // CHECK-FIXES: for (int I : ConstVRef)
718   // CHECK-FIXES-NEXT: sum += I;
719 }
720 
721 // Check for loops that don't mention containers.
722 void noContainer() {
723   for (auto I = 0; I < V.size(); ++I) {
724   }
725 
726   for (auto I = 0; I < V.size(); ++I)
727     ;
728 }
729 
730 struct NoBeginEnd {
731   unsigned size() const;
732   unsigned& operator[](int);
733   const unsigned& operator[](int) const;
734 };
735 
736 struct NoConstBeginEnd {
737   NoConstBeginEnd();
738   unsigned size() const;
739   unsigned* begin();
740   unsigned* end();
741   unsigned& operator[](int);
742   const unsigned& operator[](int) const;
743 };
744 
745 struct ConstBeginEnd {
746   ConstBeginEnd();
747   unsigned size() const;
748   unsigned* begin() const;
749   unsigned* end() const;
750   unsigned& operator[](int);
751   const unsigned& operator[](int) const;
752 };
753 
754 // Shouldn't transform pseudo-array uses if the container doesn't provide
755 // begin() and end() of the right const-ness.
756 void NoBeginEndTest() {
757   NoBeginEnd NBE;
758   for (unsigned I = 0, E = NBE.size(); I < E; ++I)
759     printf("%d\n", NBE[I]);
760 
761   const NoConstBeginEnd Const_NCBE;
762   for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
763     printf("%d\n", Const_NCBE[I]);
764 
765   ConstBeginEnd CBE;
766   for (unsigned I = 0, E = CBE.size(); I < E; ++I)
767     printf("%d\n", CBE[I]);
768   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
769   // CHECK-FIXES: for (unsigned int I : CBE)
770   // CHECK-FIXES-NEXT: printf("%d\n", I);
771 
772   const ConstBeginEnd Const_CBE;
773   for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
774     printf("%d\n", Const_CBE[I]);
775   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
776   // CHECK-FIXES: for (unsigned int I : Const_CBE)
777   // CHECK-FIXES-NEXT: printf("%d\n", I);
778 }
779 
780 struct DerefByValue {
781   DerefByValue();
782   struct iter { unsigned operator*(); };
783   unsigned size() const;
784   iter begin();
785   iter end();
786   unsigned operator[](int);
787 };
788 
789 void derefByValueTest() {
790   DerefByValue DBV;
791   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
792     printf("%d\n", DBV[I]);
793   }
794   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
795   // CHECK-FIXES: for (unsigned int I : DBV)
796   // CHECK-FIXES-NEXT: printf("%d\n", I);
797 
798   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
799     auto f = [DBV, I]() {};
800     printf("%d\n", DBV[I]);
801   }
802   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
803   // CHECK-FIXES: for (unsigned int I : DBV)
804   // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
805   // CHECK-FIXES-NEXT: printf("%d\n", I);
806 }
807 
808 void fundamentalTypesTest() {
809   const int N = 10;
810   bool Bools[N];
811   for (int i = 0; i < N; ++i)
812     printf("%d", Bools[i]);
813   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
814   // CHECK-FIXES: for (bool Bool : Bools)
815 
816   int Ints[N];
817   unsigned short int Shorts[N];
818   for (int i = 0; i < N; ++i)
819     printf("%d", Shorts[i]);
820   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
821   // CHECK-FIXES: for (unsigned short Short : Shorts)
822 
823   signed long Longs[N];
824   for (int i = 0; i < N; ++i)
825     printf("%d", Longs[i]);
826   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
827   // CHECK-FIXES: for (long Long : Longs)
828 
829   long long int LongLongs[N];
830   for (int i = 0; i < N; ++i)
831     printf("%d", LongLongs[i]);
832   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
833   // CHECK-FIXES: for (long long LongLong : LongLongs)
834 
835   char Chars[N];
836   for (int i = 0; i < N; ++i)
837     printf("%d", Chars[i]);
838   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
839   // CHECK-FIXES: for (char Char : Chars)
840 
841   wchar_t WChars[N];
842   for (int i = 0; i < N; ++i)
843     printf("%d", WChars[i]);
844   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
845   // CHECK-FIXES: for (wchar_t WChar : WChars)
846 
847   float Floats[N];
848   for (int i = 0; i < N; ++i)
849     printf("%d", Floats[i]);
850   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
851   // CHECK-FIXES: for (float Float : Floats)
852 
853   double Doubles[N];
854   for (int i = 0; i < N; ++i)
855     printf("%d", Doubles[i]);
856   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
857   // CHECK-FIXES: for (double Double : Doubles)
858 }
859 
860 } // namespace PseudoArray
861