1// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -I %S/Inputs/loop-convert
2
3#include "structures.h"
4
5namespace Dependency {
6
7void f() {
8 const int N = 6;
9 const int M = 8;
10 int Arr[N][M];
11
12 for (int I = 0; I < N; ++I) {
13 int A = 0;
14 int B = Arr[I][A];
15 }
16 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
17 // CHECK-FIXES: for (auto & I : Arr)
18 // CHECK-FIXES-NEXT: int A = 0;
19 // CHECK-FIXES-NEXT: int B = I[A];
20
21 for (int J = 0; J < M; ++J) {
22 int A = 0;
23 int B = Arr[A][J];
24 }
25}
26
27} // namespace Dependency
28
29namespace NamingAlias {
30
31const int N = 10;
32
33Val Arr[N];
34dependent<Val> V;
35dependent<Val> *Pv;
36Val &func(Val &);
37void sideEffect(int);
38
39void aliasing() {
40 // If the loop container is only used for a declaration of a temporary
41 // variable to hold each element, we can name the new variable for the
42 // converted range-based loop as the temporary variable's name.
43
44 // In the following case, "T" is used as a temporary variable to hold each
45 // element, and thus we consider the name "T" aliased to the loop.
46 // The extra blank braces are left as a placeholder for after the variable
47 // declaration is deleted.
48 for (int I = 0; I < N; ++I) {
49 Val &T = Arr[I];
50 {}
51 int Y = T.X;
52 }
53 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
54 // CHECK-FIXES: for (auto & T : Arr)
55 // CHECK-FIXES-NOT: Val &{{[a-z_]+}} =
56 // CHECK-FIXES-NEXT: {}
57 // CHECK-FIXES-NEXT: int Y = T.X;
58
59 // The container was not only used to initialize a temporary loop variable for
60 // the container's elements, so we do not alias the new loop variable.
61 for (int I = 0; I < N; ++I) {
62 Val &T = Arr[I];
63 int Y = T.X;
64 int Z = Arr[I].X + T.X;
65 }
66 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
67 // CHECK-FIXES: for (auto & I : Arr)
68 // CHECK-FIXES-NEXT: Val &T = I;
69 // CHECK-FIXES-NEXT: int Y = T.X;
70 // CHECK-FIXES-NEXT: int Z = I.X + T.X;
71
72 for (int I = 0; I < N; ++I) {
73 Val T = Arr[I];
74 int Y = T.X;
75 int Z = Arr[I].X + T.X;
76 }
77 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
78 // CHECK-FIXES: for (auto & I : Arr)
79 // CHECK-FIXES-NEXT: Val T = I;
80 // CHECK-FIXES-NEXT: int Y = T.X;
81 // CHECK-FIXES-NEXT: int Z = I.X + T.X;
82
83 // The same for pseudo-arrays like std::vector<T> (or here dependent<Val>)
84 // which provide a subscript operator[].
85 for (int I = 0; I < V.size(); ++I) {
86 Val &T = V[I];
87 {}
88 int Y = T.X;
89 }
90 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
91 // CHECK-FIXES: for (auto & T : V)
92 // CHECK-FIXES-NEXT: {}
93 // CHECK-FIXES-NEXT: int Y = T.X;
94
95 // The same with a call to at()
96 for (int I = 0; I < Pv->size(); ++I) {
97 Val &T = Pv->at(I);
98 {}
99 int Y = T.X;
100 }
101 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
102 // CHECK-FIXES: for (auto & T : *Pv)
103 // CHECK-FIXES-NEXT: {}
104 // CHECK-FIXES-NEXT: int Y = T.X;
105
106 for (int I = 0; I < N; ++I) {
107 Val &T = func(Arr[I]);
108 int Y = T.X;
109 }
110 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
111 // CHECK-FIXES: for (auto & I : Arr)
112 // CHECK-FIXES-NEXT: Val &T = func(I);
113 // CHECK-FIXES-NEXT: int Y = T.X;
114
115 int IntArr[N];
116 for (unsigned I = 0; I < N; ++I) {
117 if (int Alias = IntArr[I]) {
118 sideEffect(Alias);
119 }
120 }
121 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
122 // CHECK-FIXES: for (int Alias : IntArr)
123 // CHECK-FIXES-NEXT: if (Alias)
124
125 for (unsigned I = 0; I < N; ++I) {
126 while (int Alias = IntArr[I]) {
127 sideEffect(Alias);
128 }
129 }
130 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
131 // CHECK-FIXES: for (int Alias : IntArr)
132 // CHECK-FIXES-NEXT: while (Alias)
133
134 for (unsigned I = 0; I < N; ++I) {
135 switch (int Alias = IntArr[I]) {
136 default:
137 sideEffect(Alias);
138 }
139 }
140 // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
141 // CHECK-FIXES: for (int Alias : IntArr)
142 // CHECK-FIXES-NEXT: switch (Alias)
143
144 for (unsigned I = 0; I < N; ++I) {
145 for (int Alias = IntArr[I]; Alias < N; ++Alias) {
146 sideEffect(Alias);
147 }
148 }
149 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
150 // CHECK-FIXES: for (int Alias : IntArr)
151 // CHECK-FIXES-NEXT: for (; Alias < N; ++Alias)
152
153 for (unsigned I = 0; I < N; ++I) {
154 for (unsigned J = 0; int Alias = IntArr[I]; ++J) {
155 sideEffect(Alias);
156 }
157 }
158 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
159 // CHECK-FIXES: for (int Alias : IntArr)
160 // CHECK-FIXES-NEXT: for (unsigned J = 0; Alias; ++J)
161
162 struct IntRef { IntRef(); IntRef(const int& i); operator int*(); };
163 for (int I = 0; I < N; ++I) {
164 IntRef Int(IntArr[I]);
165 }
166 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
167 // CHECK-FIXES: for (int I : IntArr)
168 // CHECK-FIXES-NEXT: IntRef Int(I);
169
170 int *PtrArr[N];
171 for (unsigned I = 0; I < N; ++I) {
172 const int* const P = PtrArr[I];
173 printf("%d\n", *P);
174 }
175 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
176 // CHECK-FIXES: for (auto P : PtrArr)
177 // CHECK-FIXES-NEXT: printf("%d\n", *P);
178
179 IntRef Refs[N];
180 for (unsigned I = 0; I < N; ++I) {
181 int *P = Refs[I];
182 printf("%d\n", *P);
183 }
184 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
185 // CHECK-FIXES: for (auto & Ref : Refs)
186 // CHECK-FIXES-NEXT: int *P = Ref;
187 // CHECK-FIXES-NEXT: printf("%d\n", *P);
188
189 // Ensure that removing the alias doesn't leave empty lines behind.
190 for (int I = 0; I < N; ++I) {
191 auto &X = IntArr[I];
192 X = 0;
193 }
194 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
195 // CHECK-FIXES: for (int & X : IntArr) {
196 // CHECK-FIXES-NEXT: {{^ X = 0;$}}
197 // CHECK-FIXES-NEXT: {{^ }$}}
198}
199
200void refs_and_vals() {
201 // The following tests check that the transform correctly preserves the
202 // reference or value qualifiers of the aliased variable. That is, if the
203 // variable was declared as a value, the loop variable will be declared as a
204 // value and vice versa for references.
205
206 S Ss;
207 const S S_const = Ss;
208
209 for (S::const_iterator It = S_const.begin(); It != S_const.end(); ++It) {
210 MutableVal Alias = *It;
211 {}
212 Alias.X = 0;
213 }
214 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
215 // CHECK-FIXES: for (auto Alias : S_const)
216 // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =
217 // CHECK-FIXES-NEXT: {}
218 // CHECK-FIXES-NEXT: Alias.X = 0;
219
220 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
221 MutableVal Alias = *It;
222 {}
223 Alias.X = 0;
224 }
225 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
226 // CHECK-FIXES: for (auto Alias : Ss)
227 // CHECK-FIXES-NOT: MutableVal {{[a-z_]+}} =
228 // CHECK-FIXES-NEXT: {}
229 // CHECK-FIXES-NEXT: Alias.X = 0;
230
231 for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) {
232 MutableVal &Alias = *It;
233 {}
234 Alias.X = 0;
235 }
236 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
237 // CHECK-FIXES: for (auto & Alias : Ss)
238 // CHECK-FIXES-NOT: MutableVal &{{[a-z_]+}} =
239 // CHECK-FIXES-NEXT: {}
240 // CHECK-FIXES-NEXT: Alias.X = 0;
241
242 dependent<int> Dep, Other;
243 for (dependent<int>::iterator It = Dep.begin(), E = Dep.end(); It != E; ++It) {
244 printf("%d\n", *It);
245 const int& Idx = Other[0];
246 unsigned Othersize = Other.size();
247 }
248 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
249 // CHECK-FIXES: for (int & It : Dep)
250 // CHECK-FIXES-NEXT: printf("%d\n", It);
251 // CHECK-FIXES-NEXT: const int& Idx = Other[0];
252 // CHECK-FIXES-NEXT: unsigned Othersize = Other.size();
253
254 for (int i = 0; i < Other.size(); ++i) {
255 Other.at(i);
256 }
257 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
258 // CHECK-FIXES: for (int & i : Other)
259 // CHECK-FIXES: i;
260
261 for (int I = 0, E = Dep.size(); I != E; ++I) {
262 int Idx = Other.at(I);
263 Other.at(I, I); // Should not trigger assert failure.
264 }
265}
266
267struct MemberNaming {
268 const static int N = 10;
269 int Ints[N], Ints_[N];
270 dependent<int> DInts;
271 void loops() {
272 for (int I = 0; I < N; ++I) {
273 printf("%d\n", Ints[I]);
274 }
275 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
276 // CHECK-FIXES: for (int Int : Ints)
277 // CHECK-FIXES-NEXT: printf("%d\n", Int);
278
279 for (int I = 0; I < N; ++I) {
280 printf("%d\n", Ints_[I]);
281 }
282 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
283 // CHECK-FIXES: for (int Int : Ints_)
284 // CHECK-FIXES-NEXT: printf("%d\n", Int);
285
286 for (int I = 0; I < DInts.size(); ++I) {
287 printf("%d\n", DInts[I]);
288 }
289 // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead
290 // CHECK-FIXES: for (int DInt : DInts)
291 // CHECK-FIXES-NEXT: printf("%d\n", DInt);
292 }
293
294 void outOfLine();
295};
296void MemberNaming::outOfLine() {
297 for (int I = 0; I < N; ++I) {
298 printf("%d\n", Ints[I]);
299 }
300 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
301 // CHECK-FIXES: for (int Int : Ints)
302 // CHECK-FIXES-NEXT: printf("%d\n", Int);
303
304 for (int I = 0; I < N; ++I) {
305 printf("%d\n", Ints_[I]);
306 }
307 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
308 // CHECK-FIXES: for (int Int : Ints_)
309 // CHECK-FIXES-NEXT: printf("%d\n", Int);
310}
311
312} // namespace NamingAlias
313
314namespace NamingConlict {
315
316#define MAX(a, b) (a > b) ? a : b
317#define DEF 5
318
319const int N = 10;
320int Nums[N];
321int Sum = 0;
322
323namespace ns {
324struct St {
325 int X;
326};
327}
328
329void sameNames() {
330 int Num = 0;
331 for (int I = 0; I < N; ++I) {
332 printf("Fibonacci number is %d\n", Nums[I]);
333 Sum += Nums[I] + 2 + Num;
334 (void)Nums[I];
335 }
336 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
337 // CHECK-FIXES: for (int & I : Nums)
338 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
339 // CHECK-FIXES-NEXT: Sum += I + 2 + Num;
340 // CHECK-FIXES-NEXT: (void)I;
341
342 int Elem = 0;
343 for (int I = 0; I < N; ++I) {
344 printf("Fibonacci number is %d\n", Nums[I]);
345 Sum += Nums[I] + 2 + Num + Elem;
346 (void)Nums[I];
347 }
348 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
349 // CHECK-FIXES: for (int & I : Nums)
350 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I);
351 // CHECK-FIXES-NEXT: Sum += I + 2 + Num + Elem;
352 // CHECK-FIXES-NEXT: (void)I;
353}
354
355void oldIndexConflict() {
356 for (int Num = 0; Num < N; ++Num) {
357 printf("Num: %d\n", Nums[Num]);
358 }
359 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
360 // CHECK-FIXES: for (int Num : Nums)
361 // CHECK-FIXES-NEXT: printf("Num: %d\n", Num);
362
363 S Things;
364 for (S::iterator Thing = Things.begin(), End = Things.end(); Thing != End; ++Thing) {
365 printf("Thing: %d %d\n", Thing->X, (*Thing).X);
366 }
367 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
368 // CHECK-FIXES: for (auto & Thing : Things)
369 // CHECK-FIXES-NEXT: printf("Thing: %d %d\n", Thing.X, Thing.X);
370}
371
372void macroConflict() {
373 S MAXs;
374 for (S::iterator It = MAXs.begin(), E = MAXs.end(); It != E; ++It) {
375 printf("s has value %d\n", (*It).X);
376 printf("Max of 3 and 5: %d\n", MAX(3, 5));
377 }
378 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
379 // CHECK-FIXES: for (auto & It : MAXs)
380 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
381 // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
382
383 for (S::const_iterator It = MAXs.begin(), E = MAXs.end(); It != E; ++It) {
384 printf("s has value %d\n", (*It).X);
385 printf("Max of 3 and 5: %d\n", MAX(3, 5));
386 }
387 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
388 // CHECK-FIXES: for (auto It : MAXs)
389 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
390 // CHECK-FIXES-NEXT: printf("Max of 3 and 5: %d\n", MAX(3, 5));
391
392 T DEFs;
393 for (T::iterator It = DEFs.begin(), E = DEFs.end(); It != E; ++It) {
394 if (*It == DEF) {
395 printf("I found %d\n", *It);
396 }
397 }
398 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
399 // CHECK-FIXES: for (int & It : DEFs)
400 // CHECK-FIXES-NEXT: if (It == DEF)
401 // CHECK-FIXES-NEXT: printf("I found %d\n", It);
402}
403
404void keywordConflict() {
405 T ints;
406 for (T::iterator It = ints.begin(), E = ints.end(); It != E; ++It) {
407 *It = 5;
408 }
409 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
410 // CHECK-FIXES: for (int & It : ints)
411 // CHECK-FIXES-NEXT: It = 5;
412
413 U __FUNCTION__s;
414 for (U::iterator It = __FUNCTION__s.begin(), E = __FUNCTION__s.end();
415 It != E; ++It) {
416 int __FUNCTION__s_It = (*It).X + 2;
417 }
418 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
419 // CHECK-FIXES: for (auto & It : __FUNCTION__s)
420 // CHECK-FIXES-NEXT: int __FUNCTION__s_It = It.X + 2;
421}
422
423void typeConflict() {
424 T Vals;
425 // Using the name "Val", although it is the name of an existing struct, is
426 // safe in this loop since it will only exist within this scope.
427 for (T::iterator It = Vals.begin(), E = Vals.end(); It != E; ++It)
428 (void) *It;
429 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
430 // CHECK-FIXES: for (int & Val : Vals)
431
432 // We cannot use the name "Val" in this loop since there is a reference to
433 // it in the body of the loop.
434 for (T::iterator It = Vals.begin(), E = Vals.end(); It != E; ++It) {
435 *It = sizeof(Val);
436 }
437 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
438 // CHECK-FIXES: for (int & It : Vals)
439 // CHECK-FIXES-NEXT: It = sizeof(Val);
440
441 typedef struct Val TD;
442 U TDs;
443 // Naming the variable "TD" within this loop is safe because the typedef
444 // was never used within the loop.
445 for (U::iterator It = TDs.begin(), E = TDs.end(); It != E; ++It)
446 (void) *It;
447 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
448 // CHECK-FIXES: for (auto & TD : TDs)
449
450 // "TD" cannot be used in this loop since the typedef is being used.
451 for (U::iterator It = TDs.begin(), E = TDs.end(); It != E; ++It) {
452 TD V;
453 V.X = 5;
454 (void) *It;
455 }
456 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
457 // CHECK-FIXES: for (auto & It : TDs)
458 // CHECK-FIXES-NEXT: TD V;
459 // CHECK-FIXES-NEXT: V.X = 5;
460
461 using ns::St;
462 T Sts;
463 for (T::iterator It = Sts.begin(), E = Sts.end(); It != E; ++It) {
464 *It = sizeof(St);
465 }
466 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
467 // CHECK-FIXES: for (int & It : Sts)
468 // CHECK-FIXES-NEXT: It = sizeof(St);
469}
470
471} // namespace NamingConflict
472
473namespace FreeBeginEnd {
474
475// FIXME: Loop Convert should detect free begin()/end() functions.
476
477struct MyArray {
478 unsigned size();
479};
480
481template <typename T>
482struct MyContainer {
483};
484
485int *begin(const MyArray &Arr);
486int *end(const MyArray &Arr);
487
488template <typename T>
489T *begin(const MyContainer<T> &C);
490template <typename T>
491T *end(const MyContainer<T> &C);
492
493// The Loop Convert Transform doesn't detect free functions begin()/end() and
494// so fails to transform these cases which it should.
495void f() {
496 MyArray Arr;
497 for (unsigned I = 0, E = Arr.size(); I < E; ++I) {
498 }
499
500 MyContainer<int> C;
501 for (int *I = begin(C), *E = end(C); I != E; ++I) {
502 }
503}
504
505} // namespace FreeBeginEnd
506
507namespace Nesting {
508
509void g(S::iterator It);
510void const_g(S::const_iterator It);
511class Foo {
512 public:
513 void g(S::iterator It);
514 void const_g(S::const_iterator It);
515};
516
517void f() {
518 const int N = 10;
519 const int M = 15;
520 Val Arr[N];
521 for (int I = 0; I < N; ++I) {
522 for (int J = 0; J < N; ++J) {
523 int K = Arr[I].X + Arr[J].X;
524 // The repeat is there to allow FileCheck to make sure the two variable
525 // names aren't the same.
526 int L = Arr[I].X + Arr[J].X;
527 }
528 }
529 // CHECK-MESSAGES: :[[@LINE-8]]:3: warning: use range-based for loop instead
530 // CHECK-MESSAGES: :[[@LINE-8]]:5: warning: use range-based for loop instead
531 // CHECK-FIXES: for (auto & I : Arr)
532 // CHECK-FIXES-NEXT: for (auto & J : Arr)
533 // CHECK-FIXES-NEXT: int K = I.X + J.X;
534 // CHECK-FIXES-NOT: int L = I.X + I.X;
535
536 // The inner loop is also convertible, but doesn't need to be converted
537 // immediately. FIXME: update this test when that changes.
538 Val Nest[N][M];
539 for (int I = 0; I < N; ++I) {
540 for (int J = 0; J < M; ++J) {
541 printf("Got item %d", Nest[I][J].X);
542 }
543 }
544 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
545 // CHECK-FIXES: for (auto & I : Nest)
546 // CHECK-FIXES-NEXT: for (int J = 0; J < M; ++J)
547 // CHECK-FIXES-NEXT: printf("Got item %d", I[J].X);
548
549 // Note that the order of M and N are switched for this test.
550 for (int J = 0; J < M; ++J) {
551 for (int I = 0; I < N; ++I) {
552 printf("Got item %d", Nest[I][J].X);
553 }
554 }
555 // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop instead
556 // CHECK-FIXES-NOT: for (auto & {{[a-zA-Z_]+}} : Nest[I])
557 // CHECK-FIXES: for (int J = 0; J < M; ++J)
558 // CHECK-FIXES-NEXT: for (auto & I : Nest)
559 // CHECK-FIXES-NEXT: printf("Got item %d", I[J].X);
560
561 // The inner loop is also convertible.
562 Nested<T> NestT;
563 for (Nested<T>::iterator I = NestT.begin(), E = NestT.end(); I != E; ++I) {
564 for (T::iterator TI = (*I).begin(), TE = (*I).end(); TI != TE; ++TI) {
565 printf("%d", *TI);
566 }
567 }
568 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
569 // CHECK-FIXES: for (auto & I : NestT)
570 // CHECK-FIXES-NEXT: for (T::iterator TI = I.begin(), TE = I.end(); TI != TE; ++TI)
571 // CHECK-FIXES-NEXT: printf("%d", *TI);
572
573 // The inner loop is also convertible.
574 Nested<S> NestS;
575 for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
576 for (S::const_iterator SI = (*I).begin(), SE = (*I).end(); SI != SE; ++SI) {
577 printf("%d", *SI);
578 }
579 }
580 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
581 // CHECK-FIXES: for (auto I : NestS)
582 // CHECK-FIXES-NEXT: for (S::const_iterator SI = I.begin(), SE = I.end(); SI != SE; ++SI)
583 // CHECK-FIXES-NEXT: printf("%d", *SI);
584
585 for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
586 const S &Ss = *I;
587 for (S::const_iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
588 printf("%d", *SI);
589 const_g(SI);
590 }
591 }
592 // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
593 // CHECK-FIXES: for (auto Ss : NestS)
594
595 for (Nested<S>::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
596 S &Ss = *I;
597 for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
598 printf("%d", *SI);
599 g(SI);
600 }
601 }
602 // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
603 // CHECK-FIXES: for (auto & Ss : NestS)
604
605 Foo foo;
606 for (Nested<S>::const_iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
607 const S &Ss = *I;
608 for (S::const_iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
609 printf("%d", *SI);
610 foo.const_g(SI);
611 }
612 }
613 // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
614 // CHECK-FIXES: for (auto Ss : NestS)
615
616 for (Nested<S>::iterator I = NestS.begin(), E = NestS.end(); I != E; ++I) {
617 S &Ss = *I;
618 for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI) {
619 printf("%d", *SI);
620 foo.g(SI);
621 }
622 }
623 // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
624 // CHECK-FIXES: for (auto & Ss : NestS)
625
626}
627
628} // namespace Nesting
629
630namespace SingleIterator {
631
632void complexContainer() {
633 X Exes[5];
634 int Index = 0;
635
636 for (S::iterator I = Exes[Index].getS().begin(), E = Exes[Index].getS().end(); I != E; ++I) {
637 MutableVal K = *I;
638 MutableVal J = *I;
639 }
640 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
641 // CHECK-FIXES: for (auto & I : Exes[Index].getS())
642 // CHECK-FIXES-NEXT: MutableVal K = I;
643 // CHECK-FIXES-NEXT: MutableVal J = I;
644}
645
646void f() {
647 /// begin()/end() - based for loops here:
648 T Tt;
649 for (T::iterator It = Tt.begin(); It != Tt.end(); ++It) {
650 printf("I found %d\n", *It);
651 }
652 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
653 // CHECK-FIXES: for (int & It : Tt)
654 // CHECK-FIXES-NEXT: printf("I found %d\n", It);
655
656 T *Pt;
657 for (T::iterator It = Pt->begin(); It != Pt->end(); ++It) {
658 printf("I found %d\n", *It);
659 }
660 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
661 // CHECK-FIXES: for (int & It : *Pt)
662 // CHECK-FIXES-NEXT: printf("I found %d\n", It);
663
664 S Ss;
665 for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
666 printf("s has value %d\n", (*It).X);
667 }
668 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
669 // CHECK-FIXES: for (auto & It : Ss)
670 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
671
672 S *Ps;
673 for (S::iterator It = Ps->begin(); It != Ps->end(); ++It) {
674 printf("s has value %d\n", (*It).X);
675 }
676 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
677 // CHECK-FIXES: for (auto & P : *Ps)
678 // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
679
680 for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
681 printf("s has value %d\n", It->X);
682 }
683 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
684 // CHECK-FIXES: for (auto & It : Ss)
685 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
686
687 for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
688 It->X = 3;
689 }
690 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
691 // CHECK-FIXES: for (auto & It : Ss)
692 // CHECK-FIXES-NEXT: It.X = 3;
693
694 for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
695 (*It).X = 3;
696 }
697 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
698 // CHECK-FIXES: for (auto & It : Ss)
699 // CHECK-FIXES-NEXT: It.X = 3;
700
701 for (S::iterator It = Ss.begin(); It != Ss.end(); ++It) {
702 It->nonConstFun(4, 5);
703 }
704 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
705 // CHECK-FIXES: for (auto & It : Ss)
706 // CHECK-FIXES-NEXT: It.nonConstFun(4, 5);
707
708 U Uu;
709 for (U::iterator It = Uu.begin(); It != Uu.end(); ++It) {
710 printf("s has value %d\n", It->X);
711 }
712 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
713 // CHECK-FIXES: for (auto & It : Uu)
714 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
715
716 for (U::iterator It = Uu.begin(); It != Uu.end(); ++It) {
717 printf("s has value %d\n", (*It).X);
718 }
719 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
720 // CHECK-FIXES: for (auto & It : Uu)
721 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
722
723 U::iterator A;
724 for (U::iterator I = Uu.begin(); I != Uu.end(); ++I)
725 int K = A->X + I->X;
726 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
727 // CHECK-FIXES: for (auto & I : Uu)
728 // CHECK-FIXES-NEXT: int K = A->X + I.X;
729
730 dependent<int> V;
731 for (dependent<int>::iterator It = V.begin();
732 It != V.end(); ++It) {
733 printf("Fibonacci number is %d\n", *It);
734 }
735 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
736 // CHECK-FIXES: for (int & It : V)
737 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
738
739 for (dependent<int>::iterator It(V.begin());
740 It != V.end(); ++It) {
741 printf("Fibonacci number is %d\n", *It);
742 }
743 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
744 // CHECK-FIXES: for (int & It : V)
745 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
746
747 doublyDependent<int, int> intmap;
748 for (doublyDependent<int, int>::iterator It = intmap.begin();
749 It != intmap.end(); ++It) {
750 printf("intmap[%d] = %d", It->first, It->second);
751 }
752 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
753 // CHECK-FIXES: for (auto & It : intmap)
754 // CHECK-FIXES-NEXT: printf("intmap[%d] = %d", It.first, It.second);
755}
756
757void different_type() {
758 // Tests to verify the proper use of auto where the init variable type and the
759 // initializer type differ or are mostly the same except for const qualifiers.
760
761 // Ss.begin() returns a type 'iterator' which is just a non-const pointer and
762 // differs from const_iterator only on the const qualification.
763 S Ss;
764 for (S::const_iterator It = Ss.begin(); It != Ss.end(); ++It) {
765 printf("s has value %d\n", (*It).X);
766 }
767 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
768 // CHECK-FIXES: for (auto It : Ss)
769 // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X);
770
771 S *Ps;
772 for (S::const_iterator It = Ps->begin(); It != Ps->end(); ++It) {
773 printf("s has value %d\n", (*It).X);
774 }
775 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
776 // CHECK-FIXES: for (auto P : *Ps)
777 // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X);
778
779 dependent<int> V;
780 for (dependent<int>::const_iterator It = V.begin(); It != V.end(); ++It) {
781 printf("Fibonacci number is %d\n", *It);
782 }
783 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
784 // CHECK-FIXES: for (int It : V)
785 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
786
787 for (dependent<int>::const_iterator It(V.begin()); It != V.end(); ++It) {
788 printf("Fibonacci number is %d\n", *It);
789 }
790 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
791 // CHECK-FIXES: for (int It : V)
792 // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It);
793}
794
795} // namespace SingleIterator
796
797
798namespace Macros {
799
800#define TWO_PARAM(x, y) if (x == y) {}
801#define THREE_PARAM(x, y, z) if (x == y) {z;}
802
803const int N = 10;
804int Arr[N];
805
806void messing_with_macros() {
807 for (int I = 0; I < N; ++I) {
808 printf("Value: %d\n", Arr[I]);
809 }
810 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
811 // CHECK-FIXES: for (int I : Arr)
812 // CHECK-FIXES-NEXT: printf("Value: %d\n", I);
813
814 for (int I = 0; I < N; ++I) {
815 printf("Value: %d\n", CONT Arr[I]);
816 }
817
818 // Multiple macro arguments.
819 for (int I = 0; I < N; ++I) {
820 TWO_PARAM(Arr[I], Arr[I]);
821 THREE_PARAM(Arr[I], Arr[I], Arr[I]);
822 }
823 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
824 // CHECK-FIXES: for (int & I : Arr)
825 // CHECK-FIXES-NEXT: TWO_PARAM(I, I);
826 // CHECK-FIXES-NEXT: THREE_PARAM(I, I, I);
827}
828
829} // namespace Macros
830
831namespace Templates {
832
833template <class Container>
834void set_union(Container &container) {
835 for (typename Container::const_iterator SI = container.begin(),
836 SE = container.end(); SI != SE; ++SI) {
837 (void) *SI;
838 }
839
840 S Ss;
841 for (S::iterator SI = Ss.begin(), SE = Ss.end(); SI != SE; ++SI)
842 (void) *SI;
843 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
844 // CHECK-FIXES: for (auto & SI : Ss)
845}
846
847void template_instantiation() {
848 S Ss;
849 set_union(Ss);
850}
851
852} // namespace Templates
853
854namespace Lambdas {
855
856void capturesIndex() {
857 const int N = 10;
858 int Arr[N];
859 // FIXME: the next four loops could be convertible, if the capture list is
860 // also changed.
861
862 for (int I = 0; I < N; ++I)
863 auto F1 = [Arr, I]() { int R1 = Arr[I] + 1; };
864 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
865 // CHECK-FIXES: for (int I : Arr)
866 // CHECK-FIXES-NEXT: auto F1 = [Arr, &I]() { int R1 = I + 1; };
867
868 for (int I = 0; I < N; ++I)
869 auto F2 = [Arr, &I]() { int R2 = Arr[I] + 3; };
870 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
871 // CHECK-FIXES: for (int I : Arr)
872 // CHECK-FIXES-NEXT: auto F2 = [Arr, &I]() { int R2 = I + 3; };
873
874 // FIXME: alias don't work if the index is captured.
875 // Alias declared inside lambda (by value).
876 for (int I = 0; I < N; ++I)
877 auto F3 = [&Arr, I]() { int R3 = Arr[I]; };
878 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
879 // CHECK-FIXES: for (int I : Arr)
880 // CHECK-FIXES-NEXT: auto F3 = [&Arr, &I]() { int R3 = I; };
881
882
883 for (int I = 0; I < N; ++I)
884 auto F4 = [&Arr, &I]() { int R4 = Arr[I]; };
885 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
886 // CHECK-FIXES: for (int I : Arr)
887 // CHECK-FIXES-NEXT: auto F4 = [&Arr, &I]() { int R4 = I; };
888
889 // Alias declared inside lambda (by reference).
890 for (int I = 0; I < N; ++I)
891 auto F5 = [&Arr, I]() { int &R5 = Arr[I]; };
892 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
893 // CHECK-FIXES: for (int & I : Arr)
894 // CHECK-FIXES-NEXT: auto F5 = [&Arr, &I]() { int &R5 = I; };
895
896
897 for (int I = 0; I < N; ++I)
898 auto F6 = [&Arr, &I]() { int &R6 = Arr[I]; };
899 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
900 // CHECK-FIXES: for (int & I : Arr)
901 // CHECK-FIXES-NEXT: auto F6 = [&Arr, &I]() { int &R6 = I; };
902
903 for (int I = 0; I < N; ++I) {
904 auto F = [Arr, I](int k) {
905 printf("%d\n", Arr[I] + k);
906 };
907 F(Arr[I]);
908 }
909 // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
910 // CHECK-FIXES: for (int I : Arr)
911 // CHECK-FIXES-NEXT: auto F = [Arr, &I](int k)
912 // CHECK-FIXES-NEXT: printf("%d\n", I + k);
913 // CHECK-FIXES: F(I);
914}
915
916void implicitCapture() {
917 const int N = 10;
918 int Arr[N];
919 // Index is used, not convertible.
920 for (int I = 0; I < N; ++I) {
921 auto G1 = [&]() {
922 int R = Arr[I];
923 int J = I;
924 };
925 }
926
927 for (int I = 0; I < N; ++I) {
928 auto G2 = [=]() {
929 int R = Arr[I];
930 int J = I;
931 };
932 }
933
934 // Convertible.
935 for (int I = 0; I < N; ++I) {
936 auto G3 = [&]() {
937 int R3 = Arr[I];
938 int J3 = Arr[I] + R3;
939 };
940 }
941 // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
942 // CHECK-FIXES: for (int I : Arr)
943 // CHECK-FIXES-NEXT: auto G3 = [&]()
944 // CHECK-FIXES-NEXT: int R3 = I;
945 // CHECK-FIXES-NEXT: int J3 = I + R3;
946
947 for (int I = 0; I < N; ++I) {
948 auto G4 = [=]() {
949 int R4 = Arr[I] + 5;
950 };
951 }
952 // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead
953 // CHECK-FIXES: for (int I : Arr)
954 // CHECK-FIXES-NEXT: auto G4 = [=]()
955 // CHECK-FIXES-NEXT: int R4 = I + 5;
956
957 // Alias by value.
958 for (int I = 0; I < N; ++I) {
959 auto G5 = [&]() {
960 int R5 = Arr[I];
961 int J5 = 8 + R5;
962 };
963 }
964 // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
965 // CHECK-FIXES: for (int R5 : Arr)
966 // CHECK-FIXES-NEXT: auto G5 = [&]()
967 // CHECK-FIXES-NEXT: int J5 = 8 + R5;
968
969 // Alias by reference.
970 for (int I = 0; I < N; ++I) {
971 auto G6 = [&]() {
972 int &R6 = Arr[I];
973 int J6 = -1 + R6;
974 };
975 }
976 // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead
977 // CHECK-FIXES: for (int & R6 : Arr)
978 // CHECK-FIXES-NEXT: auto G6 = [&]()
979 // CHECK-FIXES-NEXT: int J6 = -1 + R6;
980}
981
982void iterators() {
983 dependent<int> Dep;
984
985 for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)
986 auto H1 = [&I]() { int R = *I; };
987 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
988 // CHECK-FIXES: for (int & I : Dep)
989 // CHECK-FIXES-NEXT: auto H1 = [&I]() { int R = I; };
990
991 for (dependent<int>::iterator I = Dep.begin(), E = Dep.end(); I != E; ++I)
992 auto H2 = [&]() { int R = *I + 2; };
993 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
994 // CHECK-FIXES: for (int & I : Dep)
995 // CHECK-FIXES-NEXT: auto H2 = [&]() { int R = I + 2; };
996
997 for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
998 I != E; ++I)
999 auto H3 = [I]() { int R = *I; };
1000 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1001 // CHECK-FIXES: for (int I : Dep)
1002 // CHECK-FIXES-NEXT: auto H3 = [&I]() { int R = I; };
1003
1004 for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
1005 I != E; ++I)
1006 auto H4 = [&]() { int R = *I + 1; };
1007 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1008 // CHECK-FIXES: for (int I : Dep)
1009 // CHECK-FIXES-NEXT: auto H4 = [&]() { int R = I + 1; };
1010
1011 for (dependent<int>::const_iterator I = Dep.begin(), E = Dep.end();
1012 I != E; ++I)
1013 auto H5 = [=]() { int R = *I; };
1014 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1015 // CHECK-FIXES: for (int R : Dep)
1016 // CHECK-FIXES-NEXT: auto H5 = [=]() { };
1017}
1018
1019void captureByValue() {
1020 // When the index is captured by value, we should replace this by a capture
1021 // by reference. This avoids extra copies.
1022 // FIXME: this could change semantics on array or pseudoarray loops if the
1023 // container is captured by copy.
1024 const int N = 10;
1025 int Arr[N];
1026 dependent<int> Dep;
1027
1028 for (int I = 0; I < N; ++I) {
1029 auto C1 = [&Arr, I]() { if (Arr[I] == 1); };
1030 }
1031 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1032 // CHECK-FIXES: for (int I : Arr)
1033 // CHECK-FIXES-NEXT: auto C1 = [&Arr, &I]() { if (I == 1); };
1034
1035 for (unsigned I = 0; I < Dep.size(); ++I) {
1036 auto C2 = [&Dep, I]() { if (Dep[I] == 2); };
1037 }
1038 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead
1039 // CHECK-FIXES: for (int I : Dep)
1040 // CHECK-FIXES-NEXT: auto C2 = [&Dep, &I]() { if (I == 2); };
1041}
1042
1043} // namespace Lambdas
1044
1045namespace InitLists {
1046
1047struct D { int Ii; };
1048struct E { D Dd; };
1049int g(int B);
1050
1051void f() {
1052 const unsigned N = 3;
1053 int Array[N];
1054
1055 // Subtrees of InitListExpr are visited twice. Test that we do not do repeated
1056 // replacements.
1057 for (unsigned I = 0; I < N; ++I) {
1058 int A{ Array[I] };
1059 int B{ g(B: Array[I]) };
1060 int C{ g( B: { Array[I] } ) };
1061 D Dd{ .Ii: { g( B: { Array[I] } ) } };
1062 E Ee{ .Dd: { .Ii: { g( B: { Array[I] } ) } } };
1063 }
1064 // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead
1065 // CHECK-FIXES: for (int I : Array)
1066 // CHECK-FIXES-NEXT: int A{ I };
1067 // CHECK-FIXES-NEXT: int B{ g(I) };
1068 // CHECK-FIXES-NEXT: int C{ g( { I } ) };
1069 // CHECK-FIXES-NEXT: D Dd{ { g( { I } ) } };
1070 // CHECK-FIXES-NEXT: E Ee{ { { g( { I } ) } } };
1071}
1072
1073} // namespace InitLists
1074
1075void bug28341() {
1076 char v[5];
1077 for(int i = 0; i < 5; ++i) {
1078 unsigned char value = v[i];
1079 if (value > 127)
1080 ;
1081 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead
1082 // CHECK-FIXES: for(unsigned char value : v)
1083 // CHECK-FIXES-NEXT: if (value > 127)
1084 }
1085}
1086

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