Skip to content

Commit 851460a

Browse files
committed
[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.
1 parent eb64697 commit 851460a

File tree

2 files changed

+41
-39
lines changed

2 files changed

+41
-39
lines changed

clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.cpp

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "clang/AST/Decl.h"
1616
#include "clang/Basic/Diagnostic.h"
1717
#include <optional>
18+
#include <utility>
1819

1920
namespace clang::tidy::performance {
2021
namespace {
@@ -302,6 +303,19 @@ void UnnecessaryCopyInitialization::check(
302303
}
303304
}
304305

306+
void UnnecessaryCopyInitialization::makeDiagnostic(
307+
DiagnosticBuilder Diagnostic, const VarDecl &Var, const Stmt &BlockStmt,
308+
const DeclStmt &Stmt, ASTContext &Context, bool IssueFix) {
309+
const bool IsVarUnused = isVariableUnused(Var, BlockStmt, Context);
310+
Diagnostic << &Var << IsVarUnused;
311+
if (!IssueFix)
312+
return;
313+
if (IsVarUnused)
314+
recordRemoval(Stmt, Context, Diagnostic);
315+
else
316+
recordFixes(Var, Context, Diagnostic);
317+
}
318+
305319
void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
306320
const VarDecl &Var, const Stmt &BlockStmt, const DeclStmt &Stmt,
307321
bool IssueFix, const VarDecl *ObjectArg, ASTContext &Context) {
@@ -312,52 +326,33 @@ void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
312326
!isInitializingVariableImmutable(*ObjectArg, BlockStmt, Context,
313327
ExcludedContainerTypes))
314328
return;
315-
if (isVariableUnused(Var, BlockStmt, Context)) {
316-
auto Diagnostic =
317-
diag(Var.getLocation(),
318-
"the %select{|const qualified }0variable %1 is copy-constructed "
319-
"from a const reference but is never used; consider "
320-
"removing the statement")
321-
<< IsConstQualified << &Var;
322-
if (IssueFix)
323-
recordRemoval(Stmt, Context, Diagnostic);
324-
} else {
325-
auto Diagnostic =
326-
diag(Var.getLocation(),
327-
"the %select{|const qualified }0variable %1 is copy-constructed "
328-
"from a const reference%select{ but is only used as const "
329-
"reference|}0; consider making it a const reference")
330-
<< IsConstQualified << &Var;
331-
if (IssueFix)
332-
recordFixes(Var, Context, Diagnostic);
333-
}
329+
330+
auto Diagnostic =
331+
diag(Var.getLocation(),
332+
"the %select{|const qualified }0variable %1 is copy-constructed "
333+
"from a const reference%select{"
334+
"%select{ but is only used as const reference|}0"
335+
"| but is never used}2; consider "
336+
"%select{making it a const reference|removing the statement}2")
337+
<< IsConstQualified;
338+
makeDiagnostic(std::move(Diagnostic), Var, BlockStmt, Stmt, Context,
339+
IssueFix);
334340
}
335341

336342
void UnnecessaryCopyInitialization::handleCopyFromLocalVar(
337-
const VarDecl &NewVar, const VarDecl &OldVar, const Stmt &BlockStmt,
343+
const VarDecl &Var, const VarDecl &OldVar, const Stmt &BlockStmt,
338344
const DeclStmt &Stmt, bool IssueFix, ASTContext &Context) {
339-
if (!isOnlyUsedAsConst(NewVar, BlockStmt, Context) ||
345+
if (!isOnlyUsedAsConst(Var, BlockStmt, Context) ||
340346
!isInitializingVariableImmutable(OldVar, BlockStmt, Context,
341347
ExcludedContainerTypes))
342348
return;
343-
344-
if (isVariableUnused(NewVar, BlockStmt, Context)) {
345-
auto Diagnostic = diag(NewVar.getLocation(),
346-
"local copy %0 of the variable %1 is never modified "
347-
"and never used; "
348-
"consider removing the statement")
349-
<< &NewVar << &OldVar;
350-
if (IssueFix)
351-
recordRemoval(Stmt, Context, Diagnostic);
352-
} else {
353-
auto Diagnostic =
354-
diag(NewVar.getLocation(),
355-
"local copy %0 of the variable %1 is never modified; "
356-
"consider avoiding the copy")
357-
<< &NewVar << &OldVar;
358-
if (IssueFix)
359-
recordFixes(NewVar, Context, Diagnostic);
360-
}
349+
auto Diagnostic = diag(Var.getLocation(),
350+
"local copy %1 of the variable %0 is never modified"
351+
"%select{| and never used}2; consider "
352+
"%select{avoiding the copy|removing the statement}2")
353+
<< &OldVar;
354+
makeDiagnostic(std::move(Diagnostic), Var, BlockStmt, Stmt, Context,
355+
IssueFix);
361356
}
362357

363358
void UnnecessaryCopyInitialization::storeOptions(

clang-tools-extra/clang-tidy/performance/UnnecessaryCopyInitialization.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ class UnnecessaryCopyInitialization : public ClangTidyCheck {
3232
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
3333
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
3434

35+
protected:
36+
// This is virtual so that derived classes can implement additional behavior.
37+
virtual void makeDiagnostic(DiagnosticBuilder Diagnostic, const VarDecl &Var,
38+
const Stmt &BlockStmt, const DeclStmt &Stmt,
39+
ASTContext &Context, bool IssueFix);
40+
3541
private:
3642
void handleCopyFromMethodReturn(const VarDecl &Var, const Stmt &BlockStmt,
3743
const DeclStmt &Stmt, bool IssueFix,
@@ -40,6 +46,7 @@ class UnnecessaryCopyInitialization : public ClangTidyCheck {
4046
void handleCopyFromLocalVar(const VarDecl &NewVar, const VarDecl &OldVar,
4147
const Stmt &BlockStmt, const DeclStmt &Stmt,
4248
bool IssueFix, ASTContext &Context);
49+
4350
const std::vector<StringRef> AllowedTypes;
4451
const std::vector<StringRef> ExcludedContainerTypes;
4552
};

0 commit comments

Comments
 (0)