@@ -36,6 +36,21 @@ allDeclRefExprsHonourLambda(const VarDecl &VarDecl, const Decl &Decl,
3636 return DeclRefs;
3737}
3838
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+
3954static const Expr *
4055getLastVarUsage (const llvm::SmallPtrSet<const DeclRefExpr *, 16 > &Exprs) {
4156 const Expr *LastExpr = nullptr ;
@@ -54,6 +69,15 @@ AST_MATCHER(CXXRecordDecl, hasTrivialMoveConstructor) {
5469 return Node.hasDefinition () && Node.hasTrivialMoveConstructor ();
5570}
5671
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+
5781void LostStdMoveCheck::registerMatchers (MatchFinder *Finder) {
5882 auto ReturnParent =
5983 hasParent (expr (hasParent (cxxConstructExpr (hasParent (returnStmt ())))));
@@ -125,15 +149,17 @@ void LostStdMoveCheck::check(const MatchFinder::MatchResult &Result) {
125149 return ;
126150 }
127151
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"
134157 return ;
135158 }
136159 }
160+
161+ llvm::SmallPtrSet<const DeclRefExpr *, 16 > AllReferences =
162+ allDeclRefExprsHonourLambda (*MatchedDecl, *MatchedFunc, *Result.Context );
137163 const Expr *LastUsage = getLastVarUsage (AllReferences);
138164
139165 if (LastUsage && LastUsage->getBeginLoc () > MatchedUse->getBeginLoc ()) {
0 commit comments