xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp (revision e43295209bb86e93008363c66c1277c7d8bb148c)
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 dependent_derived<int> VD;
579 
580 void f() {
581   int Sum = 0;
582   for (int I = 0, E = V.size(); I < E; ++I) {
583     printf("Fibonacci number is %d\n", V[I]);
584     Sum += V[I] + 2;
585   }
586   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
587   // CHECK-FIXES: for (int I : V)
588   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
589   // CHECK-FIXES-NEXT: Sum += I + 2;
590 
591   for (int I = 0, E = V.size(); I < E; ++I) {
592     printf("Fibonacci number is %d\n", V.at(I));
593     Sum += V.at(I) + 2;
594   }
595   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
596   // CHECK-FIXES: for (int I : V)
597   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
598   // CHECK-FIXES-NEXT: Sum += I + 2;
599 
600   for (int I = 0, E = Pv->size(); I < E; ++I) {
601     printf("Fibonacci number is %d\n", Pv->at(I));
602     Sum += Pv->at(I) + 2;
603   }
604   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
605   // CHECK-FIXES: for (int I : *Pv)
606   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
607   // CHECK-FIXES-NEXT: Sum += I + 2;
608 
609   // This test will fail if size() isn't called repeatedly, since it
610   // returns unsigned int, and 0 is deduced to be signed int.
611   // FIXME: Insert the necessary explicit conversion, or write out the types
612   // explicitly.
613   for (int I = 0; I < Pv->size(); ++I) {
614     printf("Fibonacci number is %d\n", (*Pv).at(I));
615     Sum += (*Pv)[I] + 2;
616   }
617   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
618   // CHECK-FIXES: for (int I : *Pv)
619   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
620   // CHECK-FIXES-NEXT: Sum += I + 2;
621 
622   for (int I = 0; I < Cv->size(); ++I) {
623     printf("Fibonacci number is %d\n", Cv->at(I));
624     Sum += Cv->at(I) + 2;
625   }
626   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
627   // CHECK-FIXES: for (int I : *Cv)
628   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
629   // CHECK-FIXES-NEXT: Sum += I + 2;
630 
631   for (int I = 0, E = V.size(); E > I; ++I) {
632     printf("Fibonacci number is %d\n", V[I]);
633     Sum += V[I] + 2;
634   }
635   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
636   // CHECK-FIXES: for (int I : V)
637   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
638   // CHECK-FIXES-NEXT: Sum += I + 2;
639 
640   for (int I = 0, E = V.size(); I != E; ++I) {
641     printf("Fibonacci number is %d\n", V[I]);
642     Sum += V[I] + 2;
643   }
644   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
645   // CHECK-FIXES: for (int I : V)
646   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
647   // CHECK-FIXES-NEXT: Sum += I + 2;
648 
649   for (int I = 0, E = V.size(); E != I; ++I) {
650     printf("Fibonacci number is %d\n", V[I]);
651     Sum += V[I] + 2;
652   }
653   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
654   // CHECK-FIXES: for (int I : V)
655   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
656   // CHECK-FIXES-NEXT: Sum += I + 2;
657 
658   for (int I = 0, E = VD.size(); E != I; ++I) {
659     printf("Fibonacci number is %d\n", VD[I]);
660     Sum += VD[I] + 2;
661   }
662   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
663   // CHECK-FIXES: for (int I : VD)
664   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
665   // CHECK-FIXES-NEXT: Sum += I + 2;
666 }
667 
668 // Ensure that 'const auto &' is used with containers of non-trivial types.
669 void constness() {
670   int Sum = 0;
671   for (int I = 0, E = Constv.size(); I < E; ++I) {
672     printf("Fibonacci number is %d\n", Constv[I].X);
673     Sum += Constv[I].X + 2;
674   }
675   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
676   // CHECK-FIXES: for (const auto & I : Constv)
677   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
678   // CHECK-FIXES-NEXT: Sum += I.X + 2;
679 
680   for (int I = 0, E = Constv.size(); I < E; ++I) {
681     printf("Fibonacci number is %d\n", Constv.at(I).X);
682     Sum += Constv.at(I).X + 2;
683   }
684   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
685   // CHECK-FIXES: for (const auto & I : Constv)
686   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
687   // CHECK-FIXES-NEXT: Sum += I.X + 2;
688 
689   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
690     printf("Fibonacci number is %d\n", Pconstv->at(I).X);
691     Sum += Pconstv->at(I).X + 2;
692   }
693   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
694   // CHECK-FIXES: for (const auto & I : *Pconstv)
695   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
696   // CHECK-FIXES-NEXT: Sum += I.X + 2;
697 
698   // This test will fail if size() isn't called repeatedly, since it
699   // returns unsigned int, and 0 is deduced to be signed int.
700   // FIXME: Insert the necessary explicit conversion, or write out the types
701   // explicitly.
702   for (int I = 0; I < Pconstv->size(); ++I) {
703     printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
704     Sum += (*Pconstv)[I].X + 2;
705   }
706   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
707   // CHECK-FIXES: for (const auto & I : *Pconstv)
708   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
709   // CHECK-FIXES-NEXT: Sum += I.X + 2;
710 }
711 
712 void constRef(const dependent<int>& ConstVRef) {
713   int sum = 0;
714   // FIXME: This does not work with size_t (probably due to the implementation
715   // of dependent); make dependent work exactly like a std container type.
716   for (int I = 0; I < ConstVRef.size(); ++I) {
717     sum += ConstVRef[I];
718   }
719   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
720   // CHECK-FIXES: for (int I : ConstVRef)
721   // CHECK-FIXES-NEXT: sum += I;
722 
723   for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
724     sum += *I;
725   }
726   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
727   // CHECK-FIXES: for (int I : ConstVRef)
728   // CHECK-FIXES-NEXT: sum += I;
729 }
730 
731 // Check for loops that don't mention containers.
732 void noContainer() {
733   for (auto I = 0; I < V.size(); ++I) {
734   }
735 
736   for (auto I = 0; I < V.size(); ++I)
737     ;
738 }
739 
740 struct NoBeginEnd {
741   unsigned size() const;
742   unsigned& operator[](int);
743   const unsigned& operator[](int) const;
744 };
745 
746 struct NoConstBeginEnd {
747   NoConstBeginEnd();
748   unsigned size() const;
749   unsigned* begin();
750   unsigned* end();
751   unsigned& operator[](int);
752   const unsigned& operator[](int) const;
753 };
754 
755 struct ConstBeginEnd {
756   ConstBeginEnd();
757   unsigned size() const;
758   unsigned* begin() const;
759   unsigned* end() const;
760   unsigned& operator[](int);
761   const unsigned& operator[](int) const;
762 };
763 
764 // Shouldn't transform pseudo-array uses if the container doesn't provide
765 // begin() and end() of the right const-ness.
766 void NoBeginEndTest() {
767   NoBeginEnd NBE;
768   for (unsigned I = 0, E = NBE.size(); I < E; ++I)
769     printf("%d\n", NBE[I]);
770 
771   const NoConstBeginEnd Const_NCBE;
772   for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
773     printf("%d\n", Const_NCBE[I]);
774 
775   ConstBeginEnd CBE;
776   for (unsigned I = 0, E = CBE.size(); I < E; ++I)
777     printf("%d\n", CBE[I]);
778   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
779   // CHECK-FIXES: for (unsigned int I : CBE)
780   // CHECK-FIXES-NEXT: printf("%d\n", I);
781 
782   const ConstBeginEnd Const_CBE;
783   for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
784     printf("%d\n", Const_CBE[I]);
785   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
786   // CHECK-FIXES: for (unsigned int I : Const_CBE)
787   // CHECK-FIXES-NEXT: printf("%d\n", I);
788 }
789 
790 struct DerefByValue {
791   DerefByValue();
792   struct iter { unsigned operator*(); };
793   unsigned size() const;
794   iter begin();
795   iter end();
796   unsigned operator[](int);
797 };
798 
799 void derefByValueTest() {
800   DerefByValue DBV;
801   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
802     printf("%d\n", DBV[I]);
803   }
804   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
805   // CHECK-FIXES: for (unsigned int I : DBV)
806   // CHECK-FIXES-NEXT: printf("%d\n", I);
807 
808   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
809     auto f = [DBV, I]() {};
810     printf("%d\n", DBV[I]);
811   }
812   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
813   // CHECK-FIXES: for (unsigned int I : DBV)
814   // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
815   // CHECK-FIXES-NEXT: printf("%d\n", I);
816 }
817 
818 void fundamentalTypesTest() {
819   const int N = 10;
820   bool Bools[N];
821   for (int i = 0; i < N; ++i)
822     printf("%d", Bools[i]);
823   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
824   // CHECK-FIXES: for (bool Bool : Bools)
825 
826   int Ints[N];
827   unsigned short int Shorts[N];
828   for (int i = 0; i < N; ++i)
829     printf("%d", Shorts[i]);
830   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
831   // CHECK-FIXES: for (unsigned short Short : Shorts)
832 
833   signed long Longs[N];
834   for (int i = 0; i < N; ++i)
835     printf("%d", Longs[i]);
836   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
837   // CHECK-FIXES: for (long Long : Longs)
838 
839   long long int LongLongs[N];
840   for (int i = 0; i < N; ++i)
841     printf("%d", LongLongs[i]);
842   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
843   // CHECK-FIXES: for (long long LongLong : LongLongs)
844 
845   char Chars[N];
846   for (int i = 0; i < N; ++i)
847     printf("%d", Chars[i]);
848   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
849   // CHECK-FIXES: for (char Char : Chars)
850 
851   wchar_t WChars[N];
852   for (int i = 0; i < N; ++i)
853     printf("%d", WChars[i]);
854   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
855   // CHECK-FIXES: for (wchar_t WChar : WChars)
856 
857   float Floats[N];
858   for (int i = 0; i < N; ++i)
859     printf("%d", Floats[i]);
860   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
861   // CHECK-FIXES: for (float Float : Floats)
862 
863   double Doubles[N];
864   for (int i = 0; i < N; ++i)
865     printf("%d", Doubles[i]);
866   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
867   // CHECK-FIXES: for (double Double : Doubles)
868 }
869 
870 } // namespace PseudoArray
871