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