1 // RUN: %check_clang_tidy %s modernize-loop-convert %t
2 
3 struct 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 copy
13 // assignment take non-const references.
14 struct ModifiesRightSide {
15   ModifiesRightSide() = default;
16   ModifiesRightSide(ModifiesRightSide &) = default;
17   bool operator<(ModifiesRightSide &) const;
18   ModifiesRightSide &operator=(ModifiesRightSide &) = default;
19 };
20 
21 template <typename T>
22 void copyArg(T);
23 
24 template <typename T>
25 void 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&".
29 void constRefArg(const Str &);
30 void constRefArg(const ModifiesRightSide &);
31 void constRefArg(const int &);
32 
33 void foo();
34 
35 const int N = 10;
36 Str Array[N], OtherStr;
37 ModifiesRightSide Right[N], OtherRight;
38 int Ints[N], OtherInt;
39 
memberFunctionsAndOperators()40 void 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 loop
54   // 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 loop
61   // 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 loop
69   // 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 loop
76   // 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 loop
83   // CHECK-FIXES: for (auto & I : Right)
84   // CHECK-FIXES-NEXT: I = OtherRight;
85 }
86 
usedAsParameterToFunctionOrOperator()87 void 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 loop
93   // 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 loop
100   // 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 loop
108   // 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 loop
116   // 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 loop
123   // 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 loop
131   // 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 loop
137   // 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 loop
144   // CHECK-FIXES: for (auto & I : Right)
145   // CHECK-FIXES-NEXT: if (OtherRight < I)
146 }
147 
primitiveTypes()148 void 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 loop
154   // 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 loop
160   // 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 loop
166   // 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 loop
176   // 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 loop
184   // 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 loop
192   // 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 loop
199   // 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 loop
206   // 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 loop
214   // 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 loop
221   // 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 loop
228   // CHECK-FIXES: for (int Int : Ints)
229   // CHECK-FIXES-NEXT: int Res = 5 * (Int + 1) - Int;
230 }
231 
takingReferences()232 void 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 loop
241   // 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 loop
249   // 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 loop
259   // 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 loop
267   // 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 loop
277   // 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 loop
283   // 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 loop
290   // 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 loop
297   // CHECK-FIXES: for (int & J : Ints)
298 }
299 
300 template <class T>
301 struct 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.
testContainerOfConstIents()312 void 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 loop
318   // 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 loop
326   // CHECK-FIXES: for (auto Str : Strs)
327 }
328 
329 // When we are inside a const-qualified member functions, all the data members
330 // are implicitly set as const. As before, there won't be any ImplicitCast to
331 // const in their usages.
332 class TestInsideConstFunction {
333   const static int N = 10;
334   int Ints[N];
335   Str Array[N];
336   vector<int> V;
337 
foo() const338   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 loop
344     // 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 loop
351     // 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 loop
358     // CHECK-FIXES: for (int I : V)
359   }
360 };
361