|  | // RUN: %check_clang_tidy %s modernize-loop-convert %t | 
|  |  | 
|  | struct Str { | 
|  | Str() = default; | 
|  | Str(const Str &) = default; | 
|  | void constMember(int) const; | 
|  | void nonConstMember(int); | 
|  | bool operator<(const Str &str) const;     // const operator. | 
|  | Str &operator=(const Str &str) = default; // non const operator. | 
|  | }; | 
|  |  | 
|  | // This class is non-trivially copyable because the copy-constructor and copy | 
|  | // assignment take non-const references. | 
|  | struct ModifiesRightSide { | 
|  | ModifiesRightSide() = default; | 
|  | ModifiesRightSide(ModifiesRightSide &) = default; | 
|  | bool operator<(ModifiesRightSide &) const; | 
|  | ModifiesRightSide &operator=(ModifiesRightSide &) = default; | 
|  | }; | 
|  |  | 
|  | template <typename T> | 
|  | void copyArg(T); | 
|  |  | 
|  | template <typename T> | 
|  | void nonConstRefArg(T &); | 
|  |  | 
|  | // If we define this as a template, the type is deduced to "T&", | 
|  | // and "const (T&) &" is the same as "T& &", and this collapses to "T&". | 
|  | void constRefArg(const Str &); | 
|  | void constRefArg(const ModifiesRightSide &); | 
|  | void constRefArg(const int &); | 
|  |  | 
|  | void foo(); | 
|  |  | 
|  | const int N = 10; | 
|  | Str Array[N], OtherStr; | 
|  | ModifiesRightSide Right[N], OtherRight; | 
|  | int Ints[N], OtherInt; | 
|  |  | 
|  | void memberFunctionsAndOperators() { | 
|  | // Calling const member functions or operator is a const usage. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | Array[I].constMember(0); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert] | 
|  | // CHECK-FIXES: for (auto I : Array) | 
|  | // CHECK-FIXES-NEXT: I.constMember(0); | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | if (Array[I] < OtherStr) | 
|  | foo(); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto I : Array) | 
|  | // CHECK-FIXES-NEXT: if (I < OtherStr) | 
|  | for (int I = 0; I < N; ++I) { | 
|  | if (Right[I] < OtherRight) | 
|  | foo(); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (const auto & I : Right) | 
|  | // CHECK-FIXES-NEXT: if (I < OtherRight) | 
|  |  | 
|  | // Calling non-const member functions is not. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | Array[I].nonConstMember(0); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto & I : Array) | 
|  | // CHECK-FIXES-NEXT: I.nonConstMember(0); | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | Array[I] = OtherStr; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto & I : Array) | 
|  | // CHECK-FIXES-NEXT: I = OtherStr; | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | Right[I] = OtherRight; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto & I : Right) | 
|  | // CHECK-FIXES-NEXT: I = OtherRight; | 
|  | } | 
|  |  | 
|  | void usedAsParameterToFunctionOrOperator() { | 
|  | // Copying is OK, as long as the copy constructor takes a const-reference. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | copyArg(Array[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto I : Array) | 
|  | // CHECK-FIXES-NEXT: copyArg(I); | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | copyArg(Right[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto & I : Right) | 
|  | // CHECK-FIXES-NEXT: copyArg(I); | 
|  |  | 
|  | // Using as a const reference argument is allowed. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | constRefArg(Array[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto I : Array) | 
|  | // CHECK-FIXES-NEXT: constRefArg(I); | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | if (OtherStr < Array[I]) | 
|  | foo(); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto I : Array) | 
|  | // CHECK-FIXES-NEXT: if (OtherStr < I) | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | constRefArg(Right[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (const auto & I : Right) | 
|  | // CHECK-FIXES-NEXT: constRefArg(I); | 
|  |  | 
|  | // Using as a non-const reference is not. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | nonConstRefArg(Array[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto & I : Array) | 
|  | // CHECK-FIXES-NEXT: nonConstRefArg(I); | 
|  | for (int I = 0; I < N; ++I) { | 
|  | nonConstRefArg(Right[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto & I : Right) | 
|  | // CHECK-FIXES-NEXT: nonConstRefArg(I); | 
|  | for (int I = 0; I < N; ++I) { | 
|  | if (OtherRight < Right[I]) | 
|  | foo(); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto & I : Right) | 
|  | // CHECK-FIXES-NEXT: if (OtherRight < I) | 
|  | } | 
|  |  | 
|  | void primitiveTypes() { | 
|  | // As argument to a function. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | copyArg(Ints[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int Int : Ints) | 
|  | // CHECK-FIXES-NEXT: copyArg(Int); | 
|  | for (int I = 0; I < N; ++I) { | 
|  | constRefArg(Ints[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int Int : Ints) | 
|  | // CHECK-FIXES-NEXT: constRefArg(Int); | 
|  | for (int I = 0; I < N; ++I) { | 
|  | nonConstRefArg(Ints[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int & Int : Ints) | 
|  | // CHECK-FIXES-NEXT: nonConstRefArg(Int); | 
|  |  | 
|  | // Builtin operators. | 
|  | // Comparisons. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | if (Ints[I] < N) | 
|  | foo(); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int Int : Ints) | 
|  | // CHECK-FIXES-NEXT: if (Int < N) | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | if (N == Ints[I]) | 
|  | foo(); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int Int : Ints) | 
|  | // CHECK-FIXES-NEXT: if (N == Int) | 
|  |  | 
|  | // Assignment. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | Ints[I] = OtherInt; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int & Int : Ints) | 
|  | // CHECK-FIXES-NEXT: Int = OtherInt; | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | OtherInt = Ints[I]; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int Int : Ints) | 
|  | // CHECK-FIXES-NEXT: OtherInt = Int; | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | OtherInt = Ints[I] = OtherInt; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int & Int : Ints) | 
|  | // CHECK-FIXES-NEXT: OtherInt = Int = OtherInt; | 
|  |  | 
|  | // Arithmetic operations. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | OtherInt += Ints[I]; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int Int : Ints) | 
|  | // CHECK-FIXES-NEXT: OtherInt += Int; | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | Ints[I] += Ints[I]; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int & Int : Ints) | 
|  | // CHECK-FIXES-NEXT: Int += Int; | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | int Res = 5 * (Ints[I] + 1) - Ints[I]; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int Int : Ints) | 
|  | // CHECK-FIXES-NEXT: int Res = 5 * (Int + 1) - Int; | 
|  | } | 
|  |  | 
|  | void takingReferences() { | 
|  | // We do it twice to prevent the check from thinking that they are aliases. | 
|  |  | 
|  | // Class type. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | Str &J = Array[I]; | 
|  | Str &K = Array[I]; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto & I : Array) | 
|  | // CHECK-FIXES-NEXT: Str &J = I; | 
|  | // CHECK-FIXES-NEXT: Str &K = I; | 
|  | for (int I = 0; I < N; ++I) { | 
|  | const Str &J = Array[I]; | 
|  | const Str &K = Array[I]; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto I : Array) | 
|  | // CHECK-FIXES-NEXT: const Str &J = I; | 
|  | // CHECK-FIXES-NEXT: const Str &K = I; | 
|  |  | 
|  | // Primitive type. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | int &J = Ints[I]; | 
|  | int &K = Ints[I]; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int & Int : Ints) | 
|  | // CHECK-FIXES-NEXT: int &J = Int; | 
|  | // CHECK-FIXES-NEXT: int &K = Int; | 
|  | for (int I = 0; I < N; ++I) { | 
|  | const int &J = Ints[I]; | 
|  | const int &K = Ints[I]; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int Int : Ints) | 
|  | // CHECK-FIXES-NEXT: const int &J = Int; | 
|  | // CHECK-FIXES-NEXT: const int &K = Int; | 
|  |  | 
|  | // Aliases. | 
|  | for (int I = 0; I < N; ++I) { | 
|  | const Str &J = Array[I]; | 
|  | (void)J; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto J : Array) | 
|  | for (int I = 0; I < N; ++I) { | 
|  | Str &J = Array[I]; | 
|  | (void)J; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto & J : Array) | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | const int &J = Ints[I]; | 
|  | (void)J; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int J : Ints) | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | int &J = Ints[I]; | 
|  | (void)J; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int & J : Ints) | 
|  | } | 
|  |  | 
|  | template <class T> | 
|  | struct vector { | 
|  | unsigned size() const; | 
|  | const T &operator[](int) const; | 
|  | T &operator[](int); | 
|  | T *begin(); | 
|  | T *end(); | 
|  | const T *begin() const; | 
|  | const T *end() const; | 
|  | }; | 
|  |  | 
|  | // If the elements are already constant, we won't do any ImplicitCast to const. | 
|  | void testContainerOfConstIents() { | 
|  | const int Ints[N]{}; | 
|  | for (int I = 0; I < N; ++I) { | 
|  | OtherInt -= Ints[I]; | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int Int : Ints) | 
|  |  | 
|  | vector<const Str> Strs; | 
|  | for (int I = 0; I < Strs.size(); ++I) { | 
|  | Strs[I].constMember(0); | 
|  | constRefArg(Strs[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto Str : Strs) | 
|  | } | 
|  |  | 
|  | // When we are inside a const-qualified member functions, all the data members | 
|  | // are implicitly set as const. As before, there won't be any ImplicitCast to | 
|  | // const in their usages. | 
|  | class TestInsideConstFunction { | 
|  | const static int N = 10; | 
|  | int Ints[N]; | 
|  | Str Array[N]; | 
|  | vector<int> V; | 
|  |  | 
|  | void foo() const { | 
|  | for (int I = 0; I < N; ++I) { | 
|  | if (Ints[I]) | 
|  | copyArg(Ints[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int Int : Ints) | 
|  |  | 
|  | for (int I = 0; I < N; ++I) { | 
|  | Array[I].constMember(0); | 
|  | constRefArg(Array[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (auto I : Array) | 
|  |  | 
|  | for (int I = 0; I < V.size(); ++I) { | 
|  | if (V[I]) | 
|  | copyArg(V[I]); | 
|  | } | 
|  | // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop | 
|  | // CHECK-FIXES: for (int I : V) | 
|  | } | 
|  | }; |