clang: lib/Analysis/CallGraph.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

23#include "llvm/ADT/PostOrderIterator.h"

24#include "llvm/ADT/Statistic.h"

25#include "llvm/Support/Casting.h"

26#include "llvm/Support/Compiler.h"

27#include "llvm/Support/DOTGraphTraits.h"

28#include "llvm/Support/GraphWriter.h"

29#include "llvm/Support/raw_ostream.h"

30#include

31#include

32#include

33

34using namespace clang;

35

36#define DEBUG_TYPE "CallGraph"

37

38STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges");

39STATISTIC(NumBlockCallEdges, "Number of block call edges");

40

41namespace {

42

43

44

45class CGBuilder : public StmtVisitor {

48

49public:

51

52 void VisitStmt(Stmt *S) { VisitChildren(S); }

53

54 Decl *getDeclFromCall(CallExpr *CE) {

56 return CalleeDecl;

57

58

60 if (BlockExpr *Block = dyn_cast(CEE)) {

61 NumBlockCallEdges++;

62 return Block->getBlockDecl();

63 }

64

65 return nullptr;

66 }

67

68 void addCalledDecl(Decl *D, Expr *CallExpr) {

69 if (G->includeCalleeInGraph(D)) {

70 CallGraphNode *CalleeNode = G->getOrInsertNode(D);

71 CallerNode->addCallee({CalleeNode, CallExpr});

72 }

73 }

74

75 void VisitCallExpr(CallExpr *CE) {

76 if (Decl *D = getDeclFromCall(CE))

77 addCalledDecl(D, CE);

78 VisitChildren(CE);

79 }

80

81 void VisitLambdaExpr(LambdaExpr *LE) {

82 if (FunctionTemplateDecl *FTD = LE->getDependentCallOperator())

83 for (FunctionDecl *FD : FTD->specializations())

84 G->VisitFunctionDecl(FD);

85 else if (CXXMethodDecl *MD = LE->getCallOperator())

86 G->VisitFunctionDecl(MD);

87 }

88

89 void VisitCXXNewExpr(CXXNewExpr *E) {

91 addCalledDecl(FD, E);

92 VisitChildren(E);

93 }

94

95 void VisitCXXConstructExpr(CXXConstructExpr *E) {

98 addCalledDecl(Def, E);

99 VisitChildren(E);

100 }

101

102

103 void VisitCXXDefaultArgExpr(CXXDefaultArgExpr *E) {

105 }

106

107

108 void VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E) {

110 }

111

112

113 void VisitObjCMessageExpr(ObjCMessageExpr *ME) {

116

117

118 Decl *D = nullptr;

120 D = IDecl->lookupPrivateMethod(Sel);

121 else

122 D = IDecl->lookupPrivateClassMethod(Sel);

123 if (D) {

124 addCalledDecl(D, ME);

125 NumObjCCallEdges++;

126 }

127 }

128 }

129

130 void VisitChildren(Stmt *S) {

131 for (Stmt *SubStmt : S->children())

132 if (SubStmt)

133 this->Visit(SubStmt);

134 }

135};

136

137}

138

140 if (BlockDecl *BD = dyn_cast(D))

141 addNodeForDecl(BD, true);

142

143 for (auto *I : D->decls())

144 if (auto *DC = dyn_cast(I))

146}

147

154

156

158 assert(D);

160 return false;

161

163}

164

166 if (const FunctionDecl *FD = dyn_cast(D)) {

167

168

169 if (FD->isDependentContext())

170 return false;

171

173 if (II && II->getName().starts_with("__inline"))

174 return false;

175 }

176

177 return true;

178}

179

180void CallGraph::addNodeForDecl(Decl* D, bool IsGlobal) {

181 assert(D);

182

183

185

186

187 CGBuilder builder(this, Node);

189 builder.Visit(Body);

190

191

192 if (auto constructor = dyn_cast(D)) {

194 builder.Visit(init->getInit());

195 }

196 }

197}

198

200 FunctionMapTy::const_iterator I = FunctionMap.find(F);

201 if (I == FunctionMap.end()) return nullptr;

202 return I->second.get();

203}

204

208

209 std::unique_ptr &Node = FunctionMap[F];

210 if (Node)

211 return Node.get();

212

213 Node = std::make_unique(F);

214

215 if (F)

216 Root->addCallee({Node.get(), nullptr});

217 return Node.get();

218}

219

221 OS << " --- Call graph Dump --- \n";

222

223

224

225 llvm::ReversePostOrderTraversal<const CallGraph *> RPOT(this);

227 OS << " Function: ";

228 if (N == Root)

229 OS << "< root >";

230 else

231 N->print(OS);

232

233 OS << " calls: ";

235 CE = N->end(); CI != CE; ++CI) {

236 assert(CI->Callee != Root && "No one can call the root node.");

237 CI->Callee->print(OS);

238 OS << " ";

239 }

240 OS << '\n';

241 }

242 OS.flush();

243}

244

246 print(llvm::errs());

247}

248

250 llvm::ViewGraph(this, "CallGraph");

251}

252

254 if (const NamedDecl *ND = dyn_cast_or_null(FD))

255 return ND->printQualifiedName(os);

256 os << "< >";

257}

258

260 print(llvm::errs());

261}

262

263namespace llvm {

264

265template <>

268

271 if (CG->getRoot() == Node) {

272 return "< root >";

273 }

274 if (const NamedDecl *ND = dyn_cast_or_null(Node->getDecl()))

275 return ND->getNameAsString();

276 else

277 return "< >";

278 }

279};

280

281}

STATISTIC(NumObjCCallEdges, "Number of Objective-C method call edges")

Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Represents a block literal declaration, which is like an unnamed FunctionDecl.

CXXConstructorDecl * getConstructor() const

Get the constructor that this expression will (ultimately) call.

Represents a C++ base or member initializer.

Expr * getExpr()

Get the initialization expression that will be used.

FunctionDecl * getOperatorNew() const

FunctionDecl * getDirectCallee()

If the callee is a FunctionDecl, return it. Otherwise return null.

void dump() const

Definition CallGraph.cpp:259

void print(raw_ostream &os) const

Definition CallGraph.cpp:253

SmallVectorImpl< CallRecord >::const_iterator const_iterator

The AST-based call graph.

void viewGraph() const

Definition CallGraph.cpp:249

CallGraph()

Definition CallGraph.cpp:148

CallGraphNode * getNode(const Decl *) const

Lookup the node for the given declaration.

Definition CallGraph.cpp:199

void dump() const

Definition CallGraph.cpp:245

void addNodesForBlocks(DeclContext *D)

Definition CallGraph.cpp:139

CallGraphNode * getOrInsertNode(Decl *)

Lookup the node for the given declaration.

Definition CallGraph.cpp:205

void print(raw_ostream &os) const

Definition CallGraph.cpp:220

friend class CallGraphNode

static bool includeCalleeInGraph(const Decl *D)

Determine if a declaration should be included in the graph for the purposes of being a callee.

Definition CallGraph.cpp:165

CallGraphNode * getRoot() const

Get the virtual root of the graph, all the functions available externally are represented as callees ...

static bool includeInGraph(const Decl *D)

Determine if a declaration should be included in the graph.

Definition CallGraph.cpp:157

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

decl_range decls() const

decls_begin/decls_end - Iterate over the declarations stored in this context.

Decl - This represents one declaration (or definition), e.g.

virtual Stmt * getBody() const

getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...

virtual bool hasBody() const

Returns true if this Decl represents a declaration for a body of code, such as a function or method d...

virtual Decl * getCanonicalDecl()

Retrieves the "canonical" declaration of the given declaration.

bool ShouldVisitTemplateInstantiations

bool ShouldVisitImplicitCode

bool ShouldWalkTypesOfTypeLocs

Expr * IgnoreParenImpCasts() LLVM_READONLY

Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...

Represents a function declaration or definition.

FunctionDecl * getDefinition()

Get the definition for this declaration.

One of these records is kept for each identifier that is lexed.

StringRef getName() const

Return the actual identifier string.

This represents a decl that may have a name.

Selector getSelector() const

bool isInstanceMessage() const

Determine whether this is an instance message to either a computed object or to super.

ObjCInterfaceDecl * getReceiverInterface() const

Retrieve the Objective-C interface to which this message is being directed, if known.

StmtVisitor - This class implements a simple visitor for Stmt subclasses.

Stmt - This represents one statement.

bool LE(InterpState &S, CodePtr OpPC)

std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl

All declarations that can appear in a module declaration.

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

Diagnostic wrappers for TextAPI types for error reporting.

DOTGraphTraits(bool isSimple=false)

Definition CallGraph.cpp:267

static std::string getNodeLabel(const CallGraphNode *Node, const CallGraph *CG)

Definition CallGraph.cpp:269