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