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