AnalysisContext.h revision 326be568e2cb04285c84e6e26a3e6b3822607361
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 25namespace clang { 26 27class Decl; 28class Stmt; 29class CFG; 30class CFGBlock; 31class LiveVariables; 32class ParentMap; 33class ImplicitParamDecl; 34class LocationContextManager; 35class StackFrameContext; 36 37/// AnalysisContext contains the context data for the function or method under 38/// analysis. 39class AnalysisContext { 40 const Decl *D; 41 42 // AnalysisContext owns the following data. 43 CFG *cfg; 44 LiveVariables *liveness; 45 ParentMap *PM; 46 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; 47 llvm::BumpPtrAllocator A; 48 bool AddEHEdges; 49public: 50 AnalysisContext(const Decl *d, bool addehedges = false) 51 : D(d), cfg(0), liveness(0), PM(0), ReferencedBlockVars(0), 52 AddEHEdges(addehedges) {} 53 54 ~AnalysisContext(); 55 56 ASTContext &getASTContext() { return D->getASTContext(); } 57 const Decl *getDecl() { return D; } 58 /// getAddEHEdges - Return true iff we are adding exceptional edges from 59 /// callExprs. If this is false, then try/catch statements and blocks 60 /// reachable from them can appear to be dead in the CFG, analysis passes must 61 /// cope with that. 62 bool getAddEHEdges() const { return AddEHEdges; } 63 Stmt *getBody(); 64 CFG *getCFG(); 65 ParentMap &getParentMap(); 66 LiveVariables *getLiveVariables(); 67 68 typedef const VarDecl * const * referenced_decls_iterator; 69 70 std::pair<referenced_decls_iterator, referenced_decls_iterator> 71 getReferencedBlockVars(const BlockDecl *BD); 72 73 /// Return the ImplicitParamDecl* associated with 'self' if this 74 /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise. 75 const ImplicitParamDecl *getSelfDecl() const; 76}; 77 78class AnalysisContextManager { 79 typedef llvm::DenseMap<const Decl*, AnalysisContext*> ContextMap; 80 ContextMap Contexts; 81public: 82 ~AnalysisContextManager(); 83 84 AnalysisContext *getContext(const Decl *D); 85 86 // Discard all previously created AnalysisContexts. 87 void clear(); 88}; 89 90class LocationContext : public llvm::FoldingSetNode { 91public: 92 enum ContextKind { StackFrame, Scope, Block }; 93 94private: 95 ContextKind Kind; 96 AnalysisContext *Ctx; 97 const LocationContext *Parent; 98 99protected: 100 LocationContext(ContextKind k, AnalysisContext *ctx, 101 const LocationContext *parent) 102 : Kind(k), Ctx(ctx), Parent(parent) {} 103 104public: 105 virtual ~LocationContext(); 106 107 ContextKind getKind() const { return Kind; } 108 109 AnalysisContext *getAnalysisContext() const { return Ctx; } 110 111 const LocationContext *getParent() const { return Parent; } 112 113 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); } 114 115 CFG *getCFG() const { return getAnalysisContext()->getCFG(); } 116 117 LiveVariables *getLiveVariables() const { 118 return getAnalysisContext()->getLiveVariables(); 119 } 120 121 ParentMap &getParentMap() const { 122 return getAnalysisContext()->getParentMap(); 123 } 124 125 const ImplicitParamDecl *getSelfDecl() const { 126 return Ctx->getSelfDecl(); 127 } 128 129 const StackFrameContext *getCurrentStackFrame() const; 130 const StackFrameContext * 131 getStackFrameForDeclContext(const DeclContext *DC) const; 132 133 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; 134 135 static bool classof(const LocationContext*) { return true; } 136 137public: 138 static void ProfileCommon(llvm::FoldingSetNodeID &ID, 139 ContextKind ck, 140 AnalysisContext *ctx, 141 const LocationContext *parent, 142 const void* data); 143}; 144 145class StackFrameContext : public LocationContext { 146 // The callsite where this stack frame is established. 147 const Stmt *CallSite; 148 149 // The parent block of the callsite. 150 const CFGBlock *Block; 151 152 // The index of the callsite in the CFGBlock. 153 unsigned Index; 154 155 friend class LocationContextManager; 156 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, 157 const Stmt *s, const CFGBlock *blk, unsigned idx) 158 : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk), 159 Index(idx) {} 160 161public: 162 ~StackFrameContext() {} 163 164 const Stmt *getCallSite() const { return CallSite; } 165 166 const CFGBlock *getCallSiteBlock() const { return Block; } 167 168 unsigned getIndex() const { return Index; } 169 170 void Profile(llvm::FoldingSetNodeID &ID); 171 172 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 173 const LocationContext *parent, const Stmt *s, 174 const CFGBlock *blk, unsigned idx) { 175 ProfileCommon(ID, StackFrame, ctx, parent, s); 176 ID.AddPointer(blk); 177 ID.AddInteger(idx); 178 } 179 180 static bool classof(const LocationContext* Ctx) { 181 return Ctx->getKind() == StackFrame; 182 } 183}; 184 185class ScopeContext : public LocationContext { 186 const Stmt *Enter; 187 188 friend class LocationContextManager; 189 ScopeContext(AnalysisContext *ctx, const LocationContext *parent, 190 const Stmt *s) 191 : LocationContext(Scope, ctx, parent), Enter(s) {} 192 193public: 194 ~ScopeContext() {} 195 196 void Profile(llvm::FoldingSetNodeID &ID); 197 198 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 199 const LocationContext *parent, const Stmt *s) { 200 ProfileCommon(ID, Scope, ctx, parent, s); 201 } 202 203 static bool classof(const LocationContext* Ctx) { 204 return Ctx->getKind() == Scope; 205 } 206}; 207 208class BlockInvocationContext : public LocationContext { 209 // FIXME: Add back context-sensivity (we don't want libAnalysis to know 210 // about MemRegion). 211 const BlockDecl *BD; 212 213 friend class LocationContextManager; 214 215 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, 216 const BlockDecl *bd) 217 : LocationContext(Block, ctx, parent), BD(bd) {} 218 219public: 220 ~BlockInvocationContext() {} 221 222 const BlockDecl *getBlockDecl() const { return BD; } 223 224 void Profile(llvm::FoldingSetNodeID &ID); 225 226 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 227 const LocationContext *parent, const BlockDecl *bd) { 228 ProfileCommon(ID, Block, ctx, parent, bd); 229 } 230 231 static bool classof(const LocationContext* Ctx) { 232 return Ctx->getKind() == Block; 233 } 234}; 235 236class LocationContextManager { 237 llvm::FoldingSet<LocationContext> Contexts; 238public: 239 ~LocationContextManager(); 240 241 const StackFrameContext *getStackFrame(AnalysisContext *ctx, 242 const LocationContext *parent, 243 const Stmt *s, const CFGBlock *blk, 244 unsigned idx); 245 246 const ScopeContext *getScope(AnalysisContext *ctx, 247 const LocationContext *parent, 248 const Stmt *s); 249 250 /// Discard all previously created LocationContext objects. 251 void clear(); 252private: 253 template <typename LOC, typename DATA> 254 const LOC *getLocationContext(AnalysisContext *ctx, 255 const LocationContext *parent, 256 const DATA *d); 257}; 258 259} // end clang namespace 260#endif 261