24
24
#include " llvm/ADT/STLExtras.h"
25
25
#include " llvm/ADT/SetVector.h"
26
26
#include " llvm/ADT/SmallVector.h"
27
+ #include " llvm/ADT/iterator_range.h"
27
28
#include < memory>
28
29
29
30
namespace clang {
@@ -136,14 +137,23 @@ class CallGraph : public RecursiveASTVisitor<CallGraph> {
136
137
private:
137
138
// / Add the given declaration to the call graph.
138
139
void addNodeForDecl (Decl *D, bool IsGlobal);
139
-
140
- // / Allocate a new node in the graph.
141
- CallGraphNode *allocateNewNode (Decl *);
142
140
};
143
141
144
142
class CallGraphNode {
145
143
public:
146
- using CallRecord = CallGraphNode *;
144
+ struct CallRecord {
145
+ CallGraphNode *Callee;
146
+ Expr *CallExpr;
147
+
148
+ CallRecord () = default ;
149
+
150
+ CallRecord (CallGraphNode *Callee_, Expr *CallExpr_)
151
+ : Callee(Callee_), CallExpr(CallExpr_) {}
152
+
153
+ // The call destination is the only important data here,
154
+ // allow to transparently unwrap into it.
155
+ operator CallGraphNode *() const { return Callee; }
156
+ };
147
157
148
158
private:
149
159
// / The function/method declaration.
@@ -164,24 +174,63 @@ class CallGraphNode {
164
174
const_iterator begin () const { return CalledFunctions.begin (); }
165
175
const_iterator end () const { return CalledFunctions.end (); }
166
176
177
+ // / Iterator access to callees/children of the node.
178
+ llvm::iterator_range<iterator> callees () {
179
+ return llvm::make_range (begin (), end ());
180
+ }
181
+ llvm::iterator_range<const_iterator> callees () const {
182
+ return llvm::make_range (begin (), end ());
183
+ }
184
+
167
185
bool empty () const { return CalledFunctions.empty (); }
168
186
unsigned size () const { return CalledFunctions.size (); }
169
187
170
- void addCallee (CallGraphNode *N) {
171
- CalledFunctions.push_back (N);
172
- }
188
+ void addCallee (CallRecord Call) { CalledFunctions.push_back (Call); }
173
189
174
190
Decl *getDecl () const { return FD; }
175
191
176
192
void print (raw_ostream &os) const ;
177
193
void dump () const ;
178
194
};
179
195
196
+ // NOTE: we are comparing based on the callee only. So different call records
197
+ // (with different call expressions) to the same callee will compare equal!
198
+ inline bool operator ==(const CallGraphNode::CallRecord &LHS,
199
+ const CallGraphNode::CallRecord &RHS) {
200
+ return LHS.Callee == RHS.Callee ;
201
+ }
202
+
180
203
} // namespace clang
181
204
182
- // Graph traits for iteration, viewing.
183
205
namespace llvm {
184
206
207
+ // Specialize DenseMapInfo for clang::CallGraphNode::CallRecord.
208
+ template <> struct DenseMapInfo <clang::CallGraphNode::CallRecord> {
209
+ static inline clang::CallGraphNode::CallRecord getEmptyKey () {
210
+ return clang::CallGraphNode::CallRecord (
211
+ DenseMapInfo<clang::CallGraphNode *>::getEmptyKey (),
212
+ DenseMapInfo<clang::Expr *>::getEmptyKey ());
213
+ }
214
+
215
+ static inline clang::CallGraphNode::CallRecord getTombstoneKey () {
216
+ return clang::CallGraphNode::CallRecord (
217
+ DenseMapInfo<clang::CallGraphNode *>::getTombstoneKey (),
218
+ DenseMapInfo<clang::Expr *>::getTombstoneKey ());
219
+ }
220
+
221
+ static unsigned getHashValue (const clang::CallGraphNode::CallRecord &Val) {
222
+ // NOTE: we are comparing based on the callee only.
223
+ // Different call records with the same callee will compare equal!
224
+ return DenseMapInfo<clang::CallGraphNode *>::getHashValue (Val.Callee );
225
+ }
226
+
227
+ static bool isEqual (const clang::CallGraphNode::CallRecord &LHS,
228
+ const clang::CallGraphNode::CallRecord &RHS) {
229
+ return LHS == RHS;
230
+ }
231
+ };
232
+
233
+ // Graph traits for iteration, viewing.
185
234
template <> struct GraphTraits <clang::CallGraphNode*> {
186
235
using NodeType = clang::CallGraphNode;
187
236
using NodeRef = clang::CallGraphNode *;
0 commit comments