| // RUN: grep -Ev "// *[A-Z-]+:" %s > %t.cpp |
| // RUN: cpp11-migrate -loop-convert %t.cpp -- -I %S/Inputs |
| // RUN: FileCheck -input-file=%t.cpp %s |
| |
| #include "structures.h" |
| |
| // Single FileCheck line to make sure that no loops are converted. |
| // CHECK-NOT: for ({{.*[^:]:[^:].*}}) |
| |
| 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: Disallow this except for containers passed by value and/or const |
| // reference. Or maybe this is correct enough for any container? |
| void containerPassedToFunction() { |
| // for (T::iterator i = t.begin(), e = t.end(); i != e; ++i) |
| // f(t, *i); |
| // for (T::iterator i = t.begin(), e = t.end(); i != e; ++i) |
| // g(t, *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; |
| } |