Skip to content

Commit b48a1f7

Browse files
committed
f(x, x)
1 parent 35ac17a commit b48a1f7

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ void LostStdMoveCheck::registerMatchers(MatchFinder *Finder) {
2424
auto returnParent =
2525
hasParent(expr(hasParent(cxxConstructExpr(hasParent(returnStmt())))));
2626

27+
auto outermostExpr = expr(unless(hasParent(expr())));
28+
auto leafStatement = stmt(outermostExpr, unless(hasDescendant(outermostExpr)));
29+
2730
Finder->addMatcher(
2831
declRefExpr(
2932
// not "return x;"
@@ -46,6 +49,8 @@ void LostStdMoveCheck::registerMatchers(MatchFinder *Finder) {
4649
unless(hasDeclaration(
4750
varDecl(hasType(qualType(lValueReferenceType()))))),
4851

52+
hasAncestor(leafStatement.bind("leaf_statement")),
53+
4954
hasDeclaration(
5055
varDecl(hasAncestor(functionDecl().bind("func"))).bind("decl")),
5156

@@ -71,11 +76,19 @@ const Expr *LostStdMoveCheck::getLastVarUsage(const VarDecl &Var,
7176
return LastExpr;
7277
}
7378

79+
template <typename Node>
80+
void extractNodesByIdTo(ArrayRef<BoundNodes> Matches, StringRef ID,
81+
llvm::SmallPtrSet<const Node *, 16> &Nodes) {
82+
for (const auto &Match : Matches)
83+
Nodes.insert(Match.getNodeAs<Node>(ID));
84+
}
85+
7486
void LostStdMoveCheck::check(const MatchFinder::MatchResult &Result) {
7587
const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>("decl");
7688
const auto *MatchedFunc = Result.Nodes.getNodeAs<FunctionDecl>("func");
7789
const auto *MatchedUse = Result.Nodes.getNodeAs<Expr>("use");
7890
const auto *MatchedUseCall = Result.Nodes.getNodeAs<CallExpr>("use_parent");
91+
const auto *MatchedLeafStatement = Result.Nodes.getNodeAs<Stmt>("leaf_statement");
7992

8093
if (MatchedUseCall)
8194
return;
@@ -90,6 +103,15 @@ void LostStdMoveCheck::check(const MatchFinder::MatchResult &Result) {
90103
return;
91104
}
92105

106+
// Calculate X usage count in the statement
107+
llvm::SmallPtrSet<const DeclRefExpr *, 16> DeclRefs;
108+
auto Matches = match(findAll(declRefExpr(to(varDecl(equalsNode(MatchedDecl)))).bind("ref")), *MatchedLeafStatement, *Result.Context);
109+
extractNodesByIdTo(Matches, "ref", DeclRefs);
110+
if (DeclRefs.size() > 1) {
111+
// Unspecified order of evaluation, e.g. f(x, x)
112+
return;
113+
}
114+
93115
diag(LastUsage->getBeginLoc(), "Could be std::move()");
94116
}
95117

clang-tools-extra/test/clang-tidy/checkers/performance/lost-std-move.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,9 @@ void f_cycle4()
106106
f(ptr);
107107
} while (*ptr);
108108
}
109+
110+
int f_multiple_usages()
111+
{
112+
std::shared_ptr<int> ptr;
113+
return f(ptr) + f(ptr);
114+
}

0 commit comments

Comments
 (0)