361 lines · cpp
1// RUN: %check_clang_tidy %s modernize-loop-convert %t2 3struct Str {4 Str() = default;5 Str(const Str &) = default;6 void constMember(int) const;7 void nonConstMember(int);8 bool operator<(const Str &str) const; // const operator.9 Str &operator=(const Str &str) = default; // non const operator.10};11 12// This class is non-trivially copyable because the copy-constructor and copy13// assignment take non-const references and are user-provided.14struct ModifiesRightSide {15 ModifiesRightSide() = default;16 ModifiesRightSide(ModifiesRightSide &);17 bool operator<(ModifiesRightSide &) const;18 ModifiesRightSide &operator=(ModifiesRightSide &);19};20 21template <typename T>22void copyArg(T);23 24template <typename T>25void nonConstRefArg(T &);26 27// If we define this as a template, the type is deduced to "T&",28// and "const (T&) &" is the same as "T& &", and this collapses to "T&".29void constRefArg(const Str &);30void constRefArg(const ModifiesRightSide &);31void constRefArg(const int &);32 33void foo();34 35const int N = 10;36Str Array[N], OtherStr;37ModifiesRightSide Right[N], OtherRight;38int Ints[N], OtherInt;39 40void memberFunctionsAndOperators() {41 // Calling const member functions or operator is a const usage.42 for (int I = 0; I < N; ++I) {43 Array[I].constMember(0);44 }45 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop instead [modernize-loop-convert]46 // CHECK-FIXES: for (auto I : Array) {47 // CHECK-FIXES-NEXT: I.constMember(0);48 49 for (int I = 0; I < N; ++I) {50 if (Array[I] < OtherStr)51 foo();52 }53 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop54 // CHECK-FIXES: for (auto I : Array) {55 // CHECK-FIXES-NEXT: if (I < OtherStr)56 for (int I = 0; I < N; ++I) {57 if (Right[I] < OtherRight)58 foo();59 }60 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop61 // CHECK-FIXES: for (const auto & I : Right) {62 // CHECK-FIXES-NEXT: if (I < OtherRight)63 64 // Calling non-const member functions is not.65 for (int I = 0; I < N; ++I) {66 Array[I].nonConstMember(0);67 }68 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop69 // CHECK-FIXES: for (auto & I : Array) {70 // CHECK-FIXES-NEXT: I.nonConstMember(0);71 72 for (int I = 0; I < N; ++I) {73 Array[I] = OtherStr;74 }75 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop76 // CHECK-FIXES: for (auto & I : Array) {77 // CHECK-FIXES-NEXT: I = OtherStr;78 79 for (int I = 0; I < N; ++I) {80 Right[I] = OtherRight;81 }82 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop83 // CHECK-FIXES: for (auto & I : Right) {84 // CHECK-FIXES-NEXT: I = OtherRight;85}86 87void usedAsParameterToFunctionOrOperator() {88 // Copying is OK, as long as the copy constructor takes a const-reference.89 for (int I = 0; I < N; ++I) {90 copyArg(Array[I]);91 }92 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop93 // CHECK-FIXES: for (auto I : Array) {94 // CHECK-FIXES-NEXT: copyArg(I);95 96 for (int I = 0; I < N; ++I) {97 copyArg(Right[I]);98 }99 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop100 // CHECK-FIXES: for (auto & I : Right) {101 // CHECK-FIXES-NEXT: copyArg(I);102 103 // Using as a const reference argument is allowed.104 for (int I = 0; I < N; ++I) {105 constRefArg(Array[I]);106 }107 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop108 // CHECK-FIXES: for (auto I : Array) {109 // CHECK-FIXES-NEXT: constRefArg(I);110 111 for (int I = 0; I < N; ++I) {112 if (OtherStr < Array[I])113 foo();114 }115 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop116 // CHECK-FIXES: for (auto I : Array) {117 // CHECK-FIXES-NEXT: if (OtherStr < I)118 119 for (int I = 0; I < N; ++I) {120 constRefArg(Right[I]);121 }122 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop123 // CHECK-FIXES: for (const auto & I : Right) {124 // CHECK-FIXES-NEXT: constRefArg(I);125 126 // Using as a non-const reference is not.127 for (int I = 0; I < N; ++I) {128 nonConstRefArg(Array[I]);129 }130 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop131 // CHECK-FIXES: for (auto & I : Array) {132 // CHECK-FIXES-NEXT: nonConstRefArg(I);133 for (int I = 0; I < N; ++I) {134 nonConstRefArg(Right[I]);135 }136 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop137 // CHECK-FIXES: for (auto & I : Right) {138 // CHECK-FIXES-NEXT: nonConstRefArg(I);139 for (int I = 0; I < N; ++I) {140 if (OtherRight < Right[I])141 foo();142 }143 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop144 // CHECK-FIXES: for (auto & I : Right) {145 // CHECK-FIXES-NEXT: if (OtherRight < I)146}147 148void primitiveTypes() {149 // As argument to a function.150 for (int I = 0; I < N; ++I) {151 copyArg(Ints[I]);152 }153 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop154 // CHECK-FIXES: for (int Int : Ints) {155 // CHECK-FIXES-NEXT: copyArg(Int);156 for (int I = 0; I < N; ++I) {157 constRefArg(Ints[I]);158 }159 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop160 // CHECK-FIXES: for (int Int : Ints) {161 // CHECK-FIXES-NEXT: constRefArg(Int);162 for (int I = 0; I < N; ++I) {163 nonConstRefArg(Ints[I]);164 }165 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop166 // CHECK-FIXES: for (int & Int : Ints) {167 // CHECK-FIXES-NEXT: nonConstRefArg(Int);168 169 // Builtin operators.170 // Comparisons.171 for (int I = 0; I < N; ++I) {172 if (Ints[I] < N)173 foo();174 }175 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop176 // CHECK-FIXES: for (int Int : Ints) {177 // CHECK-FIXES-NEXT: if (Int < N)178 179 for (int I = 0; I < N; ++I) {180 if (N == Ints[I])181 foo();182 }183 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop184 // CHECK-FIXES: for (int Int : Ints) {185 // CHECK-FIXES-NEXT: if (N == Int)186 187 // Assignment.188 for (int I = 0; I < N; ++I) {189 Ints[I] = OtherInt;190 }191 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop192 // CHECK-FIXES: for (int & Int : Ints) {193 // CHECK-FIXES-NEXT: Int = OtherInt;194 195 for (int I = 0; I < N; ++I) {196 OtherInt = Ints[I];197 }198 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop199 // CHECK-FIXES: for (int Int : Ints) {200 // CHECK-FIXES-NEXT: OtherInt = Int;201 202 for (int I = 0; I < N; ++I) {203 OtherInt = Ints[I] = OtherInt;204 }205 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop206 // CHECK-FIXES: for (int & Int : Ints) {207 // CHECK-FIXES-NEXT: OtherInt = Int = OtherInt;208 209 // Arithmetic operations.210 for (int I = 0; I < N; ++I) {211 OtherInt += Ints[I];212 }213 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop214 // CHECK-FIXES: for (int Int : Ints) {215 // CHECK-FIXES-NEXT: OtherInt += Int;216 217 for (int I = 0; I < N; ++I) {218 Ints[I] += Ints[I];219 }220 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop221 // CHECK-FIXES: for (int & Int : Ints) {222 // CHECK-FIXES-NEXT: Int += Int;223 224 for (int I = 0; I < N; ++I) {225 int Res = 5 * (Ints[I] + 1) - Ints[I];226 }227 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop228 // CHECK-FIXES: for (int Int : Ints) {229 // CHECK-FIXES-NEXT: int Res = 5 * (Int + 1) - Int;230}231 232void takingReferences() {233 // We do it twice to prevent the check from thinking that they are aliases.234 235 // Class type.236 for (int I = 0; I < N; ++I) {237 Str &J = Array[I];238 Str &K = Array[I];239 }240 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop241 // CHECK-FIXES: for (auto & I : Array) {242 // CHECK-FIXES-NEXT: Str &J = I;243 // CHECK-FIXES-NEXT: Str &K = I;244 for (int I = 0; I < N; ++I) {245 const Str &J = Array[I];246 const Str &K = Array[I];247 }248 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop249 // CHECK-FIXES: for (auto I : Array) {250 // CHECK-FIXES-NEXT: const Str &J = I;251 // CHECK-FIXES-NEXT: const Str &K = I;252 253 // Primitive type.254 for (int I = 0; I < N; ++I) {255 int &J = Ints[I];256 int &K = Ints[I];257 }258 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop259 // CHECK-FIXES: for (int & Int : Ints) {260 // CHECK-FIXES-NEXT: int &J = Int;261 // CHECK-FIXES-NEXT: int &K = Int;262 for (int I = 0; I < N; ++I) {263 const int &J = Ints[I];264 const int &K = Ints[I];265 }266 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop267 // CHECK-FIXES: for (int Int : Ints) {268 // CHECK-FIXES-NEXT: const int &J = Int;269 // CHECK-FIXES-NEXT: const int &K = Int;270 271 // Aliases.272 for (int I = 0; I < N; ++I) {273 const Str &J = Array[I];274 (void)J;275 }276 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop277 // CHECK-FIXES: for (auto J : Array) {278 for (int I = 0; I < N; ++I) {279 Str &J = Array[I];280 (void)J;281 }282 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop283 // CHECK-FIXES: for (auto & J : Array) {284 285 for (int I = 0; I < N; ++I) {286 const int &J = Ints[I];287 (void)J;288 }289 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop290 // CHECK-FIXES: for (int J : Ints) {291 292 for (int I = 0; I < N; ++I) {293 int &J = Ints[I];294 (void)J;295 }296 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop297 // CHECK-FIXES: for (int & J : Ints) {298}299 300template <class T>301struct vector {302 unsigned size() const;303 const T &operator[](int) const;304 T &operator[](int);305 T *begin();306 T *end();307 const T *begin() const;308 const T *end() const;309};310 311// If the elements are already constant, we won't do any ImplicitCast to const.312void testContainerOfConstIents() {313 const int Ints[N]{};314 for (int I = 0; I < N; ++I) {315 OtherInt -= Ints[I];316 }317 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: use range-based for loop318 // CHECK-FIXES: for (int Int : Ints) {319 320 vector<const Str> Strs;321 for (int I = 0; I < Strs.size(); ++I) {322 Strs[I].constMember(0);323 constRefArg(Strs[I]);324 }325 // CHECK-MESSAGES: :[[@LINE-4]]:3: warning: use range-based for loop326 // CHECK-FIXES: for (auto Str : Strs) {327}328 329// When we are inside a const-qualified member functions, all the data members330// are implicitly set as const. As before, there won't be any ImplicitCast to331// const in their usages.332class TestInsideConstFunction {333 const static int N = 10;334 int Ints[N];335 Str Array[N];336 vector<int> V;337 338 void foo() const {339 for (int I = 0; I < N; ++I) {340 if (Ints[I])341 copyArg(Ints[I]);342 }343 // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop344 // CHECK-FIXES: for (int Int : Ints) {345 346 for (int I = 0; I < N; ++I) {347 Array[I].constMember(0);348 constRefArg(Array[I]);349 }350 // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop351 // CHECK-FIXES: for (auto I : Array) {352 353 for (int I = 0; I < V.size(); ++I) {354 if (V[I])355 copyArg(V[I]);356 }357 // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use range-based for loop358 // CHECK-FIXES: for (int I : V) {359 }360};361