AnalysisContext.h revision 8ddf7cead8a67342a4584a203e0bf736b7efedbe
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  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  bool isParentOf(const LocationContext *LC) const;
114
115  const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
116
117  CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
118
119  LiveVariables *getLiveVariables() const {
120    return getAnalysisContext()->getLiveVariables();
121  }
122
123  ParentMap &getParentMap() const {
124    return getAnalysisContext()->getParentMap();
125  }
126
127  const ImplicitParamDecl *getSelfDecl() const {
128    return Ctx->getSelfDecl();
129  }
130
131  const StackFrameContext *getCurrentStackFrame() const;
132  const StackFrameContext *
133    getStackFrameForDeclContext(const DeclContext *DC) const;
134
135  virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
136
137  static bool classof(const LocationContext*) { return true; }
138
139public:
140  static void ProfileCommon(llvm::FoldingSetNodeID &ID,
141                            ContextKind ck,
142                            AnalysisContext *ctx,
143                            const LocationContext *parent,
144                            const void* data);
145};
146
147class StackFrameContext : public LocationContext {
148  // The callsite where this stack frame is established.
149  const Stmt *CallSite;
150
151  // The parent block of the callsite.
152  const CFGBlock *Block;
153
154  // The index of the callsite in the CFGBlock.
155  unsigned Index;
156
157  friend class LocationContextManager;
158  StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
159                    const Stmt *s, const CFGBlock *blk, unsigned idx)
160    : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
161      Index(idx) {}
162
163public:
164  ~StackFrameContext() {}
165
166  const Stmt *getCallSite() const { return CallSite; }
167
168  const CFGBlock *getCallSiteBlock() const { return Block; }
169
170  unsigned getIndex() const { return Index; }
171
172  void Profile(llvm::FoldingSetNodeID &ID);
173
174  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
175                      const LocationContext *parent, const Stmt *s,
176                      const CFGBlock *blk, unsigned idx) {
177    ProfileCommon(ID, StackFrame, ctx, parent, s);
178    ID.AddPointer(blk);
179    ID.AddInteger(idx);
180  }
181
182  static bool classof(const LocationContext* Ctx) {
183    return Ctx->getKind() == StackFrame;
184  }
185};
186
187class ScopeContext : public LocationContext {
188  const Stmt *Enter;
189
190  friend class LocationContextManager;
191  ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
192               const Stmt *s)
193    : LocationContext(Scope, ctx, parent), Enter(s) {}
194
195public:
196  ~ScopeContext() {}
197
198  void Profile(llvm::FoldingSetNodeID &ID);
199
200  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
201                      const LocationContext *parent, const Stmt *s) {
202    ProfileCommon(ID, Scope, ctx, parent, s);
203  }
204
205  static bool classof(const LocationContext* Ctx) {
206    return Ctx->getKind() == Scope;
207  }
208};
209
210class BlockInvocationContext : public LocationContext {
211  // FIXME: Add back context-sensivity (we don't want libAnalysis to know
212  //  about MemRegion).
213  const BlockDecl *BD;
214
215  friend class LocationContextManager;
216
217  BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
218                         const BlockDecl *bd)
219    : LocationContext(Block, ctx, parent), BD(bd) {}
220
221public:
222  ~BlockInvocationContext() {}
223
224  const BlockDecl *getBlockDecl() const { return BD; }
225
226  void Profile(llvm::FoldingSetNodeID &ID);
227
228  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
229                      const LocationContext *parent, const BlockDecl *bd) {
230    ProfileCommon(ID, Block, ctx, parent, bd);
231  }
232
233  static bool classof(const LocationContext* Ctx) {
234    return Ctx->getKind() == Block;
235  }
236};
237
238class LocationContextManager {
239  llvm::FoldingSet<LocationContext> Contexts;
240public:
241  ~LocationContextManager();
242
243  const StackFrameContext *getStackFrame(AnalysisContext *ctx,
244                                         const LocationContext *parent,
245                                         const Stmt *s, const CFGBlock *blk,
246                                         unsigned idx);
247
248  const ScopeContext *getScope(AnalysisContext *ctx,
249                               const LocationContext *parent,
250                               const Stmt *s);
251
252  /// Discard all previously created LocationContext objects.
253  void clear();
254private:
255  template <typename LOC, typename DATA>
256  const LOC *getLocationContext(AnalysisContext *ctx,
257                                const LocationContext *parent,
258                                const DATA *d);
259};
260
261} // end clang namespace
262#endif
263