AnalysisContext.h revision ee30965ce96e0a7b04b1aa16df60e9ba8b0a33c9
1//=== 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  bool builtCFG;
45  LiveVariables *liveness;
46  ParentMap *PM;
47  llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
48  llvm::BumpPtrAllocator A;
49  bool AddEHEdges;
50public:
51  AnalysisContext(const Decl *d, bool addehedges = false)
52    : D(d), cfg(0), builtCFG(false), liveness(0), PM(0),
53      ReferencedBlockVars(0), AddEHEdges(addehedges) {}
54
55  ~AnalysisContext();
56
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
62  /// cope with that.
63  bool getAddEHEdges() const { return AddEHEdges; }
64  Stmt *getBody();
65  CFG *getCFG();
66  ParentMap &getParentMap();
67  LiveVariables *getLiveVariables();
68
69  typedef const VarDecl * const * referenced_decls_iterator;
70
71  std::pair<referenced_decls_iterator, referenced_decls_iterator>
72    getReferencedBlockVars(const BlockDecl *BD);
73
74  /// Return the ImplicitParamDecl* associated with 'self' if this
75  /// AnalysisContext wraps an ObjCMethodDecl.  Returns NULL otherwise.
76  const ImplicitParamDecl *getSelfDecl() const;
77};
78
79class AnalysisContextManager {
80  typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
81  ContextMap Contexts;
82public:
83  ~AnalysisContextManager();
84
85  AnalysisContext *getContext(const Decl *D);
86
87  // Discard all previously created AnalysisContexts.
88  void clear();
89};
90
91class LocationContext : public llvm::FoldingSetNode {
92public:
93  enum ContextKind { StackFrame, Scope, Block };
94
95private:
96  ContextKind Kind;
97  AnalysisContext *Ctx;
98  const LocationContext *Parent;
99
100protected:
101  LocationContext(ContextKind k, AnalysisContext *ctx,
102                  const LocationContext *parent)
103    : Kind(k), Ctx(ctx), Parent(parent) {}
104
105public:
106  virtual ~LocationContext();
107
108  ContextKind getKind() const { return Kind; }
109
110  AnalysisContext *getAnalysisContext() const { return Ctx; }
111
112  const LocationContext *getParent() const { return Parent; }
113
114  bool isParentOf(const LocationContext *LC) const;
115
116  const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
117
118  CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
119
120  LiveVariables *getLiveVariables() const {
121    return getAnalysisContext()->getLiveVariables();
122  }
123
124  ParentMap &getParentMap() const {
125    return getAnalysisContext()->getParentMap();
126  }
127
128  const ImplicitParamDecl *getSelfDecl() const {
129    return Ctx->getSelfDecl();
130  }
131
132  const StackFrameContext *getCurrentStackFrame() const;
133  const StackFrameContext *
134    getStackFrameForDeclContext(const DeclContext *DC) const;
135
136  virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
137
138  static bool classof(const LocationContext*) { return true; }
139
140public:
141  static void ProfileCommon(llvm::FoldingSetNodeID &ID,
142                            ContextKind ck,
143                            AnalysisContext *ctx,
144                            const LocationContext *parent,
145                            const void* data);
146};
147
148class StackFrameContext : public LocationContext {
149  // The callsite where this stack frame is established.
150  const Stmt *CallSite;
151
152  // The parent block of the callsite.
153  const CFGBlock *Block;
154
155  // The index of the callsite in the CFGBlock.
156  unsigned Index;
157
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),
162      Index(idx) {}
163
164public:
165  ~StackFrameContext() {}
166
167  const Stmt *getCallSite() const { return CallSite; }
168
169  const CFGBlock *getCallSiteBlock() const { return Block; }
170
171  unsigned getIndex() const { return Index; }
172
173  void Profile(llvm::FoldingSetNodeID &ID);
174
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);
179    ID.AddPointer(blk);
180    ID.AddInteger(idx);
181  }
182
183  static bool classof(const LocationContext* Ctx) {
184    return Ctx->getKind() == StackFrame;
185  }
186};
187
188class ScopeContext : public LocationContext {
189  const Stmt *Enter;
190
191  friend class LocationContextManager;
192  ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
193               const Stmt *s)
194    : LocationContext(Scope, ctx, parent), Enter(s) {}
195
196public:
197  ~ScopeContext() {}
198
199  void Profile(llvm::FoldingSetNodeID &ID);
200
201  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
202                      const LocationContext *parent, const Stmt *s) {
203    ProfileCommon(ID, Scope, ctx, parent, s);
204  }
205
206  static bool classof(const LocationContext* Ctx) {
207    return Ctx->getKind() == Scope;
208  }
209};
210
211class BlockInvocationContext : public LocationContext {
212  // FIXME: Add back context-sensivity (we don't want libAnalysis to know
213  //  about MemRegion).
214  const BlockDecl *BD;
215
216  friend class LocationContextManager;
217
218  BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
219                         const BlockDecl *bd)
220    : LocationContext(Block, ctx, parent), BD(bd) {}
221
222public:
223  ~BlockInvocationContext() {}
224
225  const BlockDecl *getBlockDecl() const { return BD; }
226
227  void Profile(llvm::FoldingSetNodeID &ID);
228
229  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
230                      const LocationContext *parent, const BlockDecl *bd) {
231    ProfileCommon(ID, Block, ctx, parent, bd);
232  }
233
234  static bool classof(const LocationContext* Ctx) {
235    return Ctx->getKind() == Block;
236  }
237};
238
239class LocationContextManager {
240  llvm::FoldingSet<LocationContext> Contexts;
241public:
242  ~LocationContextManager();
243
244  const StackFrameContext *getStackFrame(AnalysisContext *ctx,
245                                         const LocationContext *parent,
246                                         const Stmt *s, const CFGBlock *blk,
247                                         unsigned idx);
248
249  const ScopeContext *getScope(AnalysisContext *ctx,
250                               const LocationContext *parent,
251                               const Stmt *s);
252
253  /// Discard all previously created LocationContext objects.
254  void clear();
255private:
256  template <typename LOC, typename DATA>
257  const LOC *getLocationContext(AnalysisContext *ctx,
258                                const LocationContext *parent,
259                                const DATA *d);
260};
261
262} // end clang namespace
263#endif
264