Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang-tidy] fix false negative in cppcoreguidelines-missing-std-forward #83987

Merged
merged 1 commit into from
Mar 6, 2024

Conversation

jcsxky
Copy link
Contributor

@jcsxky jcsxky commented Mar 5, 2024

Try to fix #83845
When std::forward is invoked in a function, make sure it uses correct parameter by checking if the bounded var equals the parameter.

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 5, 2024

@llvm/pr-subscribers-clang-tidy

@llvm/pr-subscribers-clang-tools-extra

Author: Qizhi Hu (jcsxky)

Changes

Try to fix #83845
When std::forward is invoked in a function, make sure it uses correct parameter by checking if the bounded var equals the parameter.


Full diff: https://github.com/llvm/llvm-project/pull/83987.diff

3 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp (+6-4)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+2-1)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/missing-std-forward.cpp (+10)
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
index c633683570f748..87fd8adf997082 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/MissingStdForwardCheck.cpp
@@ -112,10 +112,12 @@ void MissingStdForwardCheck::registerMatchers(MatchFinder *Finder) {
 
   auto ForwardCallMatcher = callExpr(
       callExpr().bind("call"), argumentCountIs(1),
-      hasArgument(
-          0, declRefExpr(to(
-                 varDecl(optionally(equalsBoundNode("param"))).bind("var")))),
-      forCallable(anyOf(equalsBoundNode("func"), CapturedInLambda)),
+      hasArgument(0, declRefExpr(to(varDecl().bind("var")))),
+      forCallable(
+          anyOf(allOf(equalsBoundNode("func"),
+                      functionDecl(hasAnyParameter(parmVarDecl(allOf(
+                          equalsBoundNode("param"), equalsBoundNode("var")))))),
+                CapturedInLambda)),
       callee(unresolvedLookupExpr(hasAnyDeclaration(
           namedDecl(hasUnderlyingDecl(hasName("::std::forward")))))),
 
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 143ae230fc443c..1abe45bae8a84d 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -156,7 +156,8 @@ Changes in existing checks
 
 - Improved :doc:`cppcoreguidelines-missing-std-forward
   <clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check by no longer
-  giving false positives for deleted functions.
+  giving false positives for deleted functions and fix false negative when one
+  parameter is forwarded, but some other parameter isn't.
 
 - Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer
   <clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>`
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 20e43f04180ff3..29af67b60614c8 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
@@ -95,6 +95,16 @@ void lambda_value_capture_copy(T&& t) {
   [&,t]() { T other = std::forward<T>(t); };
 }
 
+template <typename X>
+void use(const X &x) {}
+
+template <typename X, typename Y>
+void foo(X &&x, Y &&y) {
+  // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: forwarding reference parameter 't' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward]
+    use(std::forward<X>(x));
+    use(y);
+}
+
 } // namespace positive_cases
 
 namespace negative_cases {

Copy link
Contributor

@HerrCai0907 HerrCai0907 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM since it is helpful to improve this check.
But I still take a negative view about use std::forward in lambda body.

Comment on lines 159 to 160
giving false positives for deleted functions and fix false negative when one
parameter is forwarded, but some other parameter isn't.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
giving false positives for deleted functions and fix false negative when one
parameter is forwarded, but some other parameter isn't.
giving false positives for deleted functions and fix false negative when some
parameters are forwarded, but other aren't.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for review to make the description more clear!
I think you can check

void lambda_value_reference_auxiliary_var(T&& t) {
[&x = t]() { T other = std::forward<T>(x); };
}

this testcase may helpful for solving confusions.

Copy link
Member

@PiotrZSL PiotrZSL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jcsxky jcsxky force-pushed the fix-83845 branch 2 times, most recently from d07d397 to ed7bd1a Compare March 6, 2024 01:27
@jcsxky jcsxky merged commit 8b326d5 into llvm:main Mar 6, 2024
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

clang-tidy doesn't report missing forward when one parameter is forwarded, but some other parameter isn't
4 participants