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/STLExtras.h"

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

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

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

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

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

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

31#include

32#include

33#include

34

35using namespace clang;

36

37#define DEBUG_TYPE "CallGraph"

38

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

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

41

42namespace {

43

44

45

46class CGBuilder : public StmtVisitor {

49

50public:

52

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

54

57 return CalleeDecl;

58

59

62 NumBlockCallEdges++;

63 return Block->getBlockDecl();

64 }

65

66 return nullptr;

67 }

68

73 }

74 }

75

76 void VisitCallExpr(CallExpr *CE) {

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

78 addCalledDecl(D, CE);

79 VisitChildren(CE);

80 }

81

82 void VisitLambdaExpr(LambdaExpr *LE) {

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

88 }

89

92 addCalledDecl(FD, E);

93 VisitChildren(E);

94 }

95

99 addCalledDecl(Def, E);

100 VisitChildren(E);

101 }

102

103

106 }

107

108

111 }

112

113

117

118

119 Decl *D = nullptr;

121 D = IDecl->lookupPrivateMethod(Sel);

122 else

123 D = IDecl->lookupPrivateClassMethod(Sel);

124 if (D) {

125 addCalledDecl(D, ME);

126 NumObjCCallEdges++;

127 }

128 }

129 }

130

131 void VisitChildren(Stmt *S) {

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

133 if (SubStmt)

134 this->Visit(SubStmt);

135 }

136};

137

138}

139

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

142 addNodeForDecl(BD, true);

143

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

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

147}

148

154}

155

157

159 assert(D);

161 return false;

162

164}

165

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

168

169

170 if (FD->isDependentContext())

171 return false;

172

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

175 return false;

176 }

177

178 return true;

179}

180

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

182 assert(D);

183

184

186

187

188 CGBuilder builder(this, Node);

190 builder.Visit(Body);

191

192

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

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

196 }

197 }

198}

199

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

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

203 return I->second.get();

204}

205

207 if (F && !isa(F))

209

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

213

214 Node = std::make_unique(F);

215

216 if (F)

219}

220

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

223

224

225

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

227 for (llvm::ReversePostOrderTraversal<const CallGraph *>::rpo_iterator

228 I = RPOT.begin(), E = RPOT.end(); I != E; ++I) {

230

231 OS << " Function: ";

232 if (N == Root)

233 OS << "< root >";

234 else

236

237 OS << " calls: ";

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

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

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

242 OS << " ";

243 }

244 OS << '\n';

245 }

246 OS.flush();

247}

248

250 print(llvm::errs());

251}

252

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

255}

256

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

259 return ND->printQualifiedName(os);

260 os << "< >";

261}

262

264 print(llvm::errs());

265}

266

267namespace llvm {

268

269template <>

272

276 return "< root >";

277 }

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

279 return ND->getNameAsString();

280 else

281 return "< >";

282 }

283};

284

285}

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.

BlockExpr - Adaptor class for mixing a BlockDecl with expressions.

Represents a call to a C++ constructor.

Represents a C++ constructor within a class.

Represents a C++ base or member initializer.

A default argument (C++ [dcl.fct.default]).

A use of a default initializer in a constructor or in aggregate initialization.

Represents a static or instance method of a struct/union/class.

Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

FunctionDecl * getDirectCallee()

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

iterator begin()

Iterators through all the callees/children of the node.

void print(raw_ostream &os) const

SmallVectorImpl< CallRecord >::const_iterator const_iterator

void addCallee(CallRecord Call)

The AST-based call graph.

CallGraphNode * getNode(const Decl *) const

Lookup the node for the given declaration.

void addNodesForBlocks(DeclContext *D)

bool VisitFunctionDecl(FunctionDecl *FD) override

Part of recursive declaration visitation.

CallGraphNode * getOrInsertNode(Decl *)

Lookup the node for the given declaration.

void print(raw_ostream &os) const

static bool includeCalleeInGraph(const Decl *D)

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

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.

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

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.

const T * get() const

Retrieve the stored node as type T.

bool ShouldWalkTypesOfTypeLocs

Whether this visitor should recurse into the types of TypeLocs.

bool ShouldVisitImplicitCode

Whether this visitor should recurse into implicit code, e.g.

bool ShouldVisitTemplateInstantiations

Whether this visitor should recurse into template instantiations.

This represents one expression.

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.

Declaration of a template function.

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

StringRef getName() const

Return the actual identifier string.

A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...

This represents a decl that may have a name.

Represents an ObjC class declaration.

An expression that sends a message to the given Objective-C object or class.

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.

Smart pointer class that efficiently represents Objective-C method names.

RetTy Visit(PTR(Stmt) S, ParamTys... P)

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

Stmt - This represents one statement.

bool LE(InterpState &S, CodePtr OpPC)

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

Diagnostic wrappers for TextAPI types for error reporting.

DOTGraphTraits(bool isSimple=false)

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