[clang-tools-extra] [clang-tidy][cppcoreguidelines-missing-std-forward] Do not warn when the parameter is used in a `static_cast<T&>`. (PR #99477)

Clement Courbet via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 28 08:08:21 PDT 2024


https://github.com/legrosbuffle updated https://github.com/llvm/llvm-project/pull/99477

>From d64268021d53e05fb64a4788e99fcd966d7b559a Mon Sep 17 00:00:00 2001
From: Clement Courbet <courbet at google.com>
Date: Thu, 18 Jul 2024 11:47:56 +0000
Subject: [PATCH 1/8] [clang-tidy][cppcoreguidelines-missing-std-forward] Do
 not warn when the parameter is used in a `static_cast`.

This provides a way to inform the check that we're intending to use an
the forwarding reference as a specific reference category

Fixes #99474.
---
 .../MissingStdForwardCheck.cpp                  |  8 ++++++--
 clang-tools-extra/docs/ReleaseNotes.rst         |  5 +++++
 .../cppcoreguidelines/missing-std-forward.rst   |  3 +++
 .../cppcoreguidelines/missing-std-forward.cpp   | 17 +++++++++++++++++
 4 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
index bbb35228ce47fb..726e9fffc628b5 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
@@ -129,6 +129,9 @@ void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
       unless(anyOf(hasAncestor(typeLoc()),
                    hasAncestor(expr(hasUnevaluatedContext())))));
 
+  auto StaticCast = cxxStaticCastExpr(
+      hasSourceExpression(declRefExpr(to(equalsBoundNode("param")))));
+
   Finder->addMatcher(
       parmVarDecl(
           parmVarDecl().bind("param"), hasIdentifier(),
@@ -136,8 +139,9 @@ void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
           hasAncestor(functionDecl().bind("func")),
           hasAncestor(functionDecl(
               isDefinition(), equalsBoundNode("func"), ToParam,
-              unless(anyOf(isDeleted(),
-                           hasDescendant(std::move(ForwardCallMatcher))))))),
+              unless(anyOf(isDeleted(), hasDescendant(expr(
+                                            anyOf(std::move(ForwardCallMatcher),
+                                                  std::move(StaticCast))))))))),
       this);
 }
 
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b001a6ad446695..a0a18322bedf00 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -121,6 +121,11 @@ Changes in existing checks
   <clang-tidy/checks/readability/redundant-smartptr-get>` check to
   remove `->`, when redundant `get()` is removed.
 
+- Improved :doc:`cppcoreguidelines-missing-std-forward
+  <clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check to allow
+  using ``static_cast<T&>`` to explicitly convey the intention of using a
+  forwarding reference as an lvalue reference.
+
 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 0c311b59a5d5a4..12765b45088de2 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
@@ -38,3 +38,6 @@ Example:
 This check implements `F.19
 <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-forward>`_
 from the C++ Core Guidelines.
+
+Users who want to use the forwarding reference as an lvalue reference can convey
+the intention by using ``static_cast<T&>(t)``.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
index 8116db58c937d4..519d2822948bb4 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
@@ -211,3 +211,20 @@ template<typename F>
 void unused_argument3(F&& _) {}
 
 } // namespace unused_arguments
+
+namespace escape_hatch {
+
+template<typename T>
+void used_as_lvalue_on_purpose(T&& t) {
+  static_cast<T&>(t);
+  static_cast<const T&>(t);
+}
+
+template<typename T>
+void used_as_rvalue_on_purpose(T&& t) {
+  static_cast<const T&&>(t);
+  // Typically used as another spelling for `std::forward`.
+  static_cast<T&&>(t);
+}
+
+}

>From 5c2ebbd2d69899721e039c80ab3bf3bf3a6459fa Mon Sep 17 00:00:00 2001
From: Clement Courbet <courbet at google.com>
Date: Fri, 19 Jul 2024 08:20:30 +0000
Subject: [PATCH 2/8] Add a check option to ignore `static_cast`s.

---
 .../MissingStdForwardCheck.cpp                |  6 ++--
 clang-tools-extra/docs/ReleaseNotes.rst       | 14 ++++-----
 .../cppcoreguidelines/missing-std-forward.rst | 12 ++++++--
 .../missing-std-forward-casts.cpp             | 29 +++++++++++++++++++
 .../cppcoreguidelines/missing-std-forward.cpp | 15 +++-------
 5 files changed, 52 insertions(+), 24 deletions(-)
 create mode 100644 clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
index 726e9fffc628b5..9490e4873be849 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
@@ -129,8 +129,10 @@ void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
       unless(anyOf(hasAncestor(typeLoc()),
                    hasAncestor(expr(hasUnevaluatedContext())))));
 
-  auto StaticCast = cxxStaticCastExpr(
-      hasSourceExpression(declRefExpr(to(equalsBoundNode("param")))));
+  auto StaticCast = Options.get("IgnoreStaticCasts", false)
+                        ? cxxStaticCastExpr(hasSourceExpression(
+                              declRefExpr(to(equalsBoundNode("param")))))
+                        : cxxStaticCastExpr(unless(anything()));
 
   Finder->addMatcher(
       parmVarDecl(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index a0a18322bedf00..059b9e5e96ea63 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -104,14 +104,15 @@ New check aliases
 Changes in existing checks
 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+- Improved :doc:`cppcoreguidelines-missing-std-forward
+  <clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check to allow
+  using ``static_cast<T&>`` to explicitly convey the intention of using a
+  forwarding reference as an lvalue reference.Removed checks
+
 - Improved :doc:`modernize-use-std-format
   <clang-tidy/checks/modernize/use-std-format>` check to support replacing
   member function calls too.
 
-- Improved :doc:`modernize-use-std-print
-  <clang-tidy/checks/modernize/use-std-print>` check to support replacing
-  member function calls too.
-
 - Improved :doc:`readablility-implicit-bool-conversion
   <clang-tidy/checks/readability/implicit-bool-conversion>` check
   by adding the option `UseUpperCaseLiteralSuffix` to select the
@@ -121,11 +122,6 @@ Changes in existing checks
   <clang-tidy/checks/readability/redundant-smartptr-get>` check to
   remove `->`, when redundant `get()` is removed.
 
-- Improved :doc:`cppcoreguidelines-missing-std-forward
-  <clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check to allow
-  using ``static_cast<T&>`` to explicitly convey the intention of using a
-  forwarding reference as an lvalue reference.
-
 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 12765b45088de2..b1adc9eedc5684 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
@@ -39,5 +39,13 @@ This check implements `F.19
 <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-forward>`_
 from the C++ Core Guidelines.
 
-Users who want to use the forwarding reference as an lvalue reference can convey
-the intention by using ``static_cast<T&>(t)``.
+
+Options
+-------
+
+.. option:: IgnoreStaticCasts
+
+Boolean flag to allow users who want to use the forwarding reference as an
+lvalue reference to convey he intention by using ``static_cast<T&>(t)`` to
+disable warning. Default value is `false`.
+
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp
new file mode 100644
index 00000000000000..d3c8ef79ab8b8c
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp
@@ -0,0 +1,29 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-missing-std-forward %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN:     {cppcoreguidelines-missing-std-forward.IgnoreStaticCasts: true }}" \
+// RUN: -- -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;
+
+} // namespace std
+// NOLINTEND
+
+namespace in_static_cast {
+
+template<typename T>
+void static_cast_to_lvalue_ref(T&& t) {
+  static_cast<T&>(t);
+}
+
+} // namespace in_static_cast
+
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
index 519d2822948bb4..93b9b456f60773 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
@@ -212,19 +212,12 @@ void unused_argument3(F&& _) {}
 
 } // namespace unused_arguments
 
-namespace escape_hatch {
+namespace in_static_cast {
 
 template<typename T>
-void used_as_lvalue_on_purpose(T&& t) {
+void static_cast_to_lvalue_ref(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
   static_cast<T&>(t);
-  static_cast<const T&>(t);
 }
 
-template<typename T>
-void used_as_rvalue_on_purpose(T&& t) {
-  static_cast<const T&&>(t);
-  // Typically used as another spelling for `std::forward`.
-  static_cast<T&&>(t);
-}
-
-}
+} // namespace in_static_cast

>From 2c73507fcfc9377897dcef8ca0053a8d2ed6b5f0 Mon Sep 17 00:00:00 2001
From: Clement Courbet <courbet at google.com>
Date: Mon, 22 Jul 2024 08:58:52 +0000
Subject: [PATCH 3/8] only disable on cast-to-lvalue-ref. Add more tests.

---
 .../MissingStdForwardCheck.cpp                | 17 ++++--
 .../missing-std-forward-casts.cpp             | 50 ++++++++++++++++-
 .../cppcoreguidelines/missing-std-forward.cpp | 55 ++++++++++++++++++-
 3 files changed, 115 insertions(+), 7 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
index 9490e4873be849..3529f82acf9c2b 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
@@ -25,9 +25,10 @@ AST_MATCHER_P(QualType, possiblyPackExpansionOf,
   return InnerMatcher.matches(Node.getNonPackExpansionType(), Finder, Builder);
 }
 
-AST_MATCHER(ParmVarDecl, isTemplateTypeParameter) {
+AST_MATCHER_P(ParmVarDecl, isForwardingReferenceType,
+              ast_matchers::internal::Matcher<RValueReferenceType>, InnerMatcher) {
   ast_matchers::internal::Matcher<QualType> Inner = possiblyPackExpansionOf(
-      qualType(rValueReferenceType(),
+      qualType(rValueReferenceType(InnerMatcher),
                references(templateTypeParmType(
                    hasDeclaration(templateTypeParmDecl()))),
                unless(references(qualType(isConstQualified())))));
@@ -130,14 +131,22 @@ void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
                    hasAncestor(expr(hasUnevaluatedContext())))));
 
   auto StaticCast = Options.get("IgnoreStaticCasts", false)
-                        ? cxxStaticCastExpr(hasSourceExpression(
+                        ? cxxStaticCastExpr(hasDestinationType(
+        lValueReferenceType(
+            pointee(
+                type(equalsBoundNode("qtype"))
+            )
+        )
+    ),
+                                            hasSourceExpression(
                               declRefExpr(to(equalsBoundNode("param")))))
                         : cxxStaticCastExpr(unless(anything()));
 
   Finder->addMatcher(
       parmVarDecl(
           parmVarDecl().bind("param"), hasIdentifier(),
-          unless(hasAttr(attr::Kind::Unused)), isTemplateTypeParameter(),
+          unless(hasAttr(attr::Kind::Unused)),
+          isForwardingReferenceType(pointee(type().bind("qtype"))),
           hasAncestor(functionDecl().bind("func")),
           hasAncestor(functionDecl(
               isDefinition(), equalsBoundNode("func"), ToParam,
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp
index d3c8ef79ab8b8c..6e1d1756103dea 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp
@@ -15,15 +15,63 @@ template <typename T> using remove_reference_t = typename remove_reference<T>::t
 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> using add_lvalue_reference_t = __add_lvalue_reference(T);
+
 } // namespace std
 // NOLINTEND
 
 namespace in_static_cast {
 
 template<typename T>
-void static_cast_to_lvalue_ref(T&& t) {
+void to_lvalue_ref(T&& t) {
   static_cast<T&>(t);
 }
 
+template<typename T>
+void to_const_lvalue_ref(T&& t) {
+  static_cast<const T&>(t);
+}
+
+template<typename T>
+void to_rvalue_ref(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<T&&>(t);
+}
+
+template<typename T>
+void to_value(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<T>(t);
+}
+
+template<typename T>
+void to_const_float_lvalue_ref(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<float&>(t);
+}
+
+template<typename T>
+void to_float(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<float>(t);
+}
+
+template<typename T>
+void to_dependent(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<std::add_lvalue_reference_t<T>>(t);
+}
+
+template<typename... T>
+void to_float_expanded(T&&... t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  (static_cast<float>(t), ...);
+}
+
+template<typename... T>
+void to_lvalue_ref_expanded(T&&... t) {
+  (static_cast<T&>(t), ...);
+}
+
 } // namespace in_static_cast
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
index 93b9b456f60773..70bcbfd473ff44 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
@@ -13,6 +13,8 @@ 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);
 
+template<typename T> using add_lvalue_reference_t = __add_lvalue_reference(T);
+
 } // namespace std
 // NOLINTEND
 
@@ -215,9 +217,58 @@ void unused_argument3(F&& _) {}
 namespace in_static_cast {
 
 template<typename T>
-void static_cast_to_lvalue_ref(T&& t) {
-  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+void to_lvalue_ref(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
   static_cast<T&>(t);
 }
 
+template<typename T>
+void to_const_lvalue_ref(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<const T&>(t);
+}
+
+template<typename T>
+void to_rvalue_ref(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<T&&>(t);
+}
+
+template<typename T>
+void to_value(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<T>(t);
+}
+
+template<typename T>
+void to_const_float_lvalue_ref(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<float&>(t);
+}
+
+template<typename T>
+void to_float(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<float>(t);
+}
+
+template<typename T>
+void to_dependent(T&& t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  static_cast<std::add_lvalue_reference_t<T>>(t);
+}
+
+template<typename... T>
+void to_float_expanded(T&&... t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  (static_cast<float>(t), ...);
+}
+
+template<typename... T>
+void to_lvalue_ref_expanded(T&&... t) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:36: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+  (static_cast<S&>(t), ...);
+}
+
 } // namespace in_static_cast
+

>From f37630ea2c4265b03fc7e88df0783a8511d5d4bc Mon Sep 17 00:00:00 2001
From: Clement Courbet <courbet at google.com>
Date: Mon, 22 Jul 2024 09:38:58 +0000
Subject: [PATCH 4/8] clang-format

---
 .../MissingStdForwardCheck.cpp                | 21 ++++++++-----------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
index 3529f82acf9c2b..2a027a0190c1dc 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
@@ -26,7 +26,8 @@ AST_MATCHER_P(QualType, possiblyPackExpansionOf,
 }
 
 AST_MATCHER_P(ParmVarDecl, isForwardingReferenceType,
-              ast_matchers::internal::Matcher<RValueReferenceType>, InnerMatcher) {
+              ast_matchers::internal::Matcher<RValueReferenceType>,
+              InnerMatcher) {
   ast_matchers::internal::Matcher<QualType> Inner = possiblyPackExpansionOf(
       qualType(rValueReferenceType(InnerMatcher),
                references(templateTypeParmType(
@@ -130,17 +131,13 @@ void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
       unless(anyOf(hasAncestor(typeLoc()),
                    hasAncestor(expr(hasUnevaluatedContext())))));
 
-  auto StaticCast = Options.get("IgnoreStaticCasts", false)
-                        ? cxxStaticCastExpr(hasDestinationType(
-        lValueReferenceType(
-            pointee(
-                type(equalsBoundNode("qtype"))
-            )
-        )
-    ),
-                                            hasSourceExpression(
-                              declRefExpr(to(equalsBoundNode("param")))))
-                        : cxxStaticCastExpr(unless(anything()));
+  auto StaticCast =
+      Options.get("IgnoreStaticCasts", false)
+          ? cxxStaticCastExpr(
+                hasDestinationType(lValueReferenceType(
+                    pointee(type(equalsBoundNode("qtype"))))),
+                hasSourceExpression(declRefExpr(to(equalsBoundNode("param")))))
+          : cxxStaticCastExpr(unless(anything()));
 
   Finder->addMatcher(
       parmVarDecl(

>From d5784892a6f4fe8326e0a930bf86978e2eeeb16f Mon Sep 17 00:00:00 2001
From: Clement Courbet <courbet at google.com>
Date: Tue, 23 Jul 2024 09:37:29 +0000
Subject: [PATCH 5/8] Add an `IgnoreStaticCasts` bool member to store the
 option.

---
 .../cppcoreguidelines/MissingStdForwardCheck.cpp           | 7 ++++++-
 .../clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h  | 7 +++++--
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
index 2a027a0190c1dc..93627e9ab12e42 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
@@ -88,6 +88,11 @@ AST_MATCHER(VarDecl, hasIdentifier) {
 
 } // namespace
 
+MissingStdForwardCheck::MissingStdForwardCheck(StringRef Name,
+                                               ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context),
+      IgnoreStaticCasts(Options.get("IgnoreStaticCasts", false)) {}
+
 void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
   auto RefToParmImplicit = allOf(
       equalsBoundNode("var"), hasInitializer(ignoringParenImpCasts(
@@ -132,7 +137,7 @@ void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
                    hasAncestor(expr(hasUnevaluatedContext())))));
 
   auto StaticCast =
-      Options.get("IgnoreStaticCasts", false)
+      IgnoreStaticCasts
           ? cxxStaticCastExpr(
                 hasDestinationType(lValueReferenceType(
                     pointee(type(equalsBoundNode("qtype"))))),
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
index 5995ad588855ed..1d2b0da06ecc66 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
@@ -21,8 +21,8 @@ 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 +31,9 @@ class MissingStdForwardCheck : public ClangTidyCheck {
   std::optional<TraversalKind> getCheckTraversalKind() const override {
     return TK_IgnoreUnlessSpelledInSource;
   }
+
+private:
+  const bool IgnoreStaticCasts;
 };
 
 } // namespace clang::tidy::cppcoreguidelines

>From fd6e5c3dd4cf87046bc62ac267c154e95a90d1dd Mon Sep 17 00:00:00 2001
From: Clement Courbet <courbet at google.com>
Date: Tue, 23 Jul 2024 13:18:03 +0000
Subject: [PATCH 6/8] Fix indentation in doc

---
 .../checks/cppcoreguidelines/missing-std-forward.rst        | 6 +++---
 1 file changed, 3 insertions(+), 3 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 b1adc9eedc5684..8316cbdd3aeb7b 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
@@ -45,7 +45,7 @@ Options
 
 .. option:: IgnoreStaticCasts
 
-Boolean flag to allow users who want to use the forwarding reference as an
-lvalue reference to convey he intention by using ``static_cast<T&>(t)`` to
-disable warning. Default value is `false`.
+   Boolean flag to allow users who want to use the forwarding reference as an
+   lvalue reference to convey he intention by using ``static_cast<T&>(t)`` to
+   disable warning. Default value is `false`.
 

>From 5fd1800bcb148543891fe07396004e2d06ff7d92 Mon Sep 17 00:00:00 2001
From: Clement Courbet <courbet at google.com>
Date: Wed, 28 Aug 2024 13:50:41 +0000
Subject: [PATCH 7/8] remove excess newlines

---
 .../clang-tidy/checks/cppcoreguidelines/missing-std-forward.rst | 2 --
 .../checkers/cppcoreguidelines/missing-std-forward-casts.cpp    | 1 -
 .../checkers/cppcoreguidelines/missing-std-forward.cpp          | 1 -
 3 files changed, 4 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 8316cbdd3aeb7b..72126ed7f0ad41 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
@@ -39,7 +39,6 @@ This check implements `F.19
 <http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-forward>`_
 from the C++ Core Guidelines.
 
-
 Options
 -------
 
@@ -48,4 +47,3 @@ Options
    Boolean flag to allow users who want to use the forwarding reference as an
    lvalue reference to convey he intention by using ``static_cast<T&>(t)`` to
    disable warning. Default value is `false`.
-
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp
index 6e1d1756103dea..1dfcb7cd9f7a52 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward-casts.cpp
@@ -74,4 +74,3 @@ void to_lvalue_ref_expanded(T&&... t) {
 }
 
 } // namespace in_static_cast
-
diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
index 70bcbfd473ff44..b61cfa0afa7b5f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp
@@ -271,4 +271,3 @@ void to_lvalue_ref_expanded(T&&... t) {
 }
 
 } // namespace in_static_cast
-

>From ec9057d3d48c25561720167970b8c9c7ba5ede06 Mon Sep 17 00:00:00 2001
From: Clement Courbet <courbet at google.com>
Date: Wed, 28 Aug 2024 13:56:18 +0000
Subject: [PATCH 8/8] add `storeOptions`

---
 .../clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp   | 4 ++++
 .../clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h     | 1 +
 2 files changed, 5 insertions(+)

diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
index 93627e9ab12e42..fd5dc70f6d0fbc 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
@@ -93,6 +93,10 @@ MissingStdForwardCheck::MissingStdForwardCheck(StringRef Name,
     : ClangTidyCheck(Name, Context),
       IgnoreStaticCasts(Options.get("IgnoreStaticCasts", false)) {}
 
+void MissingStdForwardCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IgnoreStaticCasts", IgnoreStaticCasts);
+}
+
 void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
   auto RefToParmImplicit = allOf(
       equalsBoundNode("var"), hasInitializer(ignoringParenImpCasts(
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
index 1d2b0da06ecc66..1989730c985310 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.h
@@ -23,6 +23,7 @@ class MissingStdForwardCheck : public ClangTidyCheck {
 public:
   MissingStdForwardCheck(StringRef Name, ClangTidyContext *Context);
 
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {



More information about the cfe-commits mailing list