AnalysisContext.h revision 8ddf7cead8a67342a4584a203e0bf736b7efedbe
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 bool isParentOf(const LocationContext *LC) const; 114 115 const Decl *getDecl() const { return getAnalysisContext()->getDecl(); } 116 117 CFG *getCFG() const { return getAnalysisContext()->getCFG(); } 118 119 LiveVariables *getLiveVariables() const { 120 return getAnalysisContext()->getLiveVariables(); 121 } 122 123 ParentMap &getParentMap() const { 124 return getAnalysisContext()->getParentMap(); 125 } 126 127 const ImplicitParamDecl *getSelfDecl() const { 128 return Ctx->getSelfDecl(); 129 } 130 131 const StackFrameContext *getCurrentStackFrame() const; 132 const StackFrameContext * 133 getStackFrameForDeclContext(const DeclContext *DC) const; 134 135 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; 136 137 static bool classof(const LocationContext*) { return true; } 138 139public: 140 static void ProfileCommon(llvm::FoldingSetNodeID &ID, 141 ContextKind ck, 142 AnalysisContext *ctx, 143 const LocationContext *parent, 144 const void* data); 145}; 146 147class StackFrameContext : public LocationContext { 148 // The callsite where this stack frame is established. 149 const Stmt *CallSite; 150 151 // The parent block of the callsite. 152 const CFGBlock *Block; 153 154 // The index of the callsite in the CFGBlock. 155 unsigned Index; 156 157 friend class LocationContextManager; 158 StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, 159 const Stmt *s, const CFGBlock *blk, unsigned idx) 160 : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk), 161 Index(idx) {} 162 163public: 164 ~StackFrameContext() {} 165 166 const Stmt *getCallSite() const { return CallSite; } 167 168 const CFGBlock *getCallSiteBlock() const { return Block; } 169 170 unsigned getIndex() const { return Index; } 171 172 void Profile(llvm::FoldingSetNodeID &ID); 173 174 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 175 const LocationContext *parent, const Stmt *s, 176 const CFGBlock *blk, unsigned idx) { 177 ProfileCommon(ID, StackFrame, ctx, parent, s); 178 ID.AddPointer(blk); 179 ID.AddInteger(idx); 180 } 181 182 static bool classof(const LocationContext* Ctx) { 183 return Ctx->getKind() == StackFrame; 184 } 185}; 186 187class ScopeContext : public LocationContext { 188 const Stmt *Enter; 189 190 friend class LocationContextManager; 191 ScopeContext(AnalysisContext *ctx, const LocationContext *parent, 192 const Stmt *s) 193 : LocationContext(Scope, ctx, parent), Enter(s) {} 194 195public: 196 ~ScopeContext() {} 197 198 void Profile(llvm::FoldingSetNodeID &ID); 199 200 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 201 const LocationContext *parent, const Stmt *s) { 202 ProfileCommon(ID, Scope, ctx, parent, s); 203 } 204 205 static bool classof(const LocationContext* Ctx) { 206 return Ctx->getKind() == Scope; 207 } 208}; 209 210class BlockInvocationContext : public LocationContext { 211 // FIXME: Add back context-sensivity (we don't want libAnalysis to know 212 // about MemRegion). 213 const BlockDecl *BD; 214 215 friend class LocationContextManager; 216 217 BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, 218 const BlockDecl *bd) 219 : LocationContext(Block, ctx, parent), BD(bd) {} 220 221public: 222 ~BlockInvocationContext() {} 223 224 const BlockDecl *getBlockDecl() const { return BD; } 225 226 void Profile(llvm::FoldingSetNodeID &ID); 227 228 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, 229 const LocationContext *parent, const BlockDecl *bd) { 230 ProfileCommon(ID, Block, ctx, parent, bd); 231 } 232 233 static bool classof(const LocationContext* Ctx) { 234 return Ctx->getKind() == Block; 235 } 236}; 237 238class LocationContextManager { 239 llvm::FoldingSet<LocationContext> Contexts; 240public: 241 ~LocationContextManager(); 242 243 const StackFrameContext *getStackFrame(AnalysisContext *ctx, 244 const LocationContext *parent, 245 const Stmt *s, const CFGBlock *blk, 246 unsigned idx); 247 248 const ScopeContext *getScope(AnalysisContext *ctx, 249 const LocationContext *parent, 250 const Stmt *s); 251 252 /// Discard all previously created LocationContext objects. 253 void clear(); 254private: 255 template <typename LOC, typename DATA> 256 const LOC *getLocationContext(AnalysisContext *ctx, 257 const LocationContext *parent, 258 const DATA *d); 259}; 260 261} // end clang namespace 262#endif 263