[clang-tools-extra] [clang-tidy] Add flag to specify an alternative to std::forward (PR #138755)

Dimitrije Dobrota via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 30 11:04:09 PDT 2025


https://github.com/DimitrijeDobrota updated https://github.com/llvm/llvm-project/pull/138755

>From b6d3a401284022bca317079154764c80b18dcbdd Mon Sep 17 00:00:00 2001
From: Dimitrije Dobrota <mail at dimitrijedobrota.com>
Date: Tue, 6 May 2025 22:18:43 +0200
Subject: [PATCH 1/4] Add flag to specify an alternative to std::forward

Since std::forward is nothing more than a cast, part of STL and not the
language itself, it's easy to provide a custom implementation if one
wishes not to include the entirety of <utility>.

Added flag (ForwardFunction) provides a way to continue using this
essential check even with the custom implementation of forwarding.
---
 .../cppcoreguidelines/MissingStdForwardCheck.cpp      | 11 ++++++++++-
 .../cppcoreguidelines/MissingStdForwardCheck.h        |  7 +++++--
 clang-tools-extra/docs/ReleaseNotes.rst               |  4 ++++
 .../checks/cppcoreguidelines/missing-std-forward.rst  |  8 ++++++++
 4 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
index cf299609e646d..268b51f76a2c3 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
@@ -120,7 +120,7 @@ void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
                           equalsBoundNode("param"), equalsBoundNode("var")))))),
                 CapturedInLambda)),
       callee(unresolvedLookupExpr(hasAnyDeclaration(
-          namedDecl(hasUnderlyingDecl(hasName("::std::forward")))))),
+          namedDecl(hasUnderlyingDecl(hasName(ForwardFunction)))))),
 
       unless(anyOf(hasAncestor(typeLoc()),
                    hasAncestor(expr(hasUnevaluatedContext())))));
@@ -149,4 +149,13 @@ void MissingStdForwardCheck::check(const MatchFinder::MatchResult &Result) {
       << Param;
 }
 
+MissingStdForwardCheck::MissingStdForwardCheck(StringRef Name,
+                                               ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      ForwardFunction(Options.get("ForwardFunction", "::std::forward")) {}
+
+void MissingStdForwardCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "ForwardFunction", ForwardFunction);
+}
+
 } // namespace clang::tidy::cppcoreguidelines
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
index 5995ad588855e..f833b8031f8af 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
@@ -21,8 +21,7 @@ namespace clang::tidy::cppcoreguidelines {
 /// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/missing-std-forward.html
 class MissingStdForwardCheck : public ClangTidyCheck {
 public:
-  MissingStdForwardCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+  MissingStdForwardCheck(StringRef Name, ClangTidyContext *Context);
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
@@ -31,6 +30,10 @@ class MissingStdForwardCheck : public ClangTidyCheck {
   std::optional<TraversalKind> getCheckTraversalKind() const override {
     return TK_IgnoreUnlessSpelledInSource;
   }
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const StringRef ForwardFunction;
 };
 
 } // namespace clang::tidy::cppcoreguidelines
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index e50d40b76e8c4..fdcc51af8ead7 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -327,6 +327,10 @@ Changes in existing checks
   <clang-tidy/checks/readability/redundant-smartptr-get>` check by fixing
   some false positives involving smart pointers to arrays.
 
+- Improved :doc:`cppcoreguidelines-missing-std-forward
+  <clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check by adding a
+  flag to specify the function used for forwarding instead of ``std::forward``.
+
 Removed checks
 ^^^^^^^^^^^^^^
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
index 0c311b59a5d5a..d6cc1e53f768d 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
@@ -35,6 +35,14 @@ Example:
     f(1, 2); // Incorrect - may not invoke the desired qualified function operator
   }
 
+Options
+-------
+
+.. option:: ForwardFunction
+
+   Specify the function used for forwarding.
+   Default is `::std::forward`.
+
 This check implements `F.19
 <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-forward>`_
 from the C++ Core Guidelines.

>From af8f4e51678c0c7129e2c3f61d526c89ba237faa Mon Sep 17 00:00:00 2001
From: Dimitrije Dobrota <mail at dimitrijedobrota.com>
Date: Mon, 30 Jun 2025 00:00:17 +0200
Subject: [PATCH 2/4] Fix alphabetical order in ReleaseNotes

---
 clang-tools-extra/docs/ReleaseNotes.rst | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index fdcc51af8ead7..1e2672b388a35 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -212,6 +212,10 @@ Changes in existing checks
   <clang-tidy/checks/cppcoreguidelines/avoid-goto>` check by adding the option
   `IgnoreMacros` to ignore ``goto`` labels defined in macros.
 
+- Improved :doc:`cppcoreguidelines-missing-std-forward
+  <clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check by adding a
+  flag to specify the function used for forwarding instead of ``std::forward``.
+
 - Improved :doc:`cppcoreguidelines-special-member-functions
   <clang-tidy/checks/cppcoreguidelines/special-member-functions>` check by
   adding the option `IgnoreMacros` to ignore classes defined in macros.
@@ -327,10 +331,6 @@ Changes in existing checks
   <clang-tidy/checks/readability/redundant-smartptr-get>` check by fixing
   some false positives involving smart pointers to arrays.
 
-- Improved :doc:`cppcoreguidelines-missing-std-forward
-  <clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check by adding a
-  flag to specify the function used for forwarding instead of ``std::forward``.
-
 Removed checks
 ^^^^^^^^^^^^^^
 

>From 65fd4abf0cf6be5dd75c394a487cd1133d0aa5c1 Mon Sep 17 00:00:00 2001
From: Dimitrije Dobrota <mail at dimitrijedobrota.com>
Date: Sun, 29 Jun 2025 23:51:36 +0200
Subject: [PATCH 3/4] Add test

---
 .../missing-std-forward-custom-function.cpp   | 42 +++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-custom-function.cpp

diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-custom-function.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-custom-function.cpp
new file mode 100644
index 0000000000000..7ccac1a10015f
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-custom-function.cpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy -std=c++14 %s cppcoreguidelines-missing-std-forward %t -- \
+// RUN: -config="{CheckOptions: {cppcoreguidelines-missing-std-forward.ForwardFunction: custom_forward}}" -- -fno-delayed-template-parsing
+
+// NOLINTBEGIN
+namespace std {
+
+template <typename T> struct remove_reference      { using type = T; };
+template <typename T> struct remove_reference<T&>  { using type = T; };
+template <typename T> struct remove_reference<T&&> { using type = T; };
+
+template <typename T> using remove_reference_t = typename remove_reference<T>::type;
+
+template <typename T> constexpr T &&forward(remove_reference_t<T> &t) noexcept;
+template <typename T> constexpr T &&forward(remove_reference_t<T> &&t) noexcept;
+template <typename T> constexpr remove_reference_t<T> &&move(T &&x);
+
+} // namespace std
+// NOLINTEND
+
+template<class T>
+constexpr decltype(auto) custom_forward(std::remove_reference_t<T>& tmp) noexcept
+{
+  return static_cast<T&&>(tmp);
+}
+
+template<class T>
+constexpr decltype(auto) custom_forward(std::remove_reference_t<T>&& tmp) noexcept
+{
+  return static_cast<T&&>(tmp);
+}
+
+template<class T>
+void forward_with_std(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+
+  T other{std::forward<T>(t)};
+}
+
+template<class T>
+void move_with_custom(T&& t) {
+  T other{custom_forward<T>(t)};
+}

>From 62bbfbb901c4b8150406012c817654513affae12 Mon Sep 17 00:00:00 2001
From: Dimitrije Dobrota <mail at dimitrijedobrota.com>
Date: Mon, 30 Jun 2025 20:04:00 +0200
Subject: [PATCH 4/4] Update
 clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst

Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
 .../checks/cppcoreguidelines/missing-std-forward.rst           | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
index d6cc1e53f768d..62e38fcd3b9dc 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst
@@ -40,8 +40,7 @@ Options
 
 .. option:: ForwardFunction
 
-   Specify the function used for forwarding.
-   Default is `::std::forward`.
+   Specify the function used for forwarding. Default is `::std::forward`.
 
 This check implements `F.19
 <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-forward>`_



More information about the cfe-commits mailing list