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 "llvm/ADT/OwningPtr.h"
21 #include "llvm/ADT/FoldingSet.h"
22 #include "llvm/ADT/PointerUnion.h"
23 #include "llvm/ADT/DenseMap.h"
24 #include "llvm/Support/Allocator.h"
32 class CFGReachabilityAnalysis;
36 class PseudoConstantAnalysis;
37 class ImplicitParamDecl;
38 class LocationContextManager;
39 class StackFrameContext;
41 namespace idx { class TranslationUnit; }
43 /// AnalysisContext contains the context data for the function or method under
45 class AnalysisContext {
48 // TranslationUnit is NULL if we don't have multiple translation units.
49 idx::TranslationUnit *TU;
51 // AnalysisContext owns the following data.
52 CFG *cfg, *completeCFG;
53 CFGStmtMap *cfgStmtMap;
54 bool builtCFG, builtCompleteCFG;
55 LiveVariables *liveness;
56 LiveVariables *relaxedLiveness;
58 PseudoConstantAnalysis *PCA;
59 CFGReachabilityAnalysis *CFA;
60 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
61 llvm::BumpPtrAllocator A;
62 bool UseUnoptimizedCFG;
64 bool AddImplicitDtors;
67 AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
68 bool useUnoptimizedCFG = false,
69 bool addehedges = false,
70 bool addImplicitDtors = false,
71 bool addInitializers = false)
72 : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0),
73 builtCFG(false), builtCompleteCFG(false),
74 liveness(0), relaxedLiveness(0), PM(0), PCA(0), CFA(0),
75 ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
76 AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors),
77 AddInitializers(addInitializers) {}
81 ASTContext &getASTContext() { return D->getASTContext(); }
82 const Decl *getDecl() const { return D; }
84 idx::TranslationUnit *getTranslationUnit() const { return TU; }
86 /// getAddEHEdges - Return true iff we are adding exceptional edges from
87 /// callExprs. If this is false, then try/catch statements and blocks
88 /// reachable from them can appear to be dead in the CFG, analysis passes must
90 bool getAddEHEdges() const { return AddEHEdges; }
92 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
93 bool getAddImplicitDtors() const { return AddImplicitDtors; }
94 bool getAddInitializers() const { return AddInitializers; }
99 CFGStmtMap *getCFGStmtMap();
101 CFGReachabilityAnalysis *getCFGReachablityAnalysis();
103 /// Return a version of the CFG without any edges pruned.
104 CFG *getUnoptimizedCFG();
108 ParentMap &getParentMap();
109 PseudoConstantAnalysis *getPseudoConstantAnalysis();
110 LiveVariables *getLiveVariables();
111 LiveVariables *getRelaxedLiveVariables();
113 typedef const VarDecl * const * referenced_decls_iterator;
115 std::pair<referenced_decls_iterator, referenced_decls_iterator>
116 getReferencedBlockVars(const BlockDecl *BD);
118 /// Return the ImplicitParamDecl* associated with 'self' if this
119 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
120 const ImplicitParamDecl *getSelfDecl() const;
123 class AnalysisContextManager {
124 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
126 bool UseUnoptimizedCFG;
127 bool AddImplicitDtors;
128 bool AddInitializers;
130 AnalysisContextManager(bool useUnoptimizedCFG = false,
131 bool addImplicitDtors = false, bool addInitializers = false)
132 : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
133 AddInitializers(addInitializers) {}
135 ~AnalysisContextManager();
137 AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
139 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
140 bool getAddImplicitDtors() const { return AddImplicitDtors; }
141 bool getAddInitializers() const { return AddInitializers; }
143 // Discard all previously created AnalysisContexts.
147 class LocationContext : public llvm::FoldingSetNode {
149 enum ContextKind { StackFrame, Scope, Block };
154 // AnalysisContext can't be const since some methods may modify its member.
155 AnalysisContext *Ctx;
157 const LocationContext *Parent;
160 LocationContext(ContextKind k, AnalysisContext *ctx,
161 const LocationContext *parent)
162 : Kind(k), Ctx(ctx), Parent(parent) {}
165 virtual ~LocationContext();
167 ContextKind getKind() const { return Kind; }
169 AnalysisContext *getAnalysisContext() const { return Ctx; }
171 idx::TranslationUnit *getTranslationUnit() const {
172 return Ctx->getTranslationUnit();
175 const LocationContext *getParent() const { return Parent; }
177 bool isParentOf(const LocationContext *LC) const;
179 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
181 CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
183 LiveVariables *getLiveVariables() const {
184 return getAnalysisContext()->getLiveVariables();
187 ParentMap &getParentMap() const {
188 return getAnalysisContext()->getParentMap();
191 const ImplicitParamDecl *getSelfDecl() const {
192 return Ctx->getSelfDecl();
195 const StackFrameContext *getCurrentStackFrame() const;
196 const StackFrameContext *
197 getStackFrameForDeclContext(const DeclContext *DC) const;
199 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
201 static bool classof(const LocationContext*) { return true; }
204 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
206 AnalysisContext *ctx,
207 const LocationContext *parent,
211 class StackFrameContext : public LocationContext {
212 // The callsite where this stack frame is established.
213 const Stmt *CallSite;
215 // The parent block of the callsite.
216 const CFGBlock *Block;
218 // The index of the callsite in the CFGBlock.
221 friend class LocationContextManager;
222 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
223 const Stmt *s, const CFGBlock *blk,
225 : LocationContext(StackFrame, ctx, parent), CallSite(s),
226 Block(blk), Index(idx) {}
229 ~StackFrameContext() {}
231 const Stmt *getCallSite() const { return CallSite; }
233 const CFGBlock *getCallSiteBlock() const { return Block; }
235 unsigned getIndex() const { return Index; }
237 void Profile(llvm::FoldingSetNodeID &ID);
239 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
240 const LocationContext *parent, const Stmt *s,
241 const CFGBlock *blk, unsigned idx) {
242 ProfileCommon(ID, StackFrame, ctx, parent, s);
247 static bool classof(const LocationContext* Ctx) {
248 return Ctx->getKind() == StackFrame;
252 class ScopeContext : public LocationContext {
255 friend class LocationContextManager;
256 ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
258 : LocationContext(Scope, ctx, parent), Enter(s) {}
263 void Profile(llvm::FoldingSetNodeID &ID);
265 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
266 const LocationContext *parent, const Stmt *s) {
267 ProfileCommon(ID, Scope, ctx, parent, s);
270 static bool classof(const LocationContext* Ctx) {
271 return Ctx->getKind() == Scope;
275 class BlockInvocationContext : public LocationContext {
276 // FIXME: Add back context-sensivity (we don't want libAnalysis to know
280 friend class LocationContextManager;
282 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
284 : LocationContext(Block, ctx, parent), BD(bd) {}
287 ~BlockInvocationContext() {}
289 const BlockDecl *getBlockDecl() const { return BD; }
291 void Profile(llvm::FoldingSetNodeID &ID);
293 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
294 const LocationContext *parent, const BlockDecl *bd) {
295 ProfileCommon(ID, Block, ctx, parent, bd);
298 static bool classof(const LocationContext* Ctx) {
299 return Ctx->getKind() == Block;
303 class LocationContextManager {
304 llvm::FoldingSet<LocationContext> Contexts;
306 ~LocationContextManager();
308 const StackFrameContext *getStackFrame(AnalysisContext *ctx,
309 const LocationContext *parent,
311 const CFGBlock *blk, unsigned idx);
313 const ScopeContext *getScope(AnalysisContext *ctx,
314 const LocationContext *parent,
317 /// Discard all previously created LocationContext objects.
320 template <typename LOC, typename DATA>
321 const LOC *getLocationContext(AnalysisContext *ctx,
322 const LocationContext *parent,
326 } // end clang namespace