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/FoldingSet.h"
23 #include "llvm/ADT/PointerUnion.h"
24 #include "llvm/ADT/DenseMap.h"
25 #include "llvm/Support/Allocator.h"
31 class CFGReverseBlockReachabilityAnalysis;
35 class PseudoConstantAnalysis;
36 class ImplicitParamDecl;
37 class LocationContextManager;
38 class StackFrameContext;
40 namespace idx { class TranslationUnit; }
42 /// AnalysisContext contains the context data for the function or method under
44 class AnalysisContext {
47 // TranslationUnit is NULL if we don't have multiple translation units.
48 idx::TranslationUnit *TU;
50 llvm::OwningPtr<CFG> cfg, completeCFG;
51 llvm::OwningPtr<CFGStmtMap> cfgStmtMap;
53 CFG::BuildOptions cfgBuildOptions;
54 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs;
56 bool builtCFG, builtCompleteCFG;
57 const bool useUnoptimizedCFG;
59 llvm::OwningPtr<LiveVariables> liveness;
60 llvm::OwningPtr<LiveVariables> relaxedLiveness;
61 llvm::OwningPtr<ParentMap> PM;
62 llvm::OwningPtr<PseudoConstantAnalysis> PCA;
63 llvm::OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA;
65 llvm::BumpPtrAllocator A;
68 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
71 AnalysisContext(const Decl *d, idx::TranslationUnit *tu,
72 bool useUnoptimizedCFG = false,
73 bool addehedges = false,
74 bool addImplicitDtors = false,
75 bool addInitializers = false);
79 ASTContext &getASTContext() { return D->getASTContext(); }
80 const Decl *getDecl() const { return D; }
82 idx::TranslationUnit *getTranslationUnit() const { return TU; }
84 /// getAddEHEdges - Return true iff we are adding exceptional edges from
85 /// callExprs. If this is false, then try/catch statements and blocks
86 /// reachable from them can appear to be dead in the CFG, analysis passes must
88 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
89 bool getUseUnoptimizedCFG() const {
90 return cfgBuildOptions.PruneTriviallyFalseEdges;
92 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
93 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
95 void registerForcedBlockExpression(const Stmt *stmt);
96 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
101 CFGStmtMap *getCFGStmtMap();
103 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
105 /// Return a version of the CFG without any edges pruned.
106 CFG *getUnoptimizedCFG();
110 ParentMap &getParentMap();
111 PseudoConstantAnalysis *getPseudoConstantAnalysis();
112 LiveVariables *getLiveVariables();
113 LiveVariables *getRelaxedLiveVariables();
115 typedef const VarDecl * const * referenced_decls_iterator;
117 std::pair<referenced_decls_iterator, referenced_decls_iterator>
118 getReferencedBlockVars(const BlockDecl *BD);
120 /// Return the ImplicitParamDecl* associated with 'self' if this
121 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise.
122 const ImplicitParamDecl *getSelfDecl() const;
125 class AnalysisContextManager {
126 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap;
128 bool UseUnoptimizedCFG;
129 bool AddImplicitDtors;
130 bool AddInitializers;
132 AnalysisContextManager(bool useUnoptimizedCFG = false,
133 bool addImplicitDtors = false, bool addInitializers = false)
134 : UseUnoptimizedCFG(useUnoptimizedCFG), AddImplicitDtors(addImplicitDtors),
135 AddInitializers(addInitializers) {}
137 ~AnalysisContextManager();
139 AnalysisContext *getContext(const Decl *D, idx::TranslationUnit *TU = 0);
141 bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; }
142 bool getAddImplicitDtors() const { return AddImplicitDtors; }
143 bool getAddInitializers() const { return AddInitializers; }
145 // Discard all previously created AnalysisContexts.
149 class LocationContext : public llvm::FoldingSetNode {
151 enum ContextKind { StackFrame, Scope, Block };
156 // AnalysisContext can't be const since some methods may modify its member.
157 AnalysisContext *Ctx;
159 const LocationContext *Parent;
162 LocationContext(ContextKind k, AnalysisContext *ctx,
163 const LocationContext *parent)
164 : Kind(k), Ctx(ctx), Parent(parent) {}
167 virtual ~LocationContext();
169 ContextKind getKind() const { return Kind; }
171 AnalysisContext *getAnalysisContext() const { return Ctx; }
173 idx::TranslationUnit *getTranslationUnit() const {
174 return Ctx->getTranslationUnit();
177 const LocationContext *getParent() const { return Parent; }
179 bool isParentOf(const LocationContext *LC) const;
181 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); }
183 CFG *getCFG() const { return getAnalysisContext()->getCFG(); }
185 LiveVariables *getLiveVariables() const {
186 return getAnalysisContext()->getLiveVariables();
189 ParentMap &getParentMap() const {
190 return getAnalysisContext()->getParentMap();
193 const ImplicitParamDecl *getSelfDecl() const {
194 return Ctx->getSelfDecl();
197 const StackFrameContext *getCurrentStackFrame() const;
198 const StackFrameContext *
199 getStackFrameForDeclContext(const DeclContext *DC) const;
201 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
203 static bool classof(const LocationContext*) { return true; }
206 static void ProfileCommon(llvm::FoldingSetNodeID &ID,
208 AnalysisContext *ctx,
209 const LocationContext *parent,
213 class StackFrameContext : public LocationContext {
214 // The callsite where this stack frame is established.
215 const Stmt *CallSite;
217 // The parent block of the callsite.
218 const CFGBlock *Block;
220 // The index of the callsite in the CFGBlock.
223 friend class LocationContextManager;
224 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,
225 const Stmt *s, const CFGBlock *blk,
227 : LocationContext(StackFrame, ctx, parent), CallSite(s),
228 Block(blk), Index(idx) {}
231 ~StackFrameContext() {}
233 const Stmt *getCallSite() const { return CallSite; }
235 const CFGBlock *getCallSiteBlock() const { return Block; }
237 unsigned getIndex() const { return Index; }
239 void Profile(llvm::FoldingSetNodeID &ID);
241 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
242 const LocationContext *parent, const Stmt *s,
243 const CFGBlock *blk, unsigned idx) {
244 ProfileCommon(ID, StackFrame, ctx, parent, s);
249 static bool classof(const LocationContext* Ctx) {
250 return Ctx->getKind() == StackFrame;
254 class ScopeContext : public LocationContext {
257 friend class LocationContextManager;
258 ScopeContext(AnalysisContext *ctx, const LocationContext *parent,
260 : LocationContext(Scope, ctx, parent), Enter(s) {}
265 void Profile(llvm::FoldingSetNodeID &ID);
267 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
268 const LocationContext *parent, const Stmt *s) {
269 ProfileCommon(ID, Scope, ctx, parent, s);
272 static bool classof(const LocationContext* Ctx) {
273 return Ctx->getKind() == Scope;
277 class BlockInvocationContext : public LocationContext {
278 // FIXME: Add back context-sensivity (we don't want libAnalysis to know
282 friend class LocationContextManager;
284 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent,
286 : LocationContext(Block, ctx, parent), BD(bd) {}
289 ~BlockInvocationContext() {}
291 const BlockDecl *getBlockDecl() const { return BD; }
293 void Profile(llvm::FoldingSetNodeID &ID);
295 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,
296 const LocationContext *parent, const BlockDecl *bd) {
297 ProfileCommon(ID, Block, ctx, parent, bd);
300 static bool classof(const LocationContext* Ctx) {
301 return Ctx->getKind() == Block;
305 class LocationContextManager {
306 llvm::FoldingSet<LocationContext> Contexts;
308 ~LocationContextManager();
310 const StackFrameContext *getStackFrame(AnalysisContext *ctx,
311 const LocationContext *parent,
313 const CFGBlock *blk, unsigned idx);
315 const ScopeContext *getScope(AnalysisContext *ctx,
316 const LocationContext *parent,
319 /// Discard all previously created LocationContext objects.
322 template <typename LOC, typename DATA>
323 const LOC *getLocationContext(AnalysisContext *ctx,
324 const LocationContext *parent,
328 } // end clang namespace