Skip to content

Commit daccc50

Browse files
committed
[Summary] flag functions that call virtual funtions and non-functions
1 parent f71dd84 commit daccc50

File tree

5 files changed

+48
-30
lines changed

5 files changed

+48
-30
lines changed

clang/include/clang/Summary/SummaryAttribute.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class SummaryAttr {
2828

2929
virtual bool infer(const FunctionDecl *FD) const = 0;
3030
virtual bool merge(const FunctionSummary &Caller,
31-
const FunctionSummary &Callee) const = 0;
31+
const FunctionSummary *Callee) const = 0;
3232

3333
virtual std::string serialize() const { return std::string(Spelling); };
3434
virtual bool parse(std::string_view input) const {
@@ -42,7 +42,7 @@ class NoWriteGlobalAttr : public SummaryAttr {
4242
public:
4343
bool infer(const FunctionDecl *FD) const override final;
4444
bool merge(const FunctionSummary &Caller,
45-
const FunctionSummary &Callee) const override final;
45+
const FunctionSummary *Callee) const override final;
4646

4747
static bool classof(const SummaryAttr *A) {
4848
return A->getKind() == NO_WRITE_GLOBAL;

clang/include/clang/Summary/SummaryContext.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,16 @@ class FunctionSummary {
1010
SmallVector<char> ID;
1111
std::set<const SummaryAttr *> Attrs;
1212
std::set<SmallVector<char>> Calls;
13+
bool CallsOpaque;
1314

1415
public:
1516
FunctionSummary(SmallVector<char> ID, std::set<const SummaryAttr *> Attrs,
16-
std::set<SmallVector<char>> Calls);
17+
std::set<SmallVector<char>> Calls, bool CallsOpaque);
1718

1819
SmallVector<char> getID() const { return ID; }
1920
const std::set<const SummaryAttr *> &getAttributes() const { return Attrs; }
2021
const std::set<SmallVector<char>> &getCalls() const { return Calls; }
22+
bool callsOpaqueObject() const { return CallsOpaque; }
2123

2224
template <typename T> bool hasAttribute() const {
2325
for (auto &&attr : Attrs) {
@@ -41,7 +43,7 @@ class SummaryContext {
4143
std::vector<std::unique_ptr<SummaryAttr>> Attributes;
4244

4345
void CreateSummary(SmallVector<char> ID, std::set<const SummaryAttr *> Attrs,
44-
std::set<SmallVector<char>> Calls);
46+
std::set<SmallVector<char>> Calls, bool CallsOpaque);
4547
bool ReduceFunctionSummary(FunctionSummary &FunctionSummary);
4648

4749
template <typename T> void registerAttr();

clang/lib/Summary/SummaryAttribute.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ bool NoWriteGlobalAttr::infer(const FunctionDecl *FD) const {
3232
}
3333

3434
bool NoWriteGlobalAttr::merge(const FunctionSummary &Caller,
35-
const FunctionSummary &Callee) const {
36-
return Caller.getAttributes().count(this) &&
37-
Callee.getAttributes().count(this);
35+
const FunctionSummary *Callee) const {
36+
return !Caller.callsOpaqueObject() && Caller.getAttributes().count(this) &&
37+
Callee && Callee->getAttributes().count(this);
3838
}
3939
} // namespace clang

clang/lib/Summary/SummaryConsumer.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ void JSONPrintingSummaryConsumer::ProcessFunctionSummary(
1313
}
1414
});
1515
});
16-
JOS.attributeArray("calls", [&] {
17-
for (auto &&Call : Summary.getCalls()) {
18-
JOS.object([&] { JOS.attribute("id", llvm::json::Value(Call)); });
19-
}
16+
JOS.attributeObject("calls", [&] {
17+
JOS.attribute("opaque", llvm::json::Value(Summary.callsOpaqueObject()));
18+
JOS.attributeArray("functions", [&] {
19+
for (auto &&Call : Summary.getCalls()) {
20+
JOS.object([&] { JOS.attribute("id", llvm::json::Value(Call)); });
21+
}
22+
});
2023
});
2124
});
2225
}

clang/lib/Summary/SummaryContext.cpp

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ SmallVector<char> GetUSR(const FunctionDecl *FD) {
1515

1616
class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
1717
std::set<SmallVector<char>> Calls;
18+
bool callsOpaqueSymbol = false;
1819

1920
virtual void
2021
run(const ast_matchers::MatchFinder::MatchResult &Result) override {
@@ -23,28 +24,40 @@ class CallCollector : public ast_matchers::MatchFinder::MatchCallback {
2324
return;
2425

2526
const auto *Callee = llvm::dyn_cast<FunctionDecl>(Call->getCalleeDecl());
27+
if (!Callee) {
28+
callsOpaqueSymbol = true;
29+
return;
30+
}
31+
32+
if (const auto *MD = llvm::dyn_cast<CXXMethodDecl>(Callee);
33+
MD && MD->isVirtual()) {
34+
callsOpaqueSymbol = true;
35+
return;
36+
}
37+
2638
Calls.emplace(GetUSR(Callee));
2739
}
2840

2941
public:
30-
std::set<SmallVector<char>> collect(const FunctionDecl *FD) {
42+
std::pair<std::set<SmallVector<char>>, bool> collect(const FunctionDecl *FD) {
3143
using namespace ast_matchers;
3244
MatchFinder Finder;
3345

3446
Finder.addMatcher(functionDecl(forEachDescendant(callExpr().bind("call"))),
3547
this);
3648
Finder.match(*FD, FD->getASTContext());
3749

38-
return Calls;
50+
return {Calls, callsOpaqueSymbol};
3951
}
4052
};
4153
} // namespace
4254

4355
FunctionSummary::FunctionSummary(SmallVector<char> ID,
4456
std::set<const SummaryAttr *> FunctionAttrs,
45-
std::set<SmallVector<char>> Calls)
57+
std::set<SmallVector<char>> Calls,
58+
bool CallsOpaque)
4659
: ID(std::move(ID)), Attrs(std::move(FunctionAttrs)),
47-
Calls(std::move(Calls)) {}
60+
Calls(std::move(Calls)), CallsOpaque(CallsOpaque) {}
4861

4962
template <typename T> void SummaryContext::registerAttr() {
5063
std::unique_ptr<T> attr(new T());
@@ -60,9 +73,10 @@ SummaryContext::SummaryContext() { registerAttr<NoWriteGlobalAttr>(); }
6073

6174
void SummaryContext::CreateSummary(SmallVector<char> ID,
6275
std::set<const SummaryAttr *> Attrs,
63-
std::set<SmallVector<char>> Calls) {
76+
std::set<SmallVector<char>> Calls,
77+
bool CallsOpaque) {
6478
auto Summary = std::make_unique<FunctionSummary>(
65-
std::move(ID), std::move(Attrs), std::move(Calls));
79+
std::move(ID), std::move(Attrs), std::move(Calls), CallsOpaque);
6680
auto *SummaryPtr = FunctionSummaries.emplace_back(std::move(Summary)).get();
6781
IDToSummary[SummaryPtr->getID()] = SummaryPtr;
6882
}
@@ -81,7 +95,9 @@ void SummaryContext::SummarizeFunctionBody(const FunctionDecl *FD) {
8195
Attrs.emplace(Attr.get());
8296
}
8397

84-
CreateSummary(GetUSR(FD), std::move(Attrs), CallCollector().collect(FD));
98+
auto [calls, opaque] = CallCollector().collect(FD);
99+
100+
CreateSummary(GetUSR(FD), std::move(Attrs), std::move(calls), opaque);
85101
}
86102

87103
void SummaryContext::ParseSummaryFromJSON(const llvm::json::Array &Summary) {
@@ -101,14 +117,18 @@ void SummaryContext::ParseSummaryFromJSON(const llvm::json::Array &Summary) {
101117
}
102118

103119
std::set<SmallVector<char>> Calls;
104-
const llvm::json::Array *CallEntries = FunctionSummary->getArray("calls");
120+
const llvm::json::Object *CallsObject = FunctionSummary->getObject("calls");
121+
bool callsOpaue = *CallsObject->getBoolean("opaque");
122+
123+
const llvm::json::Array *CallEntries = CallsObject->getArray("functions");
105124
for (auto callIt = CallEntries->begin(); callIt != CallEntries->end();
106125
++callIt) {
107126
auto *Obj = callIt->getAsObject();
108127
Calls.emplace(SmallString<128>(*Obj->getString("id")));
109128
}
110129

111-
CreateSummary(std::move(ID), std::move(FunctionAttrs), std::move(Calls));
130+
CreateSummary(std::move(ID), std::move(FunctionAttrs), std::move(Calls),
131+
callsOpaue);
112132
}
113133
}
114134

@@ -118,17 +138,10 @@ bool SummaryContext::ReduceFunctionSummary(FunctionSummary &Function) {
118138
for (auto &&call : Function.getCalls()) {
119139
std::set<const SummaryAttr *> reducedAttrs;
120140

121-
// If we don't have a summary about a called function, we forget
122-
// everything about the current one as well.
123-
if (!IDToSummary.count(call)) {
124-
Function.replaceAttributes(std::move(reducedAttrs));
125-
return true;
126-
}
127-
128-
const FunctionSummary *callSummary = IDToSummary[call];
129-
141+
const FunctionSummary *callSummary =
142+
IDToSummary.count(call) ? IDToSummary[call] : nullptr;
130143
for (auto &&Attr : Attributes) {
131-
if (Attr->merge(Function, *callSummary))
144+
if (Attr->merge(Function, callSummary))
132145
reducedAttrs.emplace(Attr.get());
133146
}
134147

0 commit comments

Comments
 (0)