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