blob: 607baaed5dd3895637affd18ea93d27b4cc4c92e [file] [log] [blame]
// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -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