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