AnalysisContext.h revision 74fb1a493cf5d2dd0fb51a4eadf74e85e10a3457
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  /// Return the build options used to construct the CFG.
85  CFG::BuildOptions &getCFGBuildOptions() {
86    return cfgBuildOptions;
87  }
88
89  const CFG::BuildOptions &getCFGBuildOptions() const {
90    return cfgBuildOptions;
91  }
92
93  /// getAddEHEdges - Return true iff we are adding exceptional edges from
94  /// callExprs.  If this is false, then try/catch statements and blocks
95  /// reachable from them can appear to be dead in the CFG, analysis passes must
96  /// cope with that.
97  bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
98  bool getUseUnoptimizedCFG() const {
99      return cfgBuildOptions.PruneTriviallyFalseEdges;
100  }
101  bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
102  bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
103
104  void registerForcedBlockExpression(const Stmt *stmt);
105  const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
106
107  Stmt *getBody();
108  CFG *getCFG();
109
110  CFGStmtMap *getCFGStmtMap();
111
112  CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
113
114  /// Return a version of the CFG without any edges pruned.
115  CFG *getUnoptimizedCFG();
116
117  void dumpCFG();
118
119  /// \brief Returns true if we have built a CFG for this analysis context.
120  /// Note that this doesn't correspond to whether or not a valid CFG exists, it
121  /// corresponds to whether we *attempted* to build one.
122  bool isCFGBuilt() const { return builtCFG; }
123
124  ParentMap &getParentMap();
125  PseudoConstantAnalysis *getPseudoConstantAnalysis();
126  LiveVariables *getLiveVariables();
127  LiveVariables *getRelaxedLiveVariables();
128
129  typedef const VarDecl * const * referenced_decls_iterator;
130
131  std::pair<referenced_decls_iterator, referenced_decls_iterator>
132    getReferencedBlockVars(const BlockDecl *BD);
133
134  /// Return the ImplicitParamDecl* associated with 'self' if this
135  /// AnalysisContext wraps an ObjCMethodDecl.  Returns NULL otherwise.
136  const ImplicitParamDecl *getSelfDecl() const;
137};
138
139class AnalysisContextManager {
140  typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
141  ContextMap Contexts;
142  bool UseUnoptimizedCFG;
143  bool AddImplicitDtors;
144  bool AddInitializers;
145public:
146  AnalysisContextManager(bool useUnoptimizedCFG = false,
147      bool addImplicitDtors = false, bool addInitializers = false)
148    : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
149      AddInitializers(addInitializers) {}
150
151  ~AnalysisContextManager();
152
153  AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
154
155  bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
156  bool getAddImplicitDtors() const { return AddImplicitDtors; }
157  bool getAddInitializers() const { return AddInitializers; }
158
159  // Discard all previously created AnalysisContexts.
160  void clear();
161};
162
163class LocationContext : public llvm::FoldingSetNode {
164public:
165  enum ContextKind { StackFrame, Scope, Block };
166
167private:
168  ContextKind Kind;
169
170  // AnalysisContext can't be const since some methods may modify its member.
171  AnalysisContext *Ctx;
172
173  const LocationContext *Parent;
174
175protected:
176  LocationContext(ContextKind k, AnalysisContext *ctx,
177                  const LocationContext *parent)
178    : Kind(k), Ctx(ctx), Parent(parent) {}
179
180public:
181  virtual ~LocationContext();
182
183  ContextKind getKind() const { return Kind; }
184
185  AnalysisContext *getAnalysisContext() const { return Ctx; }
186
187  idx::TranslationUnit *getTranslationUnit() const {
188    return Ctx->getTranslationUnit();
189  }
190
191  const LocationContext *getParent() const { return Parent; }
192
193  bool isParentOf(const LocationContext *LC) const;
194
195  const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
196
197  CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
198
199  LiveVariables *getLiveVariables() const {
200    return getAnalysisContext()->getLiveVariables();
201  }
202
203  ParentMap &getParentMap() const {
204    return getAnalysisContext()->getParentMap();
205  }
206
207  const ImplicitParamDecl *getSelfDecl() const {
208    return Ctx->getSelfDecl();
209  }
210
211  const StackFrameContext *getCurrentStackFrame() const;
212  const StackFrameContext *
213    getStackFrameForDeclContext(const DeclContext *DC) const;
214
215  virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
216
217  static bool classof(const LocationContext*) { return true; }
218
219public:
220  static void ProfileCommon(llvm::FoldingSetNodeID &ID,
221                            ContextKind ck,
222                            AnalysisContext *ctx,
223                            const LocationContext *parent,
224                            const void* data);
225};
226
227class StackFrameContext : public LocationContext {
228  // The callsite where this stack frame is established.
229  const Stmt *CallSite;
230
231  // The parent block of the callsite.
232  const CFGBlock *Block;
233
234  // The index of the callsite in the CFGBlock.
235  unsigned Index;
236
237  friend class LocationContextManager;
238  StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
239                    const Stmt *s, const CFGBlock *blk,
240                    unsigned idx)
241    : LocationContext(StackFrame, ctx, parent), CallSite(s),
242      Block(blk), Index(idx) {}
243
244public:
245  ~StackFrameContext() {}
246
247  const Stmt *getCallSite() const { return CallSite; }
248
249  const CFGBlock *getCallSiteBlock() const { return Block; }
250
251  unsigned getIndex() const { return Index; }
252
253  void Profile(llvm::FoldingSetNodeID &ID);
254
255  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
256                      const LocationContext *parent, const Stmt *s,
257                      const CFGBlock *blk, unsigned idx) {
258    ProfileCommon(ID, StackFrame, ctx, parent, s);
259    ID.AddPointer(blk);
260    ID.AddInteger(idx);
261  }
262
263  static bool classof(const LocationContext* Ctx) {
264    return Ctx->getKind() == StackFrame;
265  }
266};
267
268class ScopeContext : public LocationContext {
269  const Stmt *Enter;
270
271  friend class LocationContextManager;
272  ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
273               const Stmt *s)
274    : LocationContext(Scope, ctx, parent), Enter(s) {}
275
276public:
277  ~ScopeContext() {}
278
279  void Profile(llvm::FoldingSetNodeID &ID);
280
281  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
282                      const LocationContext *parent, const Stmt *s) {
283    ProfileCommon(ID, Scope, ctx, parent, s);
284  }
285
286  static bool classof(const LocationContext* Ctx) {
287    return Ctx->getKind() == Scope;
288  }
289};
290
291class BlockInvocationContext : public LocationContext {
292  // FIXME: Add back context-sensivity (we don't want libAnalysis to know
293  //  about MemRegion).
294  const BlockDecl *BD;
295
296  friend class LocationContextManager;
297
298  BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
299                         const BlockDecl *bd)
300    : LocationContext(Block, ctx, parent), BD(bd) {}
301
302public:
303  ~BlockInvocationContext() {}
304
305  const BlockDecl *getBlockDecl() const { return BD; }
306
307  void Profile(llvm::FoldingSetNodeID &ID);
308
309  static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
310                      const LocationContext *parent, const BlockDecl *bd) {
311    ProfileCommon(ID, Block, ctx, parent, bd);
312  }
313
314  static bool classof(const LocationContext* Ctx) {
315    return Ctx->getKind() == Block;
316  }
317};
318
319class LocationContextManager {
320  llvm::FoldingSet<LocationContext> Contexts;
321public:
322  ~LocationContextManager();
323
324  const StackFrameContext *getStackFrame(AnalysisContext *ctx,
325                                         const LocationContext *parent,
326                                         const Stmt *s,
327                                         const CFGBlock *blk, unsigned idx);
328
329  const ScopeContext *getScope(AnalysisContext *ctx,
330                               const LocationContext *parent,
331                               const Stmt *s);
332
333  /// Discard all previously created LocationContext objects.
334  void clear();
335private:
336  template <typename LOC, typename DATA>
337  const LOC *getLocationContext(AnalysisContext *ctx,
338                                const LocationContext *parent,
339                                const DATA *d);
340};
341
342} // end clang namespace
343#endif
344