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; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits