blob: 851451457881cce80db28af05ba3db2b6adbfa5f [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"
Ted Kremenek892697d2010-12-16 07:46:53 +000019#include "clang/AST/Expr.h"
Ted Kremenek326be562010-01-25 05:19:37 +000020#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"
25
26namespace clang {
27
28class Decl;
29class Stmt;
30class CFG;
31class CFGBlock;
Ted Kremenek42461ee2011-02-23 01:51:59 +000032class CFGReachabilityAnalysis;
Ted Kremenek283a3582011-02-23 01:51:53 +000033class CFGStmtMap;
Ted Kremenek326be562010-01-25 05:19:37 +000034class LiveVariables;
35class ParentMap;
Tom Caredb34ab72010-08-23 19:51:57 +000036class PseudoConstantAnalysis;
Ted Kremenek326be562010-01-25 05:19:37 +000037class ImplicitParamDecl;
38class LocationContextManager;
39class StackFrameContext;
Ted Kremenekd064fdc2010-03-23 00:13:23 +000040
Zhongxing Xuc6238d22010-07-19 01:31:21 +000041namespace idx { class TranslationUnit; }
42
Ted Kremenek326be562010-01-25 05:19:37 +000043/// AnalysisContext contains the context data for the function or method under
44/// analysis.
45class AnalysisContext {
46 const Decl *D;
47
Zhongxing Xuc6238d22010-07-19 01:31:21 +000048 // TranslationUnit is NULL if we don't have multiple translation units.
Zhongxing Xu2ce43c82010-07-22 13:52:13 +000049 idx::TranslationUnit *TU;
Zhongxing Xuc6238d22010-07-19 01:31:21 +000050
Ted Kremenek326be562010-01-25 05:19:37 +000051 // AnalysisContext owns the following data.
Ted Kremenekad5a8942010-08-02 23:46:59 +000052 CFG *cfg, *completeCFG;
Ted Kremenek283a3582011-02-23 01:51:53 +000053 CFGStmtMap *cfgStmtMap;
Ted Kremenekad5a8942010-08-02 23:46:59 +000054 bool builtCFG, builtCompleteCFG;
Ted Kremenek326be562010-01-25 05:19:37 +000055 LiveVariables *liveness;
Tom Careec49bf42010-08-27 22:30:10 +000056 LiveVariables *relaxedLiveness;
Ted Kremenek326be562010-01-25 05:19:37 +000057 ParentMap *PM;
Tom Caredb34ab72010-08-23 19:51:57 +000058 PseudoConstantAnalysis *PCA;
Ted Kremenek42461ee2011-02-23 01:51:59 +000059 CFGReachabilityAnalysis *CFA;
Ted Kremenek326be562010-01-25 05:19:37 +000060 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
61 llvm::BumpPtrAllocator A;
Ted Kremenek9b823e82010-08-03 00:09:51 +000062 bool UseUnoptimizedCFG;
Ted Kremenek326be562010-01-25 05:19:37 +000063 bool AddEHEdges;
Marcin Swiderski9121ba22010-09-30 07:41:24 +000064 bool AddImplicitDtors;
65 bool AddInitializers;
Ted Kremenek326be562010-01-25 05:19:37 +000066public:
Zhongxing Xu2ce43c82010-07-22 13:52:13 +000067 AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
Ted Kremenek9b823e82010-08-03 00:09:51 +000068 bool useUnoptimizedCFG = false,
Marcin Swiderski9121ba22010-09-30 07:41:24 +000069 bool addehedges = false,
70 bool addImplicitDtors = false,
71 bool addInitializers = false)
Ted Kremenek283a3582011-02-23 01:51:53 +000072 : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0),
Ted Kremenekad5a8942010-08-02 23:46:59 +000073 builtCFG(false), builtCompleteCFG(false),
Ted Kremenek42461ee2011-02-23 01:51:59 +000074 liveness(0), relaxedLiveness(0), PM(0), PCA(0), CFA(0),
Ted Kremenek9b823e82010-08-03 00:09:51 +000075 ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
Marcin Swiderski9121ba22010-09-30 07:41:24 +000076 AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors),
77 AddInitializers(addInitializers) {}
Ted Kremenek326be562010-01-25 05:19:37 +000078
79 ~AnalysisContext();
80
81 ASTContext &getASTContext() { return D->getASTContext(); }
Zhongxing Xuc6238d22010-07-19 01:31:21 +000082 const Decl *getDecl() const { return D; }
83
Zhongxing Xu2ce43c82010-07-22 13:52:13 +000084 idx::TranslationUnit *getTranslationUnit() const { return TU; }
Zhongxing Xuc6238d22010-07-19 01:31:21 +000085
Ted Kremenek326be562010-01-25 05:19:37 +000086 /// 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
89 /// cope with that.
90 bool getAddEHEdges() const { return AddEHEdges; }
Ted Kremenek9b823e82010-08-03 00:09:51 +000091
92 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
Marcin Swiderski9121ba22010-09-30 07:41:24 +000093 bool getAddImplicitDtors() const { return AddImplicitDtors; }
94 bool getAddInitializers() const { return AddInitializers; }
Ted Kremenek9b823e82010-08-03 00:09:51 +000095
Ted Kremenek326be562010-01-25 05:19:37 +000096 Stmt *getBody();
97 CFG *getCFG();
Ted Kremenek283a3582011-02-23 01:51:53 +000098
99 CFGStmtMap *getCFGStmtMap();
Anders Carlsson04eeba42011-01-16 22:05:23 +0000100
Ted Kremenek42461ee2011-02-23 01:51:59 +0000101 CFGReachabilityAnalysis *getCFGReachablityAnalysis();
102
Ted Kremenekad5a8942010-08-02 23:46:59 +0000103 /// Return a version of the CFG without any edges pruned.
104 CFG *getUnoptimizedCFG();
105
Anders Carlsson04eeba42011-01-16 22:05:23 +0000106 void dumpCFG();
107
Ted Kremenek326be562010-01-25 05:19:37 +0000108 ParentMap &getParentMap();
Tom Caredb34ab72010-08-23 19:51:57 +0000109 PseudoConstantAnalysis *getPseudoConstantAnalysis();
Ted Kremenek326be562010-01-25 05:19:37 +0000110 LiveVariables *getLiveVariables();
Tom Careec49bf42010-08-27 22:30:10 +0000111 LiveVariables *getRelaxedLiveVariables();
Ted Kremenek326be562010-01-25 05:19:37 +0000112
113 typedef const VarDecl * const * referenced_decls_iterator;
114
115 std::pair<referenced_decls_iterator, referenced_decls_iterator>
116 getReferencedBlockVars(const BlockDecl *BD);
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000117
Ted Kremenek326be562010-01-25 05:19:37 +0000118 /// Return the ImplicitParamDecl* associated with 'self' if this
119 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
120 const ImplicitParamDecl *getSelfDecl() const;
121};
122
123class AnalysisContextManager {
124 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
125 ContextMap Contexts;
Ted Kremenek9b823e82010-08-03 00:09:51 +0000126 bool UseUnoptimizedCFG;
Marcin Swiderski9121ba22010-09-30 07:41:24 +0000127 bool AddImplicitDtors;
128 bool AddInitializers;
Ted Kremenek326be562010-01-25 05:19:37 +0000129public:
Marcin Swiderski9121ba22010-09-30 07:41:24 +0000130 AnalysisContextManager(bool useUnoptimizedCFG = false,
131 bool addImplicitDtors = false, bool addInitializers = false)
132 : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
133 AddInitializers(addInitializers) {}
Ted Kremenek9b823e82010-08-03 00:09:51 +0000134
Ted Kremenek326be562010-01-25 05:19:37 +0000135 ~AnalysisContextManager();
136
Zhongxing Xu2ce43c82010-07-22 13:52:13 +0000137 AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000138
Ted Kremenek9b823e82010-08-03 00:09:51 +0000139 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
Marcin Swiderski9121ba22010-09-30 07:41:24 +0000140 bool getAddImplicitDtors() const { return AddImplicitDtors; }
141 bool getAddInitializers() const { return AddInitializers; }
Ted Kremenek9b823e82010-08-03 00:09:51 +0000142
Ted Kremenek326be562010-01-25 05:19:37 +0000143 // Discard all previously created AnalysisContexts.
144 void clear();
145};
146
147class LocationContext : public llvm::FoldingSetNode {
148public:
149 enum ContextKind { StackFrame, Scope, Block };
150
151private:
152 ContextKind Kind;
Zhongxing Xua02d8932010-07-20 02:14:22 +0000153
154 // AnalysisContext can't be const since some methods may modify its member.
Ted Kremenek326be562010-01-25 05:19:37 +0000155 AnalysisContext *Ctx;
Zhongxing Xua02d8932010-07-20 02:14:22 +0000156
Ted Kremenek326be562010-01-25 05:19:37 +0000157 const LocationContext *Parent;
158
159protected:
160 LocationContext(ContextKind k, AnalysisContext *ctx,
161 const LocationContext *parent)
162 : Kind(k), Ctx(ctx), Parent(parent) {}
163
164public:
165 virtual ~LocationContext();
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000166
Ted Kremenek326be562010-01-25 05:19:37 +0000167 ContextKind getKind() const { return Kind; }
168
169 AnalysisContext *getAnalysisContext() const { return Ctx; }
170
Zhongxing Xu2ce43c82010-07-22 13:52:13 +0000171 idx::TranslationUnit *getTranslationUnit() const {
Zhongxing Xuc6238d22010-07-19 01:31:21 +0000172 return Ctx->getTranslationUnit();
173 }
174
Ted Kremenek326be562010-01-25 05:19:37 +0000175 const LocationContext *getParent() const { return Parent; }
176
Zhongxing Xu8ddf7ce2010-02-17 08:45:06 +0000177 bool isParentOf(const LocationContext *LC) const;
178
Ted Kremenek326be562010-01-25 05:19:37 +0000179 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
180
181 CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
182
183 LiveVariables *getLiveVariables() const {
184 return getAnalysisContext()->getLiveVariables();
185 }
186
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000187 ParentMap &getParentMap() const {
Ted Kremenek326be562010-01-25 05:19:37 +0000188 return getAnalysisContext()->getParentMap();
189 }
190
191 const ImplicitParamDecl *getSelfDecl() const {
192 return Ctx->getSelfDecl();
193 }
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000194
Ted Kremenek326be562010-01-25 05:19:37 +0000195 const StackFrameContext *getCurrentStackFrame() const;
196 const StackFrameContext *
197 getStackFrameForDeclContext(const DeclContext *DC) const;
198
199 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
200
201 static bool classof(const LocationContext*) { return true; }
202
203public:
204 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
205 ContextKind ck,
206 AnalysisContext *ctx,
207 const LocationContext *parent,
208 const void* data);
209};
210
211class StackFrameContext : public LocationContext {
Zhongxing Xu26c9cb52011-01-10 11:28:29 +0000212 // The callsite where this stack frame is established.
Ted Kremenek892697d2010-12-16 07:46:53 +0000213 const Stmt *CallSite;
Ted Kremenek326be562010-01-25 05:19:37 +0000214
215 // The parent block of the callsite.
216 const CFGBlock *Block;
217
218 // The index of the callsite in the CFGBlock.
219 unsigned Index;
220
221 friend class LocationContextManager;
222 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
Ted Kremenek892697d2010-12-16 07:46:53 +0000223 const Stmt *s, const CFGBlock *blk,
Zhongxing Xud7064342010-11-24 13:08:51 +0000224 unsigned idx)
Ted Kremenek892697d2010-12-16 07:46:53 +0000225 : LocationContext(StackFrame, ctx, parent), CallSite(s),
Zhongxing Xud7064342010-11-24 13:08:51 +0000226 Block(blk), Index(idx) {}
Ted Kremenek326be562010-01-25 05:19:37 +0000227
228public:
229 ~StackFrameContext() {}
230
Ted Kremenek892697d2010-12-16 07:46:53 +0000231 const Stmt *getCallSite() const { return CallSite; }
Zhongxing Xud7064342010-11-24 13:08:51 +0000232
Ted Kremenek326be562010-01-25 05:19:37 +0000233 const CFGBlock *getCallSiteBlock() const { return Block; }
234
235 unsigned getIndex() const { return Index; }
236
237 void Profile(llvm::FoldingSetNodeID &ID);
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000238
Ted Kremenek326be562010-01-25 05:19:37 +0000239 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000240 const LocationContext *parent, const Stmt *s,
Ted Kremenek892697d2010-12-16 07:46:53 +0000241 const CFGBlock *blk, unsigned idx) {
Ted Kremenek326be562010-01-25 05:19:37 +0000242 ProfileCommon(ID, StackFrame, ctx, parent, s);
243 ID.AddPointer(blk);
244 ID.AddInteger(idx);
245 }
246
247 static bool classof(const LocationContext* Ctx) {
248 return Ctx->getKind() == StackFrame;
249 }
250};
251
252class ScopeContext : public LocationContext {
253 const Stmt *Enter;
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000254
Ted Kremenek326be562010-01-25 05:19:37 +0000255 friend class LocationContextManager;
256 ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
257 const Stmt *s)
258 : LocationContext(Scope, ctx, parent), Enter(s) {}
259
260public:
261 ~ScopeContext() {}
262
263 void Profile(llvm::FoldingSetNodeID &ID);
264
265 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
266 const LocationContext *parent, const Stmt *s) {
267 ProfileCommon(ID, Scope, ctx, parent, s);
268 }
269
270 static bool classof(const LocationContext* Ctx) {
271 return Ctx->getKind() == Scope;
272 }
273};
274
275class BlockInvocationContext : public LocationContext {
276 // FIXME: Add back context-sensivity (we don't want libAnalysis to know
277 // about MemRegion).
278 const BlockDecl *BD;
279
280 friend class LocationContextManager;
281
282 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
283 const BlockDecl *bd)
284 : LocationContext(Block, ctx, parent), BD(bd) {}
285
286public:
287 ~BlockInvocationContext() {}
288
289 const BlockDecl *getBlockDecl() const { return BD; }
290
291 void Profile(llvm::FoldingSetNodeID &ID);
292
293 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
294 const LocationContext *parent, const BlockDecl *bd) {
295 ProfileCommon(ID, Block, ctx, parent, bd);
296 }
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000297
Ted Kremenek326be562010-01-25 05:19:37 +0000298 static bool classof(const LocationContext* Ctx) {
299 return Ctx->getKind() == Block;
300 }
301};
302
303class LocationContextManager {
304 llvm::FoldingSet<LocationContext> Contexts;
305public:
306 ~LocationContextManager();
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000307
Ted Kremenek326be562010-01-25 05:19:37 +0000308 const StackFrameContext *getStackFrame(AnalysisContext *ctx,
309 const LocationContext *parent,
Ted Kremenek892697d2010-12-16 07:46:53 +0000310 const Stmt *s,
Zhongxing Xud7064342010-11-24 13:08:51 +0000311 const CFGBlock *blk, unsigned idx);
Ted Kremenek326be562010-01-25 05:19:37 +0000312
313 const ScopeContext *getScope(AnalysisContext *ctx,
314 const LocationContext *parent,
315 const Stmt *s);
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000316
Ted Kremenek326be562010-01-25 05:19:37 +0000317 /// Discard all previously created LocationContext objects.
318 void clear();
319private:
320 template <typename LOC, typename DATA>
321 const LOC *getLocationContext(AnalysisContext *ctx,
322 const LocationContext *parent,
323 const DATA *d);
324};
325
326} // end clang namespace
327#endif