-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[clang-tide] added AllowedTypes
option to readability-qualified-auto
check
#136571
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
vbvictor
wants to merge
2
commits into
llvm:main
Choose a base branch
from
vbvictor:readability-qualified-auto-ignored-types
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
[clang-tide] added AllowedTypes
option to readability-qualified-auto
check
#136571
vbvictor
wants to merge
2
commits into
llvm:main
from
vbvictor:readability-qualified-auto-ignored-types
+188
−9
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-clang-tidy @llvm/pr-subscribers-clang-tools-extra Author: Baranov Victor (vbvictor) ChangesAdded Fixes #63461. Full diff: https://github.com/llvm/llvm-project/pull/136571.diff 5 Files Affected:
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
|
HerrCai0907
approved these changes
Apr 23, 2025
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Added
AllowedTypes
option toreadability-qualified-auto
checkFixes #63461.