]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.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 "clang/Analysis/CFG.h"
21 #include "llvm/ADT/OwningPtr.h"
22 #include "llvm/ADT/IntrusiveRefCntPtr.h"
23 #include "llvm/ADT/FoldingSet.h"
24 #include "llvm/ADT/PointerUnion.h"
25 #include "llvm/ADT/DenseMap.h"
26 #include "llvm/Support/Allocator.h"
27
28 namespace clang {
29
30 class Decl;
31 class Stmt;
32 class CFGReverseBlockReachabilityAnalysis;
33 class CFGStmtMap;
34 class LiveVariables;
35 class ManagedAnalysis;
36 class ParentMap;
37 class PseudoConstantAnalysis;
38 class ImplicitParamDecl;
39 class LocationContextManager;
40 class StackFrameContext;
41   
42 namespace idx { class TranslationUnit; }
43
44 /// The base class of a hierarchy of objects representing analyses tied
45 /// to AnalysisContext.
46 class ManagedAnalysis {
47 protected:
48   ManagedAnalysis() {}
49 public:
50   virtual ~ManagedAnalysis();
51   
52   // Subclasses need to implement:
53   //
54   //  static const void *getTag();
55   //
56   // Which returns a fixed pointer address to distinguish classes of
57   // analysis objects.  They also need to implement:
58   //
59   //  static [Derived*] create(AnalysisContext &Ctx);
60   //
61   // which creates the analysis object given an AnalysisContext.
62 };
63   
64 /// AnalysisContext contains the context data for the function or method under
65 /// analysis.
66 class AnalysisContext {
67   const Decl *D;
68
69   // TranslationUnit is NULL if we don't have multiple translation units.
70   idx::TranslationUnit *TU;
71
72   llvm::OwningPtr<CFG> cfg, completeCFG;
73   llvm::OwningPtr<CFGStmtMap> cfgStmtMap;
74
75   CFG::BuildOptions cfgBuildOptions;
76   CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
77   
78   bool builtCFG, builtCompleteCFG;
79
80   llvm::OwningPtr<LiveVariables> liveness;
81   llvm::OwningPtr<LiveVariables> relaxedLiveness;
82   llvm::OwningPtr<ParentMap> PM;
83   llvm::OwningPtr<PseudoConstantAnalysis> PCA;
84   llvm::OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA;
85
86   llvm::BumpPtrAllocator A;
87
88   // FIXME: remove.
89   llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
90
91   void *ManagedAnalyses;
92
93 public:
94   AnalysisContext(const Decl *d, idx::TranslationUnit *tu);
95
96   AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
97                   const CFG::BuildOptions &buildOptions);
98
99   ~AnalysisContext();
100
101   ASTContext &getASTContext() { return D->getASTContext(); }
102   const Decl *getDecl() const { return D; }
103
104   idx::TranslationUnit *getTranslationUnit() const { return TU; }
105
106   /// Return the build options used to construct the CFG.
107   CFG::BuildOptions &getCFGBuildOptions() {
108     return cfgBuildOptions;
109   }
110
111   const CFG::BuildOptions &getCFGBuildOptions() const {
112     return cfgBuildOptions;
113   }
114   
115   /// getAddEHEdges - Return true iff we are adding exceptional edges from
116   /// callExprs.  If this is false, then try/catch statements and blocks
117   /// reachable from them can appear to be dead in the CFG, analysis passes must
118   /// cope with that.
119   bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }  
120   bool getUseUnoptimizedCFG() const {
121       return !cfgBuildOptions.PruneTriviallyFalseEdges;
122   }
123   bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
124   bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
125
126   void registerForcedBlockExpression(const Stmt *stmt);
127   const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
128   
129   Stmt *getBody() const;
130   CFG *getCFG();
131   
132   CFGStmtMap *getCFGStmtMap();
133
134   CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
135   
136   /// Return a version of the CFG without any edges pruned.
137   CFG *getUnoptimizedCFG();
138
139   void dumpCFG();
140
141   /// \brief Returns true if we have built a CFG for this analysis context.
142   /// Note that this doesn't correspond to whether or not a valid CFG exists, it
143   /// corresponds to whether we *attempted* to build one.
144   bool isCFGBuilt() const { return builtCFG; }
145
146   ParentMap &getParentMap();
147   PseudoConstantAnalysis *getPseudoConstantAnalysis();
148
149   typedef const VarDecl * const * referenced_decls_iterator;
150
151   std::pair<referenced_decls_iterator, referenced_decls_iterator>
152     getReferencedBlockVars(const BlockDecl *BD);
153
154   /// Return the ImplicitParamDecl* associated with 'self' if this
155   /// AnalysisContext wraps an ObjCMethodDecl.  Returns NULL otherwise.
156   const ImplicitParamDecl *getSelfDecl() const;
157   
158   /// Return the specified analysis object, lazily running the analysis if
159   /// necessary.  Return NULL if the analysis could not run.
160   template <typename T>
161   T *getAnalysis() {
162     const void *tag = T::getTag();
163     ManagedAnalysis *&data = getAnalysisImpl(tag);
164     if (!data) {
165       data = T::create(*this);
166     }
167     return static_cast<T*>(data);
168   }
169 private:
170   ManagedAnalysis *&getAnalysisImpl(const void* tag);
171 };
172
173 class AnalysisContextManager {
174   typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
175   ContextMap Contexts;
176   CFG::BuildOptions cfgBuildOptions;
177 public:
178   AnalysisContextManager(bool useUnoptimizedCFG = false,
179                          bool addImplicitDtors = false,
180                          bool addInitializers = false);
181   
182   ~AnalysisContextManager();
183
184   AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
185
186   bool getUseUnoptimizedCFG() const {
187     return !cfgBuildOptions.PruneTriviallyFalseEdges;
188   }
189   
190   CFG::BuildOptions &getCFGBuildOptions() {
191     return cfgBuildOptions;
192   }
193
194   /// Discard all previously created AnalysisContexts.
195   void clear();
196 };
197
198 class LocationContext : public llvm::FoldingSetNode {
199 public:
200   enum ContextKind { StackFrame, Scope, Block };
201
202 private:
203   ContextKind Kind;
204
205   // AnalysisContext can't be const since some methods may modify its member.
206   AnalysisContext *Ctx;
207
208   const LocationContext *Parent;
209
210 protected:
211   LocationContext(ContextKind k, AnalysisContext *ctx,
212                   const LocationContext *parent)
213     : Kind(k), Ctx(ctx), Parent(parent) {}
214
215 public:
216   virtual ~LocationContext();
217
218   ContextKind getKind() const { return Kind; }
219
220   AnalysisContext *getAnalysisContext() const { return Ctx; }
221
222   idx::TranslationUnit *getTranslationUnit() const { 
223     return Ctx->getTranslationUnit(); 
224   }
225
226   const LocationContext *getParent() const { return Parent; }
227
228   bool isParentOf(const LocationContext *LC) const;
229
230   const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
231
232   CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
233
234   template <typename T>
235   T *getAnalysis() const {
236     return getAnalysisContext()->getAnalysis<T>();
237   }
238
239   ParentMap &getParentMap() const {
240     return getAnalysisContext()->getParentMap();
241   }
242
243   const ImplicitParamDecl *getSelfDecl() const {
244     return Ctx->getSelfDecl();
245   }
246
247   const StackFrameContext *getCurrentStackFrame() const;
248   const StackFrameContext *
249     getStackFrameForDeclContext(const DeclContext *DC) const;
250
251   virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
252
253   static bool classof(const LocationContext*) { return true; }
254
255 public:
256   static void ProfileCommon(llvm::FoldingSetNodeID &ID,
257                             ContextKind ck,
258                             AnalysisContext *ctx,
259                             const LocationContext *parent,
260                             const void *data);
261 };
262
263 class StackFrameContext : public LocationContext {
264   // The callsite where this stack frame is established.
265   const Stmt *CallSite;
266
267   // The parent block of the callsite.
268   const CFGBlock *Block;
269
270   // The index of the callsite in the CFGBlock.
271   unsigned Index;
272
273   friend class LocationContextManager;
274   StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
275                     const Stmt *s, const CFGBlock *blk, 
276                     unsigned idx)
277     : LocationContext(StackFrame, ctx, parent), CallSite(s),
278       Block(blk), Index(idx) {}
279
280 public:
281   ~StackFrameContext() {}
282
283   const Stmt *getCallSite() const { return CallSite; }
284
285   const CFGBlock *getCallSiteBlock() const { return Block; }
286
287   unsigned getIndex() const { return Index; }
288
289   void Profile(llvm::FoldingSetNodeID &ID);
290
291   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
292                       const LocationContext *parent, const Stmt *s,
293                       const CFGBlock *blk, unsigned idx) {
294     ProfileCommon(ID, StackFrame, ctx, parent, s);
295     ID.AddPointer(blk);
296     ID.AddInteger(idx);
297   }
298
299   static bool classof(const LocationContext *Ctx) {
300     return Ctx->getKind() == StackFrame;
301   }
302 };
303
304 class ScopeContext : public LocationContext {
305   const Stmt *Enter;
306
307   friend class LocationContextManager;
308   ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
309                const Stmt *s)
310     : LocationContext(Scope, ctx, parent), Enter(s) {}
311
312 public:
313   ~ScopeContext() {}
314
315   void Profile(llvm::FoldingSetNodeID &ID);
316
317   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
318                       const LocationContext *parent, const Stmt *s) {
319     ProfileCommon(ID, Scope, ctx, parent, s);
320   }
321
322   static bool classof(const LocationContext *Ctx) {
323     return Ctx->getKind() == Scope;
324   }
325 };
326
327 class BlockInvocationContext : public LocationContext {
328   // FIXME: Add back context-sensivity (we don't want libAnalysis to know
329   //  about MemRegion).
330   const BlockDecl *BD;
331
332   friend class LocationContextManager;
333
334   BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
335                          const BlockDecl *bd)
336     : LocationContext(Block, ctx, parent), BD(bd) {}
337
338 public:
339   ~BlockInvocationContext() {}
340
341   const BlockDecl *getBlockDecl() const { return BD; }
342
343   void Profile(llvm::FoldingSetNodeID &ID);
344
345   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
346                       const LocationContext *parent, const BlockDecl *bd) {
347     ProfileCommon(ID, Block, ctx, parent, bd);
348   }
349
350   static bool classof(const LocationContext *Ctx) {
351     return Ctx->getKind() == Block;
352   }
353 };
354
355 class LocationContextManager {
356   llvm::FoldingSet<LocationContext> Contexts;
357 public:
358   ~LocationContextManager();
359
360   const StackFrameContext *getStackFrame(AnalysisContext *ctx,
361                                          const LocationContext *parent,
362                                          const Stmt *s,
363                                          const CFGBlock *blk, unsigned idx);
364
365   const ScopeContext *getScope(AnalysisContext *ctx,
366                                const LocationContext *parent,
367                                const Stmt *s);
368
369   /// Discard all previously created LocationContext objects.
370   void clear();
371 private:
372   template <typename LOC, typename DATA>
373   const LOC *getLocationContext(AnalysisContext *ctx,
374                                 const LocationContext *parent,
375                                 const DATA *d);
376 };
377
378 } // end clang namespace
379 #endif