| // RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 -I %S/Inputs/modernize-loop-convert |
| |
| #include "structures.h" |
| |
| // CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}}) |
| // CHECK-MESSAGES-NOT: modernize-loop-convert |
| |
| namespace Negative { |
| |
| const int N = 6; |
| int Arr[N] = {1, 2, 3, 4, 5, 6}; |
| int (*pArr)[N] = &Arr; |
| int Sum = 0; |
| |
| // Checks for the Index start and end: |
| void IndexStartAndEnd() { |
| for (int I = 0; I < N + 1; ++I) |
| Sum += Arr[I]; |
| |
| for (int I = 0; I < N - 1; ++I) |
| Sum += Arr[I]; |
| |
| for (int I = 1; I < N; ++I) |
| Sum += Arr[I]; |
| |
| for (int I = 1; I < N; ++I) |
| Sum += Arr[I]; |
| |
| for (int I = 0;; ++I) |
| Sum += (*pArr)[I]; |
| } |
| |
| // Checks for invalid increment steps: |
| void increment() { |
| for (int I = 0; I < N; --I) |
| Sum += Arr[I]; |
| |
| for (int I = 0; I < N; I) |
| Sum += Arr[I]; |
| |
| for (int I = 0; I < N;) |
| Sum += Arr[I]; |
| |
| for (int I = 0; I < N; I += 2) |
| Sum++; |
| } |
| |
| // Checks to make sure that the Index isn't used outside of the array: |
| void IndexUse() { |
| for (int I = 0; I < N; ++I) |
| Arr[I] += 1 + I; |
| } |
| |
| // Check for loops that don't mention arrays |
| void noArray() { |
| for (int I = 0; I < N; ++I) |
| Sum += I; |
| |
| for (int I = 0; I < N; ++I) { |
| } |
| |
| for (int I = 0; I < N; ++I) |
| ; |
| } |
| |
| // Checks for incorrect loop variables. |
| void mixedVariables() { |
| int BadIndex; |
| for (int I = 0; BadIndex < N; ++I) |
| Sum += Arr[I]; |
| |
| for (int I = 0; I < N; ++BadIndex) |
| Sum += Arr[I]; |
| |
| for (int I = 0; BadIndex < N; ++BadIndex) |
| Sum += Arr[I]; |
| |
| for (int I = 0; BadIndex < N; ++BadIndex) |
| Sum += Arr[BadIndex]; |
| } |
| |
| // Checks for multiple arrays Indexed. |
| void multipleArrays() { |
| int BadArr[N]; |
| |
| for (int I = 0; I < N; ++I) |
| Sum += Arr[I] + BadArr[I]; |
| |
| for (int I = 0; I < N; ++I) { |
| int K = BadArr[I]; |
| Sum += Arr[I] + K; |
| } |
| } |
| |
| } |
| |
| namespace NegativeIterator { |
| |
| S Ss; |
| T Tt; |
| U Tu; |
| |
| struct BadBeginEnd : T { |
| iterator notBegin(); |
| iterator notEnd(); |
| }; |
| |
| void notBeginOrEnd() { |
| BadBeginEnd Bad; |
| for (T::iterator I = Bad.notBegin(), E = Bad.end(); I != E; ++I) |
| int K = *I; |
| |
| for (T::iterator I = Bad.begin(), E = Bad.notEnd(); I != E; ++I) |
| int K = *I; |
| } |
| |
| void badLoopShapes() { |
| for (T::iterator I = Tt.begin(), E = Tt.end(), F = E; I != E; ++I) |
| int K = *I; |
| |
| for (T::iterator I = Tt.begin(), E = Tt.end(); I != E;) |
| int K = *I; |
| |
| for (T::iterator I = Tt.begin(), E = Tt.end();; ++I) |
| int K = *I; |
| |
| T::iterator OutsideI; |
| T::iterator OutsideE; |
| |
| for (; OutsideI != OutsideE; ++OutsideI) |
| int K = *OutsideI; |
| } |
| |
| void iteratorArrayMix() { |
| int Lower; |
| const int N = 6; |
| for (T::iterator I = Tt.begin(), E = Tt.end(); Lower < N; ++I) |
| int K = *I; |
| |
| for (T::iterator I = Tt.begin(), E = Tt.end(); Lower < N; ++Lower) |
| int K = *I; |
| } |
| |
| struct ExtraConstructor : T::iterator { |
| ExtraConstructor(T::iterator, int); |
| explicit ExtraConstructor(T::iterator); |
| }; |
| |
| void badConstructor() { |
| for (T::iterator I = ExtraConstructor(Tt.begin(), 0), E = Tt.end(); |
| I != E; ++I) |
| int K = *I; |
| for (T::iterator I = ExtraConstructor(Tt.begin()), E = Tt.end(); I != E; ++I) |
| int K = *I; |
| } |
| |
| void foo(S::iterator It) {} |
| class Foo {public: void bar(S::iterator It); }; |
| Foo Fo; |
| |
| void iteratorUsed() { |
| for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) |
| foo(I); |
| |
| for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) |
| Fo.bar(I); |
| |
| S::iterator Ret; |
| for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) |
| Ret = I; |
| } |
| |
| void iteratorMemberUsed() { |
| for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I) |
| I.X = *I; |
| |
| for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I) |
| int K = I.X + *I; |
| |
| for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I) |
| int K = E.X + *I; |
| } |
| |
| void iteratorMethodCalled() { |
| for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I) |
| I.insert(3); |
| |
| for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I) |
| if (I != I) |
| int K = 3; |
| } |
| |
| void iteratorOperatorCalled() { |
| for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I) |
| int K = *(++I); |
| |
| for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) |
| MutableVal K = *(++I); |
| } |
| |
| void differentContainers() { |
| T Other; |
| for (T::iterator I = Tt.begin(), E = Other.end(); I != E; ++I) |
| int K = *I; |
| |
| for (T::iterator I = Other.begin(), E = Tt.end(); I != E; ++I) |
| int K = *I; |
| |
| S OtherS; |
| for (S::iterator I = Ss.begin(), E = OtherS.end(); I != E; ++I) |
| MutableVal K = *I; |
| |
| for (S::iterator I = OtherS.begin(), E = Ss.end(); I != E; ++I) |
| MutableVal K = *I; |
| } |
| |
| void wrongIterators() { |
| T::iterator Other; |
| for (T::iterator I = Tt.begin(), E = Tt.end(); I != Other; ++I) |
| int K = *I; |
| } |
| |
| struct EvilArrow : U { |
| // Please, no one ever write code like this. |
| U *operator->(); |
| }; |
| |
| void differentMemberAccessTypes() { |
| EvilArrow A; |
| for (EvilArrow::iterator I = A.begin(), E = A->end(); I != E; ++I) |
| Val K = *I; |
| for (EvilArrow::iterator I = A->begin(), E = A.end(); I != E; ++I) |
| Val K = *I; |
| } |
| |
| void f(const T::iterator &It, int); |
| void f(const T &It, int); |
| void g(T &It, int); |
| |
| void iteratorPassedToFunction() { |
| for (T::iterator I = Tt.begin(), E = Tt.end(); I != E; ++I) |
| f(I, *I); |
| } |
| |
| // FIXME: These tests can be removed if this tool ever does enough analysis to |
| // decide that this is a safe transformation. Until then, we don't want it |
| // applied. |
| void iteratorDefinedOutside() { |
| T::iterator TheEnd = Tt.end(); |
| for (T::iterator I = Tt.begin(); I != TheEnd; ++I) |
| int K = *I; |
| |
| T::iterator TheBegin = Tt.begin(); |
| for (T::iterator E = Tt.end(); TheBegin != E; ++TheBegin) |
| int K = *TheBegin; |
| } |
| |
| } // namespace NegativeIterator |
| |
| namespace NegativePseudoArray { |
| |
| const int N = 6; |
| dependent<int> V; |
| dependent<int> *Pv; |
| |
| int Sum = 0; |
| |
| // Checks for the Index start and end: |
| void IndexStartAndEnd() { |
| for (int I = 0; I < V.size() + 1; ++I) |
| Sum += V[I]; |
| |
| for (int I = 0; I < V.size() - 1; ++I) |
| Sum += V[I]; |
| |
| for (int I = 1; I < V.size(); ++I) |
| Sum += V[I]; |
| |
| for (int I = 1; I < V.size(); ++I) |
| Sum += V[I]; |
| |
| for (int I = 0;; ++I) |
| Sum += (*Pv)[I]; |
| } |
| |
| // Checks for invalid increment steps: |
| void increment() { |
| for (int I = 0; I < V.size(); --I) |
| Sum += V[I]; |
| |
| for (int I = 0; I < V.size(); I) |
| Sum += V[I]; |
| |
| for (int I = 0; I < V.size();) |
| Sum += V[I]; |
| |
| for (int I = 0; I < V.size(); I += 2) |
| Sum++; |
| } |
| |
| // Checks to make sure that the Index isn't used outside of the container: |
| void IndexUse() { |
| for (int I = 0; I < V.size(); ++I) |
| V[I] += 1 + I; |
| } |
| |
| // Checks for incorrect loop variables. |
| void mixedVariables() { |
| int BadIndex; |
| for (int I = 0; BadIndex < V.size(); ++I) |
| Sum += V[I]; |
| |
| for (int I = 0; I < V.size(); ++BadIndex) |
| Sum += V[I]; |
| |
| for (int I = 0; BadIndex < V.size(); ++BadIndex) |
| Sum += V[I]; |
| |
| for (int I = 0; BadIndex < V.size(); ++BadIndex) |
| Sum += V[BadIndex]; |
| } |
| |
| // Checks for an array Indexed in addition to the container. |
| void multipleArrays() { |
| int BadArr[N]; |
| |
| for (int I = 0; I < V.size(); ++I) |
| Sum += V[I] + BadArr[I]; |
| |
| for (int I = 0; I < V.size(); ++I) |
| Sum += BadArr[I]; |
| |
| for (int I = 0; I < V.size(); ++I) { |
| int K = BadArr[I]; |
| Sum += K + 2; |
| } |
| |
| for (int I = 0; I < V.size(); ++I) { |
| int K = BadArr[I]; |
| Sum += V[I] + K; |
| } |
| } |
| |
| // Checks for multiple containers being Indexed container. |
| void multipleContainers() { |
| dependent<int> BadArr; |
| |
| for (int I = 0; I < V.size(); ++I) |
| Sum += V[I] + BadArr[I]; |
| |
| for (int I = 0; I < V.size(); ++I) |
| Sum += BadArr[I]; |
| |
| for (int I = 0; I < V.size(); ++I) { |
| int K = BadArr[I]; |
| Sum += K + 2; |
| } |
| |
| for (int I = 0; I < V.size(); ++I) { |
| int K = BadArr[I]; |
| Sum += V[I] + K; |
| } |
| } |
| |
| // Check to make sure that dereferenced pointers-to-containers behave nicely. |
| void derefContainer() { |
| // Note the dependent<T>::operator*() returns another dependent<T>. |
| // This test makes sure that we don't allow an arbitrary number of *'s. |
| for (int I = 0; I < Pv->size(); ++I) |
| Sum += (**Pv).at(I); |
| |
| for (int I = 0; I < Pv->size(); ++I) |
| Sum += (**Pv)[I]; |
| } |
| |
| void wrongEnd() { |
| int Bad; |
| for (int I = 0, E = V.size(); I < Bad; ++I) |
| Sum += V[I]; |
| } |
| |
| // Checks to see that non-const member functions are not called on the container |
| // object. |
| // These could be conceivably allowed with a lower required confidence level. |
| void memberFunctionCalled() { |
| for (int I = 0; I < V.size(); ++I) { |
| Sum += V[I]; |
| V.foo(); |
| } |
| |
| for (int I = 0; I < V.size(); ++I) { |
| Sum += V[I]; |
| dependent<int>::iterator It = V.begin(); |
| } |
| } |
| |
| } // namespace NegativePseudoArray |
| |
| namespace NegativeMultiEndCall { |
| |
| S Ss; |
| T Tt; |
| U Uu; |
| |
| void f(X); |
| void f(S); |
| void f(T); |
| |
| void complexContainer() { |
| X Xx; |
| for (S::iterator I = Xx.Ss.begin(), E = Xx.Ss.end(); I != E; ++I) { |
| f(Xx); |
| MutableVal K = *I; |
| } |
| |
| for (T::iterator I = Xx.Tt.begin(), E = Xx.Tt.end(); I != E; ++I) { |
| f(Xx); |
| int K = *I; |
| } |
| |
| for (S::iterator I = Xx.Ss.begin(), E = Xx.Ss.end(); I != E; ++I) { |
| f(Xx.Ss); |
| MutableVal K = *I; |
| } |
| |
| for (T::iterator I = Xx.Tt.begin(), E = Xx.Tt.end(); I != E; ++I) { |
| f(Xx.Tt); |
| int K = *I; |
| } |
| |
| for (S::iterator I = Xx.getS().begin(), E = Xx.getS().end(); I != E; ++I) { |
| f(Xx.getS()); |
| MutableVal K = *I; |
| } |
| |
| X Exes[5]; |
| int Index = 0; |
| |
| for (S::iterator I = Exes[Index].getS().begin(), |
| E = Exes[Index].getS().end(); |
| I != E; ++I) { |
| Index++; |
| MutableVal K = *I; |
| } |
| } |
| |
| } // namespace NegativeMultiEndCall |
| |
| namespace NoUsages { |
| |
| const int N = 6; |
| int Arr[N] = {1, 2, 3, 4, 5, 6}; |
| S Ss; |
| dependent<int> V; |
| int Count = 0; |
| |
| void foo(); |
| |
| void f() { |
| for (int I = 0; I < N; ++I) {} |
| for (int I = 0; I < N; ++I) |
| printf("Hello world\n"); |
| for (int I = 0; I < N; ++I) |
| ++Count; |
| for (int I = 0; I < N; ++I) |
| foo(); |
| |
| for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) {} |
| for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) |
| printf("Hello world\n"); |
| for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) |
| ++Count; |
| for (S::iterator I = Ss.begin(), E = Ss.end(); I != E; ++I) |
| foo(); |
| |
| for (int I = 0; I < V.size(); ++I) {} |
| for (int I = 0; I < V.size(); ++I) |
| printf("Hello world\n"); |
| for (int I = 0; I < V.size(); ++I) |
| ++Count; |
| for (int I = 0; I < V.size(); ++I) |
| foo(); |
| } |
| |
| } // namespace NoUsages |