https://github.com/vbvictor updated 
https://github.com/llvm/llvm-project/pull/136571

>From 95be4b44cc7ad8f9b30b020ba3083a5267a65202 Mon Sep 17 00:00:00 2001
From: Victor Baranov <bar.victor.2...@gmail.com>
Date: Mon, 21 Apr 2025 18:29:28 +0300
Subject: [PATCH 1/2] added Allowed types to qualified-auto

---
 .../readability/QualifiedAutoCheck.cpp        |  27 +++-
 .../readability/QualifiedAutoCheck.h          |   5 +-
 clang-tools-extra/docs/ReleaseNotes.rst       |   4 +
 .../checks/readability/qualified-auto.rst     |  14 ++
 .../checkers/readability/qualified-auto.cpp   | 147 +++++++++++++++++-
 5 files changed, 188 insertions(+), 9 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
index e843c593a92cc..00999ee8310c1 100644
--- a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.cpp
@@ -8,6 +8,8 @@
 
 #include "QualifiedAutoCheck.h"
 #include "../utils/LexerUtils.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "llvm/ADT/SmallVector.h"
 #include <optional>
@@ -100,8 +102,17 @@ bool isAutoPointerConst(QualType QType) {
 
 } // namespace
 
+QualifiedAutoCheck::QualifiedAutoCheck(StringRef Name,
+                                       ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      AddConstToQualified(Options.get("AddConstToQualified", true)),
+      AllowedTypes(
+          utils::options::parseStringList(Options.get("AllowedTypes", ""))) {}
+
 void QualifiedAutoCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "AddConstToQualified", AddConstToQualified);
+  Options.store(Opts, "AllowedTypes",
+                utils::options::serializeStringList(AllowedTypes));
 }
 
 void QualifiedAutoCheck::registerMatchers(MatchFinder *Finder) {
@@ -124,20 +135,26 @@ void QualifiedAutoCheck::registerMatchers(MatchFinder 
*Finder) {
 
   auto IsBoundToType = refersToType(equalsBoundNode("type"));
   auto UnlessFunctionType = 
unless(hasUnqualifiedDesugaredType(functionType()));
-  auto IsAutoDeducedToPointer = [](const auto &...InnerMatchers) {
+  auto IsAutoDeducedToPointer = [](const std::vector<StringRef> &AllowedTypes,
+                                   const auto &...InnerMatchers) {
     return autoType(hasDeducedType(
-        hasUnqualifiedDesugaredType(pointerType(pointee(InnerMatchers...)))));
+        hasUnqualifiedDesugaredType(pointerType(pointee(InnerMatchers...))),
+        unless(hasUnqualifiedType(
+            matchers::matchesAnyListedTypeName(AllowedTypes, false))),
+        unless(pointerType(pointee(hasUnqualifiedType(
+            matchers::matchesAnyListedTypeName(AllowedTypes, false)))))));
   };
 
   Finder->addMatcher(
-      
ExplicitSingleVarDecl(hasType(IsAutoDeducedToPointer(UnlessFunctionType)),
-                            "auto"),
+      ExplicitSingleVarDecl(
+          hasType(IsAutoDeducedToPointer(AllowedTypes, UnlessFunctionType)),
+          "auto"),
       this);
 
   Finder->addMatcher(
       ExplicitSingleVarDeclInTemplate(
           allOf(hasType(IsAutoDeducedToPointer(
-                    hasUnqualifiedType(qualType().bind("type")),
+                    AllowedTypes, hasUnqualifiedType(qualType().bind("type")),
                     UnlessFunctionType)),
                 anyOf(hasAncestor(
                           functionDecl(hasAnyTemplateArgument(IsBoundToType))),
diff --git a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h 
b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h
index dae9add48e3d7..187a4cd6ee614 100644
--- a/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/QualifiedAutoCheck.h
@@ -21,9 +21,7 @@ namespace clang::tidy::readability {
 /// 
http://clang.llvm.org/extra/clang-tidy/checks/readability/qualified-auto.html
 class QualifiedAutoCheck : public ClangTidyCheck {
 public:
-  QualifiedAutoCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context),
-        AddConstToQualified(Options.get("AddConstToQualified", true)) {}
+  QualifiedAutoCheck(StringRef Name, ClangTidyContext *Context);
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
     return LangOpts.CPlusPlus11;
   }
@@ -33,6 +31,7 @@ class QualifiedAutoCheck : public ClangTidyCheck {
 
 private:
   const bool AddConstToQualified;
+  const std::vector<StringRef> AllowedTypes;
 };
 
 } // namespace clang::tidy::readability
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 761c1d3a80359..d3e4530535638 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -204,6 +204,10 @@ Changes in existing checks
   tolerating fix-it breaking compilation when functions is used as pointers
   to avoid matching usage of functions within the current compilation unit.
 
+- Improved :doc:`readability-qualified-auto
+  <clang-tidy/checks/readability/qualified-auto>` check by adding the option
+  `AllowedTypes`, that excludes specified types from adding qualifiers.
+
 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 9bc2c1295d3ec..efa085719643c 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
@@ -82,3 +82,17 @@ Otherwise it will be transformed into:
    const auto &Foo3 = cast<const int &>(Bar3);
 
 Note in the LLVM alias, the default value is `false`.
+
+.. option:: AllowedTypes
+
+  A semicolon-separated list of names of types to ignore when ``auto`` is
+  deduced to that type or a pointer to that type. Note that this distinguishes
+  type aliases from the original type, so specifying e.g. ``my_int`` will not
+  suppress reports about ``int`` even if it is defined as a ``typedef`` alias
+  for ``int``. Regular expressions are accepted, e.g. ``[Rr]ef(erence)?$``
+  matches every type with suffix ``Ref``, ``ref``, ``Reference`` and
+  ``reference``. If a name in the list contains the sequence `::` it is matched
+  against the qualified type name (i.e. ``namespace::Type``), otherwise it is
+  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.
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 6cc794882859f..7c25b853bfa0c 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
@@ -1,4 +1,7 @@
-// RUN: %check_clang_tidy %s readability-qualified-auto %t
+// 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: }}'
 
 namespace typedefs {
 typedef int *MyPtr;
@@ -238,3 +241,145 @@ void baz() {
 
   auto &MyFunctionRef2 = *getPtrFunction();
 }
+
+namespace std {
+
+template<typename T, int N>
+struct array {
+  typedef T value_type;
+
+  typedef value_type* iterator;
+  typedef value_type* Iterator;
+  using using_iterator = T*;
+  typedef const value_type* const_iterator;
+  typedef const value_type* constIterator;
+
+  struct Ignored2 {};
+  using NotIgnored2 = Ignored2;
+
+  iterator begin() { return nullptr; }
+  const_iterator begin() const { return nullptr; }
+  iterator end() { return nullptr; }
+  const_iterator end() const { return nullptr; }
+};
+
+struct Iterator {};
+
+struct Ignored2 {}; // should not be ignored
+
+} // namespace std
+
+typedef std::Iterator iterator;
+
+namespace my {
+namespace ns {
+
+struct Ignored1 {};
+
+using NotIgnored1 = Ignored1;
+typedef Ignored1 NotIgnored2;
+
+} // namespace ns
+
+struct Ignored1 {}; // should not be ignored
+
+} // namespace my
+
+typedef int *MyIgnoredPtr;
+MyIgnoredPtr getIgnoredPtr();
+
+void ignored_types() {
+  auto ignored_ptr = getIgnoredPtr();
+  // CHECK-MESSAGES-NOT: warning: 'auto ignored_ptr' can be declared as 'auto 
*ignored_ptr'
+  // CHECK-FIXES-NOT: auto *ignored_ptr = getIgnoredPtr();
+
+  std::array<int, 4> arr;
+  std::array<int, 4> carr;
+
+  auto it1 = arr.begin();
+  // CHECK-MESSAGES-NOT: warning: 'auto it' can be declared as 'auto *it'
+  // CHECK-FIXES-NOT: auto *it = vec.it_begin();
+  
+  auto it2 = carr.begin();
+  // CHECK-MESSAGES-NOT: warning: 'auto it2' can be declared as 'auto *it2'
+  // CHECK-FIXES-NOT: auto *it2 = carr.begin();
+
+  auto it3 = std::array<int, 4>::iterator{};
+  // CHECK-MESSAGES-NOT: warning: 'auto it3' can be declared as 'auto *it3'
+  // CHECK-FIXES-NOT: auto *it3 = std::array<int, 4>::iterator{};
+
+  auto it4 = std::array<int, 4>::Iterator{};
+  // CHECK-MESSAGES-NOT: warning: 'auto it4' can be declared as 'auto *it4'
+  // CHECK-FIXES-NOT: auto *it4 = std::array<int, 4>::Iterator{};
+
+  auto it5 = std::array<int, 4>::using_iterator{};
+  // CHECK-MESSAGES-NOT: warning: 'auto it5' can be declared as 'auto *it5'
+  // CHECK-FIXES-NOT: auto *it5 = std::array<int, 4>::using_iterator{};
+
+  auto it6 = std::array<int, 4>::const_iterator{};
+  // CHECK-MESSAGES-NOT: warning: 'auto it6' can be declared as 'auto *it6'
+  // CHECK-FIXES-NOT: auto *it6 = std::array<int, 4>::const_iterator{};
+
+  auto it7 = std::array<int, 4>::constIterator{};
+  // CHECK-MESSAGES-NOT: warning: 'auto it7' can be declared as 'auto *it7'
+  // CHECK-FIXES-NOT: auto *it7 = std::array<int, 4>::constIterator{};
+
+  auto it8 = new std::Iterator();
+  // CHECK-MESSAGES-NOT: warning: 'auto it8' can be declared as 'auto *it8'
+  // CHECK-FIXES-NOT: auto *it8 = new std::Iterator();
+
+  auto it9 = new iterator();
+  // CHECK-MESSAGES-NOT: warning: 'auto it9' can be declared as 'auto *it9'
+  // CHECK-FIXES-NOT: auto *it9 = new iterator();
+
+  auto arr_ignored2 = new std::array<int, 4>::Ignored2();
+  // CHECK-MESSAGES-NOT: warning: 'auto arr_ignored2' can be declared as 'auto 
*arr_ignored2'
+  // CHECK-FIXES-NOT: auto *arr_ignored2 = new std::array<int, 4>::Ignored2();
+
+  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();
+
+  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();
+
+  auto ignored1 = new my::ns::Ignored1();
+  // CHECK-MESSAGES-NOT: warning: 'auto ignored1' can be declared as 'auto 
*ignored1'
+  // CHECK-FIXES-NOT: auto *ignored1 = new my::ns::Ignored1();
+
+  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();
+
+  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();
+
+  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();
+}
+
+template <typename T>
+void ignored_types_template(std::array<T, 4> arr, const std::array<T, 4>& 
carr) {
+  auto it1 = arr.begin();
+  // CHECK-MESSAGES-NOT: warning: 'auto it' can be declared as 'auto *it'
+  // CHECK-FIXES-NOT: auto *it = arr.it_begin();
+  
+  auto it2 = carr.begin();
+  // CHECK-MESSAGES-NOT: warning: 'auto it2' can be declared as 'auto *it2'
+  // CHECK-FIXES-NOT: auto *it2 = carr.begin();
+
+  for (auto Data : arr) {
+    // CHECK-MESSAGES-NOT: warning: 'auto Data' can be declared as 'auto *Data'
+    // CHECK-FIXES-NOT: {{^}}    for (auto *Data : MClassTemplate) {
+    change(*Data);
+  }
+
+  for (auto Data : carr) {
+    // CHECK-MESSAGES-NOT: warning: 'auto Data' can be declared as 'const auto 
*Data'
+    // CHECK-FIXES-NOT: {{^}}    for (const auto *Data : MClassTemplate) {
+    change(*Data);
+  }
+}
\ No newline at end of file

>From 39d3987bc459c483da87b1e25763952ce96c4736 Mon Sep 17 00:00:00 2001
From: Victor Baranov <bar.victor.2...@gmail.com>
Date: Mon, 21 Apr 2025 18:32:17 +0300
Subject: [PATCH 2/2] added newline to end of test file

---
 .../test/clang-tidy/checkers/readability/qualified-auto.cpp     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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 7c25b853bfa0c..77afdcafef9dd 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
@@ -382,4 +382,4 @@ void ignored_types_template(std::array<T, 4> arr, const 
std::array<T, 4>& carr)
     // CHECK-FIXES-NOT: {{^}}    for (const auto *Data : MClassTemplate) {
     change(*Data);
   }
-}
\ No newline at end of file
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to