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