1 // RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -I %S/Inputs/loop-convert
2
3 #include "structures.h"
4
5 namespace Array {
6
7 const int N = 6;
8 const int NMinusOne = N - 1;
9 int Arr[N] = {1, 2, 3, 4, 5, 6};
10 const int ConstArr[N] = {1, 2, 3, 4, 5, 6};
11 int (*PArr)[N] = &Arr;
12
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 // Do not crash because of Qq.begin() converting. Q::iterator converts with a
277 // conversion operator, which has no name, to Q::const_iterator.
278 Q Qq;
279 for (Q::const_iterator It = Qq.begin(), E = Qq.end(); It != E; ++It) {
280 printf("I found %d\n", *It);
281 }
282 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
283 // CHECK-FIXES: for (int & It : Qq)
284 // CHECK-FIXES-NEXT: printf("I found %d\n", It);
285
286 T *Pt;
287 for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) {
288 printf("I found %d\n", *It);
289 }
290 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
291 // CHECK-FIXES: for (int & It : *Pt)
292 // CHECK-FIXES-NEXT: printf("I found %d\n", It);
293
294 S Ss;
295 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
296 printf("s has value %d\n", (*It).X);
297 }
298 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
299 // CHECK-FIXES: for (auto & It : Ss)
300 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
301
302 S *Ps;
303 for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
304 printf("s has value %d\n", (*It).X);
305 }
306 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
307 // CHECK-FIXES: for (auto & P : *Ps)
308 // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
309
310 for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) {
311 printf("s has value %d\n", (*It).X);
312 }
313 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
314 // CHECK-FIXES: for (auto It : Ss)
315 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
316
317 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
318 printf("s has value %d\n", It->X);
319 }
320 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
321 // CHECK-FIXES: for (auto & It : Ss)
322 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
323
324 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
325 It->X = 3;
326 }
327 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
328 // CHECK-FIXES: for (auto & It : Ss)
329 // CHECK-FIXES-NEXT: It.X = 3;
330
331 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
332 (*It).X = 3;
333 }
334 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
335 // CHECK-FIXES: for (auto & It : Ss)
336 // CHECK-FIXES-NEXT: It.X = 3;
337
338 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
339 It->nonConstFun(4, 5);
340 }
341 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
342 // CHECK-FIXES: for (auto & It : Ss)
343 // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
344
345 U Uu;
346 for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
347 printf("s has value %d\n", It->X);
348 }
349 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
350 // CHECK-FIXES: for (auto & It : Uu)
351 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
352
353 for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
354 printf("s has value %d\n", (*It).X);
355 }
356 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
357 // CHECK-FIXES: for (auto & It : Uu)
358 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
359
360 for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) {
361 Val* a = It.operator->();
362 }
363
364 U::iterator A;
365 for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I)
366 int K = A->X + I->X;
367 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
368 // CHECK-FIXES: for (auto & I : Uu)
369 // CHECK-FIXES-NEXT: int K = A->X + I.X;
370
371 dependent<int> V;
372 for (dependent<int>::iterator It = V.begin(), E = V.end();
373 It != E; ++It) {
374 printf("Fibonacci number is %d\n", *It);
375 }
376 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
377 // CHECK-FIXES: for (int & It : V)
378 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
379
380 for (dependent<int>::iterator It(V.begin()), E = V.end();
381 It != E; ++It) {
382 printf("Fibonacci number is %d\n", *It);
383 }
384 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
385 // CHECK-FIXES: for (int & It : V)
386 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
387
388 doublyDependent<int, int> Intmap;
389 for (doublyDependent<int, int>::iterator It = Intmap.begin(), E = Intmap.end();
390 It != E; ++It) {
391 printf("Intmap[%d] = %d", It->first, It->second);
392 }
393 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
394 // CHECK-FIXES: for (auto & It : Intmap)
395 // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second);
396
397 // PtrSet's iterator dereferences by value so auto & can't be used.
398 {
399 PtrSet<int *> Val_int_ptrs;
400 for (PtrSet<int *>::iterator I = Val_int_ptrs.begin(),
401 E = Val_int_ptrs.end();
402 I != E; ++I) {
403 (void) *I;
404 }
405 // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
406 // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs)
407 }
408
409 // This container uses an iterator where the dereference type is a typedef of
410 // a reference type. Make sure non-const auto & is still used. A failure here
411 // means canonical types aren't being tested.
412 {
413 TypedefDerefContainer<int> Int_ptrs;
414 for (TypedefDerefContainer<int>::iterator I = Int_ptrs.begin(),
415 E = Int_ptrs.end();
416 I != E; ++I) {
417 (void) *I;
418 }
419 // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead
420 // CHECK-FIXES: for (int & Int_ptr : Int_ptrs)
421 }
422
423 {
424 // Iterators returning an rvalue reference should disqualify the loop from
425 // transformation.
426 RValueDerefContainer<int> Container;
427 for (RValueDerefContainer<int>::iterator I = Container.begin(),
428 E = Container.end();
429 I != E; ++I) {
430 (void) *I;
431 }
432 }
433
434 dependent<Val *> Dpp;
435 for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
436 printf("%d\n", (**I).X);
437 }
438 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
439 // CHECK-FIXES: for (auto & I : Dpp)
440 // CHECK-FIXES-NEXT: printf("%d\n", (*I).X);
441
442 for (dependent<Val *>::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) {
443 printf("%d\n", (*I)->X);
444 }
445 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
446 // CHECK-FIXES: for (auto & I : Dpp)
447 // CHECK-FIXES-NEXT: printf("%d\n", I->X);
448 }
449
450 // Tests to verify the proper use of auto where the init variable type and the
451 // initializer type differ or are mostly the same except for const qualifiers.
different_type()452 void different_type() {
453 // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
454 // differs from const_iterator only on the const qualification.
455 S Ss;
456 for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
457 printf("s has value %d\n", (*It).X);
458 }
459 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
460 // CHECK-FIXES: for (auto It : Ss)
461 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
462
463 S *Ps;
464 for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) {
465 printf("s has value %d\n", (*It).X);
466 }
467 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
468 // CHECK-FIXES: for (auto P : *Ps)
469 // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
470
471 dependent<int> V;
472 for (dependent<int>::const_iterator It = V.begin(), E = V.end();
473 It != E; ++It) {
474 printf("Fibonacci number is %d\n", *It);
475 }
476 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
477 // CHECK-FIXES: for (int It : V)
478 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
479
480 for (dependent<int>::const_iterator It(V.begin()), E = V.end();
481 It != E; ++It) {
482 printf("Fibonacci number is %d\n", *It);
483 }
484 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
485 // CHECK-FIXES: for (int It : V)
486 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
487 }
488
489 // Tests to ensure that an implicit 'this' is picked up as the container.
490 // If member calls are made to 'this' within the loop, the transform becomes
491 // risky as these calls may affect state that affects the loop.
492 class C {
493 public:
494 typedef MutableVal *iterator;
495 typedef const MutableVal *const_iterator;
496
497 iterator begin();
498 iterator end();
499 const_iterator begin() const;
500 const_iterator end() const;
501
502 void doSomething();
503 void doSomething() const;
504
doLoop()505 void doLoop() {
506 for (iterator I = begin(), E = end(); I != E; ++I)
507 (void) *I;
508 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
509 // CHECK-FIXES: for (auto & I : *this)
510
511 for (iterator I = C::begin(), E = C::end(); I != E; ++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(), E = end(); I != E; ++I) {
517 (void) *I;
518 doSomething();
519 }
520
521 for (iterator I = begin(); I != end(); ++I)
522 (void) *I;
523 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
524 // CHECK-FIXES: for (auto & I : *this)
525
526 for (iterator I = begin(); I != end(); ++I) {
527 (void) *I;
528 doSomething();
529 }
530 }
531
doLoop() const532 void doLoop() const {
533 for (const_iterator I = begin(), E = end(); I != E; ++I)
534 (void) *I;
535 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
536 // CHECK-FIXES: for (auto I : *this)
537
538 for (const_iterator I = C::begin(), E = C::end(); I != E; ++I)
539 (void) *I;
540 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
541 // CHECK-FIXES: for (auto I : *this)
542
543 for (const_iterator I = begin(), E = end(); I != E; ++I) {
544 (void) *I;
545 doSomething();
546 }
547 }
548 };
549
550 class C2 {
551 public:
552 typedef MutableVal *iterator;
553
554 iterator begin() const;
555 iterator end() const;
556
doLoop()557 void doLoop() {
558 // The implicit 'this' will have an Implicit cast to const C2* wrapped
559 // around it. Make sure the replacement still happens.
560 for (iterator I = begin(), E = end(); I != E; ++I)
561 (void) *I;
562 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead
563 // CHECK-FIXES: for (auto & I : *this)
564 }
565 };
566
567 } // namespace Iterator
568
569 namespace PseudoArray {
570
571 const int N = 6;
572 dependent<int> V;
573 dependent<int> *Pv;
574 const dependent<NonTriviallyCopyable> Constv;
575 const dependent<NonTriviallyCopyable> *Pconstv;
576
577 transparent<dependent<int>> Cv;
578
f()579 void f() {
580 int Sum = 0;
581 for (int I = 0, E = V.size(); I < E; ++I) {
582 printf("Fibonacci number is %d\n", V[I]);
583 Sum += V[I] + 2;
584 }
585 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
586 // CHECK-FIXES: for (int I : V)
587 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
588 // CHECK-FIXES-NEXT: Sum += I + 2;
589
590 for (int I = 0, E = V.size(); I < E; ++I) {
591 printf("Fibonacci number is %d\n", V.at(I));
592 Sum += V.at(I) + 2;
593 }
594 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
595 // CHECK-FIXES: for (int I : V)
596 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
597 // CHECK-FIXES-NEXT: Sum += I + 2;
598
599 for (int I = 0, E = Pv->size(); I < E; ++I) {
600 printf("Fibonacci number is %d\n", Pv->at(I));
601 Sum += Pv->at(I) + 2;
602 }
603 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
604 // CHECK-FIXES: for (int I : *Pv)
605 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
606 // CHECK-FIXES-NEXT: Sum += I + 2;
607
608 // This test will fail if size() isn't called repeatedly, since it
609 // returns unsigned int, and 0 is deduced to be signed int.
610 // FIXME: Insert the necessary explicit conversion, or write out the types
611 // explicitly.
612 for (int I = 0; I < Pv->size(); ++I) {
613 printf("Fibonacci number is %d\n", (*Pv).at(I));
614 Sum += (*Pv)[I] + 2;
615 }
616 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
617 // CHECK-FIXES: for (int I : *Pv)
618 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
619 // CHECK-FIXES-NEXT: Sum += I + 2;
620
621 for (int I = 0; I < Cv->size(); ++I) {
622 printf("Fibonacci number is %d\n", Cv->at(I));
623 Sum += Cv->at(I) + 2;
624 }
625 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
626 // CHECK-FIXES: for (int I : *Cv)
627 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
628 // CHECK-FIXES-NEXT: Sum += I + 2;
629
630 for (int I = 0, E = V.size(); E > I; ++I) {
631 printf("Fibonacci number is %d\n", V[I]);
632 Sum += V[I] + 2;
633 }
634 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
635 // CHECK-FIXES: for (int I : V)
636 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
637 // CHECK-FIXES-NEXT: Sum += I + 2;
638
639 for (int I = 0, E = V.size(); I != E; ++I) {
640 printf("Fibonacci number is %d\n", V[I]);
641 Sum += V[I] + 2;
642 }
643 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
644 // CHECK-FIXES: for (int I : V)
645 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
646 // CHECK-FIXES-NEXT: Sum += I + 2;
647
648 for (int I = 0, E = V.size(); E != I; ++I) {
649 printf("Fibonacci number is %d\n", V[I]);
650 Sum += V[I] + 2;
651 }
652 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
653 // CHECK-FIXES: for (int I : V)
654 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
655 // CHECK-FIXES-NEXT: Sum += I + 2;
656 }
657
658 // Ensure that 'const auto &' is used with containers of non-trivial types.
constness()659 void constness() {
660 int Sum = 0;
661 for (int I = 0, E = Constv.size(); I < E; ++I) {
662 printf("Fibonacci number is %d\n", Constv[I].X);
663 Sum += Constv[I].X + 2;
664 }
665 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
666 // CHECK-FIXES: for (const auto & I : Constv)
667 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
668 // CHECK-FIXES-NEXT: Sum += I.X + 2;
669
670 for (int I = 0, E = Constv.size(); I < E; ++I) {
671 printf("Fibonacci number is %d\n", Constv.at(I).X);
672 Sum += Constv.at(I).X + 2;
673 }
674 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
675 // CHECK-FIXES: for (const auto & I : Constv)
676 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
677 // CHECK-FIXES-NEXT: Sum += I.X + 2;
678
679 for (int I = 0, E = Pconstv->size(); I < E; ++I) {
680 printf("Fibonacci number is %d\n", Pconstv->at(I).X);
681 Sum += Pconstv->at(I).X + 2;
682 }
683 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
684 // CHECK-FIXES: for (const auto & I : *Pconstv)
685 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
686 // CHECK-FIXES-NEXT: Sum += I.X + 2;
687
688 // This test will fail if size() isn't called repeatedly, since it
689 // returns unsigned int, and 0 is deduced to be signed int.
690 // FIXME: Insert the necessary explicit conversion, or write out the types
691 // explicitly.
692 for (int I = 0; I < Pconstv->size(); ++I) {
693 printf("Fibonacci number is %d\n", (*Pconstv).at(I).X);
694 Sum += (*Pconstv)[I].X + 2;
695 }
696 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
697 // CHECK-FIXES: for (const auto & I : *Pconstv)
698 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X);
699 // CHECK-FIXES-NEXT: Sum += I.X + 2;
700 }
701
constRef(const dependent<int> & ConstVRef)702 void constRef(const dependent<int>& ConstVRef) {
703 int sum = 0;
704 // FIXME: This does not work with size_t (probably due to the implementation
705 // of dependent); make dependent work exactly like a std container type.
706 for (int I = 0; I < ConstVRef.size(); ++I) {
707 sum += ConstVRef[I];
708 }
709 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
710 // CHECK-FIXES: for (int I : ConstVRef)
711 // CHECK-FIXES-NEXT: sum += I;
712
713 for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) {
714 sum += *I;
715 }
716 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
717 // CHECK-FIXES: for (int I : ConstVRef)
718 // CHECK-FIXES-NEXT: sum += I;
719 }
720
721 // Check for loops that don't mention containers.
noContainer()722 void noContainer() {
723 for (auto I = 0; I < V.size(); ++I) {
724 }
725
726 for (auto I = 0; I < V.size(); ++I)
727 ;
728 }
729
730 struct NoBeginEnd {
731 unsigned size() const;
732 unsigned& operator[](int);
733 const unsigned& operator[](int) const;
734 };
735
736 struct NoConstBeginEnd {
737 NoConstBeginEnd();
738 unsigned size() const;
739 unsigned* begin();
740 unsigned* end();
741 unsigned& operator[](int);
742 const unsigned& operator[](int) const;
743 };
744
745 struct ConstBeginEnd {
746 ConstBeginEnd();
747 unsigned size() const;
748 unsigned* begin() const;
749 unsigned* end() const;
750 unsigned& operator[](int);
751 const unsigned& operator[](int) const;
752 };
753
754 // Shouldn't transform pseudo-array uses if the container doesn't provide
755 // begin() and end() of the right const-ness.
NoBeginEndTest()756 void NoBeginEndTest() {
757 NoBeginEnd NBE;
758 for (unsigned I = 0, E = NBE.size(); I < E; ++I)
759 printf("%d\n", NBE[I]);
760
761 const NoConstBeginEnd Const_NCBE;
762 for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I)
763 printf("%d\n", Const_NCBE[I]);
764
765 ConstBeginEnd CBE;
766 for (unsigned I = 0, E = CBE.size(); I < E; ++I)
767 printf("%d\n", CBE[I]);
768 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
769 // CHECK-FIXES: for (unsigned int I : CBE)
770 // CHECK-FIXES-NEXT: printf("%d\n", I);
771
772 const ConstBeginEnd Const_CBE;
773 for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I)
774 printf("%d\n", Const_CBE[I]);
775 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
776 // CHECK-FIXES: for (unsigned int I : Const_CBE)
777 // CHECK-FIXES-NEXT: printf("%d\n", I);
778 }
779
780 struct DerefByValue {
781 DerefByValue();
782 struct iter { unsigned operator*(); };
783 unsigned size() const;
784 iter begin();
785 iter end();
786 unsigned operator[](int);
787 };
788
derefByValueTest()789 void derefByValueTest() {
790 DerefByValue DBV;
791 for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
792 printf("%d\n", DBV[I]);
793 }
794 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
795 // CHECK-FIXES: for (unsigned int I : DBV)
796 // CHECK-FIXES-NEXT: printf("%d\n", I);
797
798 for (unsigned I = 0, E = DBV.size(); I < E; ++I) {
799 auto f = [DBV, I]() {};
800 printf("%d\n", DBV[I]);
801 }
802 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
803 // CHECK-FIXES: for (unsigned int I : DBV)
804 // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {};
805 // CHECK-FIXES-NEXT: printf("%d\n", I);
806 }
807
fundamentalTypesTest()808 void fundamentalTypesTest() {
809 const int N = 10;
810 bool Bools[N];
811 for (int i = 0; i < N; ++i)
812 printf("%d", Bools[i]);
813 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
814 // CHECK-FIXES: for (bool Bool : Bools)
815
816 int Ints[N];
817 unsigned short int Shorts[N];
818 for (int i = 0; i < N; ++i)
819 printf("%d", Shorts[i]);
820 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
821 // CHECK-FIXES: for (unsigned short Short : Shorts)
822
823 signed long Longs[N];
824 for (int i = 0; i < N; ++i)
825 printf("%d", Longs[i]);
826 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
827 // CHECK-FIXES: for (long Long : Longs)
828
829 long long int LongLongs[N];
830 for (int i = 0; i < N; ++i)
831 printf("%d", LongLongs[i]);
832 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
833 // CHECK-FIXES: for (long long LongLong : LongLongs)
834
835 char Chars[N];
836 for (int i = 0; i < N; ++i)
837 printf("%d", Chars[i]);
838 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
839 // CHECK-FIXES: for (char Char : Chars)
840
841 wchar_t WChars[N];
842 for (int i = 0; i < N; ++i)
843 printf("%d", WChars[i]);
844 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
845 // CHECK-FIXES: for (wchar_t WChar : WChars)
846
847 float Floats[N];
848 for (int i = 0; i < N; ++i)
849 printf("%d", Floats[i]);
850 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
851 // CHECK-FIXES: for (float Float : Floats)
852
853 double Doubles[N];
854 for (int i = 0; i < N; ++i)
855 printf("%d", Doubles[i]);
856 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
857 // CHECK-FIXES: for (double Double : Doubles)
858 }
859
860 } // namespace PseudoArray
861