Skip to content

Commit 8739704

Browse files
committed
add new attribute that checks if a function modifies a pointer argument
1 parent e08fac7 commit 8739704

File tree

3 files changed

+78
-4
lines changed

3 files changed

+78
-4
lines changed

clang/include/clang/Summary/SummaryAttribute.h

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
#include "clang/ASTMatchers/ASTMatchFinder.h"
66

77
namespace clang {
8-
enum SummaryAttrKind {
9-
NO_WRITE_GLOBAL,
10-
};
8+
enum SummaryAttrKind { NO_WRITE_GLOBAL, NO_WRITE_PTR_PARAMETER };
119

1210
class FunctionSummary;
1311
class SummaryContext;
@@ -49,6 +47,22 @@ class NoWriteGlobalAttr : public SummaryAttr {
4947
}
5048
friend class SummaryContext;
5149
};
50+
51+
// FIXME: create a macro for attr declarations?
52+
class NoWritePtrParameterAttr : public SummaryAttr {
53+
NoWritePtrParameterAttr()
54+
: SummaryAttr(NO_WRITE_PTR_PARAMETER, "no_write_ptr_parameter") {}
55+
56+
public:
57+
bool infer(const FunctionDecl *FD) const override final;
58+
bool merge(const FunctionSummary &Caller,
59+
const FunctionSummary *Callee) const override final;
60+
61+
static bool classof(const SummaryAttr *A) {
62+
return A->getKind() == NO_WRITE_PTR_PARAMETER;
63+
}
64+
friend class SummaryContext;
65+
};
5266
} // namespace clang
5367

5468
#endif // LLVM_CLANG_SUMMARY_SUMMARYATTRIBUTEH

clang/lib/Summary/SummaryAttribute.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

clang/lib/Summary/SummaryContext.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ template <typename T> void SummaryContext::registerAttr() {
7474
KindToAttribute[Kind] = Attributes.emplace_back(std::move(attr)).get();
7575
}
7676

77-
SummaryContext::SummaryContext() { registerAttr<NoWriteGlobalAttr>(); }
77+
SummaryContext::SummaryContext() {
78+
registerAttr<NoWriteGlobalAttr>();
79+
registerAttr<NoWritePtrParameterAttr>();
80+
}
7881

7982
void SummaryContext::CreateSummary(SmallVector<char> ID,
8083
std::set<const SummaryAttr *> Attrs,

0 commit comments

Comments
 (0)