1 //=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines AnalysisDeclContext, a class that manages the analysis
11 // context data for path sensitive analysis.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
16 #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
18 #include "clang/AST/Decl.h"
19 #include "clang/Analysis/CFG.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/FoldingSet.h"
22 #include "llvm/ADT/OwningPtr.h"
23 #include "llvm/Support/Allocator.h"
28 class CFGReverseBlockReachabilityAnalysis;
31 class ManagedAnalysis;
33 class PseudoConstantAnalysis;
34 class LocationContextManager;
35 class StackFrameContext;
36 class BlockInvocationContext;
37 class AnalysisDeclContextManager;
38 class LocationContext;
40 namespace idx { class TranslationUnit; }
42 /// The base class of a hierarchy of objects representing analyses tied
43 /// to AnalysisDeclContext.
44 class ManagedAnalysis {
48 virtual ~ManagedAnalysis();
50 // Subclasses need to implement:
52 // static const void *getTag();
54 // Which returns a fixed pointer address to distinguish classes of
55 // analysis objects. They also need to implement:
57 // static [Derived*] create(AnalysisDeclContext &Ctx);
59 // which creates the analysis object given an AnalysisDeclContext.
63 /// AnalysisDeclContext contains the context data for the function or method
65 class AnalysisDeclContext {
66 /// Backpoint to the AnalysisManager object that created this
67 /// AnalysisDeclContext. This may be null.
68 AnalysisDeclContextManager *Manager;
72 OwningPtr<CFG> cfg, completeCFG;
73 OwningPtr<CFGStmtMap> cfgStmtMap;
75 CFG::BuildOptions cfgBuildOptions;
76 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
78 bool builtCFG, builtCompleteCFG;
79 OwningPtr<ParentMap> PM;
80 OwningPtr<PseudoConstantAnalysis> PCA;
81 OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA;
83 llvm::BumpPtrAllocator A;
85 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
87 void *ManagedAnalyses;
90 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
93 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
95 const CFG::BuildOptions &BuildOptions);
97 ~AnalysisDeclContext();
99 ASTContext &getASTContext() const { return D->getASTContext(); }
100 const Decl *getDecl() const { return D; }
102 /// Return the AnalysisDeclContextManager (if any) that created
103 /// this AnalysisDeclContext.
104 AnalysisDeclContextManager *getManager() const {
108 /// Return the build options used to construct the CFG.
109 CFG::BuildOptions &getCFGBuildOptions() {
110 return cfgBuildOptions;
113 const CFG::BuildOptions &getCFGBuildOptions() const {
114 return cfgBuildOptions;
117 /// getAddEHEdges - Return true iff we are adding exceptional edges from
118 /// callExprs. If this is false, then try/catch statements and blocks
119 /// reachable from them can appear to be dead in the CFG, analysis passes must
121 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
122 bool getUseUnoptimizedCFG() const {
123 return !cfgBuildOptions.PruneTriviallyFalseEdges;
125 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
126 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
128 void registerForcedBlockExpression(const Stmt *stmt);
129 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
131 /// \brief Get the body of the Declaration.
132 Stmt *getBody() const;
134 /// \brief Get the body of the Declaration.
135 /// \param[out] IsAutosynthesized Specifies if the body is auto-generated
137 Stmt *getBody(bool &IsAutosynthesized) const;
139 /// \brief Checks if the body of the Decl is generated by the BodyFarm.
141 /// Note, the lookup is not free. We are going to call getBody behind
144 bool isBodyAutosynthesized() const;
148 CFGStmtMap *getCFGStmtMap();
150 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
152 /// Return a version of the CFG without any edges pruned.
153 CFG *getUnoptimizedCFG();
155 void dumpCFG(bool ShowColors);
157 /// \brief Returns true if we have built a CFG for this analysis context.
158 /// Note that this doesn't correspond to whether or not a valid CFG exists, it
159 /// corresponds to whether we *attempted* to build one.
160 bool isCFGBuilt() const { return builtCFG; }
162 ParentMap &getParentMap();
163 PseudoConstantAnalysis *getPseudoConstantAnalysis();
165 typedef const VarDecl * const * referenced_decls_iterator;
167 std::pair<referenced_decls_iterator, referenced_decls_iterator>
168 getReferencedBlockVars(const BlockDecl *BD);
170 /// Return the ImplicitParamDecl* associated with 'self' if this
171 /// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise.
172 const ImplicitParamDecl *getSelfDecl() const;
174 const StackFrameContext *getStackFrame(LocationContext const *Parent,
179 const BlockInvocationContext *
180 getBlockInvocationContext(const LocationContext *parent,
182 const void *ContextData);
184 /// Return the specified analysis object, lazily running the analysis if
185 /// necessary. Return NULL if the analysis could not run.
186 template <typename T>
188 const void *tag = T::getTag();
189 ManagedAnalysis *&data = getAnalysisImpl(tag);
191 data = T::create(*this);
193 return static_cast<T*>(data);
196 ManagedAnalysis *&getAnalysisImpl(const void* tag);
198 LocationContextManager &getLocationContextManager();
201 class LocationContext : public llvm::FoldingSetNode {
203 enum ContextKind { StackFrame, Scope, Block };
208 // AnalysisDeclContext can't be const since some methods may modify its
210 AnalysisDeclContext *Ctx;
212 const LocationContext *Parent;
215 LocationContext(ContextKind k, AnalysisDeclContext *ctx,
216 const LocationContext *parent)
217 : Kind(k), Ctx(ctx), Parent(parent) {}
220 virtual ~LocationContext();
222 ContextKind getKind() const { return Kind; }
224 AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
226 const LocationContext *getParent() const { return Parent; }
228 bool isParentOf(const LocationContext *LC) const;
230 const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); }
232 CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); }
234 template <typename T>
235 T *getAnalysis() const {
236 return getAnalysisDeclContext()->getAnalysis<T>();
239 ParentMap &getParentMap() const {
240 return getAnalysisDeclContext()->getParentMap();
243 const ImplicitParamDecl *getSelfDecl() const {
244 return Ctx->getSelfDecl();
247 const StackFrameContext *getCurrentStackFrame() const;
249 /// Return true if the current LocationContext has no caller context.
250 virtual bool inTopFrame() const;
252 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
254 void dumpStack(raw_ostream &OS, StringRef Indent = "") const;
255 LLVM_ATTRIBUTE_USED void dumpStack() const;
258 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
260 AnalysisDeclContext *ctx,
261 const LocationContext *parent,
265 class StackFrameContext : public LocationContext {
266 // The callsite where this stack frame is established.
267 const Stmt *CallSite;
269 // The parent block of the callsite.
270 const CFGBlock *Block;
272 // The index of the callsite in the CFGBlock.
275 friend class LocationContextManager;
276 StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
277 const Stmt *s, const CFGBlock *blk,
279 : LocationContext(StackFrame, ctx, parent), CallSite(s),
280 Block(blk), Index(idx) {}
283 ~StackFrameContext() {}
285 const Stmt *getCallSite() const { return CallSite; }
287 const CFGBlock *getCallSiteBlock() const { return Block; }
289 /// Return true if the current LocationContext has no caller context.
290 virtual bool inTopFrame() const { return getParent() == 0; }
292 unsigned getIndex() const { return Index; }
294 void Profile(llvm::FoldingSetNodeID &ID);
296 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
297 const LocationContext *parent, const Stmt *s,
298 const CFGBlock *blk, unsigned idx) {
299 ProfileCommon(ID, StackFrame, ctx, parent, s);
304 static bool classof(const LocationContext *Ctx) {
305 return Ctx->getKind() == StackFrame;
309 class ScopeContext : public LocationContext {
312 friend class LocationContextManager;
313 ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
315 : LocationContext(Scope, ctx, parent), Enter(s) {}
320 void Profile(llvm::FoldingSetNodeID &ID);
322 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
323 const LocationContext *parent, const Stmt *s) {
324 ProfileCommon(ID, Scope, ctx, parent, s);
327 static bool classof(const LocationContext *Ctx) {
328 return Ctx->getKind() == Scope;
332 class BlockInvocationContext : public LocationContext {
335 // FIXME: Come up with a more type-safe way to model context-sensitivity.
336 const void *ContextData;
338 friend class LocationContextManager;
340 BlockInvocationContext(AnalysisDeclContext *ctx,
341 const LocationContext *parent,
342 const BlockDecl *bd, const void *contextData)
343 : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
346 ~BlockInvocationContext() {}
348 const BlockDecl *getBlockDecl() const { return BD; }
350 const void *getContextData() const { return ContextData; }
352 void Profile(llvm::FoldingSetNodeID &ID);
354 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
355 const LocationContext *parent, const BlockDecl *bd,
356 const void *contextData) {
357 ProfileCommon(ID, Block, ctx, parent, bd);
358 ID.AddPointer(contextData);
361 static bool classof(const LocationContext *Ctx) {
362 return Ctx->getKind() == Block;
366 class LocationContextManager {
367 llvm::FoldingSet<LocationContext> Contexts;
369 ~LocationContextManager();
371 const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
372 const LocationContext *parent,
374 const CFGBlock *blk, unsigned idx);
376 const ScopeContext *getScope(AnalysisDeclContext *ctx,
377 const LocationContext *parent,
380 const BlockInvocationContext *
381 getBlockInvocationContext(AnalysisDeclContext *ctx,
382 const LocationContext *parent,
384 const void *ContextData);
386 /// Discard all previously created LocationContext objects.
389 template <typename LOC, typename DATA>
390 const LOC *getLocationContext(AnalysisDeclContext *ctx,
391 const LocationContext *parent,
395 class AnalysisDeclContextManager {
396 typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap;
399 LocationContextManager LocContexts;
400 CFG::BuildOptions cfgBuildOptions;
402 /// Flag to indicate whether or not bodies should be synthesized
403 /// for well-known functions.
404 bool SynthesizeBodies;
407 AnalysisDeclContextManager(bool useUnoptimizedCFG = false,
408 bool addImplicitDtors = false,
409 bool addInitializers = false,
410 bool addTemporaryDtors = false,
411 bool synthesizeBodies = false,
412 bool addStaticInitBranches = false);
414 ~AnalysisDeclContextManager();
416 AnalysisDeclContext *getContext(const Decl *D);
418 bool getUseUnoptimizedCFG() const {
419 return !cfgBuildOptions.PruneTriviallyFalseEdges;
422 CFG::BuildOptions &getCFGBuildOptions() {
423 return cfgBuildOptions;
426 /// Return true if faux bodies should be synthesized for well-known
428 bool synthesizeBodies() const { return SynthesizeBodies; }
430 const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
431 LocationContext const *Parent,
435 return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
438 // Get the top level stack frame.
439 const StackFrameContext *getStackFrame(const Decl *D) {
440 return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0);
443 // Get a stack frame with parent.
444 StackFrameContext const *getStackFrame(const Decl *D,
445 LocationContext const *Parent,
449 return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
452 /// Discard all previously created AnalysisDeclContexts.
456 friend class AnalysisDeclContext;
458 LocationContextManager &getLocationContextManager() {
463 } // end clang namespace