]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/Analysis/AnalysisContext.h
Merge ^/vendor/binutils/dist@214571 into contrib/binutils, which brings
[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 "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
25 namespace clang {
26
27 class Decl;
28 class Stmt;
29 class CFG;
30 class CFGBlock;
31 class LiveVariables;
32 class ParentMap;
33 class PseudoConstantAnalysis;
34 class ImplicitParamDecl;
35 class LocationContextManager;
36 class StackFrameContext;
37
38 namespace idx { class TranslationUnit; }
39
40 /// AnalysisContext contains the context data for the function or method under
41 /// analysis.
42 class 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;
59 public:
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
105 class AnalysisContextManager {
106   typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
107   ContextMap Contexts;
108   bool UseUnoptimizedCFG;
109 public:
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
123 class LocationContext : public llvm::FoldingSetNode {
124 public:
125   enum ContextKind { StackFrame, Scope, Block };
126
127 private:
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
135 protected:
136   LocationContext(ContextKind k, AnalysisContext *ctx,
137                   const LocationContext *parent)
138     : Kind(k), Ctx(ctx), Parent(parent) {}
139
140 public:
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
179 public:
180   static void ProfileCommon(llvm::FoldingSetNodeID &ID,
181                             ContextKind ck,
182                             AnalysisContext *ctx,
183                             const LocationContext *parent,
184                             const void* data);
185 };
186
187 class 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
203 public:
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
227 class 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
235 public:
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
250 class 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
261 public:
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
278 class LocationContextManager {
279   llvm::FoldingSet<LocationContext> Contexts;
280 public:
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();
294 private:
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