https://github.com/JuanBesa updated https://github.com/llvm/llvm-project/pull/147060
>From d176aa31c18a4293be9b49da671270d349a323b7 Mon Sep 17 00:00:00 2001 From: juanbesa <juanb...@devvm33299.lla0.facebook.com> Date: Thu, 26 Jun 2025 07:42:55 -0700 Subject: [PATCH 1/9] Copied over everything --- .../readability/QualifiedAutoCheck.cpp | 19 +- .../readability/QualifiedAutoCheck.h | 1 + .../readability/qualified-auto-opaque.cpp | 239 ++++++++++++++++++ 3 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto-opaque.cpp diff --git a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp index 91a08b9d8de69..d5d2163f83679 100644 --- a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp @@ -106,12 +106,14 @@ QualifiedAutoCheck::QualifiedAutoCheck(StringRef Name, : ClangTidyCheck(Name, Context), AddConstToQualified(Options.get("AddConstToQualified", true)), AllowedTypes( - utils::options::parseStringList(Options.get("AllowedTypes", ""))) {} + utils::options::parseStringList(Options.get("AllowedTypes", ""))), + RespectOpaqueTypes(Options.get("RespectOpaqueTypes", false)) {} void QualifiedAutoCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "AddConstToQualified", AddConstToQualified); Options.store(Opts, "AllowedTypes", utils::options::serializeStringList(AllowedTypes)); + Options.store(Opts, "RespectOpaqueTypes", RespectOpaqueTypes); } void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) { @@ -174,6 +176,21 @@ void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) { void QualifiedAutoCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *Var = Result.Nodes.getNodeAs<VarDecl>("auto")) { + if (RespectOpaqueTypes) { + auto DeducedType = + Var->getType()->getContainedAutoType()->getDeducedType(); + + // Remove one sugar if the type if part of a template + if (llvm::isa<SubstTemplateTypeParmType>(DeducedType)) { + DeducedType = + DeducedType->getLocallyUnqualifiedSingleStepDesugaredType(); + } + + if (!isa<PointerType>(DeducedType)) { + return; + } + } + SourceRange TypeSpecifier; if (std::optional<SourceRange> TypeSpec = getTypeSpecifierLocation(Var, Result)) { diff --git a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h index 187a4cd6ee614..f88f7e6489538 100644 --- a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h +++ b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h @@ -32,6 +32,7 @@ class QualifiedAutoCheck : public ClangTidyCheck { private: const bool AddConstToQualified; const std::vector<StringRef> AllowedTypes; + const bool RespectOpaqueTypes; }; } // namespace clang::tidy::readability diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto-opaque.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto-opaque.cpp new file mode 100644 index 0000000000000..a9a63663919f7 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto-opaque.cpp @@ -0,0 +1,239 @@ +// RUN: %check_clang_tidy %s readability-qualified-auto %t -- -config="{CheckOptions: [\ +// RUN: {key: readability-qualified-auto.RespectOpaqueTypes, value: true}]}" -- + +namespace typedefs { +typedef int *MyPtr; +typedef int &MyRef; +typedef const int *CMyPtr; +typedef const int &CMyRef; + +MyPtr getPtr(); +MyPtr* getPtrPtr(); +MyRef getRef(); +CMyPtr getCPtr(); +CMyPtr* getCPtrPtr(); +CMyRef getCRef(); +int* getIntPtr(); + +void foo() { + auto TdNakedPtr = getPtr(); + auto TdNakedPtrPtr = getPtrPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedPtrPtr' can be declared as 'auto *TdNakedPtrPtr' + // CHECK-FIXES: {{^}} auto *TdNakedPtrPtr = getPtrPtr(); + auto intPtr = getIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto intPtr' can be declared as 'auto *intPtr' + // CHECK-FIXES: {{^}} auto *intPtr = getIntPtr(); + auto TdNakedRefDeref = getRef(); + auto TdNakedCPtr = getCPtr(); + auto TdNakedCPtrPtr = getCPtrPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedCPtrPtr' can be declared as 'auto *TdNakedCPtrPtr' + // CHECK-FIXES: {{^}} auto *TdNakedCPtrPtr = getCPtrPtr(); + auto &TdNakedCRef = getCRef(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &TdNakedCRef' can be declared as 'const auto &TdNakedCRef' + // CHECK-FIXES: {{^}} const auto &TdNakedCRef = getCRef(); + auto TdNakedCRefDeref = getCRef(); +} + +}; // namespace typedefs + +namespace usings { +using MyPtr = int *; +using MyRef = int &; +using CMyPtr = const int *; +using CMyRef = const int &; + +MyPtr getPtr(); +MyPtr* getPtrPtr(); +MyRef getRef(); +CMyPtr getCPtr(); +CMyRef getCRef(); + +void foo() { + auto UNakedPtr = getPtr(); + auto UNakedPtrPtr = getPtrPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto UNakedPtrPtr' can be declared as 'auto *UNakedPtrPtr' + // CHECK-FIXES: {{^}} auto *UNakedPtrPtr = getPtrPtr(); + auto &UNakedRef = getRef(); + auto UNakedRefDeref = getRef(); + auto UNakedCPtr = getCPtr(); + auto &UNakedCRef = getCRef(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &UNakedCRef' can be declared as 'const auto &UNakedCRef' + // CHECK-FIXES: {{^}} const auto &UNakedCRef = getCRef(); + auto UNakedCRefDeref = getCRef(); +} + +}; // namespace usings + +int *getIntPtr(); +const int *getCIntPtr(); + +void foo() { + // make sure check disregards named types + int *TypedPtr = getIntPtr(); + const int *TypedConstPtr = getCIntPtr(); + int &TypedRef = *getIntPtr(); + const int &TypedConstRef = *getCIntPtr(); + + auto NakedPtr = getIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedPtr' can be declared as 'auto *NakedPtr' + // CHECK-FIXES: {{^}} auto *NakedPtr = getIntPtr(); + auto NakedCPtr = getCIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedCPtr' can be declared as 'const auto *NakedCPtr' + // CHECK-FIXES: {{^}} const auto *NakedCPtr = getCIntPtr(); + + const auto ConstPtr = getIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'const auto ConstPtr' can be declared as 'auto *const ConstPtr' + // CHECK-FIXES: {{^}} auto *const ConstPtr = getIntPtr(); + const auto ConstCPtr = getCIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'const auto ConstCPtr' can be declared as 'const auto *const ConstCPtr' + // CHECK-FIXES: {{^}} const auto *const ConstCPtr = getCIntPtr(); + + volatile auto VolatilePtr = getIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'volatile auto VolatilePtr' can be declared as 'auto *volatile VolatilePtr' + // CHECK-FIXES: {{^}} auto *volatile VolatilePtr = getIntPtr(); + volatile auto VolatileCPtr = getCIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'volatile auto VolatileCPtr' can be declared as 'const auto *volatile VolatileCPtr' + // CHECK-FIXES: {{^}} const auto *volatile VolatileCPtr = getCIntPtr(); + + auto *QualPtr = getIntPtr(); + auto *QualCPtr = getCIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *QualCPtr' can be declared as 'const auto *QualCPtr' + // CHECK-FIXES: {{^}} const auto *QualCPtr = getCIntPtr(); + auto *const ConstantQualCPtr = getCIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *const ConstantQualCPtr' can be declared as 'const auto *const ConstantQualCPtr' + // CHECK-FIXES: {{^}} const auto *const ConstantQualCPtr = getCIntPtr(); + auto *volatile VolatileQualCPtr = getCIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *volatile VolatileQualCPtr' can be declared as 'const auto *volatile VolatileQualCPtr' + // CHECK-FIXES: {{^}} const auto *volatile VolatileQualCPtr = getCIntPtr(); + const auto *ConstQualCPtr = getCIntPtr(); + + auto &Ref = *getIntPtr(); + auto &CRef = *getCIntPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &CRef' can be declared as 'const auto &CRef' + // CHECK-FIXES: {{^}} const auto &CRef = *getCIntPtr(); + const auto &ConstCRef = *getCIntPtr(); + + if (auto X = getCIntPtr()) { + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'auto X' can be declared as 'const auto *X' + // CHECK-FIXES: {{^}} if (const auto *X = getCIntPtr()) { + } +} + +namespace std { + +template <typename T> +class vector { // dummy impl + T _data[1]; + +public: + T *begin() { return _data; } + const T *begin() const { return _data; } + T *end() { return &_data[1]; } + const T *end() const { return &_data[1]; } +}; + + +} // namespace std + +namespace loops { + +void change(int &); +void observe(const int &); + +void loopRef(std::vector<int> &Mutate, const std::vector<int> &Constant) { + for (auto &Data : Mutate) { + change(Data); + } + for (auto &Data : Constant) { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto &Data' can be declared as 'const auto &Data' + // CHECK-FIXES: {{^}} for (const auto &Data : Constant) { + observe(Data); + } +} + +void loopPtr(const std::vector<int *> &Mutate, const std::vector<const int *> &Constant) { + for (auto Data : Mutate) { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'auto *Data' + // CHECK-FIXES: {{^}} for (auto *Data : Mutate) { + change(*Data); + } + for (auto Data : Constant) { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'const auto *Data' + // CHECK-FIXES: {{^}} for (const auto *Data : Constant) { + observe(*Data); + } +} + +template <typename T> +void tempLoopPtr(std::vector<T *> &MutateTemplate, std::vector<const T *> &ConstantTemplate) { + for (auto Data : MutateTemplate) { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'auto *Data' + // CHECK-FIXES: {{^}} for (auto *Data : MutateTemplate) { + change(*Data); + } + //FixMe + for (auto Data : ConstantTemplate) { + // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'const auto *Data' + // CHECK-FIXES: {{^}} for (const auto *Data : ConstantTemplate) { + observe(*Data); + } +} + +template <typename T> +class TemplateLoopPtr { +public: + void operator()(const std::vector<T *> &MClassTemplate, const std::vector<const T *> &CClassTemplate) { + for (auto Data : MClassTemplate) { + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'auto Data' can be declared as 'auto *Data' + // CHECK-FIXES: {{^}} for (auto *Data : MClassTemplate) { + change(*Data); + } + //FixMe + for (auto Data : CClassTemplate) { + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'auto Data' can be declared as 'const auto *Data' + // CHECK-FIXES: {{^}} for (const auto *Data : CClassTemplate) { + observe(*Data); + } + } +}; + +void bar() { + std::vector<int> Vec; + std::vector<int *> PtrVec; + std::vector<const int *> CPtrVec; + loopRef(Vec, Vec); + loopPtr(PtrVec, CPtrVec); + tempLoopPtr(PtrVec, CPtrVec); + TemplateLoopPtr<int>()(PtrVec, CPtrVec); +} + +typedef int *(*functionRetPtr)(); +typedef int (*functionRetVal)(); + +functionRetPtr getPtrFunction(); +functionRetVal getValFunction(); + +void baz() { + auto MyFunctionPtr = getPtrFunction(); + // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionPtr' can be declared as 'auto *MyFunctionPtr' + // CHECK-FIXES-NOT: {{^}} auto *MyFunctionPtr = getPtrFunction(); + auto MyFunctionVal = getValFunction(); + // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionVal' can be declared as 'auto *MyFunctionVal' + // CHECK-FIXES-NOT: {{^}} auto *MyFunctionVal = getValFunction(); + + auto LambdaTest = [] { return 0; }; + // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto LambdaTest' can be declared as 'auto *LambdaTest' + // CHECK-FIXES-NOT: {{^}} auto *LambdaTest = [] { return 0; }; + + auto LambdaTest2 = +[] { return 0; }; + // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto LambdaTest2' can be declared as 'auto *LambdaTest2' + // CHECK-FIXES-NOT: {{^}} auto *LambdaTest2 = +[] { return 0; }; + + auto MyFunctionRef = *getPtrFunction(); + // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionRef' can be declared as 'auto *MyFunctionRef' + // CHECK-FIXES-NOT: {{^}} auto *MyFunctionRef = *getPtrFunction(); + + auto &MyFunctionRef2 = *getPtrFunction(); +} + +} // namespace loops >From 0931979c820db83f05590e38475f4033399e3100 Mon Sep 17 00:00:00 2001 From: juanbesa <juanb...@devvm33299.lla0.facebook.com> Date: Mon, 7 Jul 2025 02:52:02 -0700 Subject: [PATCH 2/9] Respond to reviews: Specify auto type, add to release notes and check docs --- .../readability/QualifiedAutoCheck.cpp | 2 +- clang-tools-extra/docs/ReleaseNotes.rst | 7 ++++++- .../checks/readability/qualified-auto.rst | 20 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp index d5d2163f83679..30198bfaceede 100644 --- a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp @@ -177,7 +177,7 @@ void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) { void QualifiedAutoCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *Var = Result.Nodes.getNodeAs<VarDecl>("auto")) { if (RespectOpaqueTypes) { - auto DeducedType = + QualType DeducedType = Var->getType()->getContainedAutoType()->getDeducedType(); // Remove one sugar if the type if part of a template diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index f8f183e9de1cc..9078cd3f9c0fe 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -215,7 +215,7 @@ Changes in existing checks - Improved :doc:`cppcoreguidelines-missing-std-forward <clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check by adding a flag to specify the function used for forwarding instead of ``std::forward``. - + - Improved :doc:`cppcoreguidelines-pro-bounds-pointer-arithmetic <clang-tidy/checks/cppcoreguidelines/pro-bounds-pointer-arithmetic>` check by fixing false positives when calling indexing operators that do not perform @@ -342,6 +342,11 @@ Changes in existing checks <clang-tidy/checks/readability/redundant-smartptr-get>` check by fixing some false positives involving smart pointers to arrays. +- Improved :doc:`readability-qualified-auto + <clang-tidy/checks/readability/qualified-auto>` check by adding the option + `RespectOpaqueTypes`, that allows not looking at underlying types of + type aliases. + Removed checks ^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst index efa085719643c..744e5dbb42194 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst @@ -96,3 +96,23 @@ Note in the LLVM alias, the default value is `false`. matched against only the type name (i.e. ``Type``). E.g. to suppress reports for ``std::array`` iterators use `std::array<.*>::(const_)?iterator` string. The default is an empty string. + +.. option:: RespectOpaqueTypes + + If set to `false` the check will use the canonical type to determine the type that ``auto`` is deduced to. + If set to `true` the check will not look beyond the first type alias. Default value is `false`. + +.. code-block:: c++ + + using IntPtr = int*; + IntPtr foo(); + + auto bar = foo(); + +If RespectOpaqueTypes is set to `false`, it will be transformed into: + +.. code-block:: c++ + + auto *bar = foo(); + +Otherwise no changes will occur. >From 9dfd9bb927f20de9035e43bbef2a0b289da50520 Mon Sep 17 00:00:00 2001 From: juanbesa <juanb...@devvm33299.lla0.facebook.com> Date: Tue, 8 Jul 2025 08:29:45 -0700 Subject: [PATCH 3/9] Move the option logic into the Matcher --- .../readability/QualifiedAutoCheck.cpp | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp index 30198bfaceede..9738a07ba3523 100644 --- a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp @@ -136,14 +136,27 @@ void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) { auto IsBoundToType = refersToType(equalsBoundNode("type")); auto UnlessFunctionType = unless(hasUnqualifiedDesugaredType(functionType())); - auto IsAutoDeducedToPointer = [](const std::vector<StringRef> &AllowedTypes, - const auto &...InnerMatchers) { - return autoType(hasDeducedType( - hasUnqualifiedDesugaredType(pointerType(pointee(InnerMatchers...))), - unless(hasUnqualifiedType( - matchers::matchesAnyListedTypeName(AllowedTypes, false))), - unless(pointerType(pointee(hasUnqualifiedType( - matchers::matchesAnyListedTypeName(AllowedTypes, false))))))); + auto RespectOpaqueTypes = this->RespectOpaqueTypes; + auto IsAutoDeducedToPointer = [&RespectOpaqueTypes]( + const std::vector<StringRef> &AllowedTypes, + const auto &...InnerMatchers) { + if (!RespectOpaqueTypes) { + return autoType(hasDeducedType( + hasUnqualifiedDesugaredType(pointerType(pointee(InnerMatchers...))), + unless(hasUnqualifiedType( + matchers::matchesAnyListedTypeName(AllowedTypes, false))), + unless(pointerType(pointee(hasUnqualifiedType( + matchers::matchesAnyListedTypeName(AllowedTypes, false))))))); + } else { + return autoType(hasDeducedType( + anyOf(qualType(pointerType(pointee(InnerMatchers...))), + qualType(substTemplateTypeParmType(hasReplacementType( + pointerType(pointee(InnerMatchers...)))))), + unless(hasUnqualifiedType( + matchers::matchesAnyListedTypeName(AllowedTypes, false))), + unless(pointerType(pointee(hasUnqualifiedType( + matchers::matchesAnyListedTypeName(AllowedTypes, false))))))); + } }; Finder->addMatcher( @@ -176,21 +189,6 @@ void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) { void QualifiedAutoCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *Var = Result.Nodes.getNodeAs<VarDecl>("auto")) { - if (RespectOpaqueTypes) { - QualType DeducedType = - Var->getType()->getContainedAutoType()->getDeducedType(); - - // Remove one sugar if the type if part of a template - if (llvm::isa<SubstTemplateTypeParmType>(DeducedType)) { - DeducedType = - DeducedType->getLocallyUnqualifiedSingleStepDesugaredType(); - } - - if (!isa<PointerType>(DeducedType)) { - return; - } - } - SourceRange TypeSpecifier; if (std::optional<SourceRange> TypeSpec = getTypeSpecifierLocation(Var, Result)) { >From 5d0a2f5ff0552de5403ae0c215ad68c83051e8f9 Mon Sep 17 00:00:00 2001 From: juanbesa <juanb...@devvm33299.lla0.facebook.com> Date: Tue, 8 Jul 2025 08:35:53 -0700 Subject: [PATCH 4/9] Merged release notes --- clang-tools-extra/docs/ReleaseNotes.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index ee2bf747dfd83..bc07e8ebd07fc 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -338,6 +338,8 @@ Changes in existing checks - Improved :doc:`readability-qualified-auto <clang-tidy/checks/readability/qualified-auto>` check by adding the option `AllowedTypes`, that excludes specified types from adding qualifiers. + Added the option `RespectOpaqueTypes`, that allows not looking at underlying + types of type aliases. - Improved :doc:`readability-redundant-inline-specifier <clang-tidy/checks/readability/redundant-inline-specifier>` check by fixing @@ -347,10 +349,6 @@ Changes in existing checks <clang-tidy/checks/readability/redundant-smartptr-get>` check by fixing some false positives involving smart pointers to arrays. -- Improved :doc:`readability-qualified-auto - <clang-tidy/checks/readability/qualified-auto>` check by adding the option - `RespectOpaqueTypes`, that allows not looking at underlying types of - type aliases. Removed checks ^^^^^^^^^^^^^^ >From fd43946b83b367e2b0763258e293a17a8f007caf Mon Sep 17 00:00:00 2001 From: juanbesa <juanb...@devvm33299.lla0.facebook.com> Date: Tue, 8 Jul 2025 08:37:17 -0700 Subject: [PATCH 5/9] Extra space in release notes --- clang-tools-extra/docs/ReleaseNotes.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index bc07e8ebd07fc..7a692bfd49439 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -349,7 +349,6 @@ Changes in existing checks <clang-tidy/checks/readability/redundant-smartptr-get>` check by fixing some false positives involving smart pointers to arrays. - Removed checks ^^^^^^^^^^^^^^ >From 61bf13e410478eaeb439558c0bfb3792a06f9a9e Mon Sep 17 00:00:00 2001 From: Kazu Hirata <k...@google.com> Date: Fri, 4 Jul 2025 07:56:35 -0700 Subject: [PATCH 6/9] [llvm] Use llvm::fill (NFC) (#146988) We can pass a range to llvm::fill. >From 0e287e0b525ab64c6ba447e50a80806c93d3f0da Mon Sep 17 00:00:00 2001 From: juanbesa <juanb...@devvm33299.lla0.facebook.com> Date: Mon, 14 Jul 2025 08:13:13 -0700 Subject: [PATCH 7/9] Merge the tests --- .../readability/qualified-auto-opaque.cpp | 239 ------------------ .../checkers/readability/qualified-auto.cpp | 83 ++++++ 2 files changed, 83 insertions(+), 239 deletions(-) delete mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto-opaque.cpp diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto-opaque.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto-opaque.cpp deleted file mode 100644 index a9a63663919f7..0000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto-opaque.cpp +++ /dev/null @@ -1,239 +0,0 @@ -// RUN: %check_clang_tidy %s readability-qualified-auto %t -- -config="{CheckOptions: [\ -// RUN: {key: readability-qualified-auto.RespectOpaqueTypes, value: true}]}" -- - -namespace typedefs { -typedef int *MyPtr; -typedef int &MyRef; -typedef const int *CMyPtr; -typedef const int &CMyRef; - -MyPtr getPtr(); -MyPtr* getPtrPtr(); -MyRef getRef(); -CMyPtr getCPtr(); -CMyPtr* getCPtrPtr(); -CMyRef getCRef(); -int* getIntPtr(); - -void foo() { - auto TdNakedPtr = getPtr(); - auto TdNakedPtrPtr = getPtrPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedPtrPtr' can be declared as 'auto *TdNakedPtrPtr' - // CHECK-FIXES: {{^}} auto *TdNakedPtrPtr = getPtrPtr(); - auto intPtr = getIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto intPtr' can be declared as 'auto *intPtr' - // CHECK-FIXES: {{^}} auto *intPtr = getIntPtr(); - auto TdNakedRefDeref = getRef(); - auto TdNakedCPtr = getCPtr(); - auto TdNakedCPtrPtr = getCPtrPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedCPtrPtr' can be declared as 'auto *TdNakedCPtrPtr' - // CHECK-FIXES: {{^}} auto *TdNakedCPtrPtr = getCPtrPtr(); - auto &TdNakedCRef = getCRef(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &TdNakedCRef' can be declared as 'const auto &TdNakedCRef' - // CHECK-FIXES: {{^}} const auto &TdNakedCRef = getCRef(); - auto TdNakedCRefDeref = getCRef(); -} - -}; // namespace typedefs - -namespace usings { -using MyPtr = int *; -using MyRef = int &; -using CMyPtr = const int *; -using CMyRef = const int &; - -MyPtr getPtr(); -MyPtr* getPtrPtr(); -MyRef getRef(); -CMyPtr getCPtr(); -CMyRef getCRef(); - -void foo() { - auto UNakedPtr = getPtr(); - auto UNakedPtrPtr = getPtrPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto UNakedPtrPtr' can be declared as 'auto *UNakedPtrPtr' - // CHECK-FIXES: {{^}} auto *UNakedPtrPtr = getPtrPtr(); - auto &UNakedRef = getRef(); - auto UNakedRefDeref = getRef(); - auto UNakedCPtr = getCPtr(); - auto &UNakedCRef = getCRef(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &UNakedCRef' can be declared as 'const auto &UNakedCRef' - // CHECK-FIXES: {{^}} const auto &UNakedCRef = getCRef(); - auto UNakedCRefDeref = getCRef(); -} - -}; // namespace usings - -int *getIntPtr(); -const int *getCIntPtr(); - -void foo() { - // make sure check disregards named types - int *TypedPtr = getIntPtr(); - const int *TypedConstPtr = getCIntPtr(); - int &TypedRef = *getIntPtr(); - const int &TypedConstRef = *getCIntPtr(); - - auto NakedPtr = getIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedPtr' can be declared as 'auto *NakedPtr' - // CHECK-FIXES: {{^}} auto *NakedPtr = getIntPtr(); - auto NakedCPtr = getCIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedCPtr' can be declared as 'const auto *NakedCPtr' - // CHECK-FIXES: {{^}} const auto *NakedCPtr = getCIntPtr(); - - const auto ConstPtr = getIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'const auto ConstPtr' can be declared as 'auto *const ConstPtr' - // CHECK-FIXES: {{^}} auto *const ConstPtr = getIntPtr(); - const auto ConstCPtr = getCIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'const auto ConstCPtr' can be declared as 'const auto *const ConstCPtr' - // CHECK-FIXES: {{^}} const auto *const ConstCPtr = getCIntPtr(); - - volatile auto VolatilePtr = getIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'volatile auto VolatilePtr' can be declared as 'auto *volatile VolatilePtr' - // CHECK-FIXES: {{^}} auto *volatile VolatilePtr = getIntPtr(); - volatile auto VolatileCPtr = getCIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'volatile auto VolatileCPtr' can be declared as 'const auto *volatile VolatileCPtr' - // CHECK-FIXES: {{^}} const auto *volatile VolatileCPtr = getCIntPtr(); - - auto *QualPtr = getIntPtr(); - auto *QualCPtr = getCIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *QualCPtr' can be declared as 'const auto *QualCPtr' - // CHECK-FIXES: {{^}} const auto *QualCPtr = getCIntPtr(); - auto *const ConstantQualCPtr = getCIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *const ConstantQualCPtr' can be declared as 'const auto *const ConstantQualCPtr' - // CHECK-FIXES: {{^}} const auto *const ConstantQualCPtr = getCIntPtr(); - auto *volatile VolatileQualCPtr = getCIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *volatile VolatileQualCPtr' can be declared as 'const auto *volatile VolatileQualCPtr' - // CHECK-FIXES: {{^}} const auto *volatile VolatileQualCPtr = getCIntPtr(); - const auto *ConstQualCPtr = getCIntPtr(); - - auto &Ref = *getIntPtr(); - auto &CRef = *getCIntPtr(); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &CRef' can be declared as 'const auto &CRef' - // CHECK-FIXES: {{^}} const auto &CRef = *getCIntPtr(); - const auto &ConstCRef = *getCIntPtr(); - - if (auto X = getCIntPtr()) { - // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'auto X' can be declared as 'const auto *X' - // CHECK-FIXES: {{^}} if (const auto *X = getCIntPtr()) { - } -} - -namespace std { - -template <typename T> -class vector { // dummy impl - T _data[1]; - -public: - T *begin() { return _data; } - const T *begin() const { return _data; } - T *end() { return &_data[1]; } - const T *end() const { return &_data[1]; } -}; - - -} // namespace std - -namespace loops { - -void change(int &); -void observe(const int &); - -void loopRef(std::vector<int> &Mutate, const std::vector<int> &Constant) { - for (auto &Data : Mutate) { - change(Data); - } - for (auto &Data : Constant) { - // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto &Data' can be declared as 'const auto &Data' - // CHECK-FIXES: {{^}} for (const auto &Data : Constant) { - observe(Data); - } -} - -void loopPtr(const std::vector<int *> &Mutate, const std::vector<const int *> &Constant) { - for (auto Data : Mutate) { - // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'auto *Data' - // CHECK-FIXES: {{^}} for (auto *Data : Mutate) { - change(*Data); - } - for (auto Data : Constant) { - // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'const auto *Data' - // CHECK-FIXES: {{^}} for (const auto *Data : Constant) { - observe(*Data); - } -} - -template <typename T> -void tempLoopPtr(std::vector<T *> &MutateTemplate, std::vector<const T *> &ConstantTemplate) { - for (auto Data : MutateTemplate) { - // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'auto *Data' - // CHECK-FIXES: {{^}} for (auto *Data : MutateTemplate) { - change(*Data); - } - //FixMe - for (auto Data : ConstantTemplate) { - // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'const auto *Data' - // CHECK-FIXES: {{^}} for (const auto *Data : ConstantTemplate) { - observe(*Data); - } -} - -template <typename T> -class TemplateLoopPtr { -public: - void operator()(const std::vector<T *> &MClassTemplate, const std::vector<const T *> &CClassTemplate) { - for (auto Data : MClassTemplate) { - // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'auto Data' can be declared as 'auto *Data' - // CHECK-FIXES: {{^}} for (auto *Data : MClassTemplate) { - change(*Data); - } - //FixMe - for (auto Data : CClassTemplate) { - // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'auto Data' can be declared as 'const auto *Data' - // CHECK-FIXES: {{^}} for (const auto *Data : CClassTemplate) { - observe(*Data); - } - } -}; - -void bar() { - std::vector<int> Vec; - std::vector<int *> PtrVec; - std::vector<const int *> CPtrVec; - loopRef(Vec, Vec); - loopPtr(PtrVec, CPtrVec); - tempLoopPtr(PtrVec, CPtrVec); - TemplateLoopPtr<int>()(PtrVec, CPtrVec); -} - -typedef int *(*functionRetPtr)(); -typedef int (*functionRetVal)(); - -functionRetPtr getPtrFunction(); -functionRetVal getValFunction(); - -void baz() { - auto MyFunctionPtr = getPtrFunction(); - // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionPtr' can be declared as 'auto *MyFunctionPtr' - // CHECK-FIXES-NOT: {{^}} auto *MyFunctionPtr = getPtrFunction(); - auto MyFunctionVal = getValFunction(); - // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionVal' can be declared as 'auto *MyFunctionVal' - // CHECK-FIXES-NOT: {{^}} auto *MyFunctionVal = getValFunction(); - - auto LambdaTest = [] { return 0; }; - // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto LambdaTest' can be declared as 'auto *LambdaTest' - // CHECK-FIXES-NOT: {{^}} auto *LambdaTest = [] { return 0; }; - - auto LambdaTest2 = +[] { return 0; }; - // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto LambdaTest2' can be declared as 'auto *LambdaTest2' - // CHECK-FIXES-NOT: {{^}} auto *LambdaTest2 = +[] { return 0; }; - - auto MyFunctionRef = *getPtrFunction(); - // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionRef' can be declared as 'auto *MyFunctionRef' - // CHECK-FIXES-NOT: {{^}} auto *MyFunctionRef = *getPtrFunction(); - - auto &MyFunctionRef2 = *getPtrFunction(); -} - -} // namespace loops diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp index 77afdcafef9dd..7f213eab8c082 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp @@ -2,6 +2,11 @@ // RUN: -config='{CheckOptions: { \ // RUN: readability-qualified-auto.AllowedTypes: "[iI]terator$;my::ns::Ignored1;std::array<.*>::Ignored2;MyIgnoredPtr" \ // RUN: }}' +// RUN: %check_clang_tidy %s readability-qualified-auto %t \ +// RUN: -config='{CheckOptions: { \ +// RUN: readability-qualified-auto.AllowedTypes: "[iI]terator$;my::ns::Ignored1;std::array<.*>::Ignored2;MyIgnoredPtr", \ +// RUN: readability-qualified-auto.RespectOpaqueTypes: true \ +// RUN: }}' -check-suffix=ALIAS -- namespace typedefs { typedef int *MyPtr; @@ -10,22 +15,36 @@ typedef const int *CMyPtr; typedef const int &CMyRef; MyPtr getPtr(); +MyPtr* getPtrPtr(); MyRef getRef(); CMyPtr getCPtr(); +CMyPtr* getCPtrPtr(); CMyRef getCRef(); void foo() { auto TdNakedPtr = getPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedPtr' can be declared as 'auto *TdNakedPtr' // CHECK-FIXES: {{^}} auto *TdNakedPtr = getPtr(); + auto TdNakedPtrPtr = getPtrPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedPtrPtr' can be declared as 'auto *TdNakedPtrPtr' + // CHECK-FIXES: {{^}} auto *TdNakedPtrPtr = getPtrPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto TdNakedPtrPtr' can be declared as 'auto *TdNakedPtrPtr' + // CHECK-FIXES-ALIAS: {{^}} auto *TdNakedPtrPtr = getPtrPtr(); auto &TdNakedRef = getRef(); auto TdNakedRefDeref = getRef(); auto TdNakedCPtr = getCPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedCPtr' can be declared as 'const auto *TdNakedCPtr' // CHECK-FIXES: {{^}} const auto *TdNakedCPtr = getCPtr(); + auto TdNakedCPtrPtr = getCPtrPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto TdNakedCPtrPtr' can be declared as 'auto *TdNakedCPtrPtr' + // CHECK-FIXES: {{^}} auto *TdNakedCPtrPtr = getCPtrPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto TdNakedCPtrPtr' can be declared as 'auto *TdNakedCPtrPtr' + // CHECK-FIXES-ALIAS: {{^}} auto *TdNakedCPtrPtr = getCPtrPtr(); auto &TdNakedCRef = getCRef(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &TdNakedCRef' can be declared as 'const auto &TdNakedCRef' // CHECK-FIXES: {{^}} const auto &TdNakedCRef = getCRef(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto &TdNakedCRef' can be declared as 'const auto &TdNakedCRef' + // CHECK-FIXES-ALIAS: {{^}} const auto &TdNakedCRef = getCRef(); auto TdNakedCRefDeref = getCRef(); } @@ -38,6 +57,7 @@ using CMyPtr = const int *; using CMyRef = const int &; MyPtr getPtr(); +MyPtr* getPtrPtr(); MyRef getRef(); CMyPtr getCPtr(); CMyRef getCRef(); @@ -46,6 +66,11 @@ void foo() { auto UNakedPtr = getPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto UNakedPtr' can be declared as 'auto *UNakedPtr' // CHECK-FIXES: {{^}} auto *UNakedPtr = getPtr(); + auto UNakedPtrPtr = getPtrPtr(); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto UNakedPtrPtr' can be declared as 'auto *UNakedPtrPtr' + // CHECK-FIXES: {{^}} auto *UNakedPtrPtr = getPtrPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto UNakedPtrPtr' can be declared as 'auto *UNakedPtrPtr' + // CHECK-FIXES-ALIAS: {{^}} auto *UNakedPtrPtr = getPtrPtr(); auto &UNakedRef = getRef(); auto UNakedRefDeref = getRef(); auto UNakedCPtr = getCPtr(); @@ -54,6 +79,8 @@ void foo() { auto &UNakedCRef = getCRef(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &UNakedCRef' can be declared as 'const auto &UNakedCRef' // CHECK-FIXES: {{^}} const auto &UNakedCRef = getCRef(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto &UNakedCRef' can be declared as 'const auto &UNakedCRef' + // CHECK-FIXES-ALIAS: {{^}} const auto &UNakedCRef = getCRef(); auto UNakedCRefDeref = getCRef(); } @@ -77,45 +104,67 @@ void foo() { auto NakedPtr = getIntPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedPtr' can be declared as 'auto *NakedPtr' // CHECK-FIXES: {{^}} auto *NakedPtr = getIntPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto NakedPtr' can be declared as 'auto *NakedPtr' + // CHECK-FIXES-ALIAS: {{^}} auto *NakedPtr = getIntPtr(); auto NakedCPtr = getCIntPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto NakedCPtr' can be declared as 'const auto *NakedCPtr' // CHECK-FIXES: {{^}} const auto *NakedCPtr = getCIntPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto NakedCPtr' can be declared as 'const auto *NakedCPtr' + // CHECK-FIXES-ALIAS: {{^}} const auto *NakedCPtr = getCIntPtr(); const auto ConstPtr = getIntPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'const auto ConstPtr' can be declared as 'auto *const ConstPtr' // CHECK-FIXES: {{^}} auto *const ConstPtr = getIntPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'const auto ConstPtr' can be declared as 'auto *const ConstPtr' + // CHECK-FIXES-ALIAS: {{^}} auto *const ConstPtr = getIntPtr(); const auto ConstCPtr = getCIntPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'const auto ConstCPtr' can be declared as 'const auto *const ConstCPtr' // CHECK-FIXES: {{^}} const auto *const ConstCPtr = getCIntPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'const auto ConstCPtr' can be declared as 'const auto *const ConstCPtr' + // CHECK-FIXES-ALIAS: {{^}} const auto *const ConstCPtr = getCIntPtr(); volatile auto VolatilePtr = getIntPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'volatile auto VolatilePtr' can be declared as 'auto *volatile VolatilePtr' // CHECK-FIXES: {{^}} auto *volatile VolatilePtr = getIntPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'volatile auto VolatilePtr' can be declared as 'auto *volatile VolatilePtr' + // CHECK-FIXES-ALIAS: {{^}} auto *volatile VolatilePtr = getIntPtr(); volatile auto VolatileCPtr = getCIntPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'volatile auto VolatileCPtr' can be declared as 'const auto *volatile VolatileCPtr' // CHECK-FIXES: {{^}} const auto *volatile VolatileCPtr = getCIntPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'volatile auto VolatileCPtr' can be declared as 'const auto *volatile VolatileCPtr' + // CHECK-FIXES-ALIAS: {{^}} const auto *volatile VolatileCPtr = getCIntPtr(); auto *QualPtr = getIntPtr(); auto *QualCPtr = getCIntPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *QualCPtr' can be declared as 'const auto *QualCPtr' // CHECK-FIXES: {{^}} const auto *QualCPtr = getCIntPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto *QualCPtr' can be declared as 'const auto *QualCPtr' + // CHECK-FIXES-ALIAS: {{^}} const auto *QualCPtr = getCIntPtr(); auto *const ConstantQualCPtr = getCIntPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *const ConstantQualCPtr' can be declared as 'const auto *const ConstantQualCPtr' // CHECK-FIXES: {{^}} const auto *const ConstantQualCPtr = getCIntPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto *const ConstantQualCPtr' can be declared as 'const auto *const ConstantQualCPtr' + // CHECK-FIXES-ALIAS: {{^}} const auto *const ConstantQualCPtr = getCIntPtr(); auto *volatile VolatileQualCPtr = getCIntPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto *volatile VolatileQualCPtr' can be declared as 'const auto *volatile VolatileQualCPtr' // CHECK-FIXES: {{^}} const auto *volatile VolatileQualCPtr = getCIntPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto *volatile VolatileQualCPtr' can be declared as 'const auto *volatile VolatileQualCPtr' + // CHECK-FIXES-ALIAS: {{^}} const auto *volatile VolatileQualCPtr = getCIntPtr(); const auto *ConstQualCPtr = getCIntPtr(); auto &Ref = *getIntPtr(); auto &CRef = *getCIntPtr(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto &CRef' can be declared as 'const auto &CRef' // CHECK-FIXES: {{^}} const auto &CRef = *getCIntPtr(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto &CRef' can be declared as 'const auto &CRef' + // CHECK-FIXES-ALIAS: {{^}} const auto &CRef = *getCIntPtr(); const auto &ConstCRef = *getCIntPtr(); if (auto X = getCIntPtr()) { // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: 'auto X' can be declared as 'const auto *X' // CHECK-FIXES: {{^}} if (const auto *X = getCIntPtr()) { + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:7: warning: 'auto X' can be declared as 'const auto *X' + // CHECK-FIXES-ALIAS: {{^}} if (const auto *X = getCIntPtr()) { } } @@ -153,6 +202,8 @@ void loopRef(std::vector<int> &Mutate, const std::vector<int> &Constant) { for (auto &Data : Constant) { // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto &Data' can be declared as 'const auto &Data' // CHECK-FIXES: {{^}} for (const auto &Data : Constant) { + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:8: warning: 'auto &Data' can be declared as 'const auto &Data' + // CHECK-FIXES-ALIAS: {{^}} for (const auto &Data : Constant) { observe(Data); } } @@ -161,11 +212,15 @@ void loopPtr(const std::vector<int *> &Mutate, const std::vector<const int *> &C for (auto Data : Mutate) { // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'auto *Data' // CHECK-FIXES: {{^}} for (auto *Data : Mutate) { + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:8: warning: 'auto Data' can be declared as 'auto *Data' + // CHECK-FIXES-ALIAS: {{^}} for (auto *Data : Mutate) { change(*Data); } for (auto Data : Constant) { // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'const auto *Data' // CHECK-FIXES: {{^}} for (const auto *Data : Constant) { + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:8: warning: 'auto Data' can be declared as 'const auto *Data' + // CHECK-FIXES-ALIAS: {{^}} for (const auto *Data : Constant) { observe(*Data); } } @@ -175,12 +230,16 @@ void tempLoopPtr(std::vector<T *> &MutateTemplate, std::vector<const T *> &Const for (auto Data : MutateTemplate) { // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'auto *Data' // CHECK-FIXES: {{^}} for (auto *Data : MutateTemplate) { + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:8: warning: 'auto Data' can be declared as 'auto *Data' + // CHECK-FIXES-ALIAS: {{^}} for (auto *Data : MutateTemplate) { change(*Data); } //FixMe for (auto Data : ConstantTemplate) { // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: 'auto Data' can be declared as 'const auto *Data' // CHECK-FIXES: {{^}} for (const auto *Data : ConstantTemplate) { + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:8: warning: 'auto Data' can be declared as 'const auto *Data' + // CHECK-FIXES-ALIAS: {{^}} for (const auto *Data : ConstantTemplate) { observe(*Data); } } @@ -192,12 +251,16 @@ class TemplateLoopPtr { for (auto Data : MClassTemplate) { // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'auto Data' can be declared as 'auto *Data' // CHECK-FIXES: {{^}} for (auto *Data : MClassTemplate) { + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:10: warning: 'auto Data' can be declared as 'auto *Data' + // CHECK-FIXES-ALIAS: {{^}} for (auto *Data : MClassTemplate) { change(*Data); } //FixMe for (auto Data : CClassTemplate) { // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'auto Data' can be declared as 'const auto *Data' // CHECK-FIXES: {{^}} for (const auto *Data : CClassTemplate) { + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:10: warning: 'auto Data' can be declared as 'const auto *Data' + // CHECK-FIXES-ALIAS: {{^}} for (const auto *Data : CClassTemplate) { observe(*Data); } } @@ -223,21 +286,31 @@ void baz() { auto MyFunctionPtr = getPtrFunction(); // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionPtr' can be declared as 'auto *MyFunctionPtr' // CHECK-FIXES-NOT: {{^}} auto *MyFunctionPtr = getPtrFunction(); + // CHECK-MESSAGES-NOT-ALIAS: :[[@LINE-1]]:3: warning: 'auto MyFunctionPtr' can be declared as 'auto *MyFunctionPtr' + // CHECK-FIXES-NOT-ALIAS: {{^}} auto *MyFunctionPtr = getPtrFunction(); auto MyFunctionVal = getValFunction(); // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionVal' can be declared as 'auto *MyFunctionVal' // CHECK-FIXES-NOT: {{^}} auto *MyFunctionVal = getValFunction(); + // CHECK-MESSAGES-NOT-ALIAS: :[[@LINE-3]]:3: warning: 'auto MyFunctionVal' can be declared as 'auto *MyFunctionVal' + // CHECK-FIXES-NOT-ALIAS: {{^}} auto *MyFunctionVal = getValFunction(); auto LambdaTest = [] { return 0; }; // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto LambdaTest' can be declared as 'auto *LambdaTest' // CHECK-FIXES-NOT: {{^}} auto *LambdaTest = [] { return 0; }; + // CHECK-MESSAGES-NOT-ALIAS: :[[@LINE-3]]:3: warning: 'auto LambdaTest' can be declared as 'auto *LambdaTest' + // CHECK-FIXES-NOT-ALIAS: {{^}} auto *LambdaTest = [] { return 0; }; auto LambdaTest2 = +[] { return 0; }; // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto LambdaTest2' can be declared as 'auto *LambdaTest2' // CHECK-FIXES-NOT: {{^}} auto *LambdaTest2 = +[] { return 0; }; + // CHECK-MESSAGES-NOT-ALIAS: :[[@LINE-3]]:3: warning: 'auto LambdaTest2' can be declared as 'auto *LambdaTest2' + // CHECK-FIXES-NOT-ALIAS: {{^}} auto *LambdaTest2 = +[] { return 0; }; auto MyFunctionRef = *getPtrFunction(); // CHECK-MESSAGES-NOT: :[[@LINE-1]]:3: warning: 'auto MyFunctionRef' can be declared as 'auto *MyFunctionRef' // CHECK-FIXES-NOT: {{^}} auto *MyFunctionRef = *getPtrFunction(); + // CHECK-MESSAGES-NOT-ALIAS: :[[@LINE-3]]:3: warning: 'auto MyFunctionRef' can be declared as 'auto *MyFunctionRef' + // CHECK-FIXES-NOT-ALIAS: {{^}} auto *MyFunctionRef = *getPtrFunction(); auto &MyFunctionRef2 = *getPtrFunction(); } @@ -339,10 +412,14 @@ void ignored_types() { auto arr_not_ignored2 = new std::array<int, 4>::NotIgnored2(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto arr_not_ignored2' can be declared as 'auto *arr_not_ignored2' // CHECK-FIXES: auto *arr_not_ignored2 = new std::array<int, 4>::NotIgnored2(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto arr_not_ignored2' can be declared as 'auto *arr_not_ignored2' + // CHECK-FIXES-ALIAS: auto *arr_not_ignored2 = new std::array<int, 4>::NotIgnored2(); auto not_ignored2 = new std::Ignored2(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not_ignored2' can be declared as 'auto *not_ignored2' // CHECK-FIXES: auto *not_ignored2 = new std::Ignored2(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto not_ignored2' can be declared as 'auto *not_ignored2' + // CHECK-FIXES-ALIAS: auto *not_ignored2 = new std::Ignored2(); auto ignored1 = new my::ns::Ignored1(); // CHECK-MESSAGES-NOT: warning: 'auto ignored1' can be declared as 'auto *ignored1' @@ -351,14 +428,20 @@ void ignored_types() { auto not_ignored1 = new my::ns::NotIgnored1(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not_ignored1' can be declared as 'auto *not_ignored1' // CHECK-FIXES: auto *not_ignored1 = new my::ns::NotIgnored1(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto not_ignored1' can be declared as 'auto *not_ignored1' + // CHECK-FIXES-ALIAS: auto *not_ignored1 = new my::ns::NotIgnored1(); auto not2_ignored1 = new my::ns::NotIgnored2(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not2_ignored1' can be declared as 'auto *not2_ignored1' // CHECK-FIXES: auto *not2_ignored1 = new my::ns::NotIgnored2(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto not2_ignored1' can be declared as 'auto *not2_ignored1' + // CHECK-FIXES-ALIAS: auto *not2_ignored1 = new my::ns::NotIgnored2(); auto not3_ignored1 = new my::Ignored1(); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'auto not3_ignored1' can be declared as 'auto *not3_ignored1' // CHECK-FIXES: auto *not3_ignored1 = new my::Ignored1(); + // CHECK-MESSAGES-ALIAS: :[[@LINE-3]]:3: warning: 'auto not3_ignored1' can be declared as 'auto *not3_ignored1' + // CHECK-FIXES-ALIAS: auto *not3_ignored1 = new my::Ignored1(); } template <typename T> >From 591e57f502eefa5c6e49a3f7e6515db7bf02fbdf Mon Sep 17 00:00:00 2001 From: juanbesa <juanb...@devvm33299.lla0.facebook.com> Date: Mon, 14 Jul 2025 08:36:28 -0700 Subject: [PATCH 8/9] Change the name to IgnoreAliasing --- .../clang-tidy/readability/QualifiedAutoCheck.cpp | 10 +++++----- .../clang-tidy/readability/QualifiedAutoCheck.h | 2 +- .../clang-tidy/checkers/readability/qualified-auto.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp index 9738a07ba3523..92e49a6d73ba5 100644 --- a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp @@ -107,13 +107,13 @@ QualifiedAutoCheck::QualifiedAutoCheck(StringRef Name, AddConstToQualified(Options.get("AddConstToQualified", true)), AllowedTypes( utils::options::parseStringList(Options.get("AllowedTypes", ""))), - RespectOpaqueTypes(Options.get("RespectOpaqueTypes", false)) {} + IgnoreAliasing(Options.get("IgnoreAliasing", true)) {} void QualifiedAutoCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "AddConstToQualified", AddConstToQualified); Options.store(Opts, "AllowedTypes", utils::options::serializeStringList(AllowedTypes)); - Options.store(Opts, "RespectOpaqueTypes", RespectOpaqueTypes); + Options.store(Opts, "IgnoreAliasing", IgnoreAliasing); } void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) { @@ -136,11 +136,11 @@ void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) { auto IsBoundToType = refersToType(equalsBoundNode("type")); auto UnlessFunctionType = unless(hasUnqualifiedDesugaredType(functionType())); - auto RespectOpaqueTypes = this->RespectOpaqueTypes; - auto IsAutoDeducedToPointer = [&RespectOpaqueTypes]( + auto IgnoreAliasing = this->IgnoreAliasing; + auto IsAutoDeducedToPointer = [&IgnoreAliasing]( const std::vector<StringRef> &AllowedTypes, const auto &...InnerMatchers) { - if (!RespectOpaqueTypes) { + if (IgnoreAliasing) { return autoType(hasDeducedType( hasUnqualifiedDesugaredType(pointerType(pointee(InnerMatchers...))), unless(hasUnqualifiedType( diff --git a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h index f88f7e6489538..b5b713f3db6cf 100644 --- a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h +++ b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h @@ -32,7 +32,7 @@ class QualifiedAutoCheck : public ClangTidyCheck { private: const bool AddConstToQualified; const std::vector<StringRef> AllowedTypes; - const bool RespectOpaqueTypes; + const bool IgnoreAliasing; }; } // namespace clang::tidy::readability diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp index 7f213eab8c082..83b7b1dfc4676 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/qualified-auto.cpp @@ -5,7 +5,7 @@ // RUN: %check_clang_tidy %s readability-qualified-auto %t \ // RUN: -config='{CheckOptions: { \ // RUN: readability-qualified-auto.AllowedTypes: "[iI]terator$;my::ns::Ignored1;std::array<.*>::Ignored2;MyIgnoredPtr", \ -// RUN: readability-qualified-auto.RespectOpaqueTypes: true \ +// RUN: readability-qualified-auto.IgnoreAliasing: false \ // RUN: }}' -check-suffix=ALIAS -- namespace typedefs { >From 098cafa306811c872c999f7713bbbfc588d6e448 Mon Sep 17 00:00:00 2001 From: juanbesa <juanb...@devvm33299.lla0.facebook.com> Date: Mon, 14 Jul 2025 10:20:35 -0700 Subject: [PATCH 9/9] Updated the documentation, added note about limitation --- clang-tools-extra/docs/ReleaseNotes.rst | 2 +- .../checks/readability/qualified-auto.rst | 30 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 445ca26965042..d427085881c82 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -374,7 +374,7 @@ Changes in existing checks - Improved :doc:`readability-qualified-auto <clang-tidy/checks/readability/qualified-auto>` check by adding the option `AllowedTypes`, that excludes specified types from adding qualifiers. - Added the option `RespectOpaqueTypes`, that allows not looking at underlying + Added the option `IgnoreAliasing`, that allows not looking at underlying types of type aliases. - Improved :doc:`readability-redundant-inline-specifier diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst index 744e5dbb42194..cbce12a4f5da0 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability/qualified-auto.rst @@ -97,10 +97,10 @@ Note in the LLVM alias, the default value is `false`. for ``std::array`` iterators use `std::array<.*>::(const_)?iterator` string. The default is an empty string. -.. option:: RespectOpaqueTypes +.. option:: IgnoreAliasing - If set to `false` the check will use the canonical type to determine the type that ``auto`` is deduced to. - If set to `true` the check will not look beyond the first type alias. Default value is `false`. + If set to `true` the check will use the canonical type to determine the type that ``auto`` is deduced to. + If set to `false` the check will not look beyond the first type alias. Default value is `true`. .. code-block:: c++ @@ -109,10 +109,32 @@ Note in the LLVM alias, the default value is `false`. auto bar = foo(); -If RespectOpaqueTypes is set to `false`, it will be transformed into: +If IgnoreAliasing is set to `true`, it will be transformed into: .. code-block:: c++ auto *bar = foo(); Otherwise no changes will occur. + +Limitations +----------- + +When IgnoreAliasing is set to `false`, there are cases where Clang has not preserved the sugar +and the canonical type will be used so false positives may occur. +For example: +.. code-block:: c++ + + #include <vector> + + void change(int&); + + using IntPtr = int *; // Relevant typedef + + void loopPtr(const std::vector<IntPtr> &VectorIntPtr) { + + // Currently fails for IgnoreAliasing==false as AST does not have the IntPtr + for (auto Data : VectorIntPtr) { + change(*Data); + } + } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits