@@ -36,4 +36,61 @@ bool NoWriteGlobalAttr::merge(const FunctionSummary &Caller,
3636 return !Caller.callsOpaqueObject () && Caller.getAttributes ().count (this ) &&
3737 Callee && Callee->getAttributes ().count (this );
3838}
39+
40+ bool NoWritePtrParameterAttr::infer (const FunctionDecl *FD) const {
41+ using namespace ast_matchers ;
42+ MatchFinder Finder;
43+
44+ class Callback : public ast_matchers ::MatchFinder::MatchCallback {
45+ public:
46+ bool MayWritePtrParam = false ;
47+
48+ void
49+ run (const ast_matchers::MatchFinder::MatchResult &Result) override final {
50+ const auto *FD = Result.Nodes .getNodeAs <FunctionDecl>(" fn" );
51+ if (!FD)
52+ return ;
53+
54+ MayWritePtrParam = true ;
55+ }
56+ } CB;
57+
58+ auto ptrParmDeclRef = declRefExpr (
59+ allOf (unless (hasAncestor (unaryOperator (hasOperatorName (" *" )))),
60+ to (parmVarDecl (hasType (pointerType ())))));
61+ auto ptrParmDereference = unaryOperator (allOf (
62+ hasOperatorName (" *" ),
63+ hasDescendant (declRefExpr (to (parmVarDecl (hasType (pointerType ())))))));
64+
65+ Finder.addMatcher (
66+ functionDecl (
67+ anyOf (
68+ // The value of the pointer is used to initialize a local
69+ // variable.
70+ forEachDescendant (
71+ varDecl (hasInitializer (hasDescendant (ptrParmDeclRef)))),
72+ // The ptr parameter appears on the RHS of an assignment.
73+ forEachDescendant (
74+ binaryOperator (isAssignmentOperator (),
75+ hasRHS (hasDescendant (ptrParmDeclRef)))),
76+ // The ptr is dereferenced on the LHS of an assignment.
77+ forEachDescendant (binaryOperator (
78+ isAssignmentOperator (),
79+ hasLHS (anyOf (ptrParmDereference,
80+ hasDescendant (ptrParmDereference))))),
81+ // The param is const casted
82+ forEachDescendant (cxxConstCastExpr (hasDescendant (ptrParmDeclRef)))
83+ // FIXME: handle member access
84+ ))
85+ .bind (" fn" ),
86+ &CB);
87+ Finder.match (*FD, FD->getASTContext ());
88+ return !CB.MayWritePtrParam ;
89+ }
90+
91+ bool NoWritePtrParameterAttr::merge (const FunctionSummary &Caller,
92+ const FunctionSummary *Callee) const {
93+ return !Caller.callsOpaqueObject () && Caller.getAttributes ().count (this ) &&
94+ Callee && Callee->getAttributes ().count (this );
95+ }
3996} // namespace clang
0 commit comments