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 AnalysisContext, a class that manages the analysis context
11 // 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;
42 namespace idx { class TranslationUnit; }
44 /// The base class of a hierarchy of objects representing analyses tied
45 /// to AnalysisContext.
46 class ManagedAnalysis {
50 virtual ~ManagedAnalysis();
52 // Subclasses need to implement:
54 // static const void *getTag();
56 // Which returns a fixed pointer address to distinguish classes of
57 // analysis objects. They also need to implement:
59 // static [Derived*] create(AnalysisContext &Ctx);
61 // which creates the analysis object given an AnalysisContext.
64 /// AnalysisContext contains the context data for the function or method under
66 class AnalysisContext {
69 // TranslationUnit is NULL if we don't have multiple translation units.
70 idx::TranslationUnit *TU;
72 llvm::OwningPtr<CFG> cfg, completeCFG;
73 llvm::OwningPtr<CFGStmtMap> cfgStmtMap;
75 CFG::BuildOptions cfgBuildOptions;
76 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
78 bool builtCFG, builtCompleteCFG;
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;
86 llvm::BumpPtrAllocator A;
89 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
91 void *ManagedAnalyses;
94 AnalysisContext(const Decl *d, idx::TranslationUnit *tu);
96 AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
97 const CFG::BuildOptions &buildOptions);
101 ASTContext &getASTContext() { return D->getASTContext(); }
102 const Decl *getDecl() const { return D; }
104 idx::TranslationUnit *getTranslationUnit() const { return TU; }
106 /// Return the build options used to construct the CFG.
107 CFG::BuildOptions &getCFGBuildOptions() {
108 return cfgBuildOptions;
111 const CFG::BuildOptions &getCFGBuildOptions() const {
112 return cfgBuildOptions;
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
119 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
120 bool getUseUnoptimizedCFG() const {
121 return !cfgBuildOptions.PruneTriviallyFalseEdges;
123 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
124 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
126 void registerForcedBlockExpression(const Stmt *stmt);
127 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
129 Stmt *getBody() const;
132 CFGStmtMap *getCFGStmtMap();
134 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
136 /// Return a version of the CFG without any edges pruned.
137 CFG *getUnoptimizedCFG();
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; }
146 ParentMap &getParentMap();
147 PseudoConstantAnalysis *getPseudoConstantAnalysis();
149 typedef const VarDecl * const * referenced_decls_iterator;
151 std::pair<referenced_decls_iterator, referenced_decls_iterator>
152 getReferencedBlockVars(const BlockDecl *BD);
154 /// Return the ImplicitParamDecl* associated with 'self' if this
155 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
156 const ImplicitParamDecl *getSelfDecl() const;
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>
162 const void *tag = T::getTag();
163 ManagedAnalysis *&data = getAnalysisImpl(tag);
165 data = T::create(*this);
167 return static_cast<T*>(data);
170 ManagedAnalysis *&getAnalysisImpl(const void* tag);
173 class AnalysisContextManager {
174 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
176 CFG::BuildOptions cfgBuildOptions;
178 AnalysisContextManager(bool useUnoptimizedCFG = false,
179 bool addImplicitDtors = false,
180 bool addInitializers = false);
182 ~AnalysisContextManager();
184 AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
186 bool getUseUnoptimizedCFG() const {
187 return !cfgBuildOptions.PruneTriviallyFalseEdges;
190 CFG::BuildOptions &getCFGBuildOptions() {
191 return cfgBuildOptions;
194 /// Discard all previously created AnalysisContexts.
198 class LocationContext : public llvm::FoldingSetNode {
200 enum ContextKind { StackFrame, Scope, Block };
205 // AnalysisContext can't be const since some methods may modify its member.
206 AnalysisContext *Ctx;
208 const LocationContext *Parent;
211 LocationContext(ContextKind k, AnalysisContext *ctx,
212 const LocationContext *parent)
213 : Kind(k), Ctx(ctx), Parent(parent) {}
216 virtual ~LocationContext();
218 ContextKind getKind() const { return Kind; }
220 AnalysisContext *getAnalysisContext() const { return Ctx; }
222 idx::TranslationUnit *getTranslationUnit() const {
223 return Ctx->getTranslationUnit();
226 const LocationContext *getParent() const { return Parent; }
228 bool isParentOf(const LocationContext *LC) const;
230 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
232 CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
234 template <typename T>
235 T *getAnalysis() const {
236 return getAnalysisContext()->getAnalysis<T>();
239 ParentMap &getParentMap() const {
240 return getAnalysisContext()->getParentMap();
243 const ImplicitParamDecl *getSelfDecl() const {
244 return Ctx->getSelfDecl();
247 const StackFrameContext *getCurrentStackFrame() const;
248 const StackFrameContext *
249 getStackFrameForDeclContext(const DeclContext *DC) const;
251 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
253 static bool classof(const LocationContext*) { return true; }
256 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
258 AnalysisContext *ctx,
259 const LocationContext *parent,
263 class StackFrameContext : public LocationContext {
264 // The callsite where this stack frame is established.
265 const Stmt *CallSite;
267 // The parent block of the callsite.
268 const CFGBlock *Block;
270 // The index of the callsite in the CFGBlock.
273 friend class LocationContextManager;
274 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
275 const Stmt *s, const CFGBlock *blk,
277 : LocationContext(StackFrame, ctx, parent), CallSite(s),
278 Block(blk), Index(idx) {}
281 ~StackFrameContext() {}
283 const Stmt *getCallSite() const { return CallSite; }
285 const CFGBlock *getCallSiteBlock() const { return Block; }
287 unsigned getIndex() const { return Index; }
289 void Profile(llvm::FoldingSetNodeID &ID);
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);
299 static bool classof(const LocationContext *Ctx) {
300 return Ctx->getKind() == StackFrame;
304 class ScopeContext : public LocationContext {
307 friend class LocationContextManager;
308 ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
310 : LocationContext(Scope, ctx, parent), Enter(s) {}
315 void Profile(llvm::FoldingSetNodeID &ID);
317 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
318 const LocationContext *parent, const Stmt *s) {
319 ProfileCommon(ID, Scope, ctx, parent, s);
322 static bool classof(const LocationContext *Ctx) {
323 return Ctx->getKind() == Scope;
327 class BlockInvocationContext : public LocationContext {
328 // FIXME: Add back context-sensivity (we don't want libAnalysis to know
332 friend class LocationContextManager;
334 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
336 : LocationContext(Block, ctx, parent), BD(bd) {}
339 ~BlockInvocationContext() {}
341 const BlockDecl *getBlockDecl() const { return BD; }
343 void Profile(llvm::FoldingSetNodeID &ID);
345 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
346 const LocationContext *parent, const BlockDecl *bd) {
347 ProfileCommon(ID, Block, ctx, parent, bd);
350 static bool classof(const LocationContext *Ctx) {
351 return Ctx->getKind() == Block;
355 class LocationContextManager {
356 llvm::FoldingSet<LocationContext> Contexts;
358 ~LocationContextManager();
360 const StackFrameContext *getStackFrame(AnalysisContext *ctx,
361 const LocationContext *parent,
363 const CFGBlock *blk, unsigned idx);
365 const ScopeContext *getScope(AnalysisContext *ctx,
366 const LocationContext *parent,
369 /// Discard all previously created LocationContext objects.
372 template <typename LOC, typename DATA>
373 const LOC *getLocationContext(AnalysisContext *ctx,
374 const LocationContext *parent,
378 } // end clang namespace