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 ImplicitParamDecl;
34 class LocationContextManager;
35 class StackFrameContext;
37 /// AnalysisContext contains the context data for the function or method under
39 class AnalysisContext {
42 // AnalysisContext owns the following data.
45 LiveVariables *liveness;
47 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
48 llvm::BumpPtrAllocator A;
51 AnalysisContext(const Decl *d, bool addehedges = false)
52 : D(d), cfg(0), builtCFG(false), liveness(0), PM(0),
53 ReferencedBlockVars(0), AddEHEdges(addehedges) {}
57 ASTContext &getASTContext() { return D->getASTContext(); }
58 const Decl *getDecl() { return D; }
59 /// getAddEHEdges - Return true iff we are adding exceptional edges from
60 /// callExprs. If this is false, then try/catch statements and blocks
61 /// reachable from them can appear to be dead in the CFG, analysis passes must
63 bool getAddEHEdges() const { return AddEHEdges; }
66 ParentMap &getParentMap();
67 LiveVariables *getLiveVariables();
69 typedef const VarDecl * const * referenced_decls_iterator;
71 std::pair<referenced_decls_iterator, referenced_decls_iterator>
72 getReferencedBlockVars(const BlockDecl *BD);
74 /// Return the ImplicitParamDecl* associated with 'self' if this
75 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
76 const ImplicitParamDecl *getSelfDecl() const;
79 class AnalysisContextManager {
80 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
83 ~AnalysisContextManager();
85 AnalysisContext *getContext(const Decl *D);
87 // Discard all previously created AnalysisContexts.
91 class LocationContext : public llvm::FoldingSetNode {
93 enum ContextKind { StackFrame, Scope, Block };
98 const LocationContext *Parent;
101 LocationContext(ContextKind k, AnalysisContext *ctx,
102 const LocationContext *parent)
103 : Kind(k), Ctx(ctx), Parent(parent) {}
106 virtual ~LocationContext();
108 ContextKind getKind() const { return Kind; }
110 AnalysisContext *getAnalysisContext() const { return Ctx; }
112 const LocationContext *getParent() const { return Parent; }
114 bool isParentOf(const LocationContext *LC) const;
116 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
118 CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
120 LiveVariables *getLiveVariables() const {
121 return getAnalysisContext()->getLiveVariables();
124 ParentMap &getParentMap() const {
125 return getAnalysisContext()->getParentMap();
128 const ImplicitParamDecl *getSelfDecl() const {
129 return Ctx->getSelfDecl();
132 const StackFrameContext *getCurrentStackFrame() const;
133 const StackFrameContext *
134 getStackFrameForDeclContext(const DeclContext *DC) const;
136 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
138 static bool classof(const LocationContext*) { return true; }
141 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
143 AnalysisContext *ctx,
144 const LocationContext *parent,
148 class StackFrameContext : public LocationContext {
149 // The callsite where this stack frame is established.
150 const Stmt *CallSite;
152 // The parent block of the callsite.
153 const CFGBlock *Block;
155 // The index of the callsite in the CFGBlock.
158 friend class LocationContextManager;
159 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
160 const Stmt *s, const CFGBlock *blk, unsigned idx)
161 : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
165 ~StackFrameContext() {}
167 const Stmt *getCallSite() const { return CallSite; }
169 const CFGBlock *getCallSiteBlock() const { return Block; }
171 unsigned getIndex() const { return Index; }
173 void Profile(llvm::FoldingSetNodeID &ID);
175 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
176 const LocationContext *parent, const Stmt *s,
177 const CFGBlock *blk, unsigned idx) {
178 ProfileCommon(ID, StackFrame, ctx, parent, s);
183 static bool classof(const LocationContext* Ctx) {
184 return Ctx->getKind() == StackFrame;
188 class ScopeContext : public LocationContext {
191 friend class LocationContextManager;
192 ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
194 : LocationContext(Scope, ctx, parent), Enter(s) {}
199 void Profile(llvm::FoldingSetNodeID &ID);
201 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
202 const LocationContext *parent, const Stmt *s) {
203 ProfileCommon(ID, Scope, ctx, parent, s);
206 static bool classof(const LocationContext* Ctx) {
207 return Ctx->getKind() == Scope;
211 class BlockInvocationContext : public LocationContext {
212 // FIXME: Add back context-sensivity (we don't want libAnalysis to know
216 friend class LocationContextManager;
218 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
220 : LocationContext(Block, ctx, parent), BD(bd) {}
223 ~BlockInvocationContext() {}
225 const BlockDecl *getBlockDecl() const { return BD; }
227 void Profile(llvm::FoldingSetNodeID &ID);
229 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
230 const LocationContext *parent, const BlockDecl *bd) {
231 ProfileCommon(ID, Block, ctx, parent, bd);
234 static bool classof(const LocationContext* Ctx) {
235 return Ctx->getKind() == Block;
239 class LocationContextManager {
240 llvm::FoldingSet<LocationContext> Contexts;
242 ~LocationContextManager();
244 const StackFrameContext *getStackFrame(AnalysisContext *ctx,
245 const LocationContext *parent,
246 const Stmt *s, const CFGBlock *blk,
249 const ScopeContext *getScope(AnalysisContext *ctx,
250 const LocationContext *parent,
253 /// Discard all previously created LocationContext objects.
256 template <typename LOC, typename DATA>
257 const LOC *getLocationContext(AnalysisContext *ctx,
258 const LocationContext *parent,
262 } // end clang namespace