Skip to content

Commit a536444

Browse files
authored
[clang-tidy] performance-unnecessary-copy-initialization: Consider static functions (#119974)
Static member functions can be considered the same way as free functions are, so do that.
1 parent 42da120 commit a536444

File tree

3 files changed

+40
-9
lines changed

3 files changed

+40
-9
lines changed

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

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,18 @@ AST_MATCHER_FUNCTION_P(StatementMatcher,
104104
hasArgument(0, hasType(ReceiverType)))));
105105
}
106106

107+
AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); }
108+
107109
AST_MATCHER_FUNCTION(StatementMatcher, isConstRefReturningFunctionCall) {
108-
// Only allow initialization of a const reference from a free function if it
109-
// has no arguments. Otherwise it could return an alias to one of its
110-
// arguments and the arguments need to be checked for const use as well.
111-
return callExpr(callee(functionDecl(returns(hasCanonicalType(
112-
matchers::isReferenceToConst())))
113-
.bind(FunctionDeclId)),
114-
argumentCountIs(0), unless(callee(cxxMethodDecl())))
115-
.bind(InitFunctionCallId);
110+
// Only allow initialization of a const reference from a free function or
111+
// static member function if it has no arguments. Otherwise it could return
112+
// an alias to one of its arguments and the arguments need to be checked
113+
// for const use as well.
114+
return callExpr(argumentCountIs(0),
115+
callee(functionDecl(returns(hasCanonicalType(matchers::isReferenceToConst())),
116+
unless(cxxMethodDecl(unless(isStatic()))))
117+
.bind(FunctionDeclId)))
118+
.bind(InitFunctionCallId);
116119
}
117120

118121
AST_MATCHER_FUNCTION_P(StatementMatcher, initializerReturnsReferenceToConst,
@@ -232,7 +235,7 @@ UnnecessaryCopyInitialization::UnnecessaryCopyInitialization(
232235
Options.get("ExcludedContainerTypes", ""))) {}
233236

234237
void UnnecessaryCopyInitialization::registerMatchers(MatchFinder *Finder) {
235-
auto LocalVarCopiedFrom = [this](const internal::Matcher<Expr> &CopyCtorArg) {
238+
auto LocalVarCopiedFrom = [this](const ast_matchers::internal::Matcher<Expr> &CopyCtorArg) {
236239
return compoundStmt(
237240
forEachDescendant(
238241
declStmt(

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,10 @@ Changes in existing checks
339339
<clang-tidy/checks/performance/move-const-arg>` check to fix a crash when
340340
an argument type is declared but not defined.
341341

342+
- Improved :doc:`performance-unnecessary-copy-initialization`
343+
<clang-tidy/checks/performance/unnecessary-copy-initialization> check
344+
to consider static member functions the same way as free functions.
345+
342346
- Improved :doc:`readability-container-contains
343347
<clang-tidy/checks/readability/container-contains>` check to let it work on
344348
any class that has a ``contains`` method. Fix some false negatives in the

clang-tools-extra/test/clang-tidy/checkers/performance/unnecessary-copy-initialization.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ struct ExpensiveToCopyType {
2828
template <typename A>
2929
const A &templatedAccessor() const;
3030
operator int() const; // Implicit conversion to int.
31+
32+
static const ExpensiveToCopyType &instance();
3133
};
3234

3335
template <typename T>
@@ -100,6 +102,28 @@ void PositiveFunctionCall() {
100102
VarCopyConstructed.constMethod();
101103
}
102104

105+
void PositiveStaticMethodCall() {
106+
const auto AutoAssigned = ExpensiveToCopyType::instance();
107+
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned' is copy-constructed from a const reference; consider making it a const reference [performance-unnecessary-copy-initialization]
108+
// CHECK-FIXES: const auto& AutoAssigned = ExpensiveToCopyType::instance();
109+
AutoAssigned.constMethod();
110+
111+
const auto AutoCopyConstructed(ExpensiveToCopyType::instance());
112+
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
113+
// CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveToCopyType::instance());
114+
AutoCopyConstructed.constMethod();
115+
116+
const ExpensiveToCopyType VarAssigned = ExpensiveToCopyType::instance();
117+
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
118+
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveToCopyType::instance();
119+
VarAssigned.constMethod();
120+
121+
const ExpensiveToCopyType VarCopyConstructed(ExpensiveToCopyType::instance());
122+
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
123+
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveToCopyType::instance());
124+
VarCopyConstructed.constMethod();
125+
}
126+
103127
void PositiveMethodCallConstReferenceParam(const ExpensiveToCopyType &Obj) {
104128
const auto AutoAssigned = Obj.reference();
105129
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'

0 commit comments

Comments
 (0)