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