[clang-tools-extra] 01c1156 - [clang-tidy] Add IgnoreTypes option to modernize-use-nullptr
Piotr Zegar via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 10 05:52:04 PDT 2023
Author: Piotr Zegar
Date: 2023-09-10T12:22:53Z
New Revision: 01c11569fc67b2a00403f64695fff6d2b4e78fe5
URL: https://github.com/llvm/llvm-project/commit/01c11569fc67b2a00403f64695fff6d2b4e78fe5
DIFF: https://github.com/llvm/llvm-project/commit/01c11569fc67b2a00403f64695fff6d2b4e78fe5.diff
LOG: [clang-tidy] Add IgnoreTypes option to modernize-use-nullptr
New option added and configured in a way, so types
related to std::strong_ordering would be ignored.
Fixes: #63478
Reviewed By: ccotter
Differential Revision: https://reviews.llvm.org/D158928
Added:
Modified:
clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
clang-tools-extra/clang-tidy/utils/Matchers.cpp
clang-tools-extra/clang-tidy/utils/Matchers.h
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
index efffc0c80fed8d1..6a003a347badacf 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "UseNullptrCheck.h"
+#include "../utils/Matchers.h"
+#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -33,11 +35,13 @@ AST_MATCHER(Type, sugaredNullptrType) {
/// to null within.
/// Finding sequences of explicit casts is necessary so that an entire sequence
/// can be replaced instead of just the inner-most implicit cast.
-StatementMatcher makeCastSequenceMatcher() {
- StatementMatcher ImplicitCastToNull = implicitCastExpr(
+StatementMatcher makeCastSequenceMatcher(llvm::ArrayRef<StringRef> NameList) {
+ auto ImplicitCastToNull = implicitCastExpr(
anyOf(hasCastKind(CK_NullToPointer), hasCastKind(CK_NullToMemberPointer)),
unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType()))),
- unless(hasSourceExpression(hasType(sugaredNullptrType()))));
+ unless(hasSourceExpression(hasType(sugaredNullptrType()))),
+ unless(hasImplicitDestinationType(
+ qualType(matchers::matchesAnyListedTypeName(NameList)))));
auto IsOrHasDescendant = [](auto InnerMatcher) {
return anyOf(InnerMatcher, hasDescendant(InnerMatcher));
@@ -477,16 +481,21 @@ class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
- NullMacrosStr(Options.get("NullMacros", "NULL")) {
+ NullMacrosStr(Options.get("NullMacros", "NULL")),
+ IgnoredTypes(utils::options::parseStringList(Options.get(
+ "IgnoredTypes",
+ "std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec"))) {
StringRef(NullMacrosStr).split(NullMacros, ",");
}
void UseNullptrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "NullMacros", NullMacrosStr);
+ Options.store(Opts, "IgnoredTypes",
+ utils::options::serializeStringList(IgnoredTypes));
}
void UseNullptrCheck::registerMatchers(MatchFinder *Finder) {
- Finder->addMatcher(makeCastSequenceMatcher(), this);
+ Finder->addMatcher(makeCastSequenceMatcher(IgnoredTypes), this);
}
void UseNullptrCheck::check(const MatchFinder::MatchResult &Result) {
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
index a8d2a8c0667bbdf..6c32a4edb4ff96e 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/UseNullptrCheck.h
@@ -28,6 +28,7 @@ class UseNullptrCheck : public ClangTidyCheck {
private:
const StringRef NullMacrosStr;
SmallVector<StringRef, 1> NullMacros;
+ std::vector<StringRef> IgnoredTypes;
};
} // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.cpp b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
index 440038e36d76437..7e89cae1c3316e4 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.cpp
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
@@ -17,4 +17,32 @@ bool NotIdenticalStatementsPredicate::operator()(
Nodes.getNodeAs<Stmt>(ID), *Context);
}
+MatchesAnyListedTypeNameMatcher::MatchesAnyListedTypeNameMatcher(
+ llvm::ArrayRef<StringRef> NameList)
+ : NameMatchers(NameList.begin(), NameList.end()) {}
+
+MatchesAnyListedTypeNameMatcher::~MatchesAnyListedTypeNameMatcher() = default;
+
+bool MatchesAnyListedTypeNameMatcher::matches(
+ const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder,
+ ast_matchers::internal::BoundNodesTreeBuilder *Builder) const {
+
+ if (NameMatchers.empty())
+ return false;
+
+ PrintingPolicy PrintingPolicyWithSuppressedTag(
+ Finder->getASTContext().getLangOpts());
+ PrintingPolicyWithSuppressedTag.PrintCanonicalTypes = true;
+ PrintingPolicyWithSuppressedTag.SuppressElaboration = true;
+ PrintingPolicyWithSuppressedTag.SuppressScope = false;
+ PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
+ PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true;
+ std::string TypeName =
+ Node.getUnqualifiedType().getAsString(PrintingPolicyWithSuppressedTag);
+
+ return llvm::any_of(NameMatchers, [&TypeName](const llvm::Regex &NM) {
+ return NM.isValid() && NM.match(TypeName);
+ });
+}
+
} // namespace clang::tidy::matchers
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.h b/clang-tools-extra/clang-tidy/utils/Matchers.h
index cbb187899a4b79a..386ea738fbba508 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.h
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.h
@@ -158,6 +158,28 @@ AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID) {
return Builder->removeBindings(Predicate);
}
+// A matcher implementation that matches a list of type name regular expressions
+// against a QualType.
+class MatchesAnyListedTypeNameMatcher
+ : public ast_matchers::internal::MatcherInterface<QualType> {
+public:
+ explicit MatchesAnyListedTypeNameMatcher(llvm::ArrayRef<StringRef> NameList);
+ ~MatchesAnyListedTypeNameMatcher() override;
+ bool matches(
+ const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder,
+ ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override;
+
+private:
+ std::vector<llvm::Regex> NameMatchers;
+};
+
+// Returns a matcher that matches QualType against a list of provided regular.
+inline ::clang::ast_matchers::internal::Matcher<QualType>
+matchesAnyListedTypeName(llvm::ArrayRef<StringRef> NameList) {
+ return ::clang::ast_matchers::internal::makeMatcher(
+ new MatchesAnyListedTypeNameMatcher(NameList));
+}
+
} // namespace clang::tidy::matchers
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 998e763d792af6b..c1a36ac0f92a96a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -227,7 +227,7 @@ Changes in existing checks
`DeduplicateFindings` to output one finding per symbol occurrence.
- Improved :doc:`misc-include-cleaner
- <clang-tidy/checks/misc/include-cleaner>` check to avoid fixes insert
+ <clang-tidy/checks/misc/include-cleaner>` check to avoid fixes insert
same include header multiple times.
- Improved :doc:`misc-redundant-expression
@@ -242,6 +242,10 @@ Changes in existing checks
<clang-tidy/checks/modernize/use-equals-delete>` check to ignore
false-positives when special member function is actually used or implicit.
+- Improved :doc:`modernize-use-nullptr
+ <clang-tidy/checks/modernize/use-nullptr>` check by adding option
+ `IgnoredTypes` that can be used to exclude some pointer types.
+
- Improved :doc:`modernize-use-std-print
<clang-tidy/checks/modernize/use-std-print>` check to accurately generate
fixes for reordering arguments.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
index ffb1cb78dffe060..5e1ba858adf3a9c 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-nullptr.rst
@@ -39,6 +39,12 @@ transforms to:
Options
-------
+.. option:: IgnoredTypes
+
+ Semicolon-separated list of regular expressions to match pointer types for
+ which implicit casts will be ignored. Default value:
+ `std::_CmpUnspecifiedParam::;^std::__cmp_cat::__unspec`.
+
.. option:: NullMacros
Comma-separated list of macro names that will be transformed along with
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
index be59d4ed1d05698..5bc5b79b5524e2c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nullptr-cxx20.cpp
@@ -1,35 +1,51 @@
-// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t -- -- -DGCC
+// RUN: %check_clang_tidy -std=c++20 %s modernize-use-nullptr %t -- -- -DCLANG
namespace std {
class strong_ordering;
// Mock how STD defined unspecified parameters for the operators below.
+#ifdef CLANG
struct _CmpUnspecifiedParam {
consteval
_CmpUnspecifiedParam(int _CmpUnspecifiedParam::*) noexcept {}
};
+#define UNSPECIFIED_TYPE _CmpUnspecifiedParam
+#endif
+
+#ifdef GCC
+namespace __cmp_cat {
+ struct __unspec {
+ constexpr __unspec(__unspec*) noexcept { }
+ };
+}
+
+#define UNSPECIFIED_TYPE __cmp_cat::__unspec
+#endif
+
struct strong_ordering {
signed char value;
friend constexpr bool operator==(strong_ordering v,
- _CmpUnspecifiedParam) noexcept {
+ UNSPECIFIED_TYPE) noexcept {
return v.value == 0;
}
friend constexpr bool operator<(strong_ordering v,
- _CmpUnspecifiedParam) noexcept {
+ UNSPECIFIED_TYPE) noexcept {
return v.value < 0;
}
friend constexpr bool operator>(strong_ordering v,
- _CmpUnspecifiedParam) noexcept {
+ UNSPECIFIED_TYPE) noexcept {
return v.value > 0;
}
friend constexpr bool operator>=(strong_ordering v,
- _CmpUnspecifiedParam) noexcept {
+ UNSPECIFIED_TYPE) noexcept {
return v.value >= 0;
}
static const strong_ordering equal, greater, less;
};
+
constexpr strong_ordering strong_ordering::equal = {0};
constexpr strong_ordering strong_ordering::greater = {1};
constexpr strong_ordering strong_ordering::less = {-1};
@@ -59,6 +75,13 @@ void test_cxx_rewritten_binary_ops() {
// CHECK-FIXES: result = (a1 > ((a1 > (ptr == nullptr ? a1 : a2)) ? a1 : a2));
}
+void testValidZero() {
+ A a1, a2;
+ auto result = a1 <=> a2;
+ if (result < 0) {}
+ // CHECK-FIXES: if (result < 0) {}
+}
+
template<class T1, class T2>
struct P {
T1 x1;
More information about the cfe-commits
mailing list