@@ -36,6 +36,21 @@ allDeclRefExprsHonourLambda(const VarDecl &VarDecl, const Decl &Decl,
36
36
return DeclRefs;
37
37
}
38
38
39
+ static llvm::SmallPtrSet<const VarDecl *, 16 >
40
+ allVarDeclsExprs (const VarDecl &VarDecl, const Decl &Decl,
41
+ ASTContext &Context) {
42
+ auto Matches = match (
43
+ decl (forEachDescendant (
44
+ declRefExpr (to (varDecl (equalsNode (&VarDecl))),
45
+ hasParent (decl (varDecl (hasType (qualType (referenceType ()))).bind (" varDecl" ))),
46
+ unless (hasAncestor (lambdaExpr (hasAnyCapture (lambdaCapture (
47
+ capturesVar (varDecl (equalsNode (&VarDecl))))))))))),
48
+ Decl, Context);
49
+ llvm::SmallPtrSet<const class VarDecl *, 16 > VarDecls;
50
+ extractNodesByIdTo (Matches, " varDecl" , VarDecls);
51
+ return VarDecls;
52
+ }
53
+
39
54
static const Expr *
40
55
getLastVarUsage (const llvm::SmallPtrSet<const DeclRefExpr *, 16 > &Exprs) {
41
56
const Expr *LastExpr = nullptr ;
@@ -54,6 +69,15 @@ AST_MATCHER(CXXRecordDecl, hasTrivialMoveConstructor) {
54
69
return Node.hasDefinition () && Node.hasTrivialMoveConstructor ();
55
70
}
56
71
72
+ void LostStdMoveCheck::storeOptions (
73
+ ClangTidyOptions::OptionMap &Opts) {
74
+ Options.store (Opts, " StrictMode" , StrictMode);
75
+ }
76
+
77
+ LostStdMoveCheck::LostStdMoveCheck (StringRef Name, ClangTidyContext *Context)
78
+ : ClangTidyCheck(Name, Context),
79
+ StrictMode (Options.get(" StrictMode" , true )) {}
80
+
57
81
void LostStdMoveCheck::registerMatchers (MatchFinder *Finder) {
58
82
auto ReturnParent =
59
83
hasParent (expr (hasParent (cxxConstructExpr (hasParent (returnStmt ())))));
@@ -125,15 +149,17 @@ void LostStdMoveCheck::check(const MatchFinder::MatchResult &Result) {
125
149
return ;
126
150
}
127
151
128
- llvm::SmallPtrSet<const DeclRefExpr *, 16 > AllReferences =
129
- allDeclRefExprsHonourLambda (*MatchedDecl, *MatchedFunc, *Result.Context );
130
- for (const auto *Reference : AllReferences) {
131
- if (Reference->getType ()->isLValueReferenceType ()) {
132
- // variable may be caught by reference and still used via reference during
133
- // MatchedUse
152
+ if (StrictMode) {
153
+ llvm::SmallPtrSet<const VarDecl *, 16 > AllVarDecls =
154
+ allVarDeclsExprs (*MatchedDecl, *MatchedFunc, *Result.Context );
155
+ if (!AllVarDecls.empty ()) {
156
+ // x is referenced by local var, it may outlive the "use"
134
157
return ;
135
158
}
136
159
}
160
+
161
+ llvm::SmallPtrSet<const DeclRefExpr *, 16 > AllReferences =
162
+ allDeclRefExprsHonourLambda (*MatchedDecl, *MatchedFunc, *Result.Context );
137
163
const Expr *LastUsage = getLastVarUsage (AllReferences);
138
164
139
165
if (LastUsage && LastUsage->getBeginLoc () > MatchedUse->getBeginLoc ()) {
0 commit comments