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 AnalysisContext, a class that manages the analysis context
11 // 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/OwningPtr.h"
22 #include "llvm/ADT/FoldingSet.h"
23 #include "llvm/ADT/PointerUnion.h"
24 #include "llvm/ADT/DenseMap.h"
25 #include "llvm/Support/Allocator.h"
31 class CFGReverseBlockReachabilityAnalysis;
35 class PseudoConstantAnalysis;
36 class ImplicitParamDecl;
37 class LocationContextManager;
38 class StackFrameContext;
40 namespace idx { class TranslationUnit; }
42 /// AnalysisContext contains the context data for the function or method under
44 class AnalysisContext {
47 // TranslationUnit is NULL if we don't have multiple translation units.
48 idx::TranslationUnit *TU;
50 llvm::OwningPtr<CFG> cfg, completeCFG;
51 llvm::OwningPtr<CFGStmtMap> cfgStmtMap;
53 CFG::BuildOptions cfgBuildOptions;
54 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
56 bool builtCFG, builtCompleteCFG;
57 const bool useUnoptimizedCFG;
59 llvm::OwningPtr<LiveVariables> liveness;
60 llvm::OwningPtr<LiveVariables> relaxedLiveness;
61 llvm::OwningPtr<ParentMap> PM;
62 llvm::OwningPtr<PseudoConstantAnalysis> PCA;
63 llvm::OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA;
65 llvm::BumpPtrAllocator A;
68 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
71 AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
72 bool useUnoptimizedCFG = false,
73 bool addehedges = false,
74 bool addImplicitDtors = false,
75 bool addInitializers = false);
79 ASTContext &getASTContext() { return D->getASTContext(); }
80 const Decl *getDecl() const { return D; }
82 idx::TranslationUnit *getTranslationUnit() const { return TU; }
84 /// getAddEHEdges - Return true iff we are adding exceptional edges from
85 /// callExprs. If this is false, then try/catch statements and blocks
86 /// reachable from them can appear to be dead in the CFG, analysis passes must
88 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
89 bool getUseUnoptimizedCFG() const {
90 return cfgBuildOptions.PruneTriviallyFalseEdges;
92 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
93 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
95 void registerForcedBlockExpression(const Stmt *stmt);
96 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
101 CFGStmtMap *getCFGStmtMap();
103 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
105 /// Return a version of the CFG without any edges pruned.
106 CFG *getUnoptimizedCFG();
110 /// \brief Returns true if we have built a CFG for this analysis context.
111 /// Note that this doesn't correspond to whether or not a valid CFG exists, it
112 /// corresponds to whether we *attempted* to build one.
113 bool isCFGBuilt() const { return builtCFG; }
115 ParentMap &getParentMap();
116 PseudoConstantAnalysis *getPseudoConstantAnalysis();
117 LiveVariables *getLiveVariables();
118 LiveVariables *getRelaxedLiveVariables();
120 typedef const VarDecl * const * referenced_decls_iterator;
122 std::pair<referenced_decls_iterator, referenced_decls_iterator>
123 getReferencedBlockVars(const BlockDecl *BD);
125 /// Return the ImplicitParamDecl* associated with 'self' if this
126 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
127 const ImplicitParamDecl *getSelfDecl() const;
130 class AnalysisContextManager {
131 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
133 bool UseUnoptimizedCFG;
134 bool AddImplicitDtors;
135 bool AddInitializers;
137 AnalysisContextManager(bool useUnoptimizedCFG = false,
138 bool addImplicitDtors = false, bool addInitializers = false)
139 : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
140 AddInitializers(addInitializers) {}
142 ~AnalysisContextManager();
144 AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
146 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
147 bool getAddImplicitDtors() const { return AddImplicitDtors; }
148 bool getAddInitializers() const { return AddInitializers; }
150 // Discard all previously created AnalysisContexts.
154 class LocationContext : public llvm::FoldingSetNode {
156 enum ContextKind { StackFrame, Scope, Block };
161 // AnalysisContext can't be const since some methods may modify its member.
162 AnalysisContext *Ctx;
164 const LocationContext *Parent;
167 LocationContext(ContextKind k, AnalysisContext *ctx,
168 const LocationContext *parent)
169 : Kind(k), Ctx(ctx), Parent(parent) {}
172 virtual ~LocationContext();
174 ContextKind getKind() const { return Kind; }
176 AnalysisContext *getAnalysisContext() const { return Ctx; }
178 idx::TranslationUnit *getTranslationUnit() const {
179 return Ctx->getTranslationUnit();
182 const LocationContext *getParent() const { return Parent; }
184 bool isParentOf(const LocationContext *LC) const;
186 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
188 CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
190 LiveVariables *getLiveVariables() const {
191 return getAnalysisContext()->getLiveVariables();
194 ParentMap &getParentMap() const {
195 return getAnalysisContext()->getParentMap();
198 const ImplicitParamDecl *getSelfDecl() const {
199 return Ctx->getSelfDecl();
202 const StackFrameContext *getCurrentStackFrame() const;
203 const StackFrameContext *
204 getStackFrameForDeclContext(const DeclContext *DC) const;
206 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
208 static bool classof(const LocationContext*) { return true; }
211 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
213 AnalysisContext *ctx,
214 const LocationContext *parent,
218 class StackFrameContext : public LocationContext {
219 // The callsite where this stack frame is established.
220 const Stmt *CallSite;
222 // The parent block of the callsite.
223 const CFGBlock *Block;
225 // The index of the callsite in the CFGBlock.
228 friend class LocationContextManager;
229 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
230 const Stmt *s, const CFGBlock *blk,
232 : LocationContext(StackFrame, ctx, parent), CallSite(s),
233 Block(blk), Index(idx) {}
236 ~StackFrameContext() {}
238 const Stmt *getCallSite() const { return CallSite; }
240 const CFGBlock *getCallSiteBlock() const { return Block; }
242 unsigned getIndex() const { return Index; }
244 void Profile(llvm::FoldingSetNodeID &ID);
246 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
247 const LocationContext *parent, const Stmt *s,
248 const CFGBlock *blk, unsigned idx) {
249 ProfileCommon(ID, StackFrame, ctx, parent, s);
254 static bool classof(const LocationContext* Ctx) {
255 return Ctx->getKind() == StackFrame;
259 class ScopeContext : public LocationContext {
262 friend class LocationContextManager;
263 ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
265 : LocationContext(Scope, ctx, parent), Enter(s) {}
270 void Profile(llvm::FoldingSetNodeID &ID);
272 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
273 const LocationContext *parent, const Stmt *s) {
274 ProfileCommon(ID, Scope, ctx, parent, s);
277 static bool classof(const LocationContext* Ctx) {
278 return Ctx->getKind() == Scope;
282 class BlockInvocationContext : public LocationContext {
283 // FIXME: Add back context-sensivity (we don't want libAnalysis to know
287 friend class LocationContextManager;
289 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
291 : LocationContext(Block, ctx, parent), BD(bd) {}
294 ~BlockInvocationContext() {}
296 const BlockDecl *getBlockDecl() const { return BD; }
298 void Profile(llvm::FoldingSetNodeID &ID);
300 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
301 const LocationContext *parent, const BlockDecl *bd) {
302 ProfileCommon(ID, Block, ctx, parent, bd);
305 static bool classof(const LocationContext* Ctx) {
306 return Ctx->getKind() == Block;
310 class LocationContextManager {
311 llvm::FoldingSet<LocationContext> Contexts;
313 ~LocationContextManager();
315 const StackFrameContext *getStackFrame(AnalysisContext *ctx,
316 const LocationContext *parent,
318 const CFGBlock *blk, unsigned idx);
320 const ScopeContext *getScope(AnalysisContext *ctx,
321 const LocationContext *parent,
324 /// Discard all previously created LocationContext objects.
327 template <typename LOC, typename DATA>
328 const LOC *getLocationContext(AnalysisContext *ctx,
329 const LocationContext *parent,
333 } // end clang namespace