xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp (revision e984d11d7257343da366d9fa03749a43a6d6af72)
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   int Matrix[N][12];
92   unsigned size = 0;
93   for (int I = 0; I < N; ++I) {
94       size += sizeof(Matrix[I]);
95       size += sizeof Matrix[I];
96       size += sizeof((Matrix[I]));
97   }
98   // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
99   // CHECK-FIXES: for (auto & I : Matrix)
100   // CHECK-FIXES-NEXT: size += sizeof(I);
101   // CHECK-FIXES-NEXT: size += sizeof I;
102   // CHECK-FIXES-NEXT: size += sizeof(I);
103 
104   Val Teas[N];
105   for (int I = 0; I < N; ++I) {
106     Teas[I].g();
107   }
108   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
109   // CHECK-FIXES: for (auto & Tea : Teas)
110   // CHECK-FIXES-NEXT: Tea.g();
111 
112   for (int I = 0; N > I; ++I) {
113     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
114     Sum += Arr[I] + 2;
115   }
116   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
117   // CHECK-FIXES: for (int & I : Arr)
118   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
119   // CHECK-FIXES-NEXT: Sum += I + 2;
120 
121   for (int I = 0; N != I; ++I) {
122     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
123     Sum += Arr[I] + 2;
124   }
125   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
126   // CHECK-FIXES: for (int & I : Arr)
127   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
128   // CHECK-FIXES-NEXT: Sum += I + 2;
129 
130   for (int I = 0; I != N; ++I) {
131     printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]);
132     Sum += Arr[I] + 2;
133   }
134   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
135   // CHECK-FIXES: for (int & I : Arr)
136   // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I);
137   // CHECK-FIXES-NEXT: Sum += I + 2;
138 }
139 
140 const int *constArray() {
141   for (int I = 0; I < N; ++I) {
142     printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]);
143   }
144   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
145   // CHECK-FIXES: for (int I : ConstArr)
146   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I, I + I);
147 
148   const NonTriviallyCopyable NonCopy[N]{};
149   for (int I = 0; I < N; ++I) {
150     printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X);
151   }
152   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
153   // CHECK-FIXES: for (const auto & I : NonCopy)
154   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
155 
156   const TriviallyCopyableButBig Big[N]{};
157   for (int I = 0; I < N; ++I) {
158     printf("2 * %d = %d\n", Big[I].X, Big[I].X + Big[I].X);
159   }
160   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
161   // CHECK-FIXES: for (const auto & I : Big)
162   // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X);
163 
164   bool Something = false;
165   for (int I = 0; I < N; ++I) {
166     if (Something)
167       return &ConstArr[I];
168   }
169   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
170   // CHECK-FIXES: for (const int & I : ConstArr)
171   // CHECK-FIXES-NEXT: if (Something)
172   // CHECK-FIXES-NEXT: return &I;
173 }
174 
175 struct HasArr {
176   int Arr[N];
177   Val ValArr[N];
178   void implicitThis() {
179     for (int I = 0; I < N; ++I) {
180       printf("%d", Arr[I]);
181     }
182     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
183     // CHECK-FIXES: for (int I : Arr)
184     // CHECK-FIXES-NEXT: printf("%d", I);
185 
186     for (int I = 0; I < N; ++I) {
187       printf("%d", ValArr[I].X);
188     }
189     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
190     // CHECK-FIXES: for (auto & I : ValArr)
191     // CHECK-FIXES-NEXT: printf("%d", I.X);
192   }
193 
194   void explicitThis() {
195     for (int I = 0; I < N; ++I) {
196       printf("%d", this->Arr[I]);
197     }
198     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
199     // CHECK-FIXES: for (int I : this->Arr)
200     // CHECK-FIXES-NEXT: printf("%d", I);
201 
202     for (int I = 0; I < N; ++I) {
203       printf("%d", this->ValArr[I].X);
204     }
205     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
206     // CHECK-FIXES: for (auto & I : this->ValArr)
207     // CHECK-FIXES-NEXT: printf("%d", I.X);
208   }
209 };
210 
211 struct HasIndirectArr {
212   HasArr HA;
213   void implicitThis() {
214     for (int I = 0; I < N; ++I) {
215       printf("%d", HA.Arr[I]);
216     }
217     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
218     // CHECK-FIXES: for (int I : HA.Arr)
219     // CHECK-FIXES-NEXT: printf("%d", I);
220 
221     for (int I = 0; I < N; ++I) {
222       printf("%d", HA.ValArr[I].X);
223     }
224     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
225     // CHECK-FIXES: for (auto & I : HA.ValArr)
226     // CHECK-FIXES-NEXT: printf("%d", I.X);
227   }
228 
229   void explicitThis() {
230     for (int I = 0; I < N; ++I) {
231       printf("%d", this->HA.Arr[I]);
232     }
233     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
234     // CHECK-FIXES: for (int I : this->HA.Arr)
235     // CHECK-FIXES-NEXT: printf("%d", I);
236 
237     for (int I = 0; I < N; ++I) {
238       printf("%d", this->HA.ValArr[I].X);
239     }
240     // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
241     // CHECK-FIXES: for (auto & I : this->HA.ValArr)
242     // CHECK-FIXES-NEXT: printf("%d", I.X);
243   }
244 };
245 
246 // Loops whose bounds are value-dependent should not be converted.
247 template <int N>
248 void dependentExprBound() {
249   for (int I = 0; I < N; ++I)
250     Arr[I] = 0;
251 }
252 template void dependentExprBound<20>();
253 
254 void memberFunctionPointer() {
255   Val V;
256   void (Val::*mfpArr[N])(void) = {&Val::g};
257   for (int I = 0; I < N; ++I)
258     (V.*mfpArr[I])();
259   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
260   // CHECK-FIXES: for (auto & I : mfpArr)
261   // CHECK-FIXES-NEXT: (V.*I)();
262 
263   struct Foo {
264     int (Val::*f)();
265   } Foo[N];
266 
267   for (int I = 0; I < N; ++I)
268     int R = (V.*(Foo[I].f))();
269   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
270   // CHECK-FIXES: for (auto & I : Foo)
271   // CHECK-FIXES-NEXT: int R = (V.*(I.f))();
272 
273 }
274 
275 } // namespace Array
276 
277 namespace Iterator {
278 
279 void f() {
280   /// begin()/end() - based for loops here:
281   T Tt;
282   for (T::iterator It = Tt.begin(), E = Tt.end(); It != E; ++It) {
283     printf("I found %d\n", *It);
284   }
285   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
286   // CHECK-FIXES: for (int & It : Tt)
287   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
288 
289   // Do not crash because of Qq.begin() converting. Q::iterator converts with a
290   // conversion operator, which has no name, to Q::const_iterator.
291   Q Qq;
292   for (Q::const_iterator It = Qq.begin(), E = Qq.end(); It != E; ++It) {
293     printf("I found %d\n", *It);
294   }
295   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
296   // CHECK-FIXES: for (int & It : Qq)
297   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
298 
299   T *Pt;
300   for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {
301     printf("I found %d\n", *It);
302   }
303   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
304   // CHECK-FIXES: for (int & It : *Pt)
305   // CHECK-FIXES-NEXT: printf("I found %d\n", It);
306 
307   S Ss;
308   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
309     printf("s has value %d\n", (*It).X);
310   }
311   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
312   // CHECK-FIXES: for (auto & It : Ss)
313   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
314 
315   S *Ps;
316   for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
317     printf("s has value %d\n", (*It).X);
318   }
319   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
320   // CHECK-FIXES: for (auto & P : *Ps)
321   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
322 
323   for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
324     printf("s has value %d\n", (*It).X);
325   }
326   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
327   // CHECK-FIXES: for (auto It : Ss)
328   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
329 
330   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
331     printf("s has value %d\n", It->X);
332   }
333   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
334   // CHECK-FIXES: for (auto & It : Ss)
335   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
336 
337   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
338     It->X = 3;
339   }
340   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
341   // CHECK-FIXES: for (auto & It : Ss)
342   // CHECK-FIXES-NEXT: It.X = 3;
343 
344   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
345     (*It).X = 3;
346   }
347   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
348   // CHECK-FIXES: for (auto & It : Ss)
349   // CHECK-FIXES-NEXT: It.X = 3;
350 
351   for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
352     It->nonConstFun(4, 5);
353   }
354   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
355   // CHECK-FIXES: for (auto & It : Ss)
356   // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
357 
358   U Uu;
359   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
360     printf("s has value %d\n", It->X);
361   }
362   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
363   // CHECK-FIXES: for (auto & It : Uu)
364   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
365 
366   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
367     printf("s has value %d\n", (*It).X);
368   }
369   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
370   // CHECK-FIXES: for (auto & It : Uu)
371   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
372 
373   for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
374     Val* a = It.operator->();
375   }
376 
377   U::iterator A;
378   for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I)
379     int K = A->X + I->X;
380   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
381   // CHECK-FIXES: for (auto & I : Uu)
382   // CHECK-FIXES-NEXT: int K = A->X + I.X;
383 
384   dependent<int> V;
385   for (dependent<int>::iterator It = V.begin(), E = V.end();
386        It != E; ++It) {
387     printf("Fibonacci number is %d\n", *It);
388   }
389   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
390   // CHECK-FIXES: for (int & It : V)
391   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
392 
393   for (dependent<int>::iterator It(V.begin()), E = V.end();
394        It != E; ++It) {
395     printf("Fibonacci number is %d\n", *It);
396   }
397   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
398   // CHECK-FIXES: for (int & It : V)
399   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
400 
401   doublyDependent<int, int> Intmap;
402   for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end();
403        It != E; ++It) {
404     printf("Intmap[%d] = %d", It->first, It->second);
405   }
406   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
407   // CHECK-FIXES: for (auto & It : Intmap)
408   // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second);
409 
410   // PtrSet's iterator dereferences by value so auto & can't be used.
411   {
412     PtrSet<int *> Val_int_ptrs;
413     for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(),
414                                  E = Val_int_ptrs.end();
415          I != E; ++I) {
416       (void) *I;
417     }
418     // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
419     // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
420   }
421 
422   // This container uses an iterator where the dereference type is a typedef of
423   // a reference type. Make sure non-const auto & is still used. A failure here
424   // means canonical types aren't being tested.
425   {
426     TypedefDerefContainer<int> Int_ptrs;
427     for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(),
428                                               E = Int_ptrs.end();
429          I != E; ++I) {
430       (void) *I;
431     }
432     // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
433     // CHECK-FIXES: for (int & Int_ptr : Int_ptrs)
434   }
435 
436   {
437     // Iterators returning an rvalue reference should disqualify the loop from
438     // transformation.
439     RValueDerefContainer<int> Container;
440     for (RValueDerefContainer<int>::iterator I = Container.begin(),
441                                              E = Container.end();
442          I != E; ++I) {
443       (void) *I;
444     }
445   }
446 
447   dependent<Val *> Dpp;
448   for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
449     printf("%d\n", (**I).X);
450   }
451   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
452   // CHECK-FIXES: for (auto & I : Dpp)
453   // CHECK-FIXES-NEXT: printf("%d\n", (*I).X);
454 
455   for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
456     printf("%d\n", (*I)->X);
457   }
458   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
459   // CHECK-FIXES: for (auto & I : Dpp)
460   // CHECK-FIXES-NEXT: printf("%d\n", I->X);
461 
462   for (S::iterator It = begin(Ss), E = end(Ss); It != E; ++It) {
463     printf("s0 has value %d\n", (*It).X);
464   }
465   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
466   // CHECK-FIXES: for (auto & It : Ss)
467   // CHECK-FIXES-NEXT: printf("s0 has value %d\n", It.X);
468 
469   for (S::iterator It = std::begin(Ss), E = std::end(Ss); It != E; ++It) {
470     printf("s1 has value %d\n", (*It).X);
471   }
472   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
473   // CHECK-FIXES: for (auto & It : Ss)
474   // CHECK-FIXES-NEXT: printf("s1 has value %d\n", It.X);
475 
476   for (S::iterator It = begin(*Ps), E = end(*Ps); It != E; ++It) {
477     printf("s2 has value %d\n", (*It).X);
478   }
479   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
480   // CHECK-FIXES: for (auto & It : *Ps)
481   // CHECK-FIXES-NEXT: printf("s2 has value %d\n", It.X);
482 
483   for (S::iterator It = begin(*Ps); It != end(*Ps); ++It) {
484     printf("s3 has value %d\n", (*It).X);
485   }
486   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
487   // CHECK-FIXES: for (auto & It : *Ps)
488   // CHECK-FIXES-NEXT: printf("s3 has value %d\n", It.X);
489 
490   for (S::const_iterator It = cbegin(Ss), E = cend(Ss); It != E; ++It) {
491     printf("s4 has value %d\n", (*It).X);
492   }
493   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
494   // CHECK-FIXES: for (auto It : Ss)
495   // CHECK-FIXES-NEXT: printf("s4 has value %d\n", It.X);
496 }
497 
498 // Tests to verify the proper use of auto where the init variable type and the
499 // initializer type differ or are mostly the same except for const qualifiers.
500 void different_type() {
501   // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
502   // differs from const_iterator only on the const qualification.
503   S Ss;
504   for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
505     printf("s has value %d\n", (*It).X);
506   }
507   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
508   // CHECK-FIXES: for (auto It : Ss)
509   // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
510 
511   S *Ps;
512   for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
513     printf("s has value %d\n", (*It).X);
514   }
515   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
516   // CHECK-FIXES: for (auto P : *Ps)
517   // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
518 
519   dependent<int> V;
520   for (dependent<int>::const_iterator It = V.begin(), E = V.end();
521        It != E; ++It) {
522     printf("Fibonacci number is %d\n", *It);
523   }
524   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
525   // CHECK-FIXES: for (int It : V)
526   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
527 
528   for (dependent<int>::const_iterator It(V.begin()), E = V.end();
529        It != E; ++It) {
530     printf("Fibonacci number is %d\n", *It);
531   }
532   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
533   // CHECK-FIXES: for (int It : V)
534   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
535 }
536 
537 // Tests to ensure that an implicit 'this' is picked up as the container.
538 // If member calls are made to 'this' within the loop, the transform becomes
539 // risky as these calls may affect state that affects the loop.
540 class C {
541 public:
542   typedef MutableVal *iterator;
543   typedef const MutableVal *const_iterator;
544 
545   iterator begin();
546   iterator end();
547   const_iterator begin() const;
548   const_iterator end() const;
549 
550   void doSomething();
551   void doSomething() const;
552 
553   void doLoop() {
554     for (iterator I = begin(), E = end(); I != E; ++I)
555       (void) *I;
556     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
557     // CHECK-FIXES: for (auto & I : *this)
558 
559     for (iterator I = C::begin(), E = C::end(); I != E; ++I)
560       (void) *I;
561     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
562     // CHECK-FIXES: for (auto & I : *this)
563 
564     for (iterator I = begin(), E = end(); I != E; ++I) {
565       (void) *I;
566       doSomething();
567     }
568 
569     for (iterator I = begin(); I != end(); ++I)
570       (void) *I;
571     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
572     // CHECK-FIXES: for (auto & I : *this)
573 
574     for (iterator I = begin(); I != end(); ++I) {
575       (void) *I;
576       doSomething();
577     }
578   }
579 
580   void doLoop() const {
581     for (const_iterator I = begin(), E = end(); I != E; ++I)
582       (void) *I;
583     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
584     // CHECK-FIXES: for (auto I : *this)
585 
586     for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
587       (void) *I;
588     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
589     // CHECK-FIXES: for (auto I : *this)
590 
591     for (const_iterator I = begin(), E = end(); I != E; ++I) {
592       (void) *I;
593       doSomething();
594     }
595   }
596 };
597 
598 class C2 {
599 public:
600   typedef MutableVal *iterator;
601 
602   iterator begin() const;
603   iterator end() const;
604 
605   void doLoop() {
606     // The implicit 'this' will have an Implicit cast to const C2* wrapped
607     // around it. Make sure the replacement still happens.
608     for (iterator I = begin(), E = end(); I != E; ++I)
609       (void) *I;
610     // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
611     // CHECK-FIXES: for (auto & I : *this)
612   }
613 };
614 
615 } // namespace Iterator
616 
617 namespace PseudoArray {
618 
619 const int N = 6;
620 dependent<int> V;
621 dependent<int> *Pv;
622 const dependent<NonTriviallyCopyable> Constv;
623 const dependent<NonTriviallyCopyable> *Pconstv;
624 
625 transparent<dependent<int>> Cv;
626 dependent_derived<int> VD;
627 
628 void f() {
629   int Sum = 0;
630   for (int I = 0, E = V.size(); I < E; ++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.at(I));
641     Sum += V.at(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 = Pv->size(); I < E; ++I) {
649     printf("Fibonacci number is %d\n", Pv->at(I));
650     Sum += Pv->at(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   // This test will fail if size() isn't called repeatedly, since it
658   // returns unsigned int, and 0 is deduced to be signed int.
659   // FIXME: Insert the necessary explicit conversion, or write out the types
660   // explicitly.
661   for (int I = 0; I < Pv->size(); ++I) {
662     printf("Fibonacci number is %d\n", (*Pv).at(I));
663     Sum += (*Pv)[I] + 2;
664   }
665   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
666   // CHECK-FIXES: for (int I : *Pv)
667   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
668   // CHECK-FIXES-NEXT: Sum += I + 2;
669 
670   for (int I = 0; I < Cv->size(); ++I) {
671     printf("Fibonacci number is %d\n", Cv->at(I));
672     Sum += Cv->at(I) + 2;
673   }
674   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
675   // CHECK-FIXES: for (int I : *Cv)
676   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
677   // CHECK-FIXES-NEXT: Sum += I + 2;
678 
679   for (int I = 0, E = V.size(); E > I; ++I) {
680     printf("Fibonacci number is %d\n", V[I]);
681     Sum += V[I] + 2;
682   }
683   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
684   // CHECK-FIXES: for (int I : V)
685   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
686   // CHECK-FIXES-NEXT: Sum += I + 2;
687 
688   for (int I = 0, E = V.size(); I != E; ++I) {
689     printf("Fibonacci number is %d\n", V[I]);
690     Sum += V[I] + 2;
691   }
692   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
693   // CHECK-FIXES: for (int I : V)
694   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
695   // CHECK-FIXES-NEXT: Sum += I + 2;
696 
697   for (int I = 0, E = V.size(); E != I; ++I) {
698     printf("Fibonacci number is %d\n", V[I]);
699     Sum += V[I] + 2;
700   }
701   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
702   // CHECK-FIXES: for (int I : V)
703   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
704   // CHECK-FIXES-NEXT: Sum += I + 2;
705 
706   for (int I = 0, E = VD.size(); E != I; ++I) {
707     printf("Fibonacci number is %d\n", VD[I]);
708     Sum += VD[I] + 2;
709   }
710   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
711   // CHECK-FIXES: for (int I : VD)
712   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
713   // CHECK-FIXES-NEXT: Sum += I + 2;
714 
715   for (int I = 0, E = size(V); E != I; ++I) {
716     printf("Fibonacci number is %d\n", V[I]);
717     Sum += V[I] + 2;
718   }
719   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
720   // CHECK-FIXES: for (int I : V)
721   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
722   // CHECK-FIXES-NEXT: Sum += I + 2;
723 
724   for (int I = 0, E = size(V); E != I; ++I) {
725     V[I] = 0;
726   }
727   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
728   // CHECK-FIXES: for (int & I : V)
729   // CHECK-FIXES-NEXT: I = 0;
730 
731   for (int I = 0, E = std::size(V); E != I; ++I) {
732     V[I] = 0;
733   }
734   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
735   // CHECK-FIXES: for (int & I : V)
736   // CHECK-FIXES-NEXT: I = 0;
737 
738   // Although 'length' might be a valid free function, only size() is standardized
739   for (int I = 0, E = length(V); E != I; ++I) {
740     printf("Fibonacci number is %d\n", V[I]);
741     Sum += V[I] + 2;
742   }
743 
744   dependent<Val> Vals;
745   for (int I = 0, E = size(Vals); E != I; ++I) {
746     Sum += Vals[I].X;
747   }
748   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
749   // CHECK-FIXES: for (auto & Val : Vals)
750   // CHECK-FIXES-NEXT: Sum += Val.X;
751 }
752 
753 // Ensure that 'const auto &' is used with containers of non-trivial types.
754 void constness() {
755   int Sum = 0;
756   for (int I = 0, E = Constv.size(); I < E; ++I) {
757     printf("Fibonacci number is %d\n", Constv[I].X);
758     Sum += Constv[I].X + 2;
759   }
760   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
761   // CHECK-FIXES: for (const auto & I : Constv)
762   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
763   // CHECK-FIXES-NEXT: Sum += I.X + 2;
764 
765   for (int I = 0, E = Constv.size(); I < E; ++I) {
766     printf("Fibonacci number is %d\n", Constv.at(I).X);
767     Sum += Constv.at(I).X + 2;
768   }
769   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
770   // CHECK-FIXES: for (const auto & I : Constv)
771   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
772   // CHECK-FIXES-NEXT: Sum += I.X + 2;
773 
774   for (int I = 0, E = Pconstv->size(); I < E; ++I) {
775     printf("Fibonacci number is %d\n", Pconstv->at(I).X);
776     Sum += Pconstv->at(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   // This test will fail if size() isn't called repeatedly, since it
784   // returns unsigned int, and 0 is deduced to be signed int.
785   // FIXME: Insert the necessary explicit conversion, or write out the types
786   // explicitly.
787   for (int I = 0; I < Pconstv->size(); ++I) {
788     printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
789     Sum += (*Pconstv)[I].X + 2;
790   }
791   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
792   // CHECK-FIXES: for (const auto & I : *Pconstv)
793   // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
794   // CHECK-FIXES-NEXT: Sum += I.X + 2;
795 }
796 
797 void constRef(const dependent<int>& ConstVRef) {
798   int sum = 0;
799   // FIXME: This does not work with size_t (probably due to the implementation
800   // of dependent); make dependent work exactly like a std container type.
801   for (int I = 0; I < ConstVRef.size(); ++I) {
802     sum += ConstVRef[I];
803   }
804   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
805   // CHECK-FIXES: for (int I : ConstVRef)
806   // CHECK-FIXES-NEXT: sum += I;
807 
808   for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
809     sum += *I;
810   }
811   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
812   // CHECK-FIXES: for (int I : ConstVRef)
813   // CHECK-FIXES-NEXT: sum += I;
814 }
815 
816 // Check for loops that don't mention containers.
817 void noContainer() {
818   for (auto I = 0; I < V.size(); ++I) {
819   }
820 
821   for (auto I = 0; I < V.size(); ++I)
822     ;
823 }
824 
825 struct NoBeginEnd {
826   unsigned size() const;
827   unsigned& operator[](int);
828   const unsigned& operator[](int) const;
829 };
830 
831 struct NoConstBeginEnd {
832   NoConstBeginEnd();
833   unsigned size() const;
834   unsigned* begin();
835   unsigned* end();
836   unsigned& operator[](int);
837   const unsigned& operator[](int) const;
838 };
839 
840 struct ConstBeginEnd {
841   ConstBeginEnd();
842   unsigned size() const;
843   unsigned* begin() const;
844   unsigned* end() const;
845   unsigned& operator[](int);
846   const unsigned& operator[](int) const;
847 };
848 
849 // Shouldn't transform pseudo-array uses if the container doesn't provide
850 // begin() and end() of the right const-ness.
851 void NoBeginEndTest() {
852   NoBeginEnd NBE;
853   for (unsigned I = 0, E = NBE.size(); I < E; ++I)
854     printf("%d\n", NBE[I]);
855 
856   const NoConstBeginEnd Const_NCBE;
857   for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
858     printf("%d\n", Const_NCBE[I]);
859 
860   ConstBeginEnd CBE;
861   for (unsigned I = 0, E = CBE.size(); I < E; ++I)
862     printf("%d\n", CBE[I]);
863   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
864   // CHECK-FIXES: for (unsigned int I : CBE)
865   // CHECK-FIXES-NEXT: printf("%d\n", I);
866 
867   const ConstBeginEnd Const_CBE;
868   for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
869     printf("%d\n", Const_CBE[I]);
870   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
871   // CHECK-FIXES: for (unsigned int I : Const_CBE)
872   // CHECK-FIXES-NEXT: printf("%d\n", I);
873 }
874 
875 struct DerefByValue {
876   DerefByValue();
877   struct iter { unsigned operator*(); };
878   unsigned size() const;
879   iter begin();
880   iter end();
881   unsigned operator[](int);
882 };
883 
884 void derefByValueTest() {
885   DerefByValue DBV;
886   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
887     printf("%d\n", DBV[I]);
888   }
889   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
890   // CHECK-FIXES: for (unsigned int I : DBV)
891   // CHECK-FIXES-NEXT: printf("%d\n", I);
892 
893   for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
894     auto f = [DBV, I]() {};
895     printf("%d\n", DBV[I]);
896   }
897   // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
898   // CHECK-FIXES: for (unsigned int I : DBV)
899   // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
900   // CHECK-FIXES-NEXT: printf("%d\n", I);
901 }
902 
903 void fundamentalTypesTest() {
904   const int N = 10;
905   bool Bools[N];
906   for (int i = 0; i < N; ++i)
907     printf("%d", Bools[i]);
908   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
909   // CHECK-FIXES: for (bool Bool : Bools)
910 
911   int Ints[N];
912   unsigned short int Shorts[N];
913   for (int i = 0; i < N; ++i)
914     printf("%d", Shorts[i]);
915   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
916   // CHECK-FIXES: for (unsigned short Short : Shorts)
917 
918   signed long Longs[N];
919   for (int i = 0; i < N; ++i)
920     printf("%d", Longs[i]);
921   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
922   // CHECK-FIXES: for (long Long : Longs)
923 
924   long long int LongLongs[N];
925   for (int i = 0; i < N; ++i)
926     printf("%d", LongLongs[i]);
927   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
928   // CHECK-FIXES: for (long long LongLong : LongLongs)
929 
930   char Chars[N];
931   for (int i = 0; i < N; ++i)
932     printf("%d", Chars[i]);
933   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
934   // CHECK-FIXES: for (char Char : Chars)
935 
936   wchar_t WChars[N];
937   for (int i = 0; i < N; ++i)
938     printf("%d", WChars[i]);
939   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
940   // CHECK-FIXES: for (wchar_t WChar : WChars)
941 
942   float Floats[N];
943   for (int i = 0; i < N; ++i)
944     printf("%d", Floats[i]);
945   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
946   // CHECK-FIXES: for (float Float : Floats)
947 
948   double Doubles[N];
949   for (int i = 0; i < N; ++i)
950     printf("%d", Doubles[i]);
951   // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
952   // CHECK-FIXES: for (double Double : Doubles)
953 }
954 
955 template <unsigned  p> void _dependenceArrayTest() {
956   unsigned test[3][p];
957   for (unsigned i = 0; i < p; ++i)
958     for (unsigned j = 0; j < 3; ++j)
959       printf("%d", test[j][i]);
960   // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
961   // CHECK-FIXES: (auto & j : test)
962   // CHECK-FIXES: printf("%d", j[i]);
963 }
964 void dependenceArrayTest() {
965   _dependenceArrayTest<1>();
966   _dependenceArrayTest<2>();
967 }
968 
969 } // namespace PseudoArray
970 
971 namespace PR78381 {
972   struct blocked_range {
973     int begin() const;
974     int end() const;
975   };
976 
977   void test() {
978     blocked_range r;
979     for (auto i = r.begin(); i!=r.end(); ++i) {
980     }
981   }
982 }
983 
984 namespace GH109083 {
985 void test() {
986   const int N = 6;
987   int Arr[N] = {1, 2, 3, 4, 5, 6};
988 
989   for (int I = 0; I < N; ++I) {
990     auto V = [T = Arr[I]]() {};
991   }
992   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
993   // CHECK-FIXES: for (int I : Arr)
994   // CHECK-FIXES-NEXT: auto V = [T = I]() {};
995   for (int I = 0; I < N; ++I) {
996     auto V = [T = 10 + Arr[I]]() {};
997   }
998   // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]
999   // CHECK-FIXES: for (int I : Arr)
1000   // CHECK-FIXES-NEXT: auto V = [T = 10 + I]() {};
1001 
1002   for (int I = 0; I < N; ++I) {
1003     auto V = [T = I]() {};
1004   }
1005   for (int I = 0; I < N; ++I) {
1006     auto V = [T = I + 10]() {};
1007   }
1008 }
1009 } // namespace GH109083
1010