AnalysisContext.h revision 283a358aecb75e30fcd486f2206f6c03c5e7f11d
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 "clang/AST/Expr.h"
20#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;
32class CFGStmtMap;
33class LiveVariables;
34class ParentMap;
35class PseudoConstantAnalysis;
36class ImplicitParamDecl;
37class LocationContextManager;
38class StackFrameContext;
39
40namespace idx { class TranslationUnit; }
41
42/// AnalysisContext contains the context data for the function or method under
43/// analysis.
44class AnalysisContext {
45  const Decl *D;
46
47  // TranslationUnit is NULL if we don't have multiple translation units.
48  idx::TranslationUnit *TU;
49
50  // AnalysisContext owns the following data.
51  CFG *cfg, *completeCFG;
52  CFGStmtMap *cfgStmtMap;
53  bool builtCFG, builtCompleteCFG;
54  LiveVariables *liveness;
55  LiveVariables *relaxedLiveness;
56  ParentMap *PM;
57  PseudoConstantAnalysis *PCA;
58  llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
59  llvm::BumpPtrAllocator A;
60  bool UseUnoptimizedCFG;
61  bool AddEHEdges;
62  bool AddImplicitDtors;
63  bool AddInitializers;
64public:
65  AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
66                  bool useUnoptimizedCFG = false,
67                  bool addehedges = false,
68                  bool addImplicitDtors = false,
69                  bool addInitializers = false)
70    : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0),
71      builtCFG(false), builtCompleteCFG(false),
72      liveness(0), relaxedLiveness(0), PM(0), PCA(0),
73      ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG),
74      AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors),
75      AddInitializers(addInitializers) {}
76
77  ~AnalysisContext();
78
79  ASTContext &getASTContext() { return D->getASTContext(); }
80  const Decl *getDecl() const { return D; }
81
82  idx::TranslationUnit *getTranslationUnit() const { return TU; }
83
84  /// 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; }
89
90  bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
91  bool getAddImplicitDtors() const { return AddImplicitDtors; }
92  bool getAddInitializers() const { return AddInitializers; }
93
94  Stmt *getBody();
95  CFG *getCFG();
96
97  CFGStmtMap *getCFGStmtMap();
98
99  /// Return a version of the CFG without any edges pruned.
100  CFG *getUnoptimizedCFG();
101
102  void dumpCFG();
103
104  ParentMap &getParentMap();
105  PseudoConstantAnalysis *getPseudoConstantAnalysis();
106  LiveVariables *getLiveVariables();
107  LiveVariables *getRelaxedLiveVariables();
108
109  typedef const VarDecl * const * referenced_decls_iterator;
110
111  std::pair<referenced_decls_iterator, referenced_decls_iterator>
112    getReferencedBlockVars(const BlockDecl *BD);
113
114  /// 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;
122  bool UseUnoptimizedCFG;
123  bool AddImplicitDtors;
124  bool AddInitializers;
125public:
126  AnalysisContextManager(bool useUnoptimizedCFG = false,
127      bool addImplicitDtors = false, bool addInitializers = false)
128    : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
129      AddInitializers(addInitializers) {}
130
131  ~AnalysisContextManager();
132
133  AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
134
135  bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
136  bool getAddImplicitDtors() const { return AddImplicitDtors; }
137  bool getAddInitializers() const { return AddInitializers; }
138
139  // 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;
149
150  // AnalysisContext can't be const since some methods may modify its member.
151  AnalysisContext *Ctx;
152
153  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();
162
163  ContextKind getKind() const { return Kind; }
164
165  AnalysisContext *getAnalysisContext() const { return Ctx; }
166
167  idx::TranslationUnit *getTranslationUnit() const {
168    return Ctx->getTranslationUnit();
169  }
170
171  const LocationContext *getParent() const { return Parent; }
172
173  bool isParentOf(const LocationContext *LC) const;
174
175  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
183  ParentMap &getParentMap() const {
184    return getAnalysisContext()->getParentMap();
185  }
186
187  const ImplicitParamDecl *getSelfDecl() const {
188    return Ctx->getSelfDecl();
189  }
190
191  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 {
208  // The callsite where this stack frame is established.
209  const Stmt *CallSite;
210
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,
219                    const Stmt *s, const CFGBlock *blk,
220                    unsigned idx)
221    : LocationContext(StackFrame, ctx, parent), CallSite(s),
222      Block(blk), Index(idx) {}
223
224public:
225  ~StackFrameContext() {}
226
227  const Stmt *getCallSite() const { return CallSite; }
228
229  const CFGBlock *getCallSiteBlock() const { return Block; }
230
231  unsigned getIndex() const { return Index; }
232
233  void Profile(llvm::FoldingSetNodeID &ID);
234
235  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
236                      const LocationContext *parent, const Stmt *s,
237                      const CFGBlock *blk, unsigned idx) {
238    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;
250
251  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  }
293
294  static bool classof(const LocationContext* Ctx) {
295    return Ctx->getKind() == Block;
296  }
297};
298
299class LocationContextManager {
300  llvm::FoldingSet<LocationContext> Contexts;
301public:
302  ~LocationContextManager();
303
304  const StackFrameContext *getStackFrame(AnalysisContext *ctx,
305                                         const LocationContext *parent,
306                                         const Stmt *s,
307                                         const CFGBlock *blk, unsigned idx);
308
309  const ScopeContext *getScope(AnalysisContext *ctx,
310                               const LocationContext *parent,
311                               const Stmt *s);
312
313  /// 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
324