xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp (revision 6a1f8ef8a7aaefea80ef0bc7c6c462a96215b50e)
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   for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
450     printf("s0 has value %d\n", (*It).X);
451   }
452   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
453   // CHECK-FIXES: for (auto & It : Ss)
454   // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
455 
456   for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
457     printf("s1 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("s1 has value %d\n", It.X);
462 
463   for (S::iterator It = begin(*Ps), E = end(*Ps); It != E; ++It) {
464     printf("s2 has value %d\n", (*It).X);
465   }
466   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
467   // CHECK-FIXES: for (auto & It : *Ps)
468   // CHECK-FIXES-NEXT: printf("s2 has value %d\n", It.X);
469 
470   for (S::iterator It = begin(*Ps); It != end(*Ps); ++It) {
471     printf("s3 has value %d\n", (*It).X);
472   }
473   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
474   // CHECK-FIXES: for (auto & It : *Ps)
475   // CHECK-FIXES-NEXT: printf("s3 has value %d\n", It.X);
476 
477   for (S::const_iterator It = cbegin(Ss), E = cend(Ss); It != E; ++It) {
478     printf("s4 has value %d\n", (*It).X);
479   }
480   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
481   // CHECK-FIXES: for (auto It : Ss)
482   // CHECK-FIXES-NEXT: printf("s4 has value %d\n", It.X);
483 }
484 
485 // Tests to verify the proper use of auto where the init variable type and the
486 // initializer type differ or are mostly the same except for const qualifiers.
487 void different_type() {
488   // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
489   // differs from const_iterator only on the const qualification.
490   S Ss;
491   for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
492     printf("s has value %d\n", (*It).X);
493   }
494   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
495   // CHECK-FIXES: for (auto It : Ss)
496   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
497 
498   S *Ps;
499   for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
500     printf("s has value %d\n", (*It).X);
501   }
502   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
503   // CHECK-FIXES: for (auto P : *Ps)
504   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
505 
506   dependent<int> V;
507   for (dependent<int>::const_iterator It = V.begin(), E = V.end();
508        It != E; ++It) {
509     printf("Fibonacci number is %d\n", *It);
510   }
511   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
512   // CHECK-FIXES: for (int It : V)
513   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
514 
515   for (dependent<int>::const_iterator It(V.begin()), E = V.end();
516        It != E; ++It) {
517     printf("Fibonacci number is %d\n", *It);
518   }
519   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
520   // CHECK-FIXES: for (int It : V)
521   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
522 }
523 
524 // Tests to ensure that an implicit 'this' is picked up as the container.
525 // If member calls are made to 'this' within the loop, the transform becomes
526 // risky as these calls may affect state that affects the loop.
527 class C {
528 public:
529   typedef MutableVal *iterator;
530   typedef const MutableVal *const_iterator;
531 
532   iterator begin();
533   iterator end();
534   const_iterator begin() const;
535   const_iterator end() const;
536 
537   void doSomething();
538   void doSomething() const;
539 
540   void doLoop() {
541     for (iterator I = begin(), E = end(); I != E; ++I)
542       (void) *I;
543     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
544     // CHECK-FIXES: for (auto & I : *this)
545 
546     for (iterator I = C::begin(), E = C::end(); I != E; ++I)
547       (void) *I;
548     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
549     // CHECK-FIXES: for (auto & I : *this)
550 
551     for (iterator I = begin(), E = end(); I != E; ++I) {
552       (void) *I;
553       doSomething();
554     }
555 
556     for (iterator I = begin(); I != end(); ++I)
557       (void) *I;
558     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
559     // CHECK-FIXES: for (auto & I : *this)
560 
561     for (iterator I = begin(); I != end(); ++I) {
562       (void) *I;
563       doSomething();
564     }
565   }
566 
567   void doLoop() const {
568     for (const_iterator I = begin(), E = end(); I != E; ++I)
569       (void) *I;
570     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
571     // CHECK-FIXES: for (auto I : *this)
572 
573     for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
574       (void) *I;
575     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
576     // CHECK-FIXES: for (auto I : *this)
577 
578     for (const_iterator I = begin(), E = end(); I != E; ++I) {
579       (void) *I;
580       doSomething();
581     }
582   }
583 };
584 
585 class C2 {
586 public:
587   typedef MutableVal *iterator;
588 
589   iterator begin() const;
590   iterator end() const;
591 
592   void doLoop() {
593     // The implicit 'this' will have an Implicit cast to const C2* wrapped
594     // around it. Make sure the replacement still happens.
595     for (iterator I = begin(), E = end(); I != E; ++I)
596       (void) *I;
597     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
598     // CHECK-FIXES: for (auto & I : *this)
599   }
600 };
601 
602 } // namespace Iterator
603 
604 namespace PseudoArray {
605 
606 const int N = 6;
607 dependent<int> V;
608 dependent<int> *Pv;
609 const dependent<NonTriviallyCopyable> Constv;
610 const dependent<NonTriviallyCopyable> *Pconstv;
611 
612 transparent<dependent<int>> Cv;
613 dependent_derived<int> VD;
614 
615 void f() {
616   int Sum = 0;
617   for (int I = 0, E = V.size(); I < E; ++I) {
618     printf("Fibonacci number is %d\n", V[I]);
619     Sum += V[I] + 2;
620   }
621   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
622   // CHECK-FIXES: for (int I : V)
623   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
624   // CHECK-FIXES-NEXT: Sum += I + 2;
625 
626   for (int I = 0, E = V.size(); I < E; ++I) {
627     printf("Fibonacci number is %d\n", V.at(I));
628     Sum += V.at(I) + 2;
629   }
630   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
631   // CHECK-FIXES: for (int I : V)
632   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
633   // CHECK-FIXES-NEXT: Sum += I + 2;
634 
635   for (int I = 0, E = Pv->size(); I < E; ++I) {
636     printf("Fibonacci number is %d\n", Pv->at(I));
637     Sum += Pv->at(I) + 2;
638   }
639   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
640   // CHECK-FIXES: for (int I : *Pv)
641   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
642   // CHECK-FIXES-NEXT: Sum += I + 2;
643 
644   // This test will fail if size() isn't called repeatedly, since it
645   // returns unsigned int, and 0 is deduced to be signed int.
646   // FIXME: Insert the necessary explicit conversion, or write out the types
647   // explicitly.
648   for (int I = 0; I < Pv->size(); ++I) {
649     printf("Fibonacci number is %d\n", (*Pv).at(I));
650     Sum += (*Pv)[I] + 2;
651   }
652   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
653   // CHECK-FIXES: for (int I : *Pv)
654   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
655   // CHECK-FIXES-NEXT: Sum += I + 2;
656 
657   for (int I = 0; I < Cv->size(); ++I) {
658     printf("Fibonacci number is %d\n", Cv->at(I));
659     Sum += Cv->at(I) + 2;
660   }
661   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
662   // CHECK-FIXES: for (int I : *Cv)
663   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
664   // CHECK-FIXES-NEXT: Sum += I + 2;
665 
666   for (int I = 0, E = V.size(); E > I; ++I) {
667     printf("Fibonacci number is %d\n", V[I]);
668     Sum += V[I] + 2;
669   }
670   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
671   // CHECK-FIXES: for (int I : V)
672   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
673   // CHECK-FIXES-NEXT: Sum += I + 2;
674 
675   for (int I = 0, E = V.size(); I != E; ++I) {
676     printf("Fibonacci number is %d\n", V[I]);
677     Sum += V[I] + 2;
678   }
679   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
680   // CHECK-FIXES: for (int I : V)
681   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
682   // CHECK-FIXES-NEXT: Sum += I + 2;
683 
684   for (int I = 0, E = V.size(); E != I; ++I) {
685     printf("Fibonacci number is %d\n", V[I]);
686     Sum += V[I] + 2;
687   }
688   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
689   // CHECK-FIXES: for (int I : V)
690   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
691   // CHECK-FIXES-NEXT: Sum += I + 2;
692 
693   for (int I = 0, E = VD.size(); E != I; ++I) {
694     printf("Fibonacci number is %d\n", VD[I]);
695     Sum += VD[I] + 2;
696   }
697   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
698   // CHECK-FIXES: for (int I : VD)
699   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
700   // CHECK-FIXES-NEXT: Sum += I + 2;
701 
702   for (int I = 0, E = size(V); E != I; ++I) {
703     printf("Fibonacci number is %d\n", V[I]);
704     Sum += V[I] + 2;
705   }
706   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
707   // CHECK-FIXES: for (int I : V)
708   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
709   // CHECK-FIXES-NEXT: Sum += I + 2;
710 
711   for (int I = 0, E = size(V); E != I; ++I) {
712     V[I] = 0;
713   }
714   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
715   // CHECK-FIXES: for (int & I : V)
716   // CHECK-FIXES-NEXT: I = 0;
717 
718   for (int I = 0, E = std::size(V); E != I; ++I) {
719     V[I] = 0;
720   }
721   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
722   // CHECK-FIXES: for (int & I : V)
723   // CHECK-FIXES-NEXT: I = 0;
724 
725   // Although 'length' might be a valid free function, only size() is standardized
726   for (int I = 0, E = length(V); E != I; ++I) {
727     printf("Fibonacci number is %d\n", V[I]);
728     Sum += V[I] + 2;
729   }
730 
731   dependent<Val> Vals;
732   for (int I = 0, E = size(Vals); E != I; ++I) {
733     Sum += Vals[I].X;
734   }
735   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
736   // CHECK-FIXES: for (auto & Val : Vals)
737   // CHECK-FIXES-NEXT: Sum += Val.X;
738 }
739 
740 // Ensure that 'const auto &' is used with containers of non-trivial types.
741 void constness() {
742   int Sum = 0;
743   for (int I = 0, E = Constv.size(); I < E; ++I) {
744     printf("Fibonacci number is %d\n", Constv[I].X);
745     Sum += Constv[I].X + 2;
746   }
747   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
748   // CHECK-FIXES: for (const auto & I : Constv)
749   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
750   // CHECK-FIXES-NEXT: Sum += I.X + 2;
751 
752   for (int I = 0, E = Constv.size(); I < E; ++I) {
753     printf("Fibonacci number is %d\n", Constv.at(I).X);
754     Sum += Constv.at(I).X + 2;
755   }
756   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
757   // CHECK-FIXES: for (const auto & I : Constv)
758   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
759   // CHECK-FIXES-NEXT: Sum += I.X + 2;
760 
761   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
762     printf("Fibonacci number is %d\n", Pconstv->at(I).X);
763     Sum += Pconstv->at(I).X + 2;
764   }
765   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
766   // CHECK-FIXES: for (const auto & I : *Pconstv)
767   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
768   // CHECK-FIXES-NEXT: Sum += I.X + 2;
769 
770   // This test will fail if size() isn't called repeatedly, since it
771   // returns unsigned int, and 0 is deduced to be signed int.
772   // FIXME: Insert the necessary explicit conversion, or write out the types
773   // explicitly.
774   for (int I = 0; I < Pconstv->size(); ++I) {
775     printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
776     Sum += (*Pconstv)[I].X + 2;
777   }
778   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
779   // CHECK-FIXES: for (const auto & I : *Pconstv)
780   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
781   // CHECK-FIXES-NEXT: Sum += I.X + 2;
782 }
783 
784 void constRef(const dependent<int>& ConstVRef) {
785   int sum = 0;
786   // FIXME: This does not work with size_t (probably due to the implementation
787   // of dependent); make dependent work exactly like a std container type.
788   for (int I = 0; I < ConstVRef.size(); ++I) {
789     sum += ConstVRef[I];
790   }
791   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
792   // CHECK-FIXES: for (int I : ConstVRef)
793   // CHECK-FIXES-NEXT: sum += I;
794 
795   for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
796     sum += *I;
797   }
798   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
799   // CHECK-FIXES: for (int I : ConstVRef)
800   // CHECK-FIXES-NEXT: sum += I;
801 }
802 
803 // Check for loops that don't mention containers.
804 void noContainer() {
805   for (auto I = 0; I < V.size(); ++I) {
806   }
807 
808   for (auto I = 0; I < V.size(); ++I)
809     ;
810 }
811 
812 struct NoBeginEnd {
813   unsigned size() const;
814   unsigned& operator[](int);
815   const unsigned& operator[](int) const;
816 };
817 
818 struct NoConstBeginEnd {
819   NoConstBeginEnd();
820   unsigned size() const;
821   unsigned* begin();
822   unsigned* end();
823   unsigned& operator[](int);
824   const unsigned& operator[](int) const;
825 };
826 
827 struct ConstBeginEnd {
828   ConstBeginEnd();
829   unsigned size() const;
830   unsigned* begin() const;
831   unsigned* end() const;
832   unsigned& operator[](int);
833   const unsigned& operator[](int) const;
834 };
835 
836 // Shouldn't transform pseudo-array uses if the container doesn't provide
837 // begin() and end() of the right const-ness.
838 void NoBeginEndTest() {
839   NoBeginEnd NBE;
840   for (unsigned I = 0, E = NBE.size(); I < E; ++I)
841     printf("%d\n", NBE[I]);
842 
843   const NoConstBeginEnd Const_NCBE;
844   for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
845     printf("%d\n", Const_NCBE[I]);
846 
847   ConstBeginEnd CBE;
848   for (unsigned I = 0, E = CBE.size(); I < E; ++I)
849     printf("%d\n", CBE[I]);
850   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
851   // CHECK-FIXES: for (unsigned int I : CBE)
852   // CHECK-FIXES-NEXT: printf("%d\n", I);
853 
854   const ConstBeginEnd Const_CBE;
855   for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
856     printf("%d\n", Const_CBE[I]);
857   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
858   // CHECK-FIXES: for (unsigned int I : Const_CBE)
859   // CHECK-FIXES-NEXT: printf("%d\n", I);
860 }
861 
862 struct DerefByValue {
863   DerefByValue();
864   struct iter { unsigned operator*(); };
865   unsigned size() const;
866   iter begin();
867   iter end();
868   unsigned operator[](int);
869 };
870 
871 void derefByValueTest() {
872   DerefByValue DBV;
873   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
874     printf("%d\n", DBV[I]);
875   }
876   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
877   // CHECK-FIXES: for (unsigned int I : DBV)
878   // CHECK-FIXES-NEXT: printf("%d\n", I);
879 
880   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
881     auto f = [DBV, I]() {};
882     printf("%d\n", DBV[I]);
883   }
884   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
885   // CHECK-FIXES: for (unsigned int I : DBV)
886   // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
887   // CHECK-FIXES-NEXT: printf("%d\n", I);
888 }
889 
890 void fundamentalTypesTest() {
891   const int N = 10;
892   bool Bools[N];
893   for (int i = 0; i < N; ++i)
894     printf("%d", Bools[i]);
895   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
896   // CHECK-FIXES: for (bool Bool : Bools)
897 
898   int Ints[N];
899   unsigned short int Shorts[N];
900   for (int i = 0; i < N; ++i)
901     printf("%d", Shorts[i]);
902   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
903   // CHECK-FIXES: for (unsigned short Short : Shorts)
904 
905   signed long Longs[N];
906   for (int i = 0; i < N; ++i)
907     printf("%d", Longs[i]);
908   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
909   // CHECK-FIXES: for (long Long : Longs)
910 
911   long long int LongLongs[N];
912   for (int i = 0; i < N; ++i)
913     printf("%d", LongLongs[i]);
914   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
915   // CHECK-FIXES: for (long long LongLong : LongLongs)
916 
917   char Chars[N];
918   for (int i = 0; i < N; ++i)
919     printf("%d", Chars[i]);
920   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
921   // CHECK-FIXES: for (char Char : Chars)
922 
923   wchar_t WChars[N];
924   for (int i = 0; i < N; ++i)
925     printf("%d", WChars[i]);
926   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
927   // CHECK-FIXES: for (wchar_t WChar : WChars)
928 
929   float Floats[N];
930   for (int i = 0; i < N; ++i)
931     printf("%d", Floats[i]);
932   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
933   // CHECK-FIXES: for (float Float : Floats)
934 
935   double Doubles[N];
936   for (int i = 0; i < N; ++i)
937     printf("%d", Doubles[i]);
938   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
939   // CHECK-FIXES: for (double Double : Doubles)
940 }
941 
942 } // namespace PseudoArray
943