AnalysisContext.h revision db34ab70961ca4b24b600eb47053d7af304659f5
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 PseudoConstantAnalysis;
34class ImplicitParamDecl;
35class LocationContextManager;
36class StackFrameContext;
37
38namespace idx { class TranslationUnit; }
39
40/// AnalysisContext contains the context data for the function or method under
41/// analysis.
42class AnalysisContext {
43  const Decl *D;
44
45  // TranslationUnit is NULL if we don't have multiple translation units.
46  idx::TranslationUnit *TU;
47
48  // AnalysisContext owns the following data.
49  CFG *cfg, *completeCFG;
50  bool builtCFG, builtCompleteCFG;
51  LiveVariables *liveness;
52  ParentMap *PM;
53  PseudoConstantAnalysis *PCA;
54  llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
55  llvm::BumpPtrAllocator A;
56  bool UseUnoptimizedCFG;
57  bool AddEHEdges;
58public:
59  AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
60                  bool useUnoptimizedCFG = false,
61                  bool addehedges = false)
62    : D(d), TU(tu), cfg(0), completeCFG(0),
63      builtCFG(false), builtCompleteCFG(false),
64      liveness(0), PM(0), PCA(0),
65      ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
66      AddEHEdges(addehedges) {}
67
68  ~AnalysisContext();
69
70  ASTContext &getASTContext() { return D->getASTContext(); }
71  const Decl *getDecl() const { return D; }
72
73  idx::TranslationUnit *getTranslationUnit() const { return TU; }
74
75  /// getAddEHEdges - Return true iff we are adding exceptional edges from
76  /// callExprs.  If this is false, then try/catch statements and blocks
77  /// reachable from them can appear to be dead in the CFG, analysis passes must
78  /// cope with that.
79  bool getAddEHEdges() const { return AddEHEdges; }
80
81  bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
82
83  Stmt *getBody();
84  CFG *getCFG();
85
86  /// Return a version of the CFG without any edges pruned.
87  CFG *getUnoptimizedCFG();
88
89  ParentMap &getParentMap();
90  PseudoConstantAnalysis *getPseudoConstantAnalysis();
91  LiveVariables *getLiveVariables();
92
93  typedef const VarDecl * const * referenced_decls_iterator;
94
95  std::pair<referenced_decls_iterator, referenced_decls_iterator>
96    getReferencedBlockVars(const BlockDecl *BD);
97
98  /// Return the ImplicitParamDecl* associated with 'self' if this
99  /// AnalysisContext wraps an ObjCMethodDecl.  Returns NULL otherwise.
100  const ImplicitParamDecl *getSelfDecl() const;
101};
102
103class AnalysisContextManager {
104  typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
105  ContextMap Contexts;
106  bool UseUnoptimizedCFG;
107public:
108  AnalysisContextManager(bool useUnoptimizedCFG = false)
109    : UseUnoptimizedCFG(useUnoptimizedCFG) {}
110
111  ~AnalysisContextManager();
112
113  AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
114
115  bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
116
117  // Discard all previously created AnalysisContexts.
118  void clear();
119};
120
121class LocationContext : public llvm::FoldingSetNode {
122public:
123  enum ContextKind { StackFrame, Scope, Block };
124
125private:
126  ContextKind Kind;
127
128  // AnalysisContext can't be const since some methods may modify its member.
129  AnalysisContext *Ctx;
130
131  const LocationContext *Parent;
132
133protected:
134  LocationContext(ContextKind k, AnalysisContext *ctx,
135                  const LocationContext *parent)
136    : Kind(k), Ctx(ctx), Parent(parent) {}
137
138public:
139  virtual ~LocationContext();
140
141  ContextKind getKind() const { return Kind; }
142
143  AnalysisContext *getAnalysisContext() const { return Ctx; }
144
145  idx::TranslationUnit *getTranslationUnit() const {
146    return Ctx->getTranslationUnit();
147  }
148
149  const LocationContext *getParent() const { return Parent; }
150
151  bool isParentOf(const LocationContext *LC) const;
152
153  const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
154
155  CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
156
157  LiveVariables *getLiveVariables() const {
158    return getAnalysisContext()->getLiveVariables();
159  }
160
161  ParentMap &getParentMap() const {
162    return getAnalysisContext()->getParentMap();
163  }
164
165  const ImplicitParamDecl *getSelfDecl() const {
166    return Ctx->getSelfDecl();
167  }
168
169  const StackFrameContext *getCurrentStackFrame() const;
170  const StackFrameContext *
171    getStackFrameForDeclContext(const DeclContext *DC) const;
172
173  virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
174
175  static bool classof(const LocationContext*) { return true; }
176
177public:
178  static void ProfileCommon(llvm::FoldingSetNodeID &ID,
179                            ContextKind ck,
180                            AnalysisContext *ctx,
181                            const LocationContext *parent,
182                            const void* data);
183};
184
185class StackFrameContext : public LocationContext {
186  // The callsite where this stack frame is established.
187  const Stmt *CallSite;
188
189  // The parent block of the callsite.
190  const CFGBlock *Block;
191
192  // The index of the callsite in the CFGBlock.
193  unsigned Index;
194
195  friend class LocationContextManager;
196  StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
197                    const Stmt *s, const CFGBlock *blk, unsigned idx)
198    : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),
199      Index(idx) {}
200
201public:
202  ~StackFrameContext() {}
203
204  const Stmt *getCallSite() const { return CallSite; }
205
206  const CFGBlock *getCallSiteBlock() const { return Block; }
207
208  unsigned getIndex() const { return Index; }
209
210  void Profile(llvm::FoldingSetNodeID &ID);
211
212  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
213                      const LocationContext *parent, const Stmt *s,
214                      const CFGBlock *blk, unsigned idx) {
215    ProfileCommon(ID, StackFrame, ctx, parent, s);
216    ID.AddPointer(blk);
217    ID.AddInteger(idx);
218  }
219
220  static bool classof(const LocationContext* Ctx) {
221    return Ctx->getKind() == StackFrame;
222  }
223};
224
225class ScopeContext : public LocationContext {
226  const Stmt *Enter;
227
228  friend class LocationContextManager;
229  ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
230               const Stmt *s)
231    : LocationContext(Scope, ctx, parent), Enter(s) {}
232
233public:
234  ~ScopeContext() {}
235
236  void Profile(llvm::FoldingSetNodeID &ID);
237
238  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
239                      const LocationContext *parent, const Stmt *s) {
240    ProfileCommon(ID, Scope, ctx, parent, s);
241  }
242
243  static bool classof(const LocationContext* Ctx) {
244    return Ctx->getKind() == Scope;
245  }
246};
247
248class BlockInvocationContext : public LocationContext {
249  // FIXME: Add back context-sensivity (we don't want libAnalysis to know
250  //  about MemRegion).
251  const BlockDecl *BD;
252
253  friend class LocationContextManager;
254
255  BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
256                         const BlockDecl *bd)
257    : LocationContext(Block, ctx, parent), BD(bd) {}
258
259public:
260  ~BlockInvocationContext() {}
261
262  const BlockDecl *getBlockDecl() const { return BD; }
263
264  void Profile(llvm::FoldingSetNodeID &ID);
265
266  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
267                      const LocationContext *parent, const BlockDecl *bd) {
268    ProfileCommon(ID, Block, ctx, parent, bd);
269  }
270
271  static bool classof(const LocationContext* Ctx) {
272    return Ctx->getKind() == Block;
273  }
274};
275
276class LocationContextManager {
277  llvm::FoldingSet<LocationContext> Contexts;
278public:
279  ~LocationContextManager();
280
281  const StackFrameContext *getStackFrame(AnalysisContext *ctx,
282                                         const LocationContext *parent,
283                                         const Stmt *s, const CFGBlock *blk,
284                                         unsigned idx);
285
286  const ScopeContext *getScope(AnalysisContext *ctx,
287                               const LocationContext *parent,
288                               const Stmt *s);
289
290  /// Discard all previously created LocationContext objects.
291  void clear();
292private:
293  template <typename LOC, typename DATA>
294  const LOC *getLocationContext(AnalysisContext *ctx,
295                                const LocationContext *parent,
296                                const DATA *d);
297};
298
299} // end clang namespace
300#endif
301