[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:08:40 PST 2023
https://github.com/legrosbuffle updated https://github.com/llvm/llvm-project/pull/73921
>From a072ae129b1ad928c96368a3208d35cc0705e260 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
Refactor diagnostic emission and 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