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