486 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			486 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
	
| // 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
 |