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 "llvm/ADT/OwningPtr.h"
20 #include "llvm/ADT/FoldingSet.h"
21 #include "llvm/ADT/PointerUnion.h"
22 #include "llvm/ADT/DenseMap.h"
23 #include "llvm/Support/Allocator.h"
33 class PseudoConstantAnalysis;
34 class ImplicitParamDecl;
35 class LocationContextManager;
36 class StackFrameContext;
38 namespace idx { class TranslationUnit; }
40 /// AnalysisContext contains the context data for the function or method under
42 class AnalysisContext {
45 // TranslationUnit is NULL if we don't have multiple translation units.
46 idx::TranslationUnit *TU;
48 // AnalysisContext owns the following data.
49 CFG *cfg, *completeCFG;
50 bool builtCFG, builtCompleteCFG;
51 LiveVariables *liveness;
52 LiveVariables *relaxedLiveness;
54 PseudoConstantAnalysis *PCA;
55 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
56 llvm::BumpPtrAllocator A;
57 bool UseUnoptimizedCFG;
60 AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
61 bool useUnoptimizedCFG = false,
62 bool addehedges = false)
63 : D(d), TU(tu), cfg(0), completeCFG(0),
64 builtCFG(false), builtCompleteCFG(false),
65 liveness(0), relaxedLiveness(0), PM(0), PCA(0),
66 ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
67 AddEHEdges(addehedges) {}
71 ASTContext &getASTContext() { return D->getASTContext(); }
72 const Decl *getDecl() const { return D; }
74 idx::TranslationUnit *getTranslationUnit() const { return TU; }
76 /// getAddEHEdges - Return true iff we are adding exceptional edges from
77 /// callExprs. If this is false, then try/catch statements and blocks
78 /// reachable from them can appear to be dead in the CFG, analysis passes must
80 bool getAddEHEdges() const { return AddEHEdges; }
82 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
87 /// Return a version of the CFG without any edges pruned.
88 CFG *getUnoptimizedCFG();
90 ParentMap &getParentMap();
91 PseudoConstantAnalysis *getPseudoConstantAnalysis();
92 LiveVariables *getLiveVariables();
93 LiveVariables *getRelaxedLiveVariables();
95 typedef const VarDecl * const * referenced_decls_iterator;
97 std::pair<referenced_decls_iterator, referenced_decls_iterator>
98 getReferencedBlockVars(const BlockDecl *BD);
100 /// Return the ImplicitParamDecl* associated with 'self' if this
101 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
102 const ImplicitParamDecl *getSelfDecl() const;
105 class AnalysisContextManager {
106 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
108 bool UseUnoptimizedCFG;
110 AnalysisContextManager(bool useUnoptimizedCFG = false)
111 : UseUnoptimizedCFG(useUnoptimizedCFG) {}
113 ~AnalysisContextManager();
115 AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
117 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
119 // Discard all previously created AnalysisContexts.
123 class LocationContext : public llvm::FoldingSetNode {
125 enum ContextKind { StackFrame, Scope, Block };
130 // AnalysisContext can't be const since some methods may modify its member.
131 AnalysisContext *Ctx;
133 const LocationContext *Parent;
136 LocationContext(ContextKind k, AnalysisContext *ctx,
137 const LocationContext *parent)
138 : Kind(k), Ctx(ctx), Parent(parent) {}
141 virtual ~LocationContext();
143 ContextKind getKind() const { return Kind; }
145 AnalysisContext *getAnalysisContext() const { return Ctx; }
147 idx::TranslationUnit *getTranslationUnit() const {
148 return Ctx->getTranslationUnit();
151 const LocationContext *getParent() const { return Parent; }
153 bool isParentOf(const LocationContext *LC) const;
155 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
157 CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
159 LiveVariables *getLiveVariables() const {
160 return getAnalysisContext()->getLiveVariables();
163 ParentMap &getParentMap() const {
164 return getAnalysisContext()->getParentMap();
167 const ImplicitParamDecl *getSelfDecl() const {
168 return Ctx->getSelfDecl();
171 const StackFrameContext *getCurrentStackFrame() const;
172 const StackFrameContext *
173 getStackFrameForDeclContext(const DeclContext *DC) const;
175 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
177 static bool classof(const LocationContext*) { return true; }
180 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
182 AnalysisContext *ctx,
183 const LocationContext *parent,
187 class StackFrameContext : public LocationContext {
188 // The callsite where this stack frame is established.
189 const Stmt *CallSite;
191 // The parent block of the callsite.
192 const CFGBlock *Block;
194 // The index of the callsite in the CFGBlock.
197 friend class LocationContextManager;
198 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
199 const Stmt *s, const CFGBlock *blk, unsigned idx)
200 : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
204 ~StackFrameContext() {}
206 const Stmt *getCallSite() const { return CallSite; }
208 const CFGBlock *getCallSiteBlock() const { return Block; }
210 unsigned getIndex() const { return Index; }
212 void Profile(llvm::FoldingSetNodeID &ID);
214 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
215 const LocationContext *parent, const Stmt *s,
216 const CFGBlock *blk, unsigned idx) {
217 ProfileCommon(ID, StackFrame, ctx, parent, s);
222 static bool classof(const LocationContext* Ctx) {
223 return Ctx->getKind() == StackFrame;
227 class ScopeContext : public LocationContext {
230 friend class LocationContextManager;
231 ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
233 : LocationContext(Scope, ctx, parent), Enter(s) {}
238 void Profile(llvm::FoldingSetNodeID &ID);
240 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
241 const LocationContext *parent, const Stmt *s) {
242 ProfileCommon(ID, Scope, ctx, parent, s);
245 static bool classof(const LocationContext* Ctx) {
246 return Ctx->getKind() == Scope;
250 class BlockInvocationContext : public LocationContext {
251 // FIXME: Add back context-sensivity (we don't want libAnalysis to know
255 friend class LocationContextManager;
257 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
259 : LocationContext(Block, ctx, parent), BD(bd) {}
262 ~BlockInvocationContext() {}
264 const BlockDecl *getBlockDecl() const { return BD; }
266 void Profile(llvm::FoldingSetNodeID &ID);
268 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
269 const LocationContext *parent, const BlockDecl *bd) {
270 ProfileCommon(ID, Block, ctx, parent, bd);
273 static bool classof(const LocationContext* Ctx) {
274 return Ctx->getKind() == Block;
278 class LocationContextManager {
279 llvm::FoldingSet<LocationContext> Contexts;
281 ~LocationContextManager();
283 const StackFrameContext *getStackFrame(AnalysisContext *ctx,
284 const LocationContext *parent,
285 const Stmt *s, const CFGBlock *blk,
288 const ScopeContext *getScope(AnalysisContext *ctx,
289 const LocationContext *parent,
292 /// Discard all previously created LocationContext objects.
295 template <typename LOC, typename DATA>
296 const LOC *getLocationContext(AnalysisContext *ctx,
297 const LocationContext *parent,
301 } // end clang namespace