1 | // RUN: %check_clang_tidy %s readability-qualified-auto %t \ |
2 | // RUN: -config='{CheckOptions: { \ |
3 | // RUN: readability-qualified-auto.AllowedTypes: "[iI]terator$;my::ns::Ignored1;std::array<.*>::Ignored2;MyIgnoredPtr" \ |
4 | // RUN: }}' |
5 | |
6 | namespace typedefs { |
7 | typedef int *MyPtr; |
8 | typedef int &MyRef; |
9 | typedef const int *CMyPtr; |
10 | typedef const int &CMyRef; |
11 | |
12 | MyPtr getPtr(); |
13 | MyRef getRef(); |
14 | CMyPtr getCPtr(); |
15 | CMyRef getCRef(); |
16 | |
17 | void foo() { |
18 | auto TdNakedPtr = getPtr(); |
19 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedPtr' can be declared as 'auto *TdNakedPtr' |
20 | // CHECK-FIXES: {{^}} auto *TdNakedPtr = getPtr(); |
21 | auto &TdNakedRef = getRef(); |
22 | auto TdNakedRefDeref = getRef(); |
23 | auto TdNakedCPtr = getCPtr(); |
24 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedCPtr' can be declared as 'const auto *TdNakedCPtr' |
25 | // CHECK-FIXES: {{^}} const auto *TdNakedCPtr = getCPtr(); |
26 | auto &TdNakedCRef = getCRef(); |
27 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &TdNakedCRef' can be declared as 'const auto &TdNakedCRef' |
28 | // CHECK-FIXES: {{^}} const auto &TdNakedCRef = getCRef(); |
29 | auto TdNakedCRefDeref = getCRef(); |
30 | } |
31 | |
32 | }; // namespace typedefs |
33 | |
34 | namespace usings { |
35 | using MyPtr = int *; |
36 | using MyRef = int &; |
37 | using CMyPtr = const int *; |
38 | using CMyRef = const int &; |
39 | |
40 | MyPtr getPtr(); |
41 | MyRef getRef(); |
42 | CMyPtr getCPtr(); |
43 | CMyRef getCRef(); |
44 | |
45 | void foo() { |
46 | auto UNakedPtr = getPtr(); |
47 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto UNakedPtr' can be declared as 'auto *UNakedPtr' |
48 | // CHECK-FIXES: {{^}} auto *UNakedPtr = getPtr(); |
49 | auto &UNakedRef = getRef(); |
50 | auto UNakedRefDeref = getRef(); |
51 | auto UNakedCPtr = getCPtr(); |
52 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto UNakedCPtr' can be declared as 'const auto *UNakedCPtr' |
53 | // CHECK-FIXES: {{^}} const auto *UNakedCPtr = getCPtr(); |
54 | auto &UNakedCRef = getCRef(); |
55 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &UNakedCRef' can be declared as 'const auto &UNakedCRef' |
56 | // CHECK-FIXES: {{^}} const auto &UNakedCRef = getCRef(); |
57 | auto UNakedCRefDeref = getCRef(); |
58 | } |
59 | |
60 | }; // namespace usings |
61 | |
62 | int getInt(); |
63 | int *getIntPtr(); |
64 | const int *getCIntPtr(); |
65 | |
66 | void foo() { |
67 | // make sure check disregards named types |
68 | int TypedInt = getInt(); |
69 | int *TypedPtr = getIntPtr(); |
70 | const int *TypedConstPtr = getCIntPtr(); |
71 | int &TypedRef = *getIntPtr(); |
72 | const int &TypedConstRef = *getCIntPtr(); |
73 | |
74 | // make sure check disregards auto types that aren't pointers or references |
75 | auto AutoInt = getInt(); |
76 | |
77 | auto NakedPtr = getIntPtr(); |
78 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedPtr' can be declared as 'auto *NakedPtr' |
79 | // CHECK-FIXES: {{^}} auto *NakedPtr = getIntPtr(); |
80 | auto NakedCPtr = getCIntPtr(); |
81 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedCPtr' can be declared as 'const auto *NakedCPtr' |
82 | // CHECK-FIXES: {{^}} const auto *NakedCPtr = getCIntPtr(); |
83 | |
84 | const auto ConstPtr = getIntPtr(); |
85 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'const auto ConstPtr' can be declared as 'auto *const ConstPtr' |
86 | // CHECK-FIXES: {{^}} auto *const ConstPtr = getIntPtr(); |
87 | const auto ConstCPtr = getCIntPtr(); |
88 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'const auto ConstCPtr' can be declared as 'const auto *const ConstCPtr' |
89 | // CHECK-FIXES: {{^}} const auto *const ConstCPtr = getCIntPtr(); |
90 | |
91 | volatile auto VolatilePtr = getIntPtr(); |
92 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'volatile auto VolatilePtr' can be declared as 'auto *volatile VolatilePtr' |
93 | // CHECK-FIXES: {{^}} auto *volatile VolatilePtr = getIntPtr(); |
94 | volatile auto VolatileCPtr = getCIntPtr(); |
95 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'volatile auto VolatileCPtr' can be declared as 'const auto *volatile VolatileCPtr' |
96 | // CHECK-FIXES: {{^}} const auto *volatile VolatileCPtr = getCIntPtr(); |
97 | |
98 | auto *QualPtr = getIntPtr(); |
99 | auto *QualCPtr = getCIntPtr(); |
100 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *QualCPtr' can be declared as 'const auto *QualCPtr' |
101 | // CHECK-FIXES: {{^}} const auto *QualCPtr = getCIntPtr(); |
102 | auto *const ConstantQualCPtr = getCIntPtr(); |
103 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *const ConstantQualCPtr' can be declared as 'const auto *const ConstantQualCPtr' |
104 | // CHECK-FIXES: {{^}} const auto *const ConstantQualCPtr = getCIntPtr(); |
105 | auto *volatile VolatileQualCPtr = getCIntPtr(); |
106 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *volatile VolatileQualCPtr' can be declared as 'const auto *volatile VolatileQualCPtr' |
107 | // CHECK-FIXES: {{^}} const auto *volatile VolatileQualCPtr = getCIntPtr(); |
108 | const auto *ConstQualCPtr = getCIntPtr(); |
109 | |
110 | auto &Ref = *getIntPtr(); |
111 | auto &CRef = *getCIntPtr(); |
112 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &CRef' can be declared as 'const auto &CRef' |
113 | // CHECK-FIXES: {{^}} const auto &CRef = *getCIntPtr(); |
114 | const auto &ConstCRef = *getCIntPtr(); |
115 | |
116 | if (auto X = getCIntPtr()) { |
117 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'auto X' can be declared as 'const auto *X' |
118 | // CHECK-FIXES: {{^}} if (const auto *X = getCIntPtr()) { |
119 | } |
120 | } |
121 | |
122 | void macroTest() { |
123 | #define _AUTO auto |
124 | #define _CONST const |
125 | _AUTO AutoMACROPtr = getIntPtr(); |
126 | const _AUTO ConstAutoMacroPtr = getIntPtr(); |
127 | _CONST _AUTO ConstMacroAutoMacroPtr = getIntPtr(); |
128 | _CONST auto ConstMacroAutoPtr = getIntPtr(); |
129 | #undef _AUTO |
130 | #undef _CONST |
131 | } |
132 | |
133 | namespace std { |
134 | template <typename T> |
135 | class vector { // dummy impl |
136 | T _data[1]; |
137 | |
138 | public: |
139 | T *begin() { return _data; } |
140 | const T *begin() const { return _data; } |
141 | T *end() { return &_data[1]; } |
142 | const T *end() const { return &_data[1]; } |
143 | }; |
144 | } // namespace std |
145 | |
146 | void change(int &); |
147 | void observe(const int &); |
148 | |
149 | void loopRef(std::vector<int> &Mutate, const std::vector<int> &Constant) { |
150 | for (auto &Data : Mutate) { |
151 | change(Data); |
152 | } |
153 | for (auto &Data : Constant) { |
154 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto &Data' can be declared as 'const auto &Data' |
155 | // CHECK-FIXES: {{^}} for (const auto &Data : Constant) { |
156 | observe(Data); |
157 | } |
158 | } |
159 | |
160 | void loopPtr(const std::vector<int *> &Mutate, const std::vector<const int *> &Constant) { |
161 | for (auto Data : Mutate) { |
162 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'auto *Data' |
163 | // CHECK-FIXES: {{^}} for (auto *Data : Mutate) { |
164 | change(*Data); |
165 | } |
166 | for (auto Data : Constant) { |
167 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'const auto *Data' |
168 | // CHECK-FIXES: {{^}} for (const auto *Data : Constant) { |
169 | observe(*Data); |
170 | } |
171 | } |
172 | |
173 | template <typename T> |
174 | void tempLoopPtr(std::vector<T *> &MutateTemplate, std::vector<const T *> &ConstantTemplate) { |
175 | for (auto Data : MutateTemplate) { |
176 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'auto *Data' |
177 | // CHECK-FIXES: {{^}} for (auto *Data : MutateTemplate) { |
178 | change(*Data); |
179 | } |
180 | //FixMe |
181 | for (auto Data : ConstantTemplate) { |
182 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'const auto *Data' |
183 | // CHECK-FIXES: {{^}} for (const auto *Data : ConstantTemplate) { |
184 | observe(*Data); |
185 | } |
186 | } |
187 | |
188 | template <typename T> |
189 | class TemplateLoopPtr { |
190 | public: |
191 | void operator()(const std::vector<T *> &MClassTemplate, const std::vector<const T *> &CClassTemplate) { |
192 | for (auto Data : MClassTemplate) { |
193 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'auto Data' can be declared as 'auto *Data' |
194 | // CHECK-FIXES: {{^}} for (auto *Data : MClassTemplate) { |
195 | change(*Data); |
196 | } |
197 | //FixMe |
198 | for (auto Data : CClassTemplate) { |
199 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'auto Data' can be declared as 'const auto *Data' |
200 | // CHECK-FIXES: {{^}} for (const auto *Data : CClassTemplate) { |
201 | observe(*Data); |
202 | } |
203 | } |
204 | }; |
205 | |
206 | void bar() { |
207 | std::vector<int> Vec; |
208 | std::vector<int *> PtrVec; |
209 | std::vector<const int *> CPtrVec; |
210 | loopRef(Mutate&: Vec, Constant: Vec); |
211 | loopPtr(Mutate: PtrVec, Constant: CPtrVec); |
212 | tempLoopPtr(MutateTemplate&: PtrVec, ConstantTemplate&: CPtrVec); |
213 | TemplateLoopPtr<int>()(PtrVec, CPtrVec); |
214 | } |
215 | |
216 | typedef int *(*functionRetPtr)(); |
217 | typedef int (*functionRetVal)(); |
218 | |
219 | functionRetPtr getPtrFunction(); |
220 | functionRetVal getValFunction(); |
221 | |
222 | void baz() { |
223 | auto MyFunctionPtr = getPtrFunction(); |
224 | // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionPtr' can be declared as 'auto *MyFunctionPtr' |
225 | // CHECK-FIXES-NOT: {{^}} auto *MyFunctionPtr = getPtrFunction(); |
226 | auto MyFunctionVal = getValFunction(); |
227 | // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionVal' can be declared as 'auto *MyFunctionVal' |
228 | // CHECK-FIXES-NOT: {{^}} auto *MyFunctionVal = getValFunction(); |
229 | |
230 | auto LambdaTest = [] { return 0; }; |
231 | // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto LambdaTest' can be declared as 'auto *LambdaTest' |
232 | // CHECK-FIXES-NOT: {{^}} auto *LambdaTest = [] { return 0; }; |
233 | |
234 | auto LambdaTest2 = +[] { return 0; }; |
235 | // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto LambdaTest2' can be declared as 'auto *LambdaTest2' |
236 | // CHECK-FIXES-NOT: {{^}} auto *LambdaTest2 = +[] { return 0; }; |
237 | |
238 | auto MyFunctionRef = *getPtrFunction(); |
239 | // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionRef' can be declared as 'auto *MyFunctionRef' |
240 | // CHECK-FIXES-NOT: {{^}} auto *MyFunctionRef = *getPtrFunction(); |
241 | |
242 | auto &MyFunctionRef2 = *getPtrFunction(); |
243 | } |
244 | |
245 | namespace std { |
246 | |
247 | template<typename T, int N> |
248 | struct array { |
249 | typedef T value_type; |
250 | |
251 | typedef value_type* iterator; |
252 | typedef value_type* Iterator; |
253 | using using_iterator = T*; |
254 | typedef const value_type* const_iterator; |
255 | typedef const value_type* constIterator; |
256 | |
257 | struct Ignored2 {}; |
258 | using NotIgnored2 = Ignored2; |
259 | |
260 | iterator begin() { return nullptr; } |
261 | const_iterator begin() const { return nullptr; } |
262 | iterator end() { return nullptr; } |
263 | const_iterator end() const { return nullptr; } |
264 | }; |
265 | |
266 | struct Iterator {}; |
267 | |
268 | struct Ignored2 {}; // should not be ignored |
269 | |
270 | } // namespace std |
271 | |
272 | typedef std::Iterator iterator; |
273 | |
274 | namespace my { |
275 | namespace ns { |
276 | |
277 | struct Ignored1 {}; |
278 | |
279 | using NotIgnored1 = Ignored1; |
280 | typedef Ignored1 NotIgnored2; |
281 | |
282 | } // namespace ns |
283 | |
284 | struct Ignored1 {}; // should not be ignored |
285 | |
286 | } // namespace my |
287 | |
288 | typedef int *MyIgnoredPtr; |
289 | MyIgnoredPtr getIgnoredPtr(); |
290 | |
291 | void ignored_types() { |
292 | auto ignored_ptr = getIgnoredPtr(); |
293 | // CHECK-MESSAGES-NOT: warning: 'auto ignored_ptr' can be declared as 'auto *ignored_ptr' |
294 | // CHECK-FIXES-NOT: auto *ignored_ptr = getIgnoredPtr(); |
295 | |
296 | std::array<int, 4> arr; |
297 | std::array<int, 4> carr; |
298 | |
299 | auto it1 = arr.begin(); |
300 | // CHECK-MESSAGES-NOT: warning: 'auto it' can be declared as 'auto *it' |
301 | // CHECK-FIXES-NOT: auto *it = vec.it_begin(); |
302 | |
303 | auto it2 = carr.begin(); |
304 | // CHECK-MESSAGES-NOT: warning: 'auto it2' can be declared as 'auto *it2' |
305 | // CHECK-FIXES-NOT: auto *it2 = carr.begin(); |
306 | |
307 | auto it3 = std::array<int, 4>::iterator{}; |
308 | // CHECK-MESSAGES-NOT: warning: 'auto it3' can be declared as 'auto *it3' |
309 | // CHECK-FIXES-NOT: auto *it3 = std::array<int, 4>::iterator{}; |
310 | |
311 | auto it4 = std::array<int, 4>::Iterator{}; |
312 | // CHECK-MESSAGES-NOT: warning: 'auto it4' can be declared as 'auto *it4' |
313 | // CHECK-FIXES-NOT: auto *it4 = std::array<int, 4>::Iterator{}; |
314 | |
315 | auto it5 = std::array<int, 4>::using_iterator{}; |
316 | // CHECK-MESSAGES-NOT: warning: 'auto it5' can be declared as 'auto *it5' |
317 | // CHECK-FIXES-NOT: auto *it5 = std::array<int, 4>::using_iterator{}; |
318 | |
319 | auto it6 = std::array<int, 4>::const_iterator{}; |
320 | // CHECK-MESSAGES-NOT: warning: 'auto it6' can be declared as 'auto *it6' |
321 | // CHECK-FIXES-NOT: auto *it6 = std::array<int, 4>::const_iterator{}; |
322 | |
323 | auto it7 = std::array<int, 4>::constIterator{}; |
324 | // CHECK-MESSAGES-NOT: warning: 'auto it7' can be declared as 'auto *it7' |
325 | // CHECK-FIXES-NOT: auto *it7 = std::array<int, 4>::constIterator{}; |
326 | |
327 | auto it8 = new std::Iterator(); |
328 | // CHECK-MESSAGES-NOT: warning: 'auto it8' can be declared as 'auto *it8' |
329 | // CHECK-FIXES-NOT: auto *it8 = new std::Iterator(); |
330 | |
331 | auto it9 = new iterator(); |
332 | // CHECK-MESSAGES-NOT: warning: 'auto it9' can be declared as 'auto *it9' |
333 | // CHECK-FIXES-NOT: auto *it9 = new iterator(); |
334 | |
335 | auto arr_ignored2 = new std::array<int, 4>::Ignored2(); |
336 | // CHECK-MESSAGES-NOT: warning: 'auto arr_ignored2' can be declared as 'auto *arr_ignored2' |
337 | // CHECK-FIXES-NOT: auto *arr_ignored2 = new std::array<int, 4>::Ignored2(); |
338 | |
339 | auto arr_not_ignored2 = new std::array<int, 4>::NotIgnored2(); |
340 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto arr_not_ignored2' can be declared as 'auto *arr_not_ignored2' |
341 | // CHECK-FIXES: auto *arr_not_ignored2 = new std::array<int, 4>::NotIgnored2(); |
342 | |
343 | auto not_ignored2 = new std::Ignored2(); |
344 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not_ignored2' can be declared as 'auto *not_ignored2' |
345 | // CHECK-FIXES: auto *not_ignored2 = new std::Ignored2(); |
346 | |
347 | auto ignored1 = new my::ns::Ignored1(); |
348 | // CHECK-MESSAGES-NOT: warning: 'auto ignored1' can be declared as 'auto *ignored1' |
349 | // CHECK-FIXES-NOT: auto *ignored1 = new my::ns::Ignored1(); |
350 | |
351 | auto not_ignored1 = new my::ns::NotIgnored1(); |
352 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not_ignored1' can be declared as 'auto *not_ignored1' |
353 | // CHECK-FIXES: auto *not_ignored1 = new my::ns::NotIgnored1(); |
354 | |
355 | auto not2_ignored1 = new my::ns::NotIgnored2(); |
356 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not2_ignored1' can be declared as 'auto *not2_ignored1' |
357 | // CHECK-FIXES: auto *not2_ignored1 = new my::ns::NotIgnored2(); |
358 | |
359 | auto not3_ignored1 = new my::Ignored1(); |
360 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not3_ignored1' can be declared as 'auto *not3_ignored1' |
361 | // CHECK-FIXES: auto *not3_ignored1 = new my::Ignored1(); |
362 | } |
363 | |
364 | template <typename T> |
365 | void ignored_types_template(std::array<T, 4> arr, const std::array<T, 4>& carr) { |
366 | auto it1 = arr.begin(); |
367 | // CHECK-MESSAGES-NOT: warning: 'auto it' can be declared as 'auto *it' |
368 | // CHECK-FIXES-NOT: auto *it = arr.it_begin(); |
369 | |
370 | auto it2 = carr.begin(); |
371 | // CHECK-MESSAGES-NOT: warning: 'auto it2' can be declared as 'auto *it2' |
372 | // CHECK-FIXES-NOT: auto *it2 = carr.begin(); |
373 | |
374 | for (auto Data : arr) { |
375 | // CHECK-MESSAGES-NOT: warning: 'auto Data' can be declared as 'auto *Data' |
376 | // CHECK-FIXES-NOT: {{^}} for (auto *Data : MClassTemplate) { |
377 | change(*Data); |
378 | } |
379 | |
380 | for (auto Data : carr) { |
381 | // CHECK-MESSAGES-NOT: warning: 'auto Data' can be declared as 'const auto *Data' |
382 | // CHECK-FIXES-NOT: {{^}} for (const auto *Data : MClassTemplate) { |
383 | change(*Data); |
384 | } |
385 | } |
386 | |