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