https://github.com/serge-sans-paille updated https://github.com/llvm/llvm-project/pull/204789
>From fa0465b09df494651c5efc88cd46d82e7f3e03cc Mon Sep 17 00:00:00 2001 From: serge-sans-paille <[email protected]> Date: Fri, 19 Jun 2026 11:29:35 +0200 Subject: [PATCH 1/2] [clang-tidy] Extend `modernize-type-traits` to fold remove_cv_t<remove_reference_t<...>> into remove_cv_ref_t --- .../clang-tidy/modernize/TypeTraitsCheck.cpp | 29 +++++++++++++++++++ clang-tools-extra/docs/ReleaseNotes.rst | 4 +++ .../checks/modernize/type-traits.rst | 3 ++ .../modernize/type-traits-remove-cvref.cpp | 27 +++++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-remove-cvref.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index 0d03006750d07..7c43219375cdb 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -196,6 +196,20 @@ void TypeTraitsCheck::registerMatchers(MatchFinder *Finder) { this); } Finder->addMatcher(typeLoc(isType()).bind(Bind), this); + + // Only register matchers for std::remove_cvref_t simplification in c++20 + // mode. + if (getLangOpts().CPlusPlus20) { + Finder->addMatcher(templateSpecializationTypeLoc( + loc(qualType(hasDeclaration( + namedDecl(hasName("::std::remove_cv_t"))))), + hasTemplateArgumentLoc( + 0, hasTypeLoc(templateSpecializationTypeLoc(loc( + qualType(hasDeclaration(namedDecl(hasName( + "::std::remove_reference_t"))))))))) + .bind("remove_cvref"), + this); + } } static bool isNamedDeclInStdTraitsSet(const NamedDecl *ND, @@ -308,6 +322,21 @@ void TypeTraitsCheck::check(const MatchFinder::MatchResult &Result) { DNTL->getElaboratedKeywordLoc()); return; } + + if (const auto *TSTL = Result.Nodes.getNodeAs<TemplateSpecializationTypeLoc>( + "remove_cvref")) { + auto Diag = diag(TSTL->getBeginLoc(), "use c++20 type alias"); + TemplateSpecializationTypeLoc OuterTL = + TSTL->getArgLoc(0) + .getTypeSourceInfo() + ->getTypeLoc() + .castAs<TemplateSpecializationTypeLoc>(); + Diag << FixItHint::CreateReplacement( + SourceRange(TSTL->getBeginLoc(), OuterTL.getLAngleLoc()), + "std::remove_cvref_t<") + << FixItHint::CreateRemoval(OuterTL.getRAngleLoc()); + return; + } } void TypeTraitsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 64dad5fc29905..92443f2b6e6b7 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -616,6 +616,10 @@ Changes in existing checks <clang-tidy/checks/modernize/return-braced-init-list>` check to apply fix-it when type qualifiers and/or reference modifiers are used with parameters. +- Improved :doc:`modernize-type-traits + <clang-tidy/checks/modernize/type-traits>` check to suggest usage of + ``std::remove_cvref_t`` when applicable. + - Improved :doc:`modernize-use-default-member-init <clang-tidy/checks/modernize/use-default-member-init>` check by fixing a false positive when a constructor initializer refers to a declaration that diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst index fbe2b856c6b85..f5ff8bdf5524e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst @@ -25,6 +25,9 @@ Would be converted into: std::add_const_t<T> std::make_signed_t<unsigned> +Also suggests converting ``std::remove_cv_t<std::remove_reference_t<...>`` into +``std::remove_cvref_t<...>`` when targeting C++20 or above. + Options ------- diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-remove-cvref.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-remove-cvref.cpp new file mode 100644 index 0000000000000..38d3d235d5d4b --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-remove-cvref.cpp @@ -0,0 +1,27 @@ +// RUN: %check_clang_tidy -std=c++20-or-later %s modernize-type-traits %t + +namespace std { +template <class> struct remove_cv { + using type = int; +}; +template <class T> +using remove_cv_t = typename remove_cv<T>::type; // NOLINT + +template <class> struct remove_reference { + using type = int; +}; +template <class T> +using remove_reference_t = typename remove_reference<T>::type; // NOLINT +} + +using foo = std::remove_cv_t<std::remove_reference_t<int>>; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use c++20 type alias +// CHECK-FIXES: using foo = std::remove_cvref_t<int>; + +std::remove_cv_t<std::remove_reference_t<int>> var; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use c++20 type alias +// CHECK-FIXES: std::remove_cvref_t<int> var; + +template<class=std::remove_cv_t<std::remove_reference_t<int>>> struct Foo {}; +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use c++20 type alias +// CHECK-FIXES: template<class=std::remove_cvref_t<int>> struct Foo {}; >From a33eabb5061c557d47c45d158ddd19326baaecdd Mon Sep 17 00:00:00 2001 From: serge-sans-paille <[email protected]> Date: Fri, 19 Jun 2026 11:45:32 +0200 Subject: [PATCH 2/2] fixup! [clang-tidy] Extend `modernize-type-traits` to fold remove_cv_t<remove_reference_t<...>> into remove_cv_ref_t --- .../clang-tidy/modernize/TypeTraitsCheck.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp index 7c43219375cdb..ee9f9015ee55e 100644 --- a/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp @@ -326,11 +326,10 @@ void TypeTraitsCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *TSTL = Result.Nodes.getNodeAs<TemplateSpecializationTypeLoc>( "remove_cvref")) { auto Diag = diag(TSTL->getBeginLoc(), "use c++20 type alias"); - TemplateSpecializationTypeLoc OuterTL = - TSTL->getArgLoc(0) - .getTypeSourceInfo() - ->getTypeLoc() - .castAs<TemplateSpecializationTypeLoc>(); + auto OuterTL = TSTL->getArgLoc(0) + .getTypeSourceInfo() + ->getTypeLoc() + .castAs<TemplateSpecializationTypeLoc>(); Diag << FixItHint::CreateReplacement( SourceRange(TSTL->getBeginLoc(), OuterTL.getLAngleLoc()), "std::remove_cvref_t<") _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
