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
8namespace 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
16struct 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
24namespace Negative {
25
26const int N = 6;
27int Arr[N] = {1, 2, 3, 4, 5, 6};
28int (*pArr)[N] = &Arr;
29int Sum = 0;
30
31// Checks for the Index start and end:
32void 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:
50void 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:
65void 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
71void 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.
83void 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.
99void 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
113namespace NegativeIterator {
114
115S Ss;
116T Tt;
117U Tu;
118
119struct BadBeginEnd : T {
120 iterator notBegin();
121 iterator notEnd();
122 iterator begin(int);
123 iterator end(int);
124 iterator begin();
125 iterator end();
126};
127
128void 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
140void 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
157void 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
167struct ExtraConstructor : T::iterator {
168 ExtraConstructor(T::iterator, int);
169 explicit ExtraConstructor(T::iterator);
170};
171
172void 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
180void foo(S::iterator It) {}
181class Foo {public: void bar(S::iterator It); };
182Foo Fo;
183
184void 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
196void 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
207void 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
216void 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
224void 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
242void 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
253void 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
260void wrongIterators() {
261 T::iterator Other;
262 for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I)
263 int K = *I;
264}
265
266struct EvilArrow : U {
267 // Please, no one ever write code like this.
268 U *operator->();
269};
270
271void 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
279void f(const T::iterator &It, int);
280void f(const T &It, int);
281void g(T &It, int);
282
283void 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.
291void 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
303namespace NegativePseudoArray {
304
305const int N = 6;
306dependent<int> V;
307dependent<int> *Pv;
308
309int Sum = 0;
310
311// Checks for the Index start and end:
312void 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:
330void 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:
345void IndexUse() {
346 for (int I = 0; I < V.size(); ++I)
347 V[I] += 1 + I;
348}
349
350// Checks for incorrect loop variables.
351void 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.
367void 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.
388void 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.
409void 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
419void wrongEnd() {
420 int Bad;
421 for (int I = 0, E = V.size(); I < Bad; ++I)
422 Sum += V[I];
423}
424
425void 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.
435void 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
449namespace NegativeMultiEndCall {
450
451S Ss;
452T Tt;
453U Uu;
454
455void f(X);
456void f(S);
457void f(T);
458
459void 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
499namespace NoUsages {
500
501const int N = 6;
502int Arr[N] = {1, 2, 3, 4, 5, 6};
503S Ss;
504dependent<int> V;
505int Count = 0;
506
507void foo();
508
509void 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

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