blob: ffec61f7dbc87a716a6409a8bb6d8ceac0ea0aa1 [file] [log] [blame]
// RUN: $(dirname %s)/check_clang_tidy.sh %s modernize-loop-convert %t -- -std=c++11 -I %S/Inputs/modernize-loop-convert
// REQUIRES: shell
#include "structures.h"
// CHECK-FIXES-NOT: for ({{.*[^:]:[^:].*}})
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;
}
}
struct HasArr {
int Arr[N];
Val ValArr[N];
};
struct HasIndirectArr {
HasArr HA;
void implicitThis() {
for (int i = 0; i < N; ++i) {
printf("%d", HA.Arr[i]);
}
for (int i = 0; i < N; ++i) {
printf("%d", HA.ValArr[i].x);
}
}
void explicitThis() {
for (int i = 0; i < N; ++i) {
printf("%d", this->HA.Arr[i]);
}
for (int i = 0; i < N; ++i) {
printf("%d", this->HA.ValArr[i].x);
}
}
};
}
namespace NegativeIterator {
S s;
T t;
U u;
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 = t.begin(), e = t.end(), f = e; i != e; ++i)
int k = *i;
for (T::iterator i = t.begin(), e = t.end(); i != e;)
int k = *i;
for (T::iterator i = t.begin(), e = t.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 = t.begin(), e = t.end(); lower < N; ++i)
int k = *i;
for (T::iterator i = t.begin(), e = t.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(t.begin(), 0), e = t.end();
i != e; ++i)
int k = *i;
for (T::iterator i = ExtraConstructor(t.begin()), e = t.end(); i != e; ++i)
int k = *i;
}
void iteratorMemberUsed() {
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
i.x = *i;
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
int k = i.x + *i;
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
int k = e.x + *i;
}
void iteratorMethodCalled() {
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
i.insert(3);
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
if (i != i)
int k = 3;
}
void iteratorOperatorCalled() {
for (T::iterator i = t.begin(), e = t.end(); i != e; ++i)
int k = *(++i);
for (S::iterator i = s.begin(), e = s.end(); i != e; ++i)
MutableVal k = *(++i);
}
void differentContainers() {
T other;
for (T::iterator i = t.begin(), e = other.end(); i != e; ++i)
int k = *i;
for (T::iterator i = other.begin(), e = t.end(); i != e; ++i)
int k = *i;
S otherS;
for (S::iterator i = s.begin(), e = otherS.end(); i != e; ++i)
MutableVal k = *i;
for (S::iterator i = otherS.begin(), e = s.end(); i != e; ++i)
MutableVal k = *i;
}
void wrongIterators() {
T::iterator other;
for (T::iterator i = t.begin(), e = t.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 = t.begin(), e = t.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 = t.end();
for (T::iterator i = t.begin(); i != theEnd; ++i)
int k = *i;
T::iterator theBegin = t.begin();
for (T::iterator e = t.end(); theBegin != e; ++theBegin)
int k = *theBegin;
}
} // namespace NegativeIterator
namespace NegativePseudoArray {
const int N = 6;
dependent<int> v;
dependent<int> *pv;
transparent<dependent<int>> cv;
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 s;
T t;
U u;
void f(X);
void f(S);
void f(T);
void complexContainer() {
X x;
for (S::iterator i = x.s.begin(), e = x.s.end(); i != e; ++i) {
f(x);
MutableVal k = *i;
}
for (T::iterator i = x.t.begin(), e = x.t.end(); i != e; ++i) {
f(x);
int k = *i;
}
for (S::iterator i = x.s.begin(), e = x.s.end(); i != e; ++i) {
f(x.s);
MutableVal k = *i;
}
for (T::iterator i = x.t.begin(), e = x.t.end(); i != e; ++i) {
f(x.t);
int k = *i;
}
for (S::iterator i = x.getS().begin(), e = x.getS().end(); i != e; ++i) {
f(x.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