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