blob: 45f1e9369947a45aa921d54dd19fd9894e345523 [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;
Ted Kremenekd064fdc2010-03-23 00:13:23 +000036
Zhongxing Xuc6238d22010-07-19 01:31:21 +000037namespace idx { class TranslationUnit; }
38
Ted Kremenek326be562010-01-25 05:19:37 +000039/// AnalysisContext contains the context data for the function or method under
40/// analysis.
41class AnalysisContext {
42 const Decl *D;
43
Zhongxing Xuc6238d22010-07-19 01:31:21 +000044 // TranslationUnit is NULL if we don't have multiple translation units.
45 const idx::TranslationUnit *TU;
46
Ted Kremenek326be562010-01-25 05:19:37 +000047 // AnalysisContext owns the following data.
48 CFG *cfg;
Ted Kremenekd064fdc2010-03-23 00:13:23 +000049 bool builtCFG;
Ted Kremenek326be562010-01-25 05:19:37 +000050 LiveVariables *liveness;
51 ParentMap *PM;
52 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
53 llvm::BumpPtrAllocator A;
54 bool AddEHEdges;
55public:
Zhongxing Xuc6238d22010-07-19 01:31:21 +000056 AnalysisContext(const Decl *d, const idx::TranslationUnit *tu,
57 bool addehedges = false)
58 : D(d), TU(tu), cfg(0), builtCFG(false), liveness(0), PM(0),
Ted Kremenekd064fdc2010-03-23 00:13:23 +000059 ReferencedBlockVars(0), AddEHEdges(addehedges) {}
Ted Kremenek326be562010-01-25 05:19:37 +000060
61 ~AnalysisContext();
62
63 ASTContext &getASTContext() { return D->getASTContext(); }
Zhongxing Xuc6238d22010-07-19 01:31:21 +000064 const Decl *getDecl() const { return D; }
65
66 const idx::TranslationUnit *getTranslationUnit() const { return TU; }
67
Ted Kremenek326be562010-01-25 05:19:37 +000068 /// getAddEHEdges - Return true iff we are adding exceptional edges from
69 /// callExprs. If this is false, then try/catch statements and blocks
70 /// reachable from them can appear to be dead in the CFG, analysis passes must
71 /// cope with that.
72 bool getAddEHEdges() const { return AddEHEdges; }
73 Stmt *getBody();
74 CFG *getCFG();
75 ParentMap &getParentMap();
76 LiveVariables *getLiveVariables();
77
78 typedef const VarDecl * const * referenced_decls_iterator;
79
80 std::pair<referenced_decls_iterator, referenced_decls_iterator>
81 getReferencedBlockVars(const BlockDecl *BD);
Ted Kremenekd064fdc2010-03-23 00:13:23 +000082
Ted Kremenek326be562010-01-25 05:19:37 +000083 /// Return the ImplicitParamDecl* associated with 'self' if this
84 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
85 const ImplicitParamDecl *getSelfDecl() const;
86};
87
88class AnalysisContextManager {
89 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
90 ContextMap Contexts;
91public:
92 ~AnalysisContextManager();
93
Zhongxing Xuc6238d22010-07-19 01:31:21 +000094 AnalysisContext *getContext(const Decl *D,const idx::TranslationUnit *TU = 0);
Ted Kremenekd064fdc2010-03-23 00:13:23 +000095
Ted Kremenek326be562010-01-25 05:19:37 +000096 // Discard all previously created AnalysisContexts.
97 void clear();
98};
99
100class LocationContext : public llvm::FoldingSetNode {
101public:
102 enum ContextKind { StackFrame, Scope, Block };
103
104private:
105 ContextKind Kind;
Zhongxing Xua02d8932010-07-20 02:14:22 +0000106
107 // AnalysisContext can't be const since some methods may modify its member.
Ted Kremenek326be562010-01-25 05:19:37 +0000108 AnalysisContext *Ctx;
Zhongxing Xua02d8932010-07-20 02:14:22 +0000109
Ted Kremenek326be562010-01-25 05:19:37 +0000110 const LocationContext *Parent;
111
112protected:
113 LocationContext(ContextKind k, AnalysisContext *ctx,
114 const LocationContext *parent)
115 : Kind(k), Ctx(ctx), Parent(parent) {}
116
117public:
118 virtual ~LocationContext();
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000119
Ted Kremenek326be562010-01-25 05:19:37 +0000120 ContextKind getKind() const { return Kind; }
121
122 AnalysisContext *getAnalysisContext() const { return Ctx; }
123
Zhongxing Xuc6238d22010-07-19 01:31:21 +0000124 const idx::TranslationUnit *getTranslationUnit() const {
125 return Ctx->getTranslationUnit();
126 }
127
Ted Kremenek326be562010-01-25 05:19:37 +0000128 const LocationContext *getParent() const { return Parent; }
129
Zhongxing Xu8ddf7ce2010-02-17 08:45:06 +0000130 bool isParentOf(const LocationContext *LC) const;
131
Ted Kremenek326be562010-01-25 05:19:37 +0000132 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
133
134 CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
135
136 LiveVariables *getLiveVariables() const {
137 return getAnalysisContext()->getLiveVariables();
138 }
139
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000140 ParentMap &getParentMap() const {
Ted Kremenek326be562010-01-25 05:19:37 +0000141 return getAnalysisContext()->getParentMap();
142 }
143
144 const ImplicitParamDecl *getSelfDecl() const {
145 return Ctx->getSelfDecl();
146 }
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000147
Ted Kremenek326be562010-01-25 05:19:37 +0000148 const StackFrameContext *getCurrentStackFrame() const;
149 const StackFrameContext *
150 getStackFrameForDeclContext(const DeclContext *DC) const;
151
152 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
153
154 static bool classof(const LocationContext*) { return true; }
155
156public:
157 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
158 ContextKind ck,
159 AnalysisContext *ctx,
160 const LocationContext *parent,
161 const void* data);
162};
163
164class StackFrameContext : public LocationContext {
165 // The callsite where this stack frame is established.
166 const Stmt *CallSite;
167
168 // The parent block of the callsite.
169 const CFGBlock *Block;
170
171 // The index of the callsite in the CFGBlock.
172 unsigned Index;
173
174 friend class LocationContextManager;
175 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
176 const Stmt *s, const CFGBlock *blk, unsigned idx)
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000177 : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
Ted Kremenek326be562010-01-25 05:19:37 +0000178 Index(idx) {}
179
180public:
181 ~StackFrameContext() {}
182
183 const Stmt *getCallSite() const { return CallSite; }
184
185 const CFGBlock *getCallSiteBlock() const { return Block; }
186
187 unsigned getIndex() const { return Index; }
188
189 void Profile(llvm::FoldingSetNodeID &ID);
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000190
Ted Kremenek326be562010-01-25 05:19:37 +0000191 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000192 const LocationContext *parent, const Stmt *s,
Ted Kremenek326be562010-01-25 05:19:37 +0000193 const CFGBlock *blk, unsigned idx) {
194 ProfileCommon(ID, StackFrame, ctx, parent, s);
195 ID.AddPointer(blk);
196 ID.AddInteger(idx);
197 }
198
199 static bool classof(const LocationContext* Ctx) {
200 return Ctx->getKind() == StackFrame;
201 }
202};
203
204class ScopeContext : public LocationContext {
205 const Stmt *Enter;
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000206
Ted Kremenek326be562010-01-25 05:19:37 +0000207 friend class LocationContextManager;
208 ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
209 const Stmt *s)
210 : LocationContext(Scope, ctx, parent), Enter(s) {}
211
212public:
213 ~ScopeContext() {}
214
215 void Profile(llvm::FoldingSetNodeID &ID);
216
217 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
218 const LocationContext *parent, const Stmt *s) {
219 ProfileCommon(ID, Scope, ctx, parent, s);
220 }
221
222 static bool classof(const LocationContext* Ctx) {
223 return Ctx->getKind() == Scope;
224 }
225};
226
227class BlockInvocationContext : public LocationContext {
228 // FIXME: Add back context-sensivity (we don't want libAnalysis to know
229 // about MemRegion).
230 const BlockDecl *BD;
231
232 friend class LocationContextManager;
233
234 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
235 const BlockDecl *bd)
236 : LocationContext(Block, ctx, parent), BD(bd) {}
237
238public:
239 ~BlockInvocationContext() {}
240
241 const BlockDecl *getBlockDecl() const { return BD; }
242
243 void Profile(llvm::FoldingSetNodeID &ID);
244
245 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
246 const LocationContext *parent, const BlockDecl *bd) {
247 ProfileCommon(ID, Block, ctx, parent, bd);
248 }
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000249
Ted Kremenek326be562010-01-25 05:19:37 +0000250 static bool classof(const LocationContext* Ctx) {
251 return Ctx->getKind() == Block;
252 }
253};
254
255class LocationContextManager {
256 llvm::FoldingSet<LocationContext> Contexts;
257public:
258 ~LocationContextManager();
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000259
Ted Kremenek326be562010-01-25 05:19:37 +0000260 const StackFrameContext *getStackFrame(AnalysisContext *ctx,
261 const LocationContext *parent,
262 const Stmt *s, const CFGBlock *blk,
263 unsigned idx);
264
265 const ScopeContext *getScope(AnalysisContext *ctx,
266 const LocationContext *parent,
267 const Stmt *s);
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000268
Ted Kremenek326be562010-01-25 05:19:37 +0000269 /// Discard all previously created LocationContext objects.
270 void clear();
271private:
272 template <typename LOC, typename DATA>
273 const LOC *getLocationContext(AnalysisContext *ctx,
274 const LocationContext *parent,
275 const DATA *d);
276};
277
278} // end clang namespace
279#endif