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