AnalysisContext.h revision 2ce43c8f43254a9edea53a20dc0e69195bc82ae0
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
37namespace idx { class TranslationUnit; }
38
39/// AnalysisContext contains the context data for the function or method under
40/// analysis.
41class AnalysisContext {
42  const Decl *D;
43
44  // TranslationUnit is NULL if we don't have multiple translation units.
45  idx::TranslationUnit *TU;
46
47  // AnalysisContext owns the following data.
48  CFG *cfg;
49  bool builtCFG;
50  LiveVariables *liveness;
51  ParentMap *PM;
52  llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
53  llvm::BumpPtrAllocator A;
54  bool AddEHEdges;
55public:
56  AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
57                  bool addehedges = false)
58    : D(d), TU(tu), cfg(0), builtCFG(false), liveness(0), PM(0),
59      ReferencedBlockVars(0), AddEHEdges(addehedges) {}
60
61  ~AnalysisContext();
62
63  ASTContext &getASTContext() { return D->getASTContext(); }
64  const Decl *getDecl() const { return D; }
65
66  idx::TranslationUnit *getTranslationUnit() const { return TU; }
67
68  /// 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);
82
83  /// 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
94  AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
95
96  // 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;
106
107  // AnalysisContext can't be const since some methods may modify its member.
108  AnalysisContext *Ctx;
109
110  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();
119
120  ContextKind getKind() const { return Kind; }
121
122  AnalysisContext *getAnalysisContext() const { return Ctx; }
123
124  idx::TranslationUnit *getTranslationUnit() const {
125    return Ctx->getTranslationUnit();
126  }
127
128  const LocationContext *getParent() const { return Parent; }
129
130  bool isParentOf(const LocationContext *LC) const;
131
132  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
140  ParentMap &getParentMap() const {
141    return getAnalysisContext()->getParentMap();
142  }
143
144  const ImplicitParamDecl *getSelfDecl() const {
145    return Ctx->getSelfDecl();
146  }
147
148  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)
177    : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
178      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);
190
191  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
192                      const LocationContext *parent, const Stmt *s,
193                      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;
206
207  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  }
249
250  static bool classof(const LocationContext* Ctx) {
251    return Ctx->getKind() == Block;
252  }
253};
254
255class LocationContextManager {
256  llvm::FoldingSet<LocationContext> Contexts;
257public:
258  ~LocationContextManager();
259
260  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);
268
269  /// 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
280