@@ -24,6 +24,9 @@ void LostStdMoveCheck::registerMatchers(MatchFinder *Finder) {
24
24
auto returnParent =
25
25
hasParent (expr (hasParent (cxxConstructExpr (hasParent (returnStmt ())))));
26
26
27
+ auto outermostExpr = expr (unless (hasParent (expr ())));
28
+ auto leafStatement = stmt (outermostExpr, unless (hasDescendant (outermostExpr)));
29
+
27
30
Finder->addMatcher (
28
31
declRefExpr (
29
32
// not "return x;"
@@ -46,6 +49,8 @@ void LostStdMoveCheck::registerMatchers(MatchFinder *Finder) {
46
49
unless (hasDeclaration (
47
50
varDecl (hasType (qualType (lValueReferenceType ()))))),
48
51
52
+ hasAncestor (leafStatement.bind (" leaf_statement" )),
53
+
49
54
hasDeclaration (
50
55
varDecl (hasAncestor (functionDecl ().bind (" func" ))).bind (" decl" )),
51
56
@@ -71,11 +76,19 @@ const Expr *LostStdMoveCheck::getLastVarUsage(const VarDecl &Var,
71
76
return LastExpr;
72
77
}
73
78
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
+
74
86
void LostStdMoveCheck::check (const MatchFinder::MatchResult &Result) {
75
87
const auto *MatchedDecl = Result.Nodes .getNodeAs <VarDecl>(" decl" );
76
88
const auto *MatchedFunc = Result.Nodes .getNodeAs <FunctionDecl>(" func" );
77
89
const auto *MatchedUse = Result.Nodes .getNodeAs <Expr>(" use" );
78
90
const auto *MatchedUseCall = Result.Nodes .getNodeAs <CallExpr>(" use_parent" );
91
+ const auto *MatchedLeafStatement = Result.Nodes .getNodeAs <Stmt>(" leaf_statement" );
79
92
80
93
if (MatchedUseCall)
81
94
return ;
@@ -90,6 +103,15 @@ void LostStdMoveCheck::check(const MatchFinder::MatchResult &Result) {
90
103
return ;
91
104
}
92
105
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
+
93
115
diag (LastUsage->getBeginLoc (), " Could be std::move()" );
94
116
}
95
117
0 commit comments