blob: 69446eb814f676b235278e6f0bbb7352059c3232 [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 Kremenek283a3582011-02-23 01:51:53 +000032class CFGStmtMap;
Ted Kremenek326be562010-01-25 05:19:37 +000033class LiveVariables;
34class ParentMap;
Tom Caredb34ab72010-08-23 19:51:57 +000035class PseudoConstantAnalysis;
Ted Kremenek326be562010-01-25 05:19:37 +000036class ImplicitParamDecl;
37class LocationContextManager;
38class StackFrameContext;
Ted Kremenekd064fdc2010-03-23 00:13:23 +000039
Zhongxing Xuc6238d22010-07-19 01:31:21 +000040namespace idx { class TranslationUnit; }
41
Ted Kremenek326be562010-01-25 05:19:37 +000042/// AnalysisContext contains the context data for the function or method under
43/// analysis.
44class AnalysisContext {
45 const Decl *D;
46
Zhongxing Xuc6238d22010-07-19 01:31:21 +000047 // TranslationUnit is NULL if we don't have multiple translation units.
Zhongxing Xu2ce43c82010-07-22 13:52:13 +000048 idx::TranslationUnit *TU;
Zhongxing Xuc6238d22010-07-19 01:31:21 +000049
Ted Kremenek326be562010-01-25 05:19:37 +000050 // AnalysisContext owns the following data.
Ted Kremenekad5a8942010-08-02 23:46:59 +000051 CFG *cfg, *completeCFG;
Ted Kremenek283a3582011-02-23 01:51:53 +000052 CFGStmtMap *cfgStmtMap;
Ted Kremenekad5a8942010-08-02 23:46:59 +000053 bool builtCFG, builtCompleteCFG;
Ted Kremenek326be562010-01-25 05:19:37 +000054 LiveVariables *liveness;
Tom Careec49bf42010-08-27 22:30:10 +000055 LiveVariables *relaxedLiveness;
Ted Kremenek326be562010-01-25 05:19:37 +000056 ParentMap *PM;
Tom Caredb34ab72010-08-23 19:51:57 +000057 PseudoConstantAnalysis *PCA;
Ted Kremenek326be562010-01-25 05:19:37 +000058 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
59 llvm::BumpPtrAllocator A;
Ted Kremenek9b823e82010-08-03 00:09:51 +000060 bool UseUnoptimizedCFG;
Ted Kremenek326be562010-01-25 05:19:37 +000061 bool AddEHEdges;
Marcin Swiderski9121ba22010-09-30 07:41:24 +000062 bool AddImplicitDtors;
63 bool AddInitializers;
Ted Kremenek326be562010-01-25 05:19:37 +000064public:
Zhongxing Xu2ce43c82010-07-22 13:52:13 +000065 AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
Ted Kremenek9b823e82010-08-03 00:09:51 +000066 bool useUnoptimizedCFG = false,
Marcin Swiderski9121ba22010-09-30 07:41:24 +000067 bool addehedges = false,
68 bool addImplicitDtors = false,
69 bool addInitializers = false)
Ted Kremenek283a3582011-02-23 01:51:53 +000070 : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0),
Ted Kremenekad5a8942010-08-02 23:46:59 +000071 builtCFG(false), builtCompleteCFG(false),
Tom Careec49bf42010-08-27 22:30:10 +000072 liveness(0), relaxedLiveness(0), PM(0), PCA(0),
Ted Kremenek9b823e82010-08-03 00:09:51 +000073 ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
Marcin Swiderski9121ba22010-09-30 07:41:24 +000074 AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors),
75 AddInitializers(addInitializers) {}
Ted Kremenek326be562010-01-25 05:19:37 +000076
77 ~AnalysisContext();
78
79 ASTContext &getASTContext() { return D->getASTContext(); }
Zhongxing Xuc6238d22010-07-19 01:31:21 +000080 const Decl *getDecl() const { return D; }
81
Zhongxing Xu2ce43c82010-07-22 13:52:13 +000082 idx::TranslationUnit *getTranslationUnit() const { return TU; }
Zhongxing Xuc6238d22010-07-19 01:31:21 +000083
Ted Kremenek326be562010-01-25 05:19:37 +000084 /// getAddEHEdges - Return true iff we are adding exceptional edges from
85 /// callExprs. If this is false, then try/catch statements and blocks
86 /// reachable from them can appear to be dead in the CFG, analysis passes must
87 /// cope with that.
88 bool getAddEHEdges() const { return AddEHEdges; }
Ted Kremenek9b823e82010-08-03 00:09:51 +000089
90 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
Marcin Swiderski9121ba22010-09-30 07:41:24 +000091 bool getAddImplicitDtors() const { return AddImplicitDtors; }
92 bool getAddInitializers() const { return AddInitializers; }
Ted Kremenek9b823e82010-08-03 00:09:51 +000093
Ted Kremenek326be562010-01-25 05:19:37 +000094 Stmt *getBody();
95 CFG *getCFG();
Ted Kremenek283a3582011-02-23 01:51:53 +000096
97 CFGStmtMap *getCFGStmtMap();
Anders Carlsson04eeba42011-01-16 22:05:23 +000098
Ted Kremenekad5a8942010-08-02 23:46:59 +000099 /// Return a version of the CFG without any edges pruned.
100 CFG *getUnoptimizedCFG();
101
Anders Carlsson04eeba42011-01-16 22:05:23 +0000102 void dumpCFG();
103
Ted Kremenek326be562010-01-25 05:19:37 +0000104 ParentMap &getParentMap();
Tom Caredb34ab72010-08-23 19:51:57 +0000105 PseudoConstantAnalysis *getPseudoConstantAnalysis();
Ted Kremenek326be562010-01-25 05:19:37 +0000106 LiveVariables *getLiveVariables();
Tom Careec49bf42010-08-27 22:30:10 +0000107 LiveVariables *getRelaxedLiveVariables();
Ted Kremenek326be562010-01-25 05:19:37 +0000108
109 typedef const VarDecl * const * referenced_decls_iterator;
110
111 std::pair<referenced_decls_iterator, referenced_decls_iterator>
112 getReferencedBlockVars(const BlockDecl *BD);
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000113
Ted Kremenek326be562010-01-25 05:19:37 +0000114 /// Return the ImplicitParamDecl* associated with 'self' if this
115 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
116 const ImplicitParamDecl *getSelfDecl() const;
117};
118
119class AnalysisContextManager {
120 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
121 ContextMap Contexts;
Ted Kremenek9b823e82010-08-03 00:09:51 +0000122 bool UseUnoptimizedCFG;
Marcin Swiderski9121ba22010-09-30 07:41:24 +0000123 bool AddImplicitDtors;
124 bool AddInitializers;
Ted Kremenek326be562010-01-25 05:19:37 +0000125public:
Marcin Swiderski9121ba22010-09-30 07:41:24 +0000126 AnalysisContextManager(bool useUnoptimizedCFG = false,
127 bool addImplicitDtors = false, bool addInitializers = false)
128 : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
129 AddInitializers(addInitializers) {}
Ted Kremenek9b823e82010-08-03 00:09:51 +0000130
Ted Kremenek326be562010-01-25 05:19:37 +0000131 ~AnalysisContextManager();
132
Zhongxing Xu2ce43c82010-07-22 13:52:13 +0000133 AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000134
Ted Kremenek9b823e82010-08-03 00:09:51 +0000135 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
Marcin Swiderski9121ba22010-09-30 07:41:24 +0000136 bool getAddImplicitDtors() const { return AddImplicitDtors; }
137 bool getAddInitializers() const { return AddInitializers; }
Ted Kremenek9b823e82010-08-03 00:09:51 +0000138
Ted Kremenek326be562010-01-25 05:19:37 +0000139 // Discard all previously created AnalysisContexts.
140 void clear();
141};
142
143class LocationContext : public llvm::FoldingSetNode {
144public:
145 enum ContextKind { StackFrame, Scope, Block };
146
147private:
148 ContextKind Kind;
Zhongxing Xua02d8932010-07-20 02:14:22 +0000149
150 // AnalysisContext can't be const since some methods may modify its member.
Ted Kremenek326be562010-01-25 05:19:37 +0000151 AnalysisContext *Ctx;
Zhongxing Xua02d8932010-07-20 02:14:22 +0000152
Ted Kremenek326be562010-01-25 05:19:37 +0000153 const LocationContext *Parent;
154
155protected:
156 LocationContext(ContextKind k, AnalysisContext *ctx,
157 const LocationContext *parent)
158 : Kind(k), Ctx(ctx), Parent(parent) {}
159
160public:
161 virtual ~LocationContext();
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000162
Ted Kremenek326be562010-01-25 05:19:37 +0000163 ContextKind getKind() const { return Kind; }
164
165 AnalysisContext *getAnalysisContext() const { return Ctx; }
166
Zhongxing Xu2ce43c82010-07-22 13:52:13 +0000167 idx::TranslationUnit *getTranslationUnit() const {
Zhongxing Xuc6238d22010-07-19 01:31:21 +0000168 return Ctx->getTranslationUnit();
169 }
170
Ted Kremenek326be562010-01-25 05:19:37 +0000171 const LocationContext *getParent() const { return Parent; }
172
Zhongxing Xu8ddf7ce2010-02-17 08:45:06 +0000173 bool isParentOf(const LocationContext *LC) const;
174
Ted Kremenek326be562010-01-25 05:19:37 +0000175 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
176
177 CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
178
179 LiveVariables *getLiveVariables() const {
180 return getAnalysisContext()->getLiveVariables();
181 }
182
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000183 ParentMap &getParentMap() const {
Ted Kremenek326be562010-01-25 05:19:37 +0000184 return getAnalysisContext()->getParentMap();
185 }
186
187 const ImplicitParamDecl *getSelfDecl() const {
188 return Ctx->getSelfDecl();
189 }
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000190
Ted Kremenek326be562010-01-25 05:19:37 +0000191 const StackFrameContext *getCurrentStackFrame() const;
192 const StackFrameContext *
193 getStackFrameForDeclContext(const DeclContext *DC) const;
194
195 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
196
197 static bool classof(const LocationContext*) { return true; }
198
199public:
200 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
201 ContextKind ck,
202 AnalysisContext *ctx,
203 const LocationContext *parent,
204 const void* data);
205};
206
207class StackFrameContext : public LocationContext {
Zhongxing Xu26c9cb52011-01-10 11:28:29 +0000208 // The callsite where this stack frame is established.
Ted Kremenek892697d2010-12-16 07:46:53 +0000209 const Stmt *CallSite;
Ted Kremenek326be562010-01-25 05:19:37 +0000210
211 // The parent block of the callsite.
212 const CFGBlock *Block;
213
214 // The index of the callsite in the CFGBlock.
215 unsigned Index;
216
217 friend class LocationContextManager;
218 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
Ted Kremenek892697d2010-12-16 07:46:53 +0000219 const Stmt *s, const CFGBlock *blk,
Zhongxing Xud7064342010-11-24 13:08:51 +0000220 unsigned idx)
Ted Kremenek892697d2010-12-16 07:46:53 +0000221 : LocationContext(StackFrame, ctx, parent), CallSite(s),
Zhongxing Xud7064342010-11-24 13:08:51 +0000222 Block(blk), Index(idx) {}
Ted Kremenek326be562010-01-25 05:19:37 +0000223
224public:
225 ~StackFrameContext() {}
226
Ted Kremenek892697d2010-12-16 07:46:53 +0000227 const Stmt *getCallSite() const { return CallSite; }
Zhongxing Xud7064342010-11-24 13:08:51 +0000228
Ted Kremenek326be562010-01-25 05:19:37 +0000229 const CFGBlock *getCallSiteBlock() const { return Block; }
230
231 unsigned getIndex() const { return Index; }
232
233 void Profile(llvm::FoldingSetNodeID &ID);
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000234
Ted Kremenek326be562010-01-25 05:19:37 +0000235 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000236 const LocationContext *parent, const Stmt *s,
Ted Kremenek892697d2010-12-16 07:46:53 +0000237 const CFGBlock *blk, unsigned idx) {
Ted Kremenek326be562010-01-25 05:19:37 +0000238 ProfileCommon(ID, StackFrame, ctx, parent, s);
239 ID.AddPointer(blk);
240 ID.AddInteger(idx);
241 }
242
243 static bool classof(const LocationContext* Ctx) {
244 return Ctx->getKind() == StackFrame;
245 }
246};
247
248class ScopeContext : public LocationContext {
249 const Stmt *Enter;
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000250
Ted Kremenek326be562010-01-25 05:19:37 +0000251 friend class LocationContextManager;
252 ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
253 const Stmt *s)
254 : LocationContext(Scope, ctx, parent), Enter(s) {}
255
256public:
257 ~ScopeContext() {}
258
259 void Profile(llvm::FoldingSetNodeID &ID);
260
261 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
262 const LocationContext *parent, const Stmt *s) {
263 ProfileCommon(ID, Scope, ctx, parent, s);
264 }
265
266 static bool classof(const LocationContext* Ctx) {
267 return Ctx->getKind() == Scope;
268 }
269};
270
271class BlockInvocationContext : public LocationContext {
272 // FIXME: Add back context-sensivity (we don't want libAnalysis to know
273 // about MemRegion).
274 const BlockDecl *BD;
275
276 friend class LocationContextManager;
277
278 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
279 const BlockDecl *bd)
280 : LocationContext(Block, ctx, parent), BD(bd) {}
281
282public:
283 ~BlockInvocationContext() {}
284
285 const BlockDecl *getBlockDecl() const { return BD; }
286
287 void Profile(llvm::FoldingSetNodeID &ID);
288
289 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
290 const LocationContext *parent, const BlockDecl *bd) {
291 ProfileCommon(ID, Block, ctx, parent, bd);
292 }
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000293
Ted Kremenek326be562010-01-25 05:19:37 +0000294 static bool classof(const LocationContext* Ctx) {
295 return Ctx->getKind() == Block;
296 }
297};
298
299class LocationContextManager {
300 llvm::FoldingSet<LocationContext> Contexts;
301public:
302 ~LocationContextManager();
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000303
Ted Kremenek326be562010-01-25 05:19:37 +0000304 const StackFrameContext *getStackFrame(AnalysisContext *ctx,
305 const LocationContext *parent,
Ted Kremenek892697d2010-12-16 07:46:53 +0000306 const Stmt *s,
Zhongxing Xud7064342010-11-24 13:08:51 +0000307 const CFGBlock *blk, unsigned idx);
Ted Kremenek326be562010-01-25 05:19:37 +0000308
309 const ScopeContext *getScope(AnalysisContext *ctx,
310 const LocationContext *parent,
311 const Stmt *s);
Ted Kremenekd064fdc2010-03-23 00:13:23 +0000312
Ted Kremenek326be562010-01-25 05:19:37 +0000313 /// Discard all previously created LocationContext objects.
314 void clear();
315private:
316 template <typename LOC, typename DATA>
317 const LOC *getLocationContext(AnalysisContext *ctx,
318 const LocationContext *parent,
319 const DATA *d);
320};
321
322} // end clang namespace
323#endif