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