blob: ea4f5b20669c87d401966bc536dc14fc95942cff [file] [log] [blame]
Ted Kremenek326be562010-01-25 05:19:37 +00001//=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines AnalysisContext, a class that manages the analysis context
11// data for path sensitive analysis.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
16#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
17
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"
24
25namespace clang {
26
27class Decl;
28class Stmt;
29class CFG;
30class CFGBlock;
31class LiveVariables;
32class ParentMap;
33class ImplicitParamDecl;
34class LocationContextManager;
35class StackFrameContext;
36
37/// AnalysisContext contains the context data for the function or method under
38/// analysis.
39class AnalysisContext {
40 const Decl *D;
41
42 // AnalysisContext owns the following data.
43 CFG *cfg;
44 LiveVariables *liveness;
45 ParentMap *PM;
46 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
47 llvm::BumpPtrAllocator A;
48 bool AddEHEdges;
49public:
50 AnalysisContext(const Decl *d, bool addehedges = false)
51 : D(d), cfg(0), liveness(0), PM(0), ReferencedBlockVars(0),
52 AddEHEdges(addehedges) {}
53
54 ~AnalysisContext();
55
56 ASTContext &getASTContext() { return D->getASTContext(); }
57 const Decl *getDecl() { return D; }
58 /// getAddEHEdges - Return true iff we are adding exceptional edges from
59 /// callExprs. If this is false, then try/catch statements and blocks
60 /// reachable from them can appear to be dead in the CFG, analysis passes must
61 /// cope with that.
62 bool getAddEHEdges() const { return AddEHEdges; }
63 Stmt *getBody();
64 CFG *getCFG();
65 ParentMap &getParentMap();
66 LiveVariables *getLiveVariables();
67
68 typedef const VarDecl * const * referenced_decls_iterator;
69
70 std::pair<referenced_decls_iterator, referenced_decls_iterator>
71 getReferencedBlockVars(const BlockDecl *BD);
72
73 /// Return the ImplicitParamDecl* associated with 'self' if this
74 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
75 const ImplicitParamDecl *getSelfDecl() const;
76};
77
78class AnalysisContextManager {
79 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
80 ContextMap Contexts;
81public:
82 ~AnalysisContextManager();
83
84 AnalysisContext *getContext(const Decl *D);
85
86 // Discard all previously created AnalysisContexts.
87 void clear();
88};
89
90class LocationContext : public llvm::FoldingSetNode {
91public:
92 enum ContextKind { StackFrame, Scope, Block };
93
94private:
95 ContextKind Kind;
96 AnalysisContext *Ctx;
97 const LocationContext *Parent;
98
99protected:
100 LocationContext(ContextKind k, AnalysisContext *ctx,
101 const LocationContext *parent)
102 : Kind(k), Ctx(ctx), Parent(parent) {}
103
104public:
105 virtual ~LocationContext();
106
107 ContextKind getKind() const { return Kind; }
108
109 AnalysisContext *getAnalysisContext() const { return Ctx; }
110
111 const LocationContext *getParent() const { return Parent; }
112
113 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
114
115 CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
116
117 LiveVariables *getLiveVariables() const {
118 return getAnalysisContext()->getLiveVariables();
119 }
120
121 ParentMap &getParentMap() const {
122 return getAnalysisContext()->getParentMap();
123 }
124
125 const ImplicitParamDecl *getSelfDecl() const {
126 return Ctx->getSelfDecl();
127 }
128
129 const StackFrameContext *getCurrentStackFrame() const;
130 const StackFrameContext *
131 getStackFrameForDeclContext(const DeclContext *DC) const;
132
133 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
134
135 static bool classof(const LocationContext*) { return true; }
136
137public:
138 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
139 ContextKind ck,
140 AnalysisContext *ctx,
141 const LocationContext *parent,
142 const void* data);
143};
144
145class StackFrameContext : public LocationContext {
146 // The callsite where this stack frame is established.
147 const Stmt *CallSite;
148
149 // The parent block of the callsite.
150 const CFGBlock *Block;
151
152 // The index of the callsite in the CFGBlock.
153 unsigned Index;
154
155 friend class LocationContextManager;
156 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
157 const Stmt *s, const CFGBlock *blk, unsigned idx)
158 : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
159 Index(idx) {}
160
161public:
162 ~StackFrameContext() {}
163
164 const Stmt *getCallSite() const { return CallSite; }
165
166 const CFGBlock *getCallSiteBlock() const { return Block; }
167
168 unsigned getIndex() const { return Index; }
169
170 void Profile(llvm::FoldingSetNodeID &ID);
171
172 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
173 const LocationContext *parent, const Stmt *s,
174 const CFGBlock *blk, unsigned idx) {
175 ProfileCommon(ID, StackFrame, ctx, parent, s);
176 ID.AddPointer(blk);
177 ID.AddInteger(idx);
178 }
179
180 static bool classof(const LocationContext* Ctx) {
181 return Ctx->getKind() == StackFrame;
182 }
183};
184
185class ScopeContext : public LocationContext {
186 const Stmt *Enter;
187
188 friend class LocationContextManager;
189 ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
190 const Stmt *s)
191 : LocationContext(Scope, ctx, parent), Enter(s) {}
192
193public:
194 ~ScopeContext() {}
195
196 void Profile(llvm::FoldingSetNodeID &ID);
197
198 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
199 const LocationContext *parent, const Stmt *s) {
200 ProfileCommon(ID, Scope, ctx, parent, s);
201 }
202
203 static bool classof(const LocationContext* Ctx) {
204 return Ctx->getKind() == Scope;
205 }
206};
207
208class BlockInvocationContext : public LocationContext {
209 // FIXME: Add back context-sensivity (we don't want libAnalysis to know
210 // about MemRegion).
211 const BlockDecl *BD;
212
213 friend class LocationContextManager;
214
215 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
216 const BlockDecl *bd)
217 : LocationContext(Block, ctx, parent), BD(bd) {}
218
219public:
220 ~BlockInvocationContext() {}
221
222 const BlockDecl *getBlockDecl() const { return BD; }
223
224 void Profile(llvm::FoldingSetNodeID &ID);
225
226 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
227 const LocationContext *parent, const BlockDecl *bd) {
228 ProfileCommon(ID, Block, ctx, parent, bd);
229 }
230
231 static bool classof(const LocationContext* Ctx) {
232 return Ctx->getKind() == Block;
233 }
234};
235
236class LocationContextManager {
237 llvm::FoldingSet<LocationContext> Contexts;
238public:
239 ~LocationContextManager();
240
241 const StackFrameContext *getStackFrame(AnalysisContext *ctx,
242 const LocationContext *parent,
243 const Stmt *s, const CFGBlock *blk,
244 unsigned idx);
245
246 const ScopeContext *getScope(AnalysisContext *ctx,
247 const LocationContext *parent,
248 const Stmt *s);
249
250 /// Discard all previously created LocationContext objects.
251 void clear();
252private:
253 template <typename LOC, typename DATA>
254 const LOC *getLocationContext(AnalysisContext *ctx,
255 const LocationContext *parent,
256 const DATA *d);
257};
258
259} // end clang namespace
260#endif