[clang-tools-extra] [clang-tidy] added `RespectOpaqueTypes` option to `readability-qualified-auto check` (PR #147060)
Juan Besa via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 15 08:24:17 PDT 2025
https://github.com/JuanBesa updated https://github.com/llvm/llvm-project/pull/147060
>From d176aa31c18a4293be9b49da671270d349a323b7 Mon Sep 17 00:00:00 2001
From: juanbesa <juanbesa at 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 <juanbesa at 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 <juanbesa at 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 <juanbesa at 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 <juanbesa at 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 <kazu at 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 <juanbesa at 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 <juanbesa at 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 <juanbesa at 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);
+ }
+ }
More information about the cfe-commits
mailing list