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 AnalysisDeclContext, a class that manages the analysis 11 // context 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 "clang/Analysis/CFG.h" 21 #include "llvm/ADT/OwningPtr.h" 22 #include "llvm/ADT/IntrusiveRefCntPtr.h" 23 #include "llvm/ADT/FoldingSet.h" 24 #include "llvm/ADT/PointerUnion.h" 25 #include "llvm/ADT/DenseMap.h" 26 #include "llvm/Support/Allocator.h" 27 28 namespace clang { 29 30 class Decl; 31 class Stmt; 32 class CFGReverseBlockReachabilityAnalysis; 33 class CFGStmtMap; 34 class LiveVariables; 35 class ManagedAnalysis; 36 class ParentMap; 37 class PseudoConstantAnalysis; 38 class ImplicitParamDecl; 39 class LocationContextManager; 40 class StackFrameContext; 41 class BlockInvocationContext; 42 class AnalysisDeclContextManager; 43 class LocationContext; 44 45 namespace idx { class TranslationUnit; } 46 47 /// The base class of a hierarchy of objects representing analyses tied 48 /// to AnalysisDeclContext. 49 class ManagedAnalysis { 50 protected: ManagedAnalysis()51 ManagedAnalysis() {} 52 public: 53 virtual ~ManagedAnalysis(); 54 55 // Subclasses need to implement: 56 // 57 // static const void *getTag(); 58 // 59 // Which returns a fixed pointer address to distinguish classes of 60 // analysis objects. They also need to implement: 61 // 62 // static [Derived*] create(AnalysisDeclContext &Ctx); 63 // 64 // which creates the analysis object given an AnalysisDeclContext. 65 }; 66 67 68 /// AnalysisDeclContext contains the context data for the function or method 69 /// under analysis. 70 class AnalysisDeclContext { 71 /// Backpoint to the AnalysisManager object that created this 72 /// AnalysisDeclContext. This may be null. 73 AnalysisDeclContextManager *Manager; 74 75 const Decl *D; 76 77 OwningPtr<CFG> cfg, completeCFG; 78 OwningPtr<CFGStmtMap> cfgStmtMap; 79 80 CFG::BuildOptions cfgBuildOptions; 81 CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; 82 83 bool builtCFG, builtCompleteCFG; 84 85 OwningPtr<LiveVariables> liveness; 86 OwningPtr<LiveVariables> relaxedLiveness; 87 OwningPtr<ParentMap> PM; 88 OwningPtr<PseudoConstantAnalysis> PCA; 89 OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA; 90 91 llvm::BumpPtrAllocator A; 92 93 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; 94 95 void *ManagedAnalyses; 96 97 public: 98 AnalysisDeclContext(AnalysisDeclContextManager *Mgr, 99 const Decl *D); 100 101 AnalysisDeclContext(AnalysisDeclContextManager *Mgr, 102 const Decl *D, 103 const CFG::BuildOptions &BuildOptions); 104 105 ~AnalysisDeclContext(); 106 getASTContext()107 ASTContext &getASTContext() { return D->getASTContext(); } getDecl()108 const Decl *getDecl() const { return D; } 109 110 /// Return the build options used to construct the CFG. getCFGBuildOptions()111 CFG::BuildOptions &getCFGBuildOptions() { 112 return cfgBuildOptions; 113 } 114 getCFGBuildOptions()115 const CFG::BuildOptions &getCFGBuildOptions() const { 116 return cfgBuildOptions; 117 } 118 119 /// getAddEHEdges - Return true iff we are adding exceptional edges from 120 /// callExprs. If this is false, then try/catch statements and blocks 121 /// reachable from them can appear to be dead in the CFG, analysis passes must 122 /// cope with that. getAddEHEdges()123 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } getUseUnoptimizedCFG()124 bool getUseUnoptimizedCFG() const { 125 return !cfgBuildOptions.PruneTriviallyFalseEdges; 126 } getAddImplicitDtors()127 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } getAddInitializers()128 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; } 129 130 void registerForcedBlockExpression(const Stmt *stmt); 131 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); 132 133 Stmt *getBody() const; 134 CFG *getCFG(); 135 136 CFGStmtMap *getCFGStmtMap(); 137 138 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis(); 139 140 /// Return a version of the CFG without any edges pruned. 141 CFG *getUnoptimizedCFG(); 142 143 void dumpCFG(bool ShowColors); 144 145 /// \brief Returns true if we have built a CFG for this analysis context. 146 /// Note that this doesn't correspond to whether or not a valid CFG exists, it 147 /// corresponds to whether we *attempted* to build one. isCFGBuilt()148 bool isCFGBuilt() const { return builtCFG; } 149 150 ParentMap &getParentMap(); 151 PseudoConstantAnalysis *getPseudoConstantAnalysis(); 152 153 typedef const VarDecl * const * referenced_decls_iterator; 154 155 std::pair<referenced_decls_iterator, referenced_decls_iterator> 156 getReferencedBlockVars(const BlockDecl *BD); 157 158 /// Return the ImplicitParamDecl* associated with 'self' if this 159 /// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise. 160 const ImplicitParamDecl *getSelfDecl() const; 161 162 const StackFrameContext *getStackFrame(LocationContext const *Parent, 163 const Stmt *S, 164 const CFGBlock *Blk, 165 unsigned Idx); 166 167 const BlockInvocationContext * 168 getBlockInvocationContext(const LocationContext *parent, 169 const BlockDecl *BD, 170 const void *ContextData); 171 172 /// Return the specified analysis object, lazily running the analysis if 173 /// necessary. Return NULL if the analysis could not run. 174 template <typename T> getAnalysis()175 T *getAnalysis() { 176 const void *tag = T::getTag(); 177 ManagedAnalysis *&data = getAnalysisImpl(tag); 178 if (!data) { 179 data = T::create(*this); 180 } 181 return static_cast<T*>(data); 182 } 183 private: 184 ManagedAnalysis *&getAnalysisImpl(const void* tag); 185 186 LocationContextManager &getLocationContextManager(); 187 }; 188 189 class LocationContext : public llvm::FoldingSetNode { 190 public: 191 enum ContextKind { StackFrame, Scope, Block }; 192 193 private: 194 ContextKind Kind; 195 196 // AnalysisDeclContext can't be const since some methods may modify its 197 // member. 198 AnalysisDeclContext *Ctx; 199 200 const LocationContext *Parent; 201 202 protected: LocationContext(ContextKind k,AnalysisDeclContext * ctx,const LocationContext * parent)203 LocationContext(ContextKind k, AnalysisDeclContext *ctx, 204 const LocationContext *parent) 205 : Kind(k), Ctx(ctx), Parent(parent) {} 206 207 public: 208 virtual ~LocationContext(); 209 getKind()210 ContextKind getKind() const { return Kind; } 211 getAnalysisDeclContext()212 AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; } 213 getParent()214 const LocationContext *getParent() const { return Parent; } 215 216 bool isParentOf(const LocationContext *LC) const; 217 getDecl()218 const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); } 219 getCFG()220 CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); } 221 222 template <typename T> getAnalysis()223 T *getAnalysis() const { 224 return getAnalysisDeclContext()->getAnalysis<T>(); 225 } 226 getParentMap()227 ParentMap &getParentMap() const { 228 return getAnalysisDeclContext()->getParentMap(); 229 } 230 getSelfDecl()231 const ImplicitParamDecl *getSelfDecl() const { 232 return Ctx->getSelfDecl(); 233 } 234 235 const StackFrameContext *getCurrentStackFrame() const; 236 237 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; 238 classof(const LocationContext *)239 static bool classof(const LocationContext*) { return true; } 240 241 public: 242 static void ProfileCommon(llvm::FoldingSetNodeID &ID, 243 ContextKind ck, 244 AnalysisDeclContext *ctx, 245 const LocationContext *parent, 246 const void *data); 247 }; 248 249 class StackFrameContext : public LocationContext { 250 // The callsite where this stack frame is established. 251 const Stmt *CallSite; 252 253 // The parent block of the callsite. 254 const CFGBlock *Block; 255 256 // The index of the callsite in the CFGBlock. 257 unsigned Index; 258 259 friend class LocationContextManager; StackFrameContext(AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s,const CFGBlock * blk,unsigned idx)260 StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent, 261 const Stmt *s, const CFGBlock *blk, 262 unsigned idx) 263 : LocationContext(StackFrame, ctx, parent), CallSite(s), 264 Block(blk), Index(idx) {} 265 266 public: ~StackFrameContext()267 ~StackFrameContext() {} 268 getCallSite()269 const Stmt *getCallSite() const { return CallSite; } 270 getCallSiteBlock()271 const CFGBlock *getCallSiteBlock() const { return Block; } 272 getIndex()273 unsigned getIndex() const { return Index; } 274 275 void Profile(llvm::FoldingSetNodeID &ID); 276 Profile(llvm::FoldingSetNodeID & ID,AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s,const CFGBlock * blk,unsigned idx)277 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, 278 const LocationContext *parent, const Stmt *s, 279 const CFGBlock *blk, unsigned idx) { 280 ProfileCommon(ID, StackFrame, ctx, parent, s); 281 ID.AddPointer(blk); 282 ID.AddInteger(idx); 283 } 284 classof(const LocationContext * Ctx)285 static bool classof(const LocationContext *Ctx) { 286 return Ctx->getKind() == StackFrame; 287 } 288 }; 289 290 class ScopeContext : public LocationContext { 291 const Stmt *Enter; 292 293 friend class LocationContextManager; ScopeContext(AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s)294 ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent, 295 const Stmt *s) 296 : LocationContext(Scope, ctx, parent), Enter(s) {} 297 298 public: ~ScopeContext()299 ~ScopeContext() {} 300 301 void Profile(llvm::FoldingSetNodeID &ID); 302 Profile(llvm::FoldingSetNodeID & ID,AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s)303 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, 304 const LocationContext *parent, const Stmt *s) { 305 ProfileCommon(ID, Scope, ctx, parent, s); 306 } 307 classof(const LocationContext * Ctx)308 static bool classof(const LocationContext *Ctx) { 309 return Ctx->getKind() == Scope; 310 } 311 }; 312 313 class BlockInvocationContext : public LocationContext { 314 const BlockDecl *BD; 315 316 // FIXME: Come up with a more type-safe way to model context-sensitivity. 317 const void *ContextData; 318 319 friend class LocationContextManager; 320 BlockInvocationContext(AnalysisDeclContext * ctx,const LocationContext * parent,const BlockDecl * bd,const void * contextData)321 BlockInvocationContext(AnalysisDeclContext *ctx, 322 const LocationContext *parent, 323 const BlockDecl *bd, const void *contextData) 324 : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {} 325 326 public: ~BlockInvocationContext()327 ~BlockInvocationContext() {} 328 getBlockDecl()329 const BlockDecl *getBlockDecl() const { return BD; } 330 getContextData()331 const void *getContextData() const { return ContextData; } 332 333 void Profile(llvm::FoldingSetNodeID &ID); 334 Profile(llvm::FoldingSetNodeID & ID,AnalysisDeclContext * ctx,const LocationContext * parent,const BlockDecl * bd,const void * contextData)335 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, 336 const LocationContext *parent, const BlockDecl *bd, 337 const void *contextData) { 338 ProfileCommon(ID, Block, ctx, parent, bd); 339 ID.AddPointer(contextData); 340 } 341 classof(const LocationContext * Ctx)342 static bool classof(const LocationContext *Ctx) { 343 return Ctx->getKind() == Block; 344 } 345 }; 346 347 class LocationContextManager { 348 llvm::FoldingSet<LocationContext> Contexts; 349 public: 350 ~LocationContextManager(); 351 352 const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx, 353 const LocationContext *parent, 354 const Stmt *s, 355 const CFGBlock *blk, unsigned idx); 356 357 const ScopeContext *getScope(AnalysisDeclContext *ctx, 358 const LocationContext *parent, 359 const Stmt *s); 360 361 const BlockInvocationContext * 362 getBlockInvocationContext(AnalysisDeclContext *ctx, 363 const LocationContext *parent, 364 const BlockDecl *BD, 365 const void *ContextData); 366 367 /// Discard all previously created LocationContext objects. 368 void clear(); 369 private: 370 template <typename LOC, typename DATA> 371 const LOC *getLocationContext(AnalysisDeclContext *ctx, 372 const LocationContext *parent, 373 const DATA *d); 374 }; 375 376 class AnalysisDeclContextManager { 377 typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap; 378 379 ContextMap Contexts; 380 LocationContextManager LocContexts; 381 CFG::BuildOptions cfgBuildOptions; 382 383 public: 384 AnalysisDeclContextManager(bool useUnoptimizedCFG = false, 385 bool addImplicitDtors = false, 386 bool addInitializers = false, 387 bool addTemporaryDtors = false); 388 389 ~AnalysisDeclContextManager(); 390 391 AnalysisDeclContext *getContext(const Decl *D); 392 getUseUnoptimizedCFG()393 bool getUseUnoptimizedCFG() const { 394 return !cfgBuildOptions.PruneTriviallyFalseEdges; 395 } 396 getCFGBuildOptions()397 CFG::BuildOptions &getCFGBuildOptions() { 398 return cfgBuildOptions; 399 } 400 getStackFrame(AnalysisDeclContext * Ctx,LocationContext const * Parent,const Stmt * S,const CFGBlock * Blk,unsigned Idx)401 const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx, 402 LocationContext const *Parent, 403 const Stmt *S, 404 const CFGBlock *Blk, 405 unsigned Idx) { 406 return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx); 407 } 408 409 // Get the top level stack frame. getStackFrame(const Decl * D)410 const StackFrameContext *getStackFrame(const Decl *D) { 411 return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0); 412 } 413 414 // Get a stack frame with parent. getStackFrame(const Decl * D,LocationContext const * Parent,const Stmt * S,const CFGBlock * Blk,unsigned Idx)415 StackFrameContext const *getStackFrame(const Decl *D, 416 LocationContext const *Parent, 417 const Stmt *S, 418 const CFGBlock *Blk, 419 unsigned Idx) { 420 return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx); 421 } 422 423 /// Discard all previously created AnalysisDeclContexts. 424 void clear(); 425 426 private: 427 friend class AnalysisDeclContext; 428 getLocationContextManager()429 LocationContextManager &getLocationContextManager() { 430 return LocContexts; 431 } 432 }; 433 434 } // end clang namespace 435 #endif 436