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