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