]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
Merge gdtoa-20110304.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / Analysis / AnalysisContext.h
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
26 namespace clang {
27
28 class Decl;
29 class Stmt;
30 class CFG;
31 class CFGBlock;
32 class CFGReachabilityAnalysis;
33 class CFGStmtMap;
34 class LiveVariables;
35 class ParentMap;
36 class PseudoConstantAnalysis;
37 class ImplicitParamDecl;
38 class LocationContextManager;
39 class StackFrameContext;
40
41 namespace idx { class TranslationUnit; }
42
43 /// AnalysisContext contains the context data for the function or method under
44 /// analysis.
45 class 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;
66 public:
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
123 class AnalysisContextManager {
124   typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
125   ContextMap Contexts;
126   bool UseUnoptimizedCFG;
127   bool AddImplicitDtors;
128   bool AddInitializers;
129 public:
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
147 class LocationContext : public llvm::FoldingSetNode {
148 public:
149   enum ContextKind { StackFrame, Scope, Block };
150
151 private:
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
159 protected:
160   LocationContext(ContextKind k, AnalysisContext *ctx,
161                   const LocationContext *parent)
162     : Kind(k), Ctx(ctx), Parent(parent) {}
163
164 public:
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
203 public:
204   static void ProfileCommon(llvm::FoldingSetNodeID &ID,
205                             ContextKind ck,
206                             AnalysisContext *ctx,
207                             const LocationContext *parent,
208                             const void* data);
209 };
210
211 class 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
228 public:
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
252 class 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
260 public:
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
275 class 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
286 public:
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
303 class LocationContextManager {
304   llvm::FoldingSet<LocationContext> Contexts;
305 public:
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();
319 private:
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