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
6namespace typedefs {
7typedef int *MyPtr;
8typedef int &MyRef;
9typedef const int *CMyPtr;
10typedef const int &CMyRef;
11
12MyPtr getPtr();
13MyRef getRef();
14CMyPtr getCPtr();
15CMyRef getCRef();
16
17void 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
34namespace usings {
35using MyPtr = int *;
36using MyRef = int &;
37using CMyPtr = const int *;
38using CMyRef = const int &;
39
40MyPtr getPtr();
41MyRef getRef();
42CMyPtr getCPtr();
43CMyRef getCRef();
44
45void 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
62int getInt();
63int *getIntPtr();
64const int *getCIntPtr();
65
66void 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
122void 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
133namespace std {
134template <typename T>
135class vector { // dummy impl
136 T _data[1];
137
138public:
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
146void change(int &);
147void observe(const int &);
148
149void 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
160void 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
173template <typename T>
174void 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
188template <typename T>
189class TemplateLoopPtr {
190public:
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
206void 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
216typedef int *(*functionRetPtr)();
217typedef int (*functionRetVal)();
218
219functionRetPtr getPtrFunction();
220functionRetVal getValFunction();
221
222void 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
245namespace std {
246
247template<typename T, int N>
248struct 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
266struct Iterator {};
267
268struct Ignored2 {}; // should not be ignored
269
270} // namespace std
271
272typedef std::Iterator iterator;
273
274namespace my {
275namespace ns {
276
277struct Ignored1 {};
278
279using NotIgnored1 = Ignored1;
280typedef Ignored1 NotIgnored2;
281
282} // namespace ns
283
284struct Ignored1 {}; // should not be ignored
285
286} // namespace my
287
288typedef int *MyIgnoredPtr;
289MyIgnoredPtr getIgnoredPtr();
290
291void 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
364template <typename T>
365void 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

source code of clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp