1 // RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -I %S/Inputs/loop-convert
2
3 #include "structures.h"
4
5 // CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
6 // CHECK-MESSAGES-NOT: modernize-loop-convert
7
8 namespace somenamespace {
9 template <class T> auto begin(T& t) -> decltype(t.begin());
10 template <class T> auto begin(const T& t) -> decltype(t.begin());
11 template <class T> auto end(T& t) -> decltype(t.end());
12 template <class T> auto end(const T& t) -> decltype(t.end());
13 template <class T> auto size(const T& t) -> decltype(t.size());
14 } // namespace somenamespace
15
16 struct SomeClass {
17 template <class T> static auto begin(T& t) -> decltype(t.begin());
18 template <class T> static auto begin(const T& t) -> decltype(t.begin());
19 template <class T> static auto end(T& t) -> decltype(t.end());
20 template <class T> static auto end(const T& t) -> decltype(t.end());
21 template <class T> static auto size(const T& t) -> decltype(t.size());
22 };
23
24 namespace Negative {
25
26 const int N = 6;
27 int Arr[N] = {1, 2, 3, 4, 5, 6};
28 int (*pArr)[N] = &Arr;
29 int Sum = 0;
30
31 // Checks for the Index start and end:
IndexStartAndEnd()32 void IndexStartAndEnd() {
33 for (int I = 0; I < N + 1; ++I)
34 Sum += Arr[I];
35
36 for (int I = 0; I < N - 1; ++I)
37 Sum += Arr[I];
38
39 for (int I = 1; I < N; ++I)
40 Sum += Arr[I];
41
42 for (int I = 1; I < N; ++I)
43 Sum += Arr[I];
44
45 for (int I = 0;; ++I)
46 Sum += (*pArr)[I];
47 }
48
49 // Checks for invalid increment steps:
increment()50 void increment() {
51 for (int I = 0; I < N; --I)
52 Sum += Arr[I];
53
54 for (int I = 0; I < N; I)
55 Sum += Arr[I];
56
57 for (int I = 0; I < N;)
58 Sum += Arr[I];
59
60 for (int I = 0; I < N; I += 2)
61 Sum++;
62 }
63
64 // Checks to make sure that the Index isn't used outside of the array:
IndexUse()65 void IndexUse() {
66 for (int I = 0; I < N; ++I)
67 Arr[I] += 1 + I;
68 }
69
70 // Check for loops that don't mention arrays
noArray()71 void noArray() {
72 for (int I = 0; I < N; ++I)
73 Sum += I;
74
75 for (int I = 0; I < N; ++I) {
76 }
77
78 for (int I = 0; I < N; ++I)
79 ;
80 }
81
82 // Checks for incorrect loop variables.
mixedVariables()83 void mixedVariables() {
84 int BadIndex;
85 for (int I = 0; BadIndex < N; ++I)
86 Sum += Arr[I];
87
88 for (int I = 0; I < N; ++BadIndex)
89 Sum += Arr[I];
90
91 for (int I = 0; BadIndex < N; ++BadIndex)
92 Sum += Arr[I];
93
94 for (int I = 0; BadIndex < N; ++BadIndex)
95 Sum += Arr[BadIndex];
96 }
97
98 // Checks for multiple arrays Indexed.
multipleArrays()99 void multipleArrays() {
100 int BadArr[N];
101
102 for (int I = 0; I < N; ++I)
103 Sum += Arr[I] + BadArr[I];
104
105 for (int I = 0; I < N; ++I) {
106 int K = BadArr[I];
107 Sum += Arr[I] + K;
108 }
109 }
110
111 } // namespace Negative
112
113 namespace NegativeIterator {
114
115 S Ss;
116 T Tt;
117 U Tu;
118
119 struct BadBeginEnd : T {
120 iterator notBegin();
121 iterator notEnd();
122 iterator begin(int);
123 iterator end(int);
124 iterator begin();
125 iterator end();
126 };
127
notBeginOrEnd()128 void notBeginOrEnd() {
129 BadBeginEnd Bad;
130 for (T::iterator I = Bad.notBegin(), E = Bad.end(); I != E; ++I)
131 int K = *I;
132
133 for (T::iterator I = Bad.begin(), E = Bad.notEnd(); I != E; ++I)
134 int K = *I;
135
136 for (T::iterator I = Bad.begin(0), E = Bad.end(0); I != E; ++I)
137 int K = *I;
138 }
139
badLoopShapes()140 void badLoopShapes() {
141 for (T::iterator I = Tt.begin(), E = Tt.end(), F = E; I != E; ++I)
142 int K = *I;
143
144 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E;)
145 int K = *I;
146
147 for (T::iterator I = Tt.begin(), E = Tt.end();; ++I)
148 int K = *I;
149
150 T::iterator OutsideI;
151 T::iterator OutsideE;
152
153 for (; OutsideI != OutsideE; ++OutsideI)
154 int K = *OutsideI;
155 }
156
iteratorArrayMix()157 void iteratorArrayMix() {
158 int Lower;
159 const int N = 6;
160 for (T::iterator I = Tt.begin(), E = Tt.end(); Lower < N; ++I)
161 int K = *I;
162
163 for (T::iterator I = Tt.begin(), E = Tt.end(); Lower < N; ++Lower)
164 int K = *I;
165 }
166
167 struct ExtraConstructor : T::iterator {
168 ExtraConstructor(T::iterator, int);
169 explicit ExtraConstructor(T::iterator);
170 };
171
badConstructor()172 void badConstructor() {
173 for (T::iterator I = ExtraConstructor(Tt.begin(), 0), E = Tt.end();
174 I != E; ++I)
175 int K = *I;
176 for (T::iterator I = ExtraConstructor(Tt.begin()), E = Tt.end(); I != E; ++I)
177 int K = *I;
178 }
179
foo(S::iterator It)180 void foo(S::iterator It) {}
181 class Foo {public: void bar(S::iterator It); };
182 Foo Fo;
183
iteratorUsed()184 void iteratorUsed() {
185 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
186 foo(I);
187
188 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
189 Fo.bar(I);
190
191 S::iterator Ret;
192 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
193 Ret = I;
194 }
195
iteratorMemberUsed()196 void iteratorMemberUsed() {
197 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
198 I.X = *I;
199
200 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
201 int K = I.X + *I;
202
203 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
204 int K = E.X + *I;
205 }
206
iteratorMethodCalled()207 void iteratorMethodCalled() {
208 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
209 I.insert(3);
210
211 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
212 if (I != I)
213 int K = 3;
214 }
215
iteratorOperatorCalled()216 void iteratorOperatorCalled() {
217 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
218 int K = *(++I);
219
220 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
221 MutableVal K = *(++I);
222 }
223
differentContainers()224 void differentContainers() {
225 T Other;
226 for (T::iterator I = Tt.begin(), E = Other.end(); I != E; ++I)
227 int K = *I;
228 for (T::iterator I = begin(Tt), E = end(Other); I != E; ++I)
229 int K = *I;
230
231 for (T::iterator I = Other.begin(), E = Tt.end(); I != E; ++I)
232 int K = *I;
233
234 S OtherS;
235 for (S::iterator I = Ss.begin(), E = OtherS.end(); I != E; ++I)
236 MutableVal K = *I;
237
238 for (S::iterator I = OtherS.begin(), E = Ss.end(); I != E; ++I)
239 MutableVal K = *I;
240 }
241
mixedMemberAndADL()242 void mixedMemberAndADL() {
243 for (T::iterator I = Tt.begin(), E = end(Tt); I != E; ++I)
244 int K = *I;
245 for (T::iterator I = begin(Tt), E = Tt.end(); I != E; ++I)
246 int K = *I;
247 for (T::iterator I = std::begin(Tt), E = Tt.end(); I != E; ++I)
248 int K = *I;
249 for (T::iterator I = std::begin(Tt), E = end(Tt); I != E; ++I)
250 int K = *I;
251 }
252
nonADLOrStdCalls()253 void nonADLOrStdCalls() {
254 for (T::iterator I = SomeClass::begin(Tt), E = SomeClass::end(Tt); I != E; ++I)
255 int K = *I;
256 for (T::iterator I = somenamespace::begin(Tt), E = somenamespace::end(Tt); I != E; ++I)
257 int K = *I;
258 }
259
wrongIterators()260 void wrongIterators() {
261 T::iterator Other;
262 for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
263 int K = *I;
264 }
265
266 struct EvilArrow : U {
267 // Please, no one ever write code like this.
268 U *operator->();
269 };
270
differentMemberAccessTypes()271 void differentMemberAccessTypes() {
272 EvilArrow A;
273 for (EvilArrow::iterator I = A.begin(), E = A->end(); I != E; ++I)
274 Val K = *I;
275 for (EvilArrow::iterator I = A->begin(), E = A.end(); I != E; ++I)
276 Val K = *I;
277 }
278
279 void f(const T::iterator &It, int);
280 void f(const T &It, int);
281 void g(T &It, int);
282
iteratorPassedToFunction()283 void iteratorPassedToFunction() {
284 for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I)
285 f(I, *I);
286 }
287
288 // FIXME: These tests can be removed if this tool ever does enough analysis to
289 // decide that this is a safe transformation. Until then, we don't want it
290 // applied.
iteratorDefinedOutside()291 void iteratorDefinedOutside() {
292 T::iterator TheEnd = Tt.end();
293 for (T::iterator I = Tt.begin(); I != TheEnd; ++I)
294 int K = *I;
295
296 T::iterator TheBegin = Tt.begin();
297 for (T::iterator E = Tt.end(); TheBegin != E; ++TheBegin)
298 int K = *TheBegin;
299 }
300
301 } // namespace NegativeIterator
302
303 namespace NegativePseudoArray {
304
305 const int N = 6;
306 dependent<int> V;
307 dependent<int> *Pv;
308
309 int Sum = 0;
310
311 // Checks for the Index start and end:
IndexStartAndEnd()312 void IndexStartAndEnd() {
313 for (int I = 0; I < V.size() + 1; ++I)
314 Sum += V[I];
315
316 for (int I = 0; I < V.size() - 1; ++I)
317 Sum += V[I];
318
319 for (int I = 1; I < V.size(); ++I)
320 Sum += V[I];
321
322 for (int I = 1; I < V.size(); ++I)
323 Sum += V[I];
324
325 for (int I = 0;; ++I)
326 Sum += (*Pv)[I];
327 }
328
329 // Checks for invalid increment steps:
increment()330 void increment() {
331 for (int I = 0; I < V.size(); --I)
332 Sum += V[I];
333
334 for (int I = 0; I < V.size(); I)
335 Sum += V[I];
336
337 for (int I = 0; I < V.size();)
338 Sum += V[I];
339
340 for (int I = 0; I < V.size(); I += 2)
341 Sum++;
342 }
343
344 // Checks to make sure that the Index isn't used outside of the container:
IndexUse()345 void IndexUse() {
346 for (int I = 0; I < V.size(); ++I)
347 V[I] += 1 + I;
348 }
349
350 // Checks for incorrect loop variables.
mixedVariables()351 void mixedVariables() {
352 int BadIndex;
353 for (int I = 0; BadIndex < V.size(); ++I)
354 Sum += V[I];
355
356 for (int I = 0; I < V.size(); ++BadIndex)
357 Sum += V[I];
358
359 for (int I = 0; BadIndex < V.size(); ++BadIndex)
360 Sum += V[I];
361
362 for (int I = 0; BadIndex < V.size(); ++BadIndex)
363 Sum += V[BadIndex];
364 }
365
366 // Checks for an array Indexed in addition to the container.
multipleArrays()367 void multipleArrays() {
368 int BadArr[N];
369
370 for (int I = 0; I < V.size(); ++I)
371 Sum += V[I] + BadArr[I];
372
373 for (int I = 0; I < V.size(); ++I)
374 Sum += BadArr[I];
375
376 for (int I = 0; I < V.size(); ++I) {
377 int K = BadArr[I];
378 Sum += K + 2;
379 }
380
381 for (int I = 0; I < V.size(); ++I) {
382 int K = BadArr[I];
383 Sum += V[I] + K;
384 }
385 }
386
387 // Checks for multiple containers being Indexed container.
multipleContainers()388 void multipleContainers() {
389 dependent<int> BadArr;
390
391 for (int I = 0; I < V.size(); ++I)
392 Sum += V[I] + BadArr[I];
393
394 for (int I = 0; I < V.size(); ++I)
395 Sum += BadArr[I];
396
397 for (int I = 0; I < V.size(); ++I) {
398 int K = BadArr[I];
399 Sum += K + 2;
400 }
401
402 for (int I = 0; I < V.size(); ++I) {
403 int K = BadArr[I];
404 Sum += V[I] + K;
405 }
406 }
407
408 // Check to make sure that dereferenced pointers-to-containers behave nicely.
derefContainer()409 void derefContainer() {
410 // Note the dependent<T>::operator*() returns another dependent<T>.
411 // This test makes sure that we don't allow an arbitrary number of *'s.
412 for (int I = 0; I < Pv->size(); ++I)
413 Sum += (**Pv).at(I);
414
415 for (int I = 0; I < Pv->size(); ++I)
416 Sum += (**Pv)[I];
417 }
418
wrongEnd()419 void wrongEnd() {
420 int Bad;
421 for (int I = 0, E = V.size(); I < Bad; ++I)
422 Sum += V[I];
423 }
424
nonADLOrStdCalls()425 void nonADLOrStdCalls() {
426 for (int I = 0, E = somenamespace::size(V); E != I; ++I)
427 printf("Fibonacci number is %d\n", V[I]);
428 for (int I = 0, E = SomeClass::size(V); E != I; ++I)
429 printf("Fibonacci number is %d\n", V[I]);
430 }
431
432 // Checks to see that non-const member functions are not called on the container
433 // object.
434 // These could be conceivably allowed with a lower required confidence level.
memberFunctionCalled()435 void memberFunctionCalled() {
436 for (int I = 0; I < V.size(); ++I) {
437 Sum += V[I];
438 V.foo();
439 }
440
441 for (int I = 0; I < V.size(); ++I) {
442 Sum += V[I];
443 dependent<int>::iterator It = V.begin();
444 }
445 }
446
447 } // namespace NegativePseudoArray
448
449 namespace NegativeMultiEndCall {
450
451 S Ss;
452 T Tt;
453 U Uu;
454
455 void f(X);
456 void f(S);
457 void f(T);
458
complexContainer()459 void complexContainer() {
460 X Xx;
461 for (S::iterator I = Xx.Ss.begin(), E = Xx.Ss.end(); I != E; ++I) {
462 f(Xx);
463 MutableVal K = *I;
464 }
465
466 for (T::iterator I = Xx.Tt.begin(), E = Xx.Tt.end(); I != E; ++I) {
467 f(Xx);
468 int K = *I;
469 }
470
471 for (S::iterator I = Xx.Ss.begin(), E = Xx.Ss.end(); I != E; ++I) {
472 f(Xx.Ss);
473 MutableVal K = *I;
474 }
475
476 for (T::iterator I = Xx.Tt.begin(), E = Xx.Tt.end(); I != E; ++I) {
477 f(Xx.Tt);
478 int K = *I;
479 }
480
481 for (S::iterator I = Xx.getS().begin(), E = Xx.getS().end(); I != E; ++I) {
482 f(Xx.getS());
483 MutableVal K = *I;
484 }
485
486 X Exes[5];
487 int Index = 0;
488
489 for (S::iterator I = Exes[Index].getS().begin(),
490 E = Exes[Index].getS().end();
491 I != E; ++I) {
492 Index++;
493 MutableVal K = *I;
494 }
495 }
496
497 } // namespace NegativeMultiEndCall
498
499 namespace NoUsages {
500
501 const int N = 6;
502 int Arr[N] = {1, 2, 3, 4, 5, 6};
503 S Ss;
504 dependent<int> V;
505 int Count = 0;
506
507 void foo();
508
f()509 void f() {
510 for (int I = 0; I < N; ++I) {}
511 for (int I = 0; I < N; ++I)
512 printf("Hello world\n");
513 for (int I = 0; I < N; ++I)
514 ++Count;
515 for (int I = 0; I < N; ++I)
516 foo();
517
518 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) {}
519 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
520 printf("Hello world\n");
521 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
522 ++Count;
523 for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I)
524 foo();
525
526 for (int I = 0; I < V.size(); ++I) {}
527 for (int I = 0; I < V.size(); ++I)
528 printf("Hello world\n");
529 for (int I = 0; I < V.size(); ++I)
530 ++Count;
531 for (int I = 0; I < V.size(); ++I)
532 foo();
533 }
534
535 } // namespace NoUsages
536