Index: clang-tidy/modernize/LoopConvertCheck.cpp =================================================================== --- clang-tidy/modernize/LoopConvertCheck.cpp +++ clang-tidy/modernize/LoopConvertCheck.cpp @@ -368,11 +368,38 @@ return false; } +/// \brief Given an expression that represents an usage of an element from the +/// containter that we are iterating over, returns false when it can be +/// guaranteed this element cannot be modified as a result of this usage. +static bool canBeModified(ASTContext *Context, const Expr *E) { + auto Parents = Context->getParents(*E); + if (Parents.size() != 1) + return true; + if (const auto *Cast = Parents[0].get()) { + if ((Cast->getCastKind() == CK_NoOp && + Cast->getType() == E->getType().withConst()) || + (Cast->getCastKind() == CK_LValueToRValue && + !Cast->getType().isNull() && Cast->getType()->isFundamentalType())) + return false; + } + // FIXME: Make this function more generic. + return true; +} + /// \brief Returns true when it can be guaranteed that the elements of the /// container are not being modified. -static bool usagesAreConst(const UsageResult &Usages) { - // FIXME: Make this function more generic. - return Usages.empty(); +static bool usagesAreConst(ASTContext *Context, const UsageResult &Usages) { + for (const Usage &U : Usages) { + // Lambda captures are just redeclarations (VarDecl) of the same variable, + // not expressions. If we want to know if a variable that is captured by + // reference can be modified in an usage inside the lambda's body, we need + // to find the expression corresponding to that particular usage, later in + // this loop. + if (U.Kind != Usage::UK_CaptureByCopy && U.Kind != Usage::UK_CaptureByRef && + canBeModified(Context, U.Expression)) + return false; + } + return true; } /// \brief Returns true if the elements of the container are never accessed @@ -568,9 +595,8 @@ Descriptor.ElemType.isTriviallyCopyableType(*Context) && // TypeInfo::Width is in bits. Context->getTypeInfo(Descriptor.ElemType).Width <= 8 * MaxCopySize; - bool UseCopy = - CanCopy && ((VarNameFromAlias && !AliasVarIsRef) || - (Descriptor.DerefByConstRef && IsCheapToCopy)); + bool UseCopy = CanCopy && ((VarNameFromAlias && !AliasVarIsRef) || + (Descriptor.DerefByConstRef && IsCheapToCopy)); if (!UseCopy) { if (Descriptor.DerefByConstRef) { @@ -618,7 +644,7 @@ RangeDescriptor &Descriptor) { // On arrays and pseudoarrays, we must figure out the qualifiers from the // usages. - if (usagesAreConst(Usages) || + if (usagesAreConst(Context, Usages) || containerIsConst(ContainerExpr, Descriptor.ContainerNeedsDereference)) { Descriptor.DerefByConstRef = true; } Index: test/clang-tidy/modernize-loop-convert-basic.cpp =================================================================== --- test/clang-tidy/modernize-loop-convert-basic.cpp +++ test/clang-tidy/modernize-loop-convert-basic.cpp @@ -18,7 +18,7 @@ int K; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead [modernize-loop-convert] - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: Sum += Elem; // CHECK-FIXES-NEXT: int K; @@ -27,7 +27,7 @@ Sum += Arr[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; @@ -36,7 +36,7 @@ int Y = Arr[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: int X = Elem; // CHECK-FIXES-NEXT: int Y = Elem + 2; @@ -45,7 +45,7 @@ X = Arr[I]; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: int X = N; // CHECK-FIXES-NEXT: X = Elem; @@ -76,7 +76,7 @@ Sum += Arr[I]; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: Sum += Elem; for (int I = 0; I < N; ++I) { @@ -140,7 +140,7 @@ printf("%d", Arr[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: printf("%d", Elem); for (int I = 0; I < N; ++I) { @@ -156,7 +156,7 @@ printf("%d", this->Arr[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:5: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : this->Arr) + // CHECK-FIXES: for (int Elem : this->Arr) // CHECK-FIXES-NEXT: printf("%d", Elem); for (int I = 0; I < N; ++I) { @@ -504,7 +504,7 @@ Sum += V[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : V) + // CHECK-FIXES: for (int Elem : V) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; @@ -513,7 +513,7 @@ Sum += V.at(I) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : V) + // CHECK-FIXES: for (int Elem : V) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; @@ -522,7 +522,7 @@ Sum += Pv->at(I) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : *Pv) + // CHECK-FIXES: for (int Elem : *Pv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; @@ -535,7 +535,7 @@ Sum += (*Pv)[I] + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : *Pv) + // CHECK-FIXES: for (int Elem : *Pv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; @@ -544,7 +544,7 @@ Sum += Cv->at(I) + 2; } // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : *Cv) + // CHECK-FIXES: for (int Elem : *Cv) // CHECK-FIXES-NEXT: printf("Fibonacci number is %d\n", Elem); // CHECK-FIXES-NEXT: Sum += Elem + 2; } @@ -660,7 +660,7 @@ 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 & Elem : CBE) + // CHECK-FIXES: for (unsigned int Elem : CBE) // CHECK-FIXES-NEXT: printf("%d\n", Elem); const ConstBeginEnd Const_CBE; @@ -705,50 +705,50 @@ 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) + // 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) + // 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) + // 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) + // 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) + // 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) + // 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) + // 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) + // CHECK-FIXES: for (double Double : Doubles) } } // namespace PseudoArray Index: test/clang-tidy/modernize-loop-convert-camelback.cpp =================================================================== --- test/clang-tidy/modernize-loop-convert-camelback.cpp +++ test/clang-tidy/modernize-loop-convert-camelback.cpp @@ -13,14 +13,14 @@ printf("%d\n", arr[i]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert] - // CHECK-FIXES: for (int & elem : arr) + // CHECK-FIXES: for (int elem : arr) // CHECK-FIXES-NEXT: printf("%d\n", elem); for (int i = 0; i < n; ++i) { printf("%d\n", nums[i]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & num : nums) + // CHECK-FIXES: for (int num : nums) // CHECK-FIXES-NEXT: printf("%d\n", num); int num = 0; @@ -28,7 +28,7 @@ printf("%d\n", nums[i] + num); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & elem : nums) + // CHECK-FIXES: for (int elem : nums) // CHECK-FIXES-NEXT: printf("%d\n", elem + num); int elem = 0; @@ -36,7 +36,7 @@ printf("%d\n", nums[i] + num + elem); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & numsI : nums) + // CHECK-FIXES: for (int numsI : nums) // CHECK-FIXES-NEXT: printf("%d\n", numsI + num + elem); int numsI = 0; @@ -44,7 +44,7 @@ printf("%d\n", nums[i] + num + elem + numsI); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & numsElem : nums) + // CHECK-FIXES: for (int numsElem : nums) // CHECK-FIXES-NEXT: printf("%d\n", numsElem + num + elem + numsI); int numsElem = 0; @@ -52,7 +52,7 @@ printf("%d\n", nums[i] + num + elem + numsI + numsElem); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & giveMeName0 : nums) + // CHECK-FIXES: for (int giveMeName0 : nums) // CHECK-FIXES-NEXT: printf("%d\n", giveMeName0 + num + elem + numsI + numsElem); int giveMeName0 = 0; @@ -60,7 +60,7 @@ printf("%d\n", nums[i] + num + elem + numsI + numsElem + giveMeName0); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & giveMeName1 : nums) + // CHECK-FIXES: for (int giveMeName1 : nums) // CHECK-FIXES-NEXT: printf("%d\n", giveMeName1 + num + elem + numsI + numsElem + giveMeName0); int numsJ = 0; @@ -71,7 +71,7 @@ } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead - // CHECK-FIXES: for (int & giveMeName0 : nums) - // CHECK-FIXES: for (int & giveMeName1 : nums) + // CHECK-FIXES: for (int giveMeName0 : nums) + // CHECK-FIXES: for (int giveMeName1 : nums) // CHECK-FIXES-NEXT: printf("%d\n", giveMeName0 + giveMeName1 + num + elem + numsI + numsJ + numsElem); } Index: test/clang-tidy/modernize-loop-convert-const.cpp =================================================================== --- /dev/null +++ test/clang-tidy/modernize-loop-convert-const.cpp @@ -0,0 +1,298 @@ +// RUN: %check_clang_tidy %s modernize-loop-convert %t -- -- -std=c++11 + +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 +void copyArg(T); + +template +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 Elem : Array) + // CHECK-FIXES-NEXT: Elem.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 Elem : Array) + // CHECK-FIXES-NEXT: if (Elem < 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 & Elem : Right) + // CHECK-FIXES-NEXT: if (Elem < 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 & Elem : Array) + // CHECK-FIXES-NEXT: Elem.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 & Elem : Array) + // CHECK-FIXES-NEXT: Elem = 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 & Elem : Right) + // CHECK-FIXES-NEXT: Elem = 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 Elem : Array) + // CHECK-FIXES-NEXT: copyArg(Elem); + + 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 & Elem : Right) + // CHECK-FIXES-NEXT: copyArg(Elem); + + // 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 Elem : Array) + // CHECK-FIXES-NEXT: constRefArg(Elem); + + 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 Elem : Array) + // CHECK-FIXES-NEXT: if (OtherStr < Elem) + + 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 & Elem : Right) + // CHECK-FIXES-NEXT: constRefArg(Elem); + + // 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 & Elem : Array) + // CHECK-FIXES-NEXT: nonConstRefArg(Elem); + 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 & Elem : Right) + // CHECK-FIXES-NEXT: nonConstRefArg(Elem); + 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 & Elem : Right) + // CHECK-FIXES-NEXT: if (OtherRight < Elem) +} + +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 & Elem : Array) + // CHECK-FIXES-NEXT: Str &J = Elem; + // CHECK-FIXES-NEXT: Str &K = Elem; + 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 Elem : Array) + // CHECK-FIXES-NEXT: const Str &J = Elem; + // CHECK-FIXES-NEXT: const Str &K = Elem; + + // 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) +} Index: test/clang-tidy/modernize-loop-convert-extra.cpp =================================================================== --- test/clang-tidy/modernize-loop-convert-extra.cpp +++ test/clang-tidy/modernize-loop-convert-extra.cpp @@ -164,7 +164,7 @@ IntRef Int(IntArr[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : IntArr) + // CHECK-FIXES: for (int Elem : IntArr) // CHECK-FIXES-NEXT: IntRef Int(Elem); // Ensure that removing the alias doesn't leave empty lines behind. @@ -716,7 +716,7 @@ printf("Value: %d\n", Arr[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: printf("Value: %d\n", Elem); for (int I = 0; I < N; ++I) { @@ -770,13 +770,13 @@ for (int I = 0; I < N; ++I) auto F1 = [Arr, I]() { int R1 = Arr[I] + 1; }; // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: auto F1 = [Arr, &Elem]() { int R1 = Elem + 1; }; for (int I = 0; I < N; ++I) auto F2 = [Arr, &I]() { int R2 = Arr[I] + 3; }; // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: auto F2 = [Arr, &Elem]() { int R2 = Elem + 3; }; // FIXME: alias don't work if the index is captured. @@ -784,14 +784,14 @@ for (int I = 0; I < N; ++I) auto F3 = [&Arr, I]() { int R3 = Arr[I]; }; // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: auto F3 = [&Arr, &Elem]() { int R3 = Elem; }; for (int I = 0; I < N; ++I) auto F4 = [&Arr, &I]() { int R4 = Arr[I]; }; // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: auto F4 = [&Arr, &Elem]() { int R4 = Elem; }; // Alias declared inside lambda (by reference). @@ -815,7 +815,7 @@ F(Arr[I]); } // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: auto F = [Arr, &Elem](int k) // CHECK-FIXES-NEXT: printf("%d\n", Elem + k); // CHECK-FIXES: F(Elem); @@ -847,7 +847,7 @@ }; } // CHECK-MESSAGES: :[[@LINE-6]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: auto G3 = [&]() // CHECK-FIXES-NEXT: int R3 = Elem; // CHECK-FIXES-NEXT: int J3 = Elem + R3; @@ -858,7 +858,7 @@ }; } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: auto G4 = [=]() // CHECK-FIXES-NEXT: int R4 = Elem + 5; @@ -929,14 +929,14 @@ auto C1 = [&Arr, I]() { if (Arr[I] == 1); }; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Arr) + // CHECK-FIXES: for (int Elem : Arr) // CHECK-FIXES-NEXT: auto C1 = [&Arr, &Elem]() { if (Elem == 1); }; for (unsigned I = 0; I < Dep.size(); ++I) { auto C2 = [&Dep, I]() { if (Dep[I] == 2); }; } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Dep) + // CHECK-FIXES: for (int Elem : Dep) // CHECK-FIXES-NEXT: auto C2 = [&Dep, &Elem]() { if (Elem == 2); }; } @@ -962,7 +962,7 @@ E Ee{ { { g( { Array[I] } ) } } }; } // CHECK-MESSAGES: :[[@LINE-7]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & Elem : Array) + // CHECK-FIXES: for (int Elem : Array) // CHECK-FIXES-NEXT: int A{ Elem }; // CHECK-FIXES-NEXT: int B{ g(Elem) }; // CHECK-FIXES-NEXT: int C{ g( { Elem } ) }; Index: test/clang-tidy/modernize-loop-convert-lowercase.cpp =================================================================== --- test/clang-tidy/modernize-loop-convert-lowercase.cpp +++ test/clang-tidy/modernize-loop-convert-lowercase.cpp @@ -14,21 +14,21 @@ printf("%d\n", arr[i]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert] - // CHECK-FIXES: for (int & elem : arr) + // CHECK-FIXES: for (int elem : arr) // CHECK-FIXES-NEXT: printf("%d\n", elem); for (int i = 0; i < n; ++i) { printf("%d\n", nums[i]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & num : nums) + // CHECK-FIXES: for (int num : nums) // CHECK-FIXES-NEXT: printf("%d\n", num); for (int i = 0; i < n; ++i) { printf("%d\n", nums_[i]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & num : nums_) + // CHECK-FIXES: for (int num : nums_) // CHECK-FIXES-NEXT: printf("%d\n", num); int num = 0; @@ -36,7 +36,7 @@ printf("%d\n", nums[i] + num); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & elem : nums) + // CHECK-FIXES: for (int elem : nums) // CHECK-FIXES-NEXT: printf("%d\n", elem + num); int elem = 0; @@ -44,7 +44,7 @@ printf("%d\n", nums[i] + num + elem); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & nums_i : nums) + // CHECK-FIXES: for (int nums_i : nums) // CHECK-FIXES-NEXT: printf("%d\n", nums_i + num + elem); int nums_i = 0; @@ -52,7 +52,7 @@ printf("%d\n", nums[i] + num + elem + nums_i); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & nums_elem : nums) + // CHECK-FIXES: for (int nums_elem : nums) // CHECK-FIXES-NEXT: printf("%d\n", nums_elem + num + elem + nums_i); int nums_elem = 0; @@ -60,7 +60,7 @@ printf("%d\n", nums[i] + num + elem + nums_i + nums_elem); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & give_me_name_0 : nums) + // CHECK-FIXES: for (int give_me_name_0 : nums) // CHECK-FIXES-NEXT: printf("%d\n", give_me_name_0 + num + elem + nums_i + nums_elem); int give_me_name_0 = 0; @@ -68,7 +68,7 @@ printf("%d\n", nums[i] + num + elem + nums_i + nums_elem + give_me_name_0); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & give_me_name_1 : nums) + // CHECK-FIXES: for (int give_me_name_1 : nums) // CHECK-FIXES-NEXT: printf("%d\n", give_me_name_1 + num + elem + nums_i + nums_elem + give_me_name_0); int nums_j = 0; @@ -79,7 +79,7 @@ } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead - // CHECK-FIXES: for (int & give_me_name_0 : nums) - // CHECK-FIXES: for (int & give_me_name_1 : nums) + // CHECK-FIXES: for (int give_me_name_0 : nums) + // CHECK-FIXES: for (int give_me_name_1 : nums) // CHECK-FIXES-NEXT: printf("%d\n", give_me_name_0 + give_me_name_1 + num + elem + nums_i + nums_j + nums_elem); } Index: test/clang-tidy/modernize-loop-convert-uppercase.cpp =================================================================== --- test/clang-tidy/modernize-loop-convert-uppercase.cpp +++ test/clang-tidy/modernize-loop-convert-uppercase.cpp @@ -14,21 +14,21 @@ printf("%d\n", ARR[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert] - // CHECK-FIXES: for (int & ELEM : ARR) + // CHECK-FIXES: for (int ELEM : ARR) // CHECK-FIXES-NEXT: printf("%d\n", ELEM); for (int I = 0; I < N; ++I) { printf("%d\n", NUMS[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & NUM : NUMS) + // CHECK-FIXES: for (int NUM : NUMS) // CHECK-FIXES-NEXT: printf("%d\n", NUM); for (int I = 0; I < N; ++I) { printf("%d\n", NUMS_[I]); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & NUM : NUMS_) + // CHECK-FIXES: for (int NUM : NUMS_) // CHECK-FIXES-NEXT: printf("%d\n", NUM); int NUM = 0; @@ -36,7 +36,7 @@ printf("%d\n", NUMS[I] + NUM); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & ELEM : NUMS) + // CHECK-FIXES: for (int ELEM : NUMS) // CHECK-FIXES-NEXT: printf("%d\n", ELEM + NUM); int ELEM = 0; @@ -44,7 +44,7 @@ printf("%d\n", NUMS[I] + NUM + ELEM); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & NUMS_I : NUMS) + // CHECK-FIXES: for (int NUMS_I : NUMS) // CHECK-FIXES-NEXT: printf("%d\n", NUMS_I + NUM + ELEM); int NUMS_I = 0; @@ -52,7 +52,7 @@ printf("%d\n", NUMS[I] + NUM + ELEM + NUMS_I); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & NUMS_ELEM : NUMS) + // CHECK-FIXES: for (int NUMS_ELEM : NUMS) // CHECK-FIXES-NEXT: printf("%d\n", NUMS_ELEM + NUM + ELEM + NUMS_I); int NUMS_ELEM = 0; @@ -60,7 +60,7 @@ printf("%d\n", NUMS[I] + NUM + ELEM + NUMS_I + NUMS_ELEM); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & GIVE_ME_NAME_0 : NUMS) + // CHECK-FIXES: for (int GIVE_ME_NAME_0 : NUMS) // CHECK-FIXES-NEXT: printf("%d\n", GIVE_ME_NAME_0 + NUM + ELEM + NUMS_I + NUMS_ELEM); int GIVE_ME_NAME_0 = 0; @@ -68,7 +68,7 @@ printf("%d\n", NUMS[I] + NUM + ELEM + NUMS_I + NUMS_ELEM + GIVE_ME_NAME_0); } // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead - // CHECK-FIXES: for (int & GIVE_ME_NAME_1 : NUMS) + // CHECK-FIXES: for (int GIVE_ME_NAME_1 : NUMS) // CHECK-FIXES-NEXT: printf("%d\n", GIVE_ME_NAME_1 + NUM + ELEM + NUMS_I + NUMS_ELEM + GIVE_ME_NAME_0); int NUMS_J = 0; @@ -79,7 +79,7 @@ } // CHECK-MESSAGES: :[[@LINE-5]]:3: warning: use range-based for loop instead // CHECK-MESSAGES: :[[@LINE-5]]:5: warning: use range-based for loop instead - // CHECK-FIXES: for (int & GIVE_ME_NAME_0 : NUMS) - // CHECK-FIXES: for (int & GIVE_ME_NAME_1 : NUMS) + // CHECK-FIXES: for (int GIVE_ME_NAME_0 : NUMS) + // CHECK-FIXES: for (int GIVE_ME_NAME_1 : NUMS) // CHECK-FIXES-NEXT: printf("%d\n", GIVE_ME_NAME_0 + GIVE_ME_NAME_1 + NUM + ELEM + NUMS_I + NUMS_J + NUMS_ELEM); }