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