AnalysisContext.h revision 04eeba43040969c05cfcb563195ef5b199297b62
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  void dumpCFG();
99
100  ParentMap &getParentMap();
101  PseudoConstantAnalysis *getPseudoConstantAnalysis();
102  LiveVariables *getLiveVariables();
103  LiveVariables *getRelaxedLiveVariables();
104
105  typedef const VarDecl * const * referenced_decls_iterator;
106
107  std::pair<referenced_decls_iterator, referenced_decls_iterator>
108    getReferencedBlockVars(const BlockDecl *BD);
109
110  /// Return the ImplicitParamDecl* associated with 'self' if this
111  /// AnalysisContext wraps an ObjCMethodDecl.  Returns NULL otherwise.
112  const ImplicitParamDecl *getSelfDecl() const;
113};
114
115class AnalysisContextManager {
116  typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
117  ContextMap Contexts;
118  bool UseUnoptimizedCFG;
119  bool AddImplicitDtors;
120  bool AddInitializers;
121public:
122  AnalysisContextManager(bool useUnoptimizedCFG = false,
123      bool addImplicitDtors = false, bool addInitializers = false)
124    : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
125      AddInitializers(addInitializers) {}
126
127  ~AnalysisContextManager();
128
129  AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
130
131  bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
132  bool getAddImplicitDtors() const { return AddImplicitDtors; }
133  bool getAddInitializers() const { return AddInitializers; }
134
135  // Discard all previously created AnalysisContexts.
136  void clear();
137};
138
139class LocationContext : public llvm::FoldingSetNode {
140public:
141  enum ContextKind { StackFrame, Scope, Block };
142
143private:
144  ContextKind Kind;
145
146  // AnalysisContext can't be const since some methods may modify its member.
147  AnalysisContext *Ctx;
148
149  const LocationContext *Parent;
150
151protected:
152  LocationContext(ContextKind k, AnalysisContext *ctx,
153                  const LocationContext *parent)
154    : Kind(k), Ctx(ctx), Parent(parent) {}
155
156public:
157  virtual ~LocationContext();
158
159  ContextKind getKind() const { return Kind; }
160
161  AnalysisContext *getAnalysisContext() const { return Ctx; }
162
163  idx::TranslationUnit *getTranslationUnit() const {
164    return Ctx->getTranslationUnit();
165  }
166
167  const LocationContext *getParent() const { return Parent; }
168
169  bool isParentOf(const LocationContext *LC) const;
170
171  const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
172
173  CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
174
175  LiveVariables *getLiveVariables() const {
176    return getAnalysisContext()->getLiveVariables();
177  }
178
179  ParentMap &getParentMap() const {
180    return getAnalysisContext()->getParentMap();
181  }
182
183  const ImplicitParamDecl *getSelfDecl() const {
184    return Ctx->getSelfDecl();
185  }
186
187  const StackFrameContext *getCurrentStackFrame() const;
188  const StackFrameContext *
189    getStackFrameForDeclContext(const DeclContext *DC) const;
190
191  virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
192
193  static bool classof(const LocationContext*) { return true; }
194
195public:
196  static void ProfileCommon(llvm::FoldingSetNodeID &ID,
197                            ContextKind ck,
198                            AnalysisContext *ctx,
199                            const LocationContext *parent,
200                            const void* data);
201};
202
203class StackFrameContext : public LocationContext {
204  // The callsite where this stack frame is established.
205  const Stmt *CallSite;
206
207  // The parent block of the callsite.
208  const CFGBlock *Block;
209
210  // The index of the callsite in the CFGBlock.
211  unsigned Index;
212
213  friend class LocationContextManager;
214  StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
215                    const Stmt *s, const CFGBlock *blk,
216                    unsigned idx)
217    : LocationContext(StackFrame, ctx, parent), CallSite(s),
218      Block(blk), Index(idx) {}
219
220public:
221  ~StackFrameContext() {}
222
223  const Stmt *getCallSite() const { return CallSite; }
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                      const CFGBlock *blk, unsigned idx) {
234    ProfileCommon(ID, StackFrame, ctx, parent, s);
235    ID.AddPointer(blk);
236    ID.AddInteger(idx);
237  }
238
239  static bool classof(const LocationContext* Ctx) {
240    return Ctx->getKind() == StackFrame;
241  }
242};
243
244class ScopeContext : public LocationContext {
245  const Stmt *Enter;
246
247  friend class LocationContextManager;
248  ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
249               const Stmt *s)
250    : LocationContext(Scope, ctx, parent), Enter(s) {}
251
252public:
253  ~ScopeContext() {}
254
255  void Profile(llvm::FoldingSetNodeID &ID);
256
257  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
258                      const LocationContext *parent, const Stmt *s) {
259    ProfileCommon(ID, Scope, ctx, parent, s);
260  }
261
262  static bool classof(const LocationContext* Ctx) {
263    return Ctx->getKind() == Scope;
264  }
265};
266
267class BlockInvocationContext : public LocationContext {
268  // FIXME: Add back context-sensivity (we don't want libAnalysis to know
269  //  about MemRegion).
270  const BlockDecl *BD;
271
272  friend class LocationContextManager;
273
274  BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
275                         const BlockDecl *bd)
276    : LocationContext(Block, ctx, parent), BD(bd) {}
277
278public:
279  ~BlockInvocationContext() {}
280
281  const BlockDecl *getBlockDecl() const { return BD; }
282
283  void Profile(llvm::FoldingSetNodeID &ID);
284
285  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
286                      const LocationContext *parent, const BlockDecl *bd) {
287    ProfileCommon(ID, Block, ctx, parent, bd);
288  }
289
290  static bool classof(const LocationContext* Ctx) {
291    return Ctx->getKind() == Block;
292  }
293};
294
295class LocationContextManager {
296  llvm::FoldingSet<LocationContext> Contexts;
297public:
298  ~LocationContextManager();
299
300  const StackFrameContext *getStackFrame(AnalysisContext *ctx,
301                                         const LocationContext *parent,
302                                         const Stmt *s,
303                                         const CFGBlock *blk, unsigned idx);
304
305  const ScopeContext *getScope(AnalysisContext *ctx,
306                               const LocationContext *parent,
307                               const Stmt *s);
308
309  /// Discard all previously created LocationContext objects.
310  void clear();
311private:
312  template <typename LOC, typename DATA>
313  const LOC *getLocationContext(AnalysisContext *ctx,
314                                const LocationContext *parent,
315                                const DATA *d);
316};
317
318} // end clang namespace
319#endif
320