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