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

source code of clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-basic.cpp