xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-negative.cpp (revision 6a1f8ef8a7aaefea80ef0bc7c6c462a96215b50e)
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