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

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

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