| 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 | |