1 //=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines AnalysisDeclContext, a class that manages the analysis
11 // context data for path sensitive analysis.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
16 #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H
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"
32 class CFGReverseBlockReachabilityAnalysis;
35 class ManagedAnalysis;
37 class PseudoConstantAnalysis;
38 class ImplicitParamDecl;
39 class LocationContextManager;
40 class StackFrameContext;
41 class BlockInvocationContext;
42 class AnalysisDeclContextManager;
43 class LocationContext;
45 namespace idx { class TranslationUnit; }
47 /// The base class of a hierarchy of objects representing analyses tied
48 /// to AnalysisDeclContext.
49 class ManagedAnalysis {
53 virtual ~ManagedAnalysis();
55 // Subclasses need to implement:
57 // static const void *getTag();
59 // Which returns a fixed pointer address to distinguish classes of
60 // analysis objects. They also need to implement:
62 // static [Derived*] create(AnalysisDeclContext &Ctx);
64 // which creates the analysis object given an AnalysisDeclContext.
68 /// AnalysisDeclContext contains the context data for the function or method
70 class AnalysisDeclContext {
71 /// Backpoint to the AnalysisManager object that created this
72 /// AnalysisDeclContext. This may be null.
73 AnalysisDeclContextManager *Manager;
77 OwningPtr<CFG> cfg, completeCFG;
78 OwningPtr<CFGStmtMap> cfgStmtMap;
80 CFG::BuildOptions cfgBuildOptions;
81 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
83 bool builtCFG, builtCompleteCFG;
84 OwningPtr<ParentMap> PM;
85 OwningPtr<PseudoConstantAnalysis> PCA;
86 OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA;
88 llvm::BumpPtrAllocator A;
90 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
92 void *ManagedAnalyses;
95 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
98 AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
100 const CFG::BuildOptions &BuildOptions);
102 ~AnalysisDeclContext();
104 ASTContext &getASTContext() const { return D->getASTContext(); }
105 const Decl *getDecl() const { return D; }
107 /// Return the AnalysisDeclContextManager (if any) that created
108 /// this AnalysisDeclContext.
109 AnalysisDeclContextManager *getManager() const {
113 /// Return the build options used to construct the CFG.
114 CFG::BuildOptions &getCFGBuildOptions() {
115 return cfgBuildOptions;
118 const CFG::BuildOptions &getCFGBuildOptions() const {
119 return cfgBuildOptions;
122 /// getAddEHEdges - Return true iff we are adding exceptional edges from
123 /// callExprs. If this is false, then try/catch statements and blocks
124 /// reachable from them can appear to be dead in the CFG, analysis passes must
126 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
127 bool getUseUnoptimizedCFG() const {
128 return !cfgBuildOptions.PruneTriviallyFalseEdges;
130 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
131 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
133 void registerForcedBlockExpression(const Stmt *stmt);
134 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
136 Stmt *getBody() const;
139 CFGStmtMap *getCFGStmtMap();
141 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
143 /// Return a version of the CFG without any edges pruned.
144 CFG *getUnoptimizedCFG();
146 void dumpCFG(bool ShowColors);
148 /// \brief Returns true if we have built a CFG for this analysis context.
149 /// Note that this doesn't correspond to whether or not a valid CFG exists, it
150 /// corresponds to whether we *attempted* to build one.
151 bool isCFGBuilt() const { return builtCFG; }
153 ParentMap &getParentMap();
154 PseudoConstantAnalysis *getPseudoConstantAnalysis();
156 typedef const VarDecl * const * referenced_decls_iterator;
158 std::pair<referenced_decls_iterator, referenced_decls_iterator>
159 getReferencedBlockVars(const BlockDecl *BD);
161 /// Return the ImplicitParamDecl* associated with 'self' if this
162 /// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise.
163 const ImplicitParamDecl *getSelfDecl() const;
165 const StackFrameContext *getStackFrame(LocationContext const *Parent,
170 const BlockInvocationContext *
171 getBlockInvocationContext(const LocationContext *parent,
173 const void *ContextData);
175 /// Return the specified analysis object, lazily running the analysis if
176 /// necessary. Return NULL if the analysis could not run.
177 template <typename T>
179 const void *tag = T::getTag();
180 ManagedAnalysis *&data = getAnalysisImpl(tag);
182 data = T::create(*this);
184 return static_cast<T*>(data);
187 ManagedAnalysis *&getAnalysisImpl(const void* tag);
189 LocationContextManager &getLocationContextManager();
192 class LocationContext : public llvm::FoldingSetNode {
194 enum ContextKind { StackFrame, Scope, Block };
199 // AnalysisDeclContext can't be const since some methods may modify its
201 AnalysisDeclContext *Ctx;
203 const LocationContext *Parent;
206 LocationContext(ContextKind k, AnalysisDeclContext *ctx,
207 const LocationContext *parent)
208 : Kind(k), Ctx(ctx), Parent(parent) {}
211 virtual ~LocationContext();
213 ContextKind getKind() const { return Kind; }
215 AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
217 const LocationContext *getParent() const { return Parent; }
219 bool isParentOf(const LocationContext *LC) const;
221 const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); }
223 CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); }
225 template <typename T>
226 T *getAnalysis() const {
227 return getAnalysisDeclContext()->getAnalysis<T>();
230 ParentMap &getParentMap() const {
231 return getAnalysisDeclContext()->getParentMap();
234 const ImplicitParamDecl *getSelfDecl() const {
235 return Ctx->getSelfDecl();
238 const StackFrameContext *getCurrentStackFrame() const;
240 /// Return true if the current LocationContext has no caller context.
241 virtual bool inTopFrame() const;
243 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
246 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
248 AnalysisDeclContext *ctx,
249 const LocationContext *parent,
253 class StackFrameContext : public LocationContext {
254 // The callsite where this stack frame is established.
255 const Stmt *CallSite;
257 // The parent block of the callsite.
258 const CFGBlock *Block;
260 // The index of the callsite in the CFGBlock.
263 friend class LocationContextManager;
264 StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent,
265 const Stmt *s, const CFGBlock *blk,
267 : LocationContext(StackFrame, ctx, parent), CallSite(s),
268 Block(blk), Index(idx) {}
271 ~StackFrameContext() {}
273 const Stmt *getCallSite() const { return CallSite; }
275 const CFGBlock *getCallSiteBlock() const { return Block; }
277 /// Return true if the current LocationContext has no caller context.
278 virtual bool inTopFrame() const { return getParent() == 0; }
280 unsigned getIndex() const { return Index; }
282 void Profile(llvm::FoldingSetNodeID &ID);
284 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
285 const LocationContext *parent, const Stmt *s,
286 const CFGBlock *blk, unsigned idx) {
287 ProfileCommon(ID, StackFrame, ctx, parent, s);
292 static bool classof(const LocationContext *Ctx) {
293 return Ctx->getKind() == StackFrame;
297 class ScopeContext : public LocationContext {
300 friend class LocationContextManager;
301 ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
303 : LocationContext(Scope, ctx, parent), Enter(s) {}
308 void Profile(llvm::FoldingSetNodeID &ID);
310 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
311 const LocationContext *parent, const Stmt *s) {
312 ProfileCommon(ID, Scope, ctx, parent, s);
315 static bool classof(const LocationContext *Ctx) {
316 return Ctx->getKind() == Scope;
320 class BlockInvocationContext : public LocationContext {
323 // FIXME: Come up with a more type-safe way to model context-sensitivity.
324 const void *ContextData;
326 friend class LocationContextManager;
328 BlockInvocationContext(AnalysisDeclContext *ctx,
329 const LocationContext *parent,
330 const BlockDecl *bd, const void *contextData)
331 : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {}
334 ~BlockInvocationContext() {}
336 const BlockDecl *getBlockDecl() const { return BD; }
338 const void *getContextData() const { return ContextData; }
340 void Profile(llvm::FoldingSetNodeID &ID);
342 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
343 const LocationContext *parent, const BlockDecl *bd,
344 const void *contextData) {
345 ProfileCommon(ID, Block, ctx, parent, bd);
346 ID.AddPointer(contextData);
349 static bool classof(const LocationContext *Ctx) {
350 return Ctx->getKind() == Block;
354 class LocationContextManager {
355 llvm::FoldingSet<LocationContext> Contexts;
357 ~LocationContextManager();
359 const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx,
360 const LocationContext *parent,
362 const CFGBlock *blk, unsigned idx);
364 const ScopeContext *getScope(AnalysisDeclContext *ctx,
365 const LocationContext *parent,
368 const BlockInvocationContext *
369 getBlockInvocationContext(AnalysisDeclContext *ctx,
370 const LocationContext *parent,
372 const void *ContextData);
374 /// Discard all previously created LocationContext objects.
377 template <typename LOC, typename DATA>
378 const LOC *getLocationContext(AnalysisDeclContext *ctx,
379 const LocationContext *parent,
383 class AnalysisDeclContextManager {
384 typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap;
387 LocationContextManager LocContexts;
388 CFG::BuildOptions cfgBuildOptions;
390 /// Flag to indicate whether or not bodies should be synthesized
391 /// for well-known functions.
392 bool SynthesizeBodies;
395 AnalysisDeclContextManager(bool useUnoptimizedCFG = false,
396 bool addImplicitDtors = false,
397 bool addInitializers = false,
398 bool addTemporaryDtors = false,
399 bool synthesizeBodies = false);
401 ~AnalysisDeclContextManager();
403 AnalysisDeclContext *getContext(const Decl *D);
405 bool getUseUnoptimizedCFG() const {
406 return !cfgBuildOptions.PruneTriviallyFalseEdges;
409 CFG::BuildOptions &getCFGBuildOptions() {
410 return cfgBuildOptions;
413 /// Return true if faux bodies should be synthesized for well-known
415 bool synthesizeBodies() const { return SynthesizeBodies; }
417 const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx,
418 LocationContext const *Parent,
422 return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx);
425 // Get the top level stack frame.
426 const StackFrameContext *getStackFrame(const Decl *D) {
427 return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0);
430 // Get a stack frame with parent.
431 StackFrameContext const *getStackFrame(const Decl *D,
432 LocationContext const *Parent,
436 return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx);
439 /// Discard all previously created AnalysisDeclContexts.
443 friend class AnalysisDeclContext;
445 LocationContextManager &getLocationContextManager() {
450 } // end clang namespace