Skip to content

[clang-tidy] performance-unnecessary-copy-init: Add a hook... #73921

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

Merged
merged 5 commits into from
Dec 7, 2023

Conversation

legrosbuffle
Copy link
Contributor

@legrosbuffle legrosbuffle commented Nov 30, 2023

... so that derived checks can derived checks can observe for which variables a warning has been emitted. Does nothing by default, which makes this an NFC.

@llvmbot
Copy link
Member

llvmbot commented Nov 30, 2023

@llvm/pr-subscribers-clang-tidy

Author: Clement Courbet (legrosbuffle)

Changes

... so that derived checks can implement custom behaviour. Does nothing by default, which makes this an NFC.


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

2 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp (+15-9)
  • (modified) clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h (+7-2)
diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index 990e20400fbfcd2..966071e92833b87 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -294,24 +294,28 @@ void UnnecessaryCopyInitialization::check(
     return;
 
   if (OldVar == nullptr) {
-    handleCopyFromMethodReturn(*NewVar, *BlockStmt, *Stmt, IssueFix, ObjectArg,
-                               *Result.Context);
+    if (handleCopyFromMethodReturn(*NewVar, *BlockStmt, *Stmt, IssueFix,
+                                   ObjectArg, *Result.Context)) {
+      onWarningEmitted(*NewVar, *BlockStmt, *Result.Context);
+    }
   } else {
-    handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, *Stmt, IssueFix,
-                           *Result.Context);
+    if (handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, *Stmt, IssueFix,
+                               *Result.Context)) {
+      onWarningEmitted(*NewVar, *BlockStmt, *Result.Context);
+    }  
   }
 }
 
-void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
+bool UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
     const VarDecl &Var, const Stmt &BlockStmt, const DeclStmt &Stmt,
     bool IssueFix, const VarDecl *ObjectArg, ASTContext &Context) {
   bool IsConstQualified = Var.getType().isConstQualified();
   if (!IsConstQualified && !isOnlyUsedAsConst(Var, BlockStmt, Context))
-    return;
+    return false;
   if (ObjectArg != nullptr &&
       !isInitializingVariableImmutable(*ObjectArg, BlockStmt, Context,
                                        ExcludedContainerTypes))
-    return;
+    return false;
   if (isVariableUnused(Var, BlockStmt, Context)) {
     auto Diagnostic =
         diag(Var.getLocation(),
@@ -331,15 +335,16 @@ void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
     if (IssueFix)
       recordFixes(Var, Context, Diagnostic);
   }
+  return true;
 }
 
-void UnnecessaryCopyInitialization::handleCopyFromLocalVar(
+bool UnnecessaryCopyInitialization::handleCopyFromLocalVar(
     const VarDecl &NewVar, const VarDecl &OldVar, const Stmt &BlockStmt,
     const DeclStmt &Stmt, bool IssueFix, ASTContext &Context) {
   if (!isOnlyUsedAsConst(NewVar, BlockStmt, Context) ||
       !isInitializingVariableImmutable(OldVar, BlockStmt, Context,
                                        ExcludedContainerTypes))
-    return;
+    return false;
 
   if (isVariableUnused(NewVar, BlockStmt, Context)) {
     auto Diagnostic = diag(NewVar.getLocation(),
@@ -358,6 +363,7 @@ void UnnecessaryCopyInitialization::handleCopyFromLocalVar(
     if (IssueFix)
       recordFixes(NewVar, Context, Diagnostic);
   }
+  return true;
 }
 
 void UnnecessaryCopyInitialization::storeOptions(
diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
index ea009ba9979de97..7d76c9e7cab940c 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
@@ -33,13 +33,18 @@ class UnnecessaryCopyInitialization : public ClangTidyCheck {
   void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
 
 private:
-  void handleCopyFromMethodReturn(const VarDecl &Var, const Stmt &BlockStmt,
+  bool handleCopyFromMethodReturn(const VarDecl &Var, const Stmt &BlockStmt,
                                   const DeclStmt &Stmt, bool IssueFix,
                                   const VarDecl *ObjectArg,
                                   ASTContext &Context);
-  void handleCopyFromLocalVar(const VarDecl &NewVar, const VarDecl &OldVar,
+  bool handleCopyFromLocalVar(const VarDecl &NewVar, const VarDecl &OldVar,
                               const Stmt &BlockStmt, const DeclStmt &Stmt,
                               bool IssueFix, ASTContext &Context);
+
+  // A hook called for each emitted warning.
+  virtual void onWarningEmitted(const VarDecl &Var, const Stmt &BlockStmt,
+                                ASTContext &context) {}
+
   const std::vector<StringRef> AllowedTypes;
   const std::vector<StringRef> ExcludedContainerTypes;
 };

Copy link

github-actions bot commented Nov 30, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@legrosbuffle legrosbuffle force-pushed the unnecessary-copy-tidy-hook branch from e251c44 to e0d1f97 Compare November 30, 2023 10:50
@PiotrZSL
Copy link
Member

First what's a purpose of this change. Is there any other check that will need it or not ?
Second is that actually onWarningEmitted should be more a emitWarning, and those diag should be inside it, so that they could be changed if needed. Or condition required to emit a warning should be in separate methods.
With current implementation I don't see any "custom behaviour" that could be implemented, as this act more like observer.

@legrosbuffle
Copy link
Contributor Author

First what's a purpose of this change. Is there any other check that will need it or not ?

We have a downstream check that wants to do additional processing after this one. We can't submit that check because it depends on a large piece of downstream infrastructure.

With current implementation I don't see any "custom behaviour" that could be implemented, as this act more like observer.

Indeed, the downstream check does not change the behaviour, it does extra stuff in addition what the check already does. I've rephrased the commit message to make that clearer.

@legrosbuffle legrosbuffle force-pushed the unnecessary-copy-tidy-hook branch 2 times, most recently from 6050ba4 to a6bc3d7 Compare November 30, 2023 11:56
@PiotrZSL
Copy link
Member

In theory changes that are required for "private" checks should be done by you on some own private fork instead of adding that "unused" code here. But only option I see is simply moving diagnostic to separate methods, and make those methods virtual. That could be +- acceptable. Or moving "condition" into separate method. Adding empty methods & ifs to call that method is not an option.

@legrosbuffle
Copy link
Contributor Author

In theory changes that are required for "private" checks should be done by you on some own private fork instead of adding that "unused" code here. But only option I see is simply moving diagnostic to separate methods, and make those methods virtual.

I see, we don't want code that's dead upstream. Makes sense. I'll do something like what you're suggesting.

@legrosbuffle legrosbuffle force-pushed the unnecessary-copy-tidy-hook branch 3 times, most recently from a072ae1 to 0bf4d83 Compare November 30, 2023 15:09
@legrosbuffle
Copy link
Contributor Author

This is ready for another look. I took this as an opportunity to refactor the duplicated parts of the code. Let me know what you think.

Refactor diagnostic emission and add a hook so that derived checks
can observe for which variables a warning has been emitted.
@legrosbuffle legrosbuffle force-pushed the unnecessary-copy-tidy-hook branch from 0bf4d83 to 851460a Compare November 30, 2023 15:47
@legrosbuffle legrosbuffle force-pushed the unnecessary-copy-tidy-hook branch from 824be23 to a37b76a Compare December 1, 2023 09:44
Copy link

@fberger fberger left a comment

Choose a reason for hiding this comment

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

LGTM

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.

Last nits, and it will look fine.

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

@legrosbuffle
Copy link
Contributor Author

Thanks

@legrosbuffle legrosbuffle merged commit 04ce9a3 into llvm:main Dec 7, 2023
legrosbuffle added a commit to legrosbuffle/llvm-project that referenced this pull request Jul 22, 2024
…` virtual

... so that downstream checks can override behaviour to do additional processing.

Refactor the rest of the logic to `handleConstRefFix` (which is also
`virtual`).

This is otherwise and NFC.

This is similar to llvm#73921 but
for `performance-unnecessary-value-param`.
legrosbuffle added a commit that referenced this pull request Jul 23, 2024
…` virtual (#99867)

... so that downstream checks can override behaviour to do additional
processing.

Refactor the rest of the logic to `handleConstRefFix` (which is also
`virtual`).

This is otherwise and NFC.

This is similar to #73921 but
for `performance-unnecessary-value-param`.
yuxuanchen1997 pushed a commit that referenced this pull request Jul 25, 2024
…` virtual (#99867)

Summary:
... so that downstream checks can override behaviour to do additional
processing.

Refactor the rest of the logic to `handleConstRefFix` (which is also
`virtual`).

This is otherwise and NFC.

This is similar to #73921 but
for `performance-unnecessary-value-param`.

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60251087
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.

4 participants