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/AST/Expr.h"
20 #include "clang/Analysis/CFG.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/FoldingSet.h"
23 #include "llvm/ADT/IntrusiveRefCntPtr.h"
24 #include "llvm/ADT/OwningPtr.h"
25 #include "llvm/ADT/PointerUnion.h"
26 #include "llvm/Support/Allocator.h"
32 class CFGReverseBlockReachabilityAnalysis;
35 class ManagedAnalysis;
37 class PseudoConstantAnalysis;
38 class ImplicitParamDecl;
39 class LocationContextManager;
40 class StackFrameContext;
41 class BlockInvocationContext;
42 class AnalysisDeclContextManager;
43 class LocationContext;
45 namespace idx { class TranslationUnit; }
47 /// The base class of a hierarchy of objects representing analyses tied
48 /// to AnalysisDeclContext.
49 class ManagedAnalysis {
53 virtual ~ManagedAnalysis();
55 // Subclasses need to implement:
57 // static const void *getTag();
59 // Which returns a fixed pointer address to distinguish classes of
60 // analysis objects. They also need to implement:
62 // static [Derived*] create(AnalysisDeclContext &Ctx);
64 // which creates the analysis object given an AnalysisDeclContext.
68 /// AnalysisDeclContext contains the context data for the function or method
70 class AnalysisDeclContext {
71 /// Backpoint to the AnalysisManager object that created this
72 /// AnalysisDeclContext. This may be null.
73 AnalysisDeclContextManager *Manager;
77 OwningPtr<CFG> cfg, completeCFG;
78 OwningPtr<CFGStmtMap> cfgStmtMap;
80 CFG::BuildOptions cfgBuildOptions;
81 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
83 bool builtCFG, builtCompleteCFG;
84 OwningPtr<ParentMap> PM;
85 OwningPtr<PseudoConstantAnalysis> PCA;
86 OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA;
88 llvm::BumpPtrAllocator A;
90 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
92 void *ManagedAnalyses;
95 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
98 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
100 const CFG::BuildOptions &BuildOptions);
102 ~AnalysisDeclContext();
104 ASTContext &getASTContext() const { return D->getASTContext(); }
105 const Decl *getDecl() const { return D; }
107 /// Return the AnalysisDeclContextManager (if any) that created
108 /// this AnalysisDeclContext.
109 AnalysisDeclContextManager *getManager() const {
113 /// Return the build options used to construct the CFG.
114 CFG::BuildOptions &getCFGBuildOptions() {
115 return cfgBuildOptions;
118 const CFG::BuildOptions &getCFGBuildOptions() const {
119 return cfgBuildOptions;
122 /// getAddEHEdges - Return true iff we are adding exceptional edges from
123 /// callExprs. If this is false, then try/catch statements and blocks
124 /// reachable from them can appear to be dead in the CFG, analysis passes must
126 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
127 bool getUseUnoptimizedCFG() const {
128 return !cfgBuildOptions.PruneTriviallyFalseEdges;
130 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
131 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
133 void registerForcedBlockExpression(const Stmt *stmt);
134 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
136 /// \brief Get the body of the Declaration.
137 Stmt *getBody() const;
139 /// \brief Get the body of the Declaration.
140 /// \param[out] IsAutosynthesized Specifies if the body is auto-generated
142 Stmt *getBody(bool &IsAutosynthesized) const;
144 /// \brief Checks if the body of the Decl is generated by the BodyFarm.
146 /// Note, the lookup is not free. We are going to call getBody behind
149 bool isBodyAutosynthesized() const;
153 CFGStmtMap *getCFGStmtMap();
155 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
157 /// Return a version of the CFG without any edges pruned.
158 CFG *getUnoptimizedCFG();
160 void dumpCFG(bool ShowColors);
162 /// \brief Returns true if we have built a CFG for this analysis context.
163 /// Note that this doesn't correspond to whether or not a valid CFG exists, it
164 /// corresponds to whether we *attempted* to build one.
165 bool isCFGBuilt() const { return builtCFG; }
167 ParentMap &getParentMap();
168 PseudoConstantAnalysis *getPseudoConstantAnalysis();
170 typedef const VarDecl * const * referenced_decls_iterator;
172 std::pair<referenced_decls_iterator, referenced_decls_iterator>
173 getReferencedBlockVars(const BlockDecl *BD);
175 /// Return the ImplicitParamDecl* associated with 'self' if this
176 /// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise.
177 const ImplicitParamDecl *getSelfDecl() const;
179 const StackFrameContext *getStackFrame(LocationContext const *Parent,
184 const BlockInvocationContext *
185 getBlockInvocationContext(const LocationContext *parent,
187 const void *ContextData);
189 /// Return the specified analysis object, lazily running the analysis if
190 /// necessary. Return NULL if the analysis could not run.
191 template <typename T>
193 const void *tag = T::getTag();
194 ManagedAnalysis *&data = getAnalysisImpl(tag);
196 data = T::create(*this);
198 return static_cast<T*>(data);
201 ManagedAnalysis *&getAnalysisImpl(const void* tag);
203 LocationContextManager &getLocationContextManager();
206 class LocationContext : public llvm::FoldingSetNode {
208 enum ContextKind { StackFrame, Scope, Block };
213 // AnalysisDeclContext can't be const since some methods may modify its
215 AnalysisDeclContext *Ctx;
217 const LocationContext *Parent;
220 LocationContext(ContextKind k, AnalysisDeclContext *ctx,
221 const LocationContext *parent)
222 : Kind(k), Ctx(ctx), Parent(parent) {}
225 virtual ~LocationContext();
227 ContextKind getKind() const { return Kind; }
229 AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
231 const LocationContext *getParent() const { return Parent; }
233 bool isParentOf(const LocationContext *LC) const;
235 const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); }
237 CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); }
239 template <typename T>
240 T *getAnalysis() const {
241 return getAnalysisDeclContext()->getAnalysis<T>();
244 ParentMap &getParentMap() const {
245 return getAnalysisDeclContext()->getParentMap();
248 const ImplicitParamDecl *getSelfDecl() const {
249 return Ctx->getSelfDecl();
252 const StackFrameContext *getCurrentStackFrame() const;
254 /// Return true if the current LocationContext has no caller context.
255 virtual bool inTopFrame() const;
257 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
259 LLVM_ATTRIBUTE_USED void dumpStack() const;
262 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
264 AnalysisDeclContext *ctx,
265 const LocationContext *parent,
269 class StackFrameContext : public LocationContext {
270 // The callsite where this stack frame is established.
271 const Stmt *CallSite;
273 // The parent block of the callsite.
274 const CFGBlock *Block;
276 // The index of the callsite in the CFGBlock.
279 friend class LocationContextManager;
280 StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
281 const Stmt *s, const CFGBlock *blk,
283 : LocationContext(StackFrame, ctx, parent), CallSite(s),
284 Block(blk), Index(idx) {}
287 ~StackFrameContext() {}
289 const Stmt *getCallSite() const { return CallSite; }
291 const CFGBlock *getCallSiteBlock() const { return Block; }
293 /// Return true if the current LocationContext has no caller context.
294 virtual bool inTopFrame() const { return getParent() == 0; }
296 unsigned getIndex() const { return Index; }
298 void Profile(llvm::FoldingSetNodeID &ID);
300 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
301 const LocationContext *parent, const Stmt *s,
302 const CFGBlock *blk, unsigned idx) {
303 ProfileCommon(ID, StackFrame, ctx, parent, s);
308 static bool classof(const LocationContext *Ctx) {
309 return Ctx->getKind() == StackFrame;
313 class ScopeContext : public LocationContext {
316 friend class LocationContextManager;
317 ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
319 : LocationContext(Scope, ctx, parent), Enter(s) {}
324 void Profile(llvm::FoldingSetNodeID &ID);
326 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
327 const LocationContext *parent, const Stmt *s) {
328 ProfileCommon(ID, Scope, ctx, parent, s);
331 static bool classof(const LocationContext *Ctx) {
332 return Ctx->getKind() == Scope;
336 class BlockInvocationContext : public LocationContext {
339 // FIXME: Come up with a more type-safe way to model context-sensitivity.
340 const void *ContextData;
342 friend class LocationContextManager;
344 BlockInvocationContext(AnalysisDeclContext *ctx,
345 const LocationContext *parent,
346 const BlockDecl *bd, const void *contextData)
347 : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
350 ~BlockInvocationContext() {}
352 const BlockDecl *getBlockDecl() const { return BD; }
354 const void *getContextData() const { return ContextData; }
356 void Profile(llvm::FoldingSetNodeID &ID);
358 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
359 const LocationContext *parent, const BlockDecl *bd,
360 const void *contextData) {
361 ProfileCommon(ID, Block, ctx, parent, bd);
362 ID.AddPointer(contextData);
365 static bool classof(const LocationContext *Ctx) {
366 return Ctx->getKind() == Block;
370 class LocationContextManager {
371 llvm::FoldingSet<LocationContext> Contexts;
373 ~LocationContextManager();
375 const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
376 const LocationContext *parent,
378 const CFGBlock *blk, unsigned idx);
380 const ScopeContext *getScope(AnalysisDeclContext *ctx,
381 const LocationContext *parent,
384 const BlockInvocationContext *
385 getBlockInvocationContext(AnalysisDeclContext *ctx,
386 const LocationContext *parent,
388 const void *ContextData);
390 /// Discard all previously created LocationContext objects.
393 template <typename LOC, typename DATA>
394 const LOC *getLocationContext(AnalysisDeclContext *ctx,
395 const LocationContext *parent,
399 class AnalysisDeclContextManager {
400 typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap;
403 LocationContextManager LocContexts;
404 CFG::BuildOptions cfgBuildOptions;
406 /// Flag to indicate whether or not bodies should be synthesized
407 /// for well-known functions.
408 bool SynthesizeBodies;
411 AnalysisDeclContextManager(bool useUnoptimizedCFG = false,
412 bool addImplicitDtors = false,
413 bool addInitializers = false,
414 bool addTemporaryDtors = false,
415 bool synthesizeBodies = false,
416 bool addStaticInitBranches = false);
418 ~AnalysisDeclContextManager();
420 AnalysisDeclContext *getContext(const Decl *D);
422 bool getUseUnoptimizedCFG() const {
423 return !cfgBuildOptions.PruneTriviallyFalseEdges;
426 CFG::BuildOptions &getCFGBuildOptions() {
427 return cfgBuildOptions;
430 /// Return true if faux bodies should be synthesized for well-known
432 bool synthesizeBodies() const { return SynthesizeBodies; }
434 const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
435 LocationContext const *Parent,
439 return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
442 // Get the top level stack frame.
443 const StackFrameContext *getStackFrame(const Decl *D) {
444 return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0);
447 // Get a stack frame with parent.
448 StackFrameContext const *getStackFrame(const Decl *D,
449 LocationContext const *Parent,
453 return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
456 /// Discard all previously created AnalysisDeclContexts.
460 friend class AnalysisDeclContext;
462 LocationContextManager &getLocationContextManager() {
467 } // end clang namespace