[clang-tools-extra] [clang-tidy] Extend `modernize-type-traits` to fold remove_cv_t<remove_reference_t<...>> into remove_cv_ref_t (PR #204789)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 19 02:35:55 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tidy
Author: serge-sans-paille
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/204789.diff
4 Files Affected:
- (modified) clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp (+29)
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4)
- (modified) clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst (+3)
- (added) clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits-remove-cvref.cpp (+27)
``````````diff
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 {};
``````````
</details>
https://github.com/llvm/llvm-project/pull/204789
More information about the cfe-commits
mailing list