[clang-tools-extra] [clang-tidy] performance-unnecessary-copy-init: Add a hook... (PR #73921)

Clement Courbet via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 30 07:06:16 PST 2023


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

>From d729f95270aff076ff11ccb1ef12cfb6dc99a82d Mon Sep 17 00:00:00 2001
From: Clement Courbet <courbet at google.com>
Date: Thu, 30 Nov 2023 11:08:51 +0100
Subject: [PATCH] [clang-tidy] performance-unnecessary-copy-init: Add a hook...

... so that derived checks can observe for which variables a warning has been emitted.
---
 .../UnnecessaryCopyInitialization.cpp         | 80 +++++++++----------
 .../UnnecessaryCopyInitialization.h           |  6 ++
 2 files changed, 45 insertions(+), 41 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
index 990e20400fbfcd2..5b45e911fd11ed0 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp
@@ -15,6 +15,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/Basic/Diagnostic.h"
 #include <optional>
+#include <utility>
 
 namespace clang::tidy::performance {
 namespace {
@@ -294,14 +295,28 @@ void UnnecessaryCopyInitialization::check(
     return;
 
   if (OldVar == nullptr) {
-    handleCopyFromMethodReturn(*NewVar, *BlockStmt, *Stmt, IssueFix, ObjectArg,
-                               *Result.Context);
+    handleCopyFromMethodReturn(*NewVar, *BlockStmt, *Stmt, IssueFix,
+                               ObjectArg, *Result.Context);
   } else {
     handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, *Stmt, IssueFix,
                            *Result.Context);
   }
 }
 
+void UnnecessaryCopyInitialization::makeDiagnostic(
+    DiagnosticBuilder Diagnostic, const VarDecl &Var, const Stmt &BlockStmt,
+    const DeclStmt &Stmt, ASTContext &Context, bool IssueFix) {
+  const bool IsVarUnused = isVariableUnused(Var, BlockStmt, Context);
+  Diagnostic << &Var << IsVarUnused;
+  if (IssueFix) {
+    if (IsVarUnused) {
+      recordRemoval(Stmt, Context, Diagnostic);
+    } else {
+      recordFixes(Var, Context, Diagnostic);
+    }
+  }
+}
+
 void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
     const VarDecl &Var, const Stmt &BlockStmt, const DeclStmt &Stmt,
     bool IssueFix, const VarDecl *ObjectArg, ASTContext &Context) {
@@ -312,52 +327,34 @@ void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
       !isInitializingVariableImmutable(*ObjectArg, BlockStmt, Context,
                                        ExcludedContainerTypes))
     return;
-  if (isVariableUnused(Var, BlockStmt, Context)) {
-    auto Diagnostic =
-        diag(Var.getLocation(),
-             "the %select{|const qualified }0variable %1 is copy-constructed "
-             "from a const reference but is never used; consider "
-             "removing the statement")
-        << IsConstQualified << &Var;
-    if (IssueFix)
-      recordRemoval(Stmt, Context, Diagnostic);
-  } else {
-    auto Diagnostic =
-        diag(Var.getLocation(),
-             "the %select{|const qualified }0variable %1 is copy-constructed "
-             "from a const reference%select{ but is only used as const "
-             "reference|}0; consider making it a const reference")
-        << IsConstQualified << &Var;
-    if (IssueFix)
-      recordFixes(Var, Context, Diagnostic);
-  }
+
+  auto Diagnostic =
+      diag(Var.getLocation(),
+           "the %select{|const qualified }0variable %1 is copy-constructed "
+           "from a const reference%select{"
+           "%select{ but is only used as const reference|}0"
+           "| but is never used}2; consider "
+           "%select{making it a const reference|removing the statement}2")
+      << IsConstQualified;
+  makeDiagnostic(std::move(Diagnostic), Var, BlockStmt, Stmt, Context,
+                 IssueFix);
 }
 
 void UnnecessaryCopyInitialization::handleCopyFromLocalVar(
-    const VarDecl &NewVar, const VarDecl &OldVar, const Stmt &BlockStmt,
+    const VarDecl &Var, const VarDecl &OldVar, const Stmt &BlockStmt,
     const DeclStmt &Stmt, bool IssueFix, ASTContext &Context) {
-  if (!isOnlyUsedAsConst(NewVar, BlockStmt, Context) ||
+  if (!isOnlyUsedAsConst(Var, BlockStmt, Context) ||
       !isInitializingVariableImmutable(OldVar, BlockStmt, Context,
                                        ExcludedContainerTypes))
     return;
-
-  if (isVariableUnused(NewVar, BlockStmt, Context)) {
-    auto Diagnostic = diag(NewVar.getLocation(),
-                           "local copy %0 of the variable %1 is never modified "
-                           "and never used; "
-                           "consider removing the statement")
-                      << &NewVar << &OldVar;
-    if (IssueFix)
-      recordRemoval(Stmt, Context, Diagnostic);
-  } else {
-    auto Diagnostic =
-        diag(NewVar.getLocation(),
-             "local copy %0 of the variable %1 is never modified; "
-             "consider avoiding the copy")
-        << &NewVar << &OldVar;
-    if (IssueFix)
-      recordFixes(NewVar, Context, Diagnostic);
-  }
+  auto Diagnostic =
+      diag(Var.getLocation(),
+           "local copy %1 of the variable %0 is never modified"
+           "%select{| and never used}2; consider "
+           "%select{avoiding the copy|removing the statement}2")
+      << &OldVar;
+  makeDiagnostic(std::move(Diagnostic), Var, BlockStmt, Stmt, Context,
+                 IssueFix);
 }
 
 void UnnecessaryCopyInitialization::storeOptions(
@@ -369,3 +366,4 @@ void UnnecessaryCopyInitialization::storeOptions(
 }
 
 } // namespace clang::tidy::performance
+
diff --git a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
index ea009ba9979de97..eba6fbd2b9e62c8 100644
--- a/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
+++ b/clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h
@@ -32,6 +32,11 @@ class UnnecessaryCopyInitialization : public ClangTidyCheck {
   void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
   void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
 
+protected:
+  // This is virtual so that derived classes can implement additional behavior.
+  virtual void makeDiagnostic(DiagnosticBuilder Diagnostic, const VarDecl &Var,
+                              const Stmt &BlockStmt, const DeclStmt &Stmt,
+                              ASTContext &Context, bool IssueFix);
 private:
   void handleCopyFromMethodReturn(const VarDecl &Var, const Stmt &BlockStmt,
                                   const DeclStmt &Stmt, bool IssueFix,
@@ -40,6 +45,7 @@ class UnnecessaryCopyInitialization : public ClangTidyCheck {
   void handleCopyFromLocalVar(const VarDecl &NewVar, const VarDecl &OldVar,
                               const Stmt &BlockStmt, const DeclStmt &Stmt,
                               bool IssueFix, ASTContext &Context);
+
   const std::vector<StringRef> AllowedTypes;
   const std::vector<StringRef> ExcludedContainerTypes;
 };



More information about the cfe-commits mailing list