// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 -I %S/Inputs/modernize-loop-convert #include "structures.h" namespace Array { const int N = 6; const int NMinusOne = N - 1; int Arr[N] = {1, 2, 3, 4, 5, 6}; const int ConstArr[N] = {1, 2, 3, 4, 5, 6}; int (*PArr)[N] = &Arr; void f() { int Sum = 0; for (int I = 0; I < N; ++I) { Sum += Arr[I]; int K; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead [modernize-loop-convert] // CHECK-FIXES: for (int I : Arr) // CHECK-FIXES-NEXT: Sum += I; // CHECK-FIXES-NEXT: int K; for (int I = 0; I < N; ++I) { printf("Fibonacci number is %d\n", Arr[I]); Sum += Arr[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : Arr) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); // CHECK-FIXES-NEXT: Sum += I + 2; for (int I = 0; I < N; ++I) { int X = Arr[I]; int Y = Arr[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : Arr) // CHECK-FIXES-NEXT: int X = I; // CHECK-FIXES-NEXT: int Y = I + 2; for (int I = 0; I < N; ++I) { int X = N; X = Arr[I]; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : Arr) // CHECK-FIXES-NEXT: int X = N; // CHECK-FIXES-NEXT: X = I; for (int I = 0; I < N; ++I) { Arr[I] += 1; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int & I : Arr) // CHECK-FIXES-NEXT: I += 1; for (int I = 0; I < N; ++I) { int X = Arr[I] + 2; Arr[I]++; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int & I : Arr) // CHECK-FIXES-NEXT: int X = I + 2; // CHECK-FIXES-NEXT: I++; for (int I = 0; I < N; ++I) { Arr[I] = 4 + Arr[I]; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int & I : Arr) // CHECK-FIXES-NEXT: I = 4 + I; for (int I = 0; I < NMinusOne + 1; ++I) { Sum += Arr[I]; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : Arr) // CHECK-FIXES-NEXT: Sum += I; for (int I = 0; I < N; ++I) { printf("Fibonacci number %d has address %p\n", Arr[I], &Arr[I]); Sum += Arr[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int & I : Arr) // CHECK-FIXES-NEXT: printf("Fibonacci number %d has address %p\n", I, &I); // CHECK-FIXES-NEXT: Sum += I + 2; Val Teas[N]; for (int I = 0; I < N; ++I) { Teas[I].g(); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & Tea : Teas) // CHECK-FIXES-NEXT: Tea.g(); } const int *constArray() { for (int I = 0; I < N; ++I) { printf("2 * %d = %d\n", ConstArr[I], ConstArr[I] + ConstArr[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : ConstArr) // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I, I + I); const NonTriviallyCopyable NonCopy[N]{}; for (int I = 0; I < N; ++I) { printf("2 * %d = %d\n", NonCopy[I].X, NonCopy[I].X + NonCopy[I].X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & I : NonCopy) // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X); const TriviallyCopyableButBig Big[N]{}; for (int I = 0; I < N; ++I) { printf("2 * %d = %d\n", Big[I].X, Big[I].X + Big[I].X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & I : Big) // CHECK-FIXES-NEXT: printf("2 * %d = %d\n", I.X, I.X + I.X); bool Something = false; for (int I = 0; I < N; ++I) { if (Something) return &ConstArr[I]; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const int & I : ConstArr) // CHECK-FIXES-NEXT: if (Something) // CHECK-FIXES-NEXT: return &I; } struct HasArr { int Arr[N]; Val ValArr[N]; void implicitThis() { for (int I = 0; I < N; ++I) { printf("%d", Arr[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (int I : Arr) // CHECK-FIXES-NEXT: printf("%d", I); for (int I = 0; I < N; ++I) { printf("%d", ValArr[I].X); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : ValArr) // CHECK-FIXES-NEXT: printf("%d", I.X); } void explicitThis() { for (int I = 0; I < N; ++I) { printf("%d", this->Arr[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (int I : this->Arr) // CHECK-FIXES-NEXT: printf("%d", I); for (int I = 0; I < N; ++I) { printf("%d", this->ValArr[I].X); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : this->ValArr) // CHECK-FIXES-NEXT: printf("%d", I.X); } }; struct HasIndirectArr { HasArr HA; void implicitThis() { for (int I = 0; I < N; ++I) { printf("%d", HA.Arr[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (int I : HA.Arr) // CHECK-FIXES-NEXT: printf("%d", I); for (int I = 0; I < N; ++I) { printf("%d", HA.ValArr[I].X); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : HA.ValArr) // CHECK-FIXES-NEXT: printf("%d", I.X); } void explicitThis() { for (int I = 0; I < N; ++I) { printf("%d", this->HA.Arr[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (int I : this->HA.Arr) // CHECK-FIXES-NEXT: printf("%d", I); for (int I = 0; I < N; ++I) { printf("%d", this->HA.ValArr[I].X); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : this->HA.ValArr) // CHECK-FIXES-NEXT: printf("%d", I.X); } }; // Loops whose bounds are value-dependent should not be converted. template void dependentExprBound() { for (int I = 0; I < N; ++I) Arr[I] = 0; } template void dependentExprBound<20>(); void memberFunctionPointer() { Val V; void (Val::*mfpArr[N])(void) = {&Val::g}; for (int I = 0; I < N; ++I) (V.*mfpArr[I])(); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : mfpArr) // CHECK-FIXES-NEXT: (V.*I)(); struct Foo { int (Val::*f)(); } Foo[N]; for (int I = 0; I < N; ++I) int R = (V.*(Foo[I].f))(); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : Foo) // CHECK-FIXES-NEXT: int R = (V.*(I.f))(); } } // namespace Array namespace Iterator { void f() { /// begin()/end() - based for loops here: T Tt; for (T::iterator It = Tt.begin(), E = Tt.end(); It != E; ++It) { printf("I found %d\n", *It); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int & It : Tt) // CHECK-FIXES-NEXT: printf("I found %d\n", It); T *Pt; for (T::iterator It = Pt->begin(), E = Pt->end(); It != E; ++It) { printf("I found %d\n", *It); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int & It : *Pt) // CHECK-FIXES-NEXT: printf("I found %d\n", It); S Ss; for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { printf("s has value %d\n", (*It).X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & It : Ss) // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); S *Ps; for (S::iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) { printf("s has value %d\n", (*It).X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & P : *Ps) // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X); for (S::const_iterator It = Ss.cbegin(), E = Ss.cend(); It != E; ++It) { printf("s has value %d\n", (*It).X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto It : Ss) // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { printf("s has value %d\n", It->X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & It : Ss) // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { It->X = 3; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & It : Ss) // CHECK-FIXES-NEXT: It.X = 3; for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { (*It).X = 3; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & It : Ss) // CHECK-FIXES-NEXT: It.X = 3; for (S::iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { It->nonConstFun(4, 5); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & It : Ss) // CHECK-FIXES-NEXT: It.nonConstFun(4, 5); U Uu; for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) { printf("s has value %d\n", It->X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & It : Uu) // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) { printf("s has value %d\n", (*It).X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & It : Uu) // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); for (U::iterator It = Uu.begin(), E = Uu.end(); It != E; ++It) { Val* a = It.operator->(); } U::iterator A; for (U::iterator I = Uu.begin(), E = Uu.end(); I != E; ++I) int K = A->X + I->X; // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : Uu) // CHECK-FIXES-NEXT: int K = A->X + I.X; dependent V; for (dependent::iterator It = V.begin(), E = V.end(); It != E; ++It) { printf("Fibonacci number is %d\n", *It); } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int & It : V) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It); for (dependent::iterator It(V.begin()), E = V.end(); It != E; ++It) { printf("Fibonacci number is %d\n", *It); } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int & It : V) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", It); doublyDependent Intmap; for (doublyDependent::iterator It = Intmap.begin(), E = Intmap.end(); It != E; ++It) { printf("Intmap[%d] = %d", It->first, It->second); } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & It : Intmap) // CHECK-FIXES: printf("Intmap[%d] = %d", It.first, It.second); // PtrSet's iterator dereferences by value so auto & can't be used. { PtrSet Val_int_ptrs; for (PtrSet::iterator I = Val_int_ptrs.begin(), E = Val_int_ptrs.end(); I != E; ++I) { (void) *I; } // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto Val_int_ptr : Val_int_ptrs) } // This container uses an iterator where the derefence type is a typedef of // a reference type. Make sure non-const auto & is still used. A failure here // means canonical types aren't being tested. { TypedefDerefContainer Int_ptrs; for (TypedefDerefContainer::iterator I = Int_ptrs.begin(), E = Int_ptrs.end(); I != E; ++I) { (void) *I; } // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (int & Int_ptr : Int_ptrs) } { // Iterators returning an rvalue reference should disqualify the loop from // transformation. RValueDerefContainer Container; for (RValueDerefContainer::iterator I = Container.begin(), E = Container.end(); I != E; ++I) { (void) *I; } } dependent Dpp; for (dependent::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) { printf("%d\n", (**I).X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : Dpp) // CHECK-FIXES-NEXT: printf("%d\n", (*I).X); for (dependent::iterator I = Dpp.begin(), E = Dpp.end(); I != E; ++I) { printf("%d\n", (*I)->X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : Dpp) // CHECK-FIXES-NEXT: printf("%d\n", I->X); } // Tests to verify the proper use of auto where the init variable type and the // initializer type differ or are mostly the same except for const qualifiers. void different_type() { // Ss.begin() returns a type 'iterator' which is just a non-const pointer and // differs from const_iterator only on the const qualification. S Ss; for (S::const_iterator It = Ss.begin(), E = Ss.end(); It != E; ++It) { printf("s has value %d\n", (*It).X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto It : Ss) // CHECK-FIXES-NEXT: printf("s has value %d\n", It.X); S *Ps; for (S::const_iterator It = Ps->begin(), E = Ps->end(); It != E; ++It) { printf("s has value %d\n", (*It).X); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (auto P : *Ps) // CHECK-FIXES-NEXT: printf("s has value %d\n", P.X); // V.begin() returns a user-defined type 'iterator' which, since it's // different from const_iterator, disqualifies these loops from // transformation. dependent V; for (dependent::const_iterator It = V.begin(), E = V.end(); It != E; ++It) { printf("Fibonacci number is %d\n", *It); } for (dependent::const_iterator It(V.begin()), E = V.end(); It != E; ++It) { printf("Fibonacci number is %d\n", *It); } } // Tests to ensure that an implicit 'this' is picked up as the container. // If member calls are made to 'this' within the loop, the transform becomes // risky as these calls may affect state that affects the loop. class C { public: typedef MutableVal *iterator; typedef const MutableVal *const_iterator; iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; void doSomething(); void doSomething() const; void doLoop() { for (iterator I = begin(), E = end(); I != E; ++I) (void) *I; // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : *this) for (iterator I = C::begin(), E = C::end(); I != E; ++I) (void) *I; // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : *this) for (iterator I = begin(), E = end(); I != E; ++I) { (void) *I; doSomething(); } for (iterator I = begin(); I != end(); ++I) (void) *I; // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : *this) for (iterator I = begin(); I != end(); ++I) { (void) *I; doSomething(); } } void doLoop() const { for (const_iterator I = begin(), E = end(); I != E; ++I) (void) *I; // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto I : *this) for (const_iterator I = C::begin(), E = C::end(); I != E; ++I) (void) *I; // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto I : *this) for (const_iterator I = begin(), E = end(); I != E; ++I) { (void) *I; doSomething(); } } }; class C2 { public: typedef MutableVal *iterator; iterator begin() const; iterator end() const; void doLoop() { // The implicit 'this' will have an Implicit cast to const C2* wrapped // around it. Make sure the replacement still happens. for (iterator I = begin(), E = end(); I != E; ++I) (void) *I; // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use range-based for loop instead // CHECK-FIXES: for (auto & I : *this) } }; } // namespace Iterator namespace PseudoArray { const int N = 6; dependent V; dependent *Pv; const dependent Constv; const dependent *Pconstv; transparent> Cv; void f() { int Sum = 0; for (int I = 0, E = V.size(); I < E; ++I) { printf("Fibonacci number is %d\n", V[I]); Sum += V[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : V) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); // CHECK-FIXES-NEXT: Sum += I + 2; for (int I = 0, E = V.size(); I < E; ++I) { printf("Fibonacci number is %d\n", V.at(I)); Sum += V.at(I) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : V) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); // CHECK-FIXES-NEXT: Sum += I + 2; for (int I = 0, E = Pv->size(); I < E; ++I) { printf("Fibonacci number is %d\n", Pv->at(I)); Sum += Pv->at(I) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : *Pv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); // CHECK-FIXES-NEXT: Sum += I + 2; // This test will fail if size() isn't called repeatedly, since it // returns unsigned int, and 0 is deduced to be signed int. // FIXME: Insert the necessary explicit conversion, or write out the types // explicitly. for (int I = 0; I < Pv->size(); ++I) { printf("Fibonacci number is %d\n", (*Pv).at(I)); Sum += (*Pv)[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : *Pv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); // CHECK-FIXES-NEXT: Sum += I + 2; for (int I = 0; I < Cv->size(); ++I) { printf("Fibonacci number is %d\n", Cv->at(I)); Sum += Cv->at(I) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : *Cv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I); // CHECK-FIXES-NEXT: Sum += I + 2; } // Ensure that 'const auto &' is used with containers of non-trivial types. void constness() { int Sum = 0; for (int I = 0, E = Constv.size(); I < E; ++I) { printf("Fibonacci number is %d\n", Constv[I].X); Sum += Constv[I].X + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & I : Constv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X); // CHECK-FIXES-NEXT: Sum += I.X + 2; for (int I = 0, E = Constv.size(); I < E; ++I) { printf("Fibonacci number is %d\n", Constv.at(I).X); Sum += Constv.at(I).X + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & I : Constv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X); // CHECK-FIXES-NEXT: Sum += I.X + 2; for (int I = 0, E = Pconstv->size(); I < E; ++I) { printf("Fibonacci number is %d\n", Pconstv->at(I).X); Sum += Pconstv->at(I).X + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & I : *Pconstv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X); // CHECK-FIXES-NEXT: Sum += I.X + 2; // This test will fail if size() isn't called repeatedly, since it // returns unsigned int, and 0 is deduced to be signed int. // FIXME: Insert the necessary explicit conversion, or write out the types // explicitly. for (int I = 0; I < Pconstv->size(); ++I) { printf("Fibonacci number is %d\n", (*Pconstv).at(I).X); Sum += (*Pconstv)[I].X + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (const auto & I : *Pconstv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", I.X); // CHECK-FIXES-NEXT: Sum += I.X + 2; } void constRef(const dependent& ConstVRef) { int sum = 0; // FIXME: This does not work with size_t (probably due to the implementation // of dependent); make dependent work exactly like a std container type. for (int I = 0; I < ConstVRef.size(); ++I) { sum += ConstVRef[I]; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : ConstVRef) // CHECK-FIXES-NEXT: sum += I; for (auto I = ConstVRef.begin(), E = ConstVRef.end(); I != E; ++I) { sum += *I; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (int I : ConstVRef) // CHECK-FIXES-NEXT: sum += I; } // Check for loops that don't mention containers. void noContainer() { for (auto I = 0; I < V.size(); ++I) { } for (auto I = 0; I < V.size(); ++I) ; } struct NoBeginEnd { unsigned size() const; unsigned& operator[](int); const unsigned& operator[](int) const; }; struct NoConstBeginEnd { NoConstBeginEnd(); unsigned size() const; unsigned* begin(); unsigned* end(); unsigned& operator[](int); const unsigned& operator[](int) const; }; struct ConstBeginEnd { ConstBeginEnd(); unsigned size() const; unsigned* begin() const; unsigned* end() const; unsigned& operator[](int); const unsigned& operator[](int) const; }; // Shouldn't transform pseudo-array uses if the container doesn't provide // begin() and end() of the right const-ness. void NoBeginEndTest() { NoBeginEnd NBE; for (unsigned I = 0, E = NBE.size(); I < E; ++I) printf("%d\n", NBE[I]); const NoConstBeginEnd Const_NCBE; for (unsigned I = 0, E = Const_NCBE.size(); I < E; ++I) printf("%d\n", Const_NCBE[I]); ConstBeginEnd CBE; for (unsigned I = 0, E = CBE.size(); I < E; ++I) printf("%d\n", CBE[I]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (unsigned int I : CBE) // CHECK-FIXES-NEXT: printf("%d\n", I); const ConstBeginEnd Const_CBE; for (unsigned I = 0, E = Const_CBE.size(); I < E; ++I) printf("%d\n", Const_CBE[I]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (unsigned int I : Const_CBE) // CHECK-FIXES-NEXT: printf("%d\n", I); } struct DerefByValue { DerefByValue(); struct iter { unsigned operator*(); }; unsigned size() const; iter begin(); iter end(); unsigned operator[](int); }; void derefByValueTest() { DerefByValue DBV; for (unsigned I = 0, E = DBV.size(); I < E; ++I) { printf("%d\n", DBV[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (unsigned int I : DBV) // CHECK-FIXES-NEXT: printf("%d\n", I); for (unsigned I = 0, E = DBV.size(); I < E; ++I) { auto f = [DBV, I]() {}; printf("%d\n", DBV[I]); } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (unsigned int I : DBV) // CHECK-FIXES-NEXT: auto f = [DBV, &I]() {}; // CHECK-FIXES-NEXT: printf("%d\n", I); } void fundamentalTypesTest() { const int N = 10; bool Bools[N]; for (int i = 0; i < N; ++i) printf("%d", Bools[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (bool Bool : Bools) int Ints[N]; unsigned short int Shorts[N]; for (int i = 0; i < N; ++i) printf("%d", Shorts[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (unsigned short Short : Shorts) signed long Longs[N]; for (int i = 0; i < N; ++i) printf("%d", Longs[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (long Long : Longs) long long int LongLongs[N]; for (int i = 0; i < N; ++i) printf("%d", LongLongs[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (long long LongLong : LongLongs) char Chars[N]; for (int i = 0; i < N; ++i) printf("%d", Chars[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (char Char : Chars) wchar_t WChars[N]; for (int i = 0; i < N; ++i) printf("%d", WChars[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (wchar_t WChar : WChars) float Floats[N]; for (int i = 0; i < N; ++i) printf("%d", Floats[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (float Float : Floats) double Doubles[N]; for (int i = 0; i < N; ++i) printf("%d", Doubles[i]); // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead // CHECK-FIXES: for (double Double : Doubles) } } // namespace PseudoArray