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