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/DenseMap.h" 22 #include "llvm/ADT/FoldingSet.h" 23 #include "llvm/ADT/IntrusiveRefCntPtr.h" 24 #include "llvm/ADT/OwningPtr.h" 25 #include "llvm/ADT/PointerUnion.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 * const 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 OwningPtr<ParentMap> PM; 85 OwningPtr<PseudoConstantAnalysis> PCA; 86 OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA; 87 88 llvm::BumpPtrAllocator A; 89 90 llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; 91 92 void *ManagedAnalyses; 93 94 public: 95 AnalysisDeclContext(AnalysisDeclContextManager *Mgr, 96 const Decl *D); 97 98 AnalysisDeclContext(AnalysisDeclContextManager *Mgr, 99 const Decl *D, 100 const CFG::BuildOptions &BuildOptions); 101 102 ~AnalysisDeclContext(); 103 getASTContext()104 ASTContext &getASTContext() const { return D->getASTContext(); } getDecl()105 const Decl *getDecl() const { return D; } 106 107 /// Return the AnalysisDeclContextManager (if any) that created 108 /// this AnalysisDeclContext. getManager()109 AnalysisDeclContextManager *getManager() const { 110 return Manager; 111 } 112 113 /// Return the build options used to construct the CFG. getCFGBuildOptions()114 CFG::BuildOptions &getCFGBuildOptions() { 115 return cfgBuildOptions; 116 } 117 getCFGBuildOptions()118 const CFG::BuildOptions &getCFGBuildOptions() const { 119 return cfgBuildOptions; 120 } 121 122 /// getAddEHEdges - Return true iff we are adding exceptional edges from 123 /// callExprs. If this is false, then try/catch statements and blocks 124 /// reachable from them can appear to be dead in the CFG, analysis passes must 125 /// cope with that. getAddEHEdges()126 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } getUseUnoptimizedCFG()127 bool getUseUnoptimizedCFG() const { 128 return !cfgBuildOptions.PruneTriviallyFalseEdges; 129 } getAddImplicitDtors()130 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } getAddInitializers()131 bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; } 132 133 void registerForcedBlockExpression(const Stmt *stmt); 134 const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); 135 136 /// \brief Get the body of the Declaration. 137 Stmt *getBody() const; 138 139 /// \brief Get the body of the Declaration. 140 /// \param[out] IsAutosynthesized Specifies if the body is auto-generated 141 /// by the BodyFarm. 142 Stmt *getBody(bool &IsAutosynthesized) const; 143 144 /// \brief Checks if the body of the Decl is generated by the BodyFarm. 145 /// 146 /// Note, the lookup is not free. We are going to call getBody behind 147 /// the scenes. 148 /// \sa getBody 149 bool isBodyAutosynthesized() const; 150 151 CFG *getCFG(); 152 153 CFGStmtMap *getCFGStmtMap(); 154 155 CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis(); 156 157 /// Return a version of the CFG without any edges pruned. 158 CFG *getUnoptimizedCFG(); 159 160 void dumpCFG(bool ShowColors); 161 162 /// \brief Returns true if we have built a CFG for this analysis context. 163 /// Note that this doesn't correspond to whether or not a valid CFG exists, it 164 /// corresponds to whether we *attempted* to build one. isCFGBuilt()165 bool isCFGBuilt() const { return builtCFG; } 166 167 ParentMap &getParentMap(); 168 PseudoConstantAnalysis *getPseudoConstantAnalysis(); 169 170 typedef const VarDecl * const * referenced_decls_iterator; 171 172 std::pair<referenced_decls_iterator, referenced_decls_iterator> 173 getReferencedBlockVars(const BlockDecl *BD); 174 175 /// Return the ImplicitParamDecl* associated with 'self' if this 176 /// AnalysisDeclContext wraps an ObjCMethodDecl. Returns NULL otherwise. 177 const ImplicitParamDecl *getSelfDecl() const; 178 179 const StackFrameContext *getStackFrame(LocationContext const *Parent, 180 const Stmt *S, 181 const CFGBlock *Blk, 182 unsigned Idx); 183 184 const BlockInvocationContext * 185 getBlockInvocationContext(const LocationContext *parent, 186 const BlockDecl *BD, 187 const void *ContextData); 188 189 /// Return the specified analysis object, lazily running the analysis if 190 /// necessary. Return NULL if the analysis could not run. 191 template <typename T> getAnalysis()192 T *getAnalysis() { 193 const void *tag = T::getTag(); 194 ManagedAnalysis *&data = getAnalysisImpl(tag); 195 if (!data) { 196 data = T::create(*this); 197 } 198 return static_cast<T*>(data); 199 } 200 private: 201 ManagedAnalysis *&getAnalysisImpl(const void* tag); 202 203 LocationContextManager &getLocationContextManager(); 204 }; 205 206 class LocationContext : public llvm::FoldingSetNode { 207 public: 208 enum ContextKind { StackFrame, Scope, Block }; 209 210 private: 211 ContextKind Kind; 212 213 // AnalysisDeclContext can't be const since some methods may modify its 214 // member. 215 AnalysisDeclContext *Ctx; 216 217 const LocationContext *Parent; 218 219 protected: LocationContext(ContextKind k,AnalysisDeclContext * ctx,const LocationContext * parent)220 LocationContext(ContextKind k, AnalysisDeclContext *ctx, 221 const LocationContext *parent) 222 : Kind(k), Ctx(ctx), Parent(parent) {} 223 224 public: 225 virtual ~LocationContext(); 226 getKind()227 ContextKind getKind() const { return Kind; } 228 getAnalysisDeclContext()229 AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; } 230 getParent()231 const LocationContext *getParent() const { return Parent; } 232 233 bool isParentOf(const LocationContext *LC) const; 234 getDecl()235 const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); } 236 getCFG()237 CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); } 238 239 template <typename T> getAnalysis()240 T *getAnalysis() const { 241 return getAnalysisDeclContext()->getAnalysis<T>(); 242 } 243 getParentMap()244 ParentMap &getParentMap() const { 245 return getAnalysisDeclContext()->getParentMap(); 246 } 247 getSelfDecl()248 const ImplicitParamDecl *getSelfDecl() const { 249 return Ctx->getSelfDecl(); 250 } 251 252 const StackFrameContext *getCurrentStackFrame() const; 253 254 /// Return true if the current LocationContext has no caller context. 255 virtual bool inTopFrame() const; 256 257 virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; 258 259 public: 260 static void ProfileCommon(llvm::FoldingSetNodeID &ID, 261 ContextKind ck, 262 AnalysisDeclContext *ctx, 263 const LocationContext *parent, 264 const void *data); 265 }; 266 267 class StackFrameContext : public LocationContext { 268 // The callsite where this stack frame is established. 269 const Stmt *CallSite; 270 271 // The parent block of the callsite. 272 const CFGBlock *Block; 273 274 // The index of the callsite in the CFGBlock. 275 unsigned Index; 276 277 friend class LocationContextManager; StackFrameContext(AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s,const CFGBlock * blk,unsigned idx)278 StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent, 279 const Stmt *s, const CFGBlock *blk, 280 unsigned idx) 281 : LocationContext(StackFrame, ctx, parent), CallSite(s), 282 Block(blk), Index(idx) {} 283 284 public: ~StackFrameContext()285 ~StackFrameContext() {} 286 getCallSite()287 const Stmt *getCallSite() const { return CallSite; } 288 getCallSiteBlock()289 const CFGBlock *getCallSiteBlock() const { return Block; } 290 291 /// Return true if the current LocationContext has no caller context. inTopFrame()292 virtual bool inTopFrame() const { return getParent() == 0; } 293 getIndex()294 unsigned getIndex() const { return Index; } 295 296 void Profile(llvm::FoldingSetNodeID &ID); 297 Profile(llvm::FoldingSetNodeID & ID,AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s,const CFGBlock * blk,unsigned idx)298 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, 299 const LocationContext *parent, const Stmt *s, 300 const CFGBlock *blk, unsigned idx) { 301 ProfileCommon(ID, StackFrame, ctx, parent, s); 302 ID.AddPointer(blk); 303 ID.AddInteger(idx); 304 } 305 classof(const LocationContext * Ctx)306 static bool classof(const LocationContext *Ctx) { 307 return Ctx->getKind() == StackFrame; 308 } 309 }; 310 311 class ScopeContext : public LocationContext { 312 const Stmt *Enter; 313 314 friend class LocationContextManager; ScopeContext(AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s)315 ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent, 316 const Stmt *s) 317 : LocationContext(Scope, ctx, parent), Enter(s) {} 318 319 public: ~ScopeContext()320 ~ScopeContext() {} 321 322 void Profile(llvm::FoldingSetNodeID &ID); 323 Profile(llvm::FoldingSetNodeID & ID,AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s)324 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, 325 const LocationContext *parent, const Stmt *s) { 326 ProfileCommon(ID, Scope, ctx, parent, s); 327 } 328 classof(const LocationContext * Ctx)329 static bool classof(const LocationContext *Ctx) { 330 return Ctx->getKind() == Scope; 331 } 332 }; 333 334 class BlockInvocationContext : public LocationContext { 335 const BlockDecl *BD; 336 337 // FIXME: Come up with a more type-safe way to model context-sensitivity. 338 const void *ContextData; 339 340 friend class LocationContextManager; 341 BlockInvocationContext(AnalysisDeclContext * ctx,const LocationContext * parent,const BlockDecl * bd,const void * contextData)342 BlockInvocationContext(AnalysisDeclContext *ctx, 343 const LocationContext *parent, 344 const BlockDecl *bd, const void *contextData) 345 : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {} 346 347 public: ~BlockInvocationContext()348 ~BlockInvocationContext() {} 349 getBlockDecl()350 const BlockDecl *getBlockDecl() const { return BD; } 351 getContextData()352 const void *getContextData() const { return ContextData; } 353 354 void Profile(llvm::FoldingSetNodeID &ID); 355 Profile(llvm::FoldingSetNodeID & ID,AnalysisDeclContext * ctx,const LocationContext * parent,const BlockDecl * bd,const void * contextData)356 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, 357 const LocationContext *parent, const BlockDecl *bd, 358 const void *contextData) { 359 ProfileCommon(ID, Block, ctx, parent, bd); 360 ID.AddPointer(contextData); 361 } 362 classof(const LocationContext * Ctx)363 static bool classof(const LocationContext *Ctx) { 364 return Ctx->getKind() == Block; 365 } 366 }; 367 368 class LocationContextManager { 369 llvm::FoldingSet<LocationContext> Contexts; 370 public: 371 ~LocationContextManager(); 372 373 const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx, 374 const LocationContext *parent, 375 const Stmt *s, 376 const CFGBlock *blk, unsigned idx); 377 378 const ScopeContext *getScope(AnalysisDeclContext *ctx, 379 const LocationContext *parent, 380 const Stmt *s); 381 382 const BlockInvocationContext * 383 getBlockInvocationContext(AnalysisDeclContext *ctx, 384 const LocationContext *parent, 385 const BlockDecl *BD, 386 const void *ContextData); 387 388 /// Discard all previously created LocationContext objects. 389 void clear(); 390 private: 391 template <typename LOC, typename DATA> 392 const LOC *getLocationContext(AnalysisDeclContext *ctx, 393 const LocationContext *parent, 394 const DATA *d); 395 }; 396 397 class AnalysisDeclContextManager { 398 typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap; 399 400 ContextMap Contexts; 401 LocationContextManager LocContexts; 402 CFG::BuildOptions cfgBuildOptions; 403 404 /// Flag to indicate whether or not bodies should be synthesized 405 /// for well-known functions. 406 bool SynthesizeBodies; 407 408 public: 409 AnalysisDeclContextManager(bool useUnoptimizedCFG = false, 410 bool addImplicitDtors = false, 411 bool addInitializers = false, 412 bool addTemporaryDtors = false, 413 bool synthesizeBodies = false); 414 415 ~AnalysisDeclContextManager(); 416 417 AnalysisDeclContext *getContext(const Decl *D); 418 getUseUnoptimizedCFG()419 bool getUseUnoptimizedCFG() const { 420 return !cfgBuildOptions.PruneTriviallyFalseEdges; 421 } 422 getCFGBuildOptions()423 CFG::BuildOptions &getCFGBuildOptions() { 424 return cfgBuildOptions; 425 } 426 427 /// Return true if faux bodies should be synthesized for well-known 428 /// functions. synthesizeBodies()429 bool synthesizeBodies() const { return SynthesizeBodies; } 430 getStackFrame(AnalysisDeclContext * Ctx,LocationContext const * Parent,const Stmt * S,const CFGBlock * Blk,unsigned Idx)431 const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx, 432 LocationContext const *Parent, 433 const Stmt *S, 434 const CFGBlock *Blk, 435 unsigned Idx) { 436 return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx); 437 } 438 439 // Get the top level stack frame. getStackFrame(const Decl * D)440 const StackFrameContext *getStackFrame(const Decl *D) { 441 return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0); 442 } 443 444 // Get a stack frame with parent. getStackFrame(const Decl * D,LocationContext const * Parent,const Stmt * S,const CFGBlock * Blk,unsigned Idx)445 StackFrameContext const *getStackFrame(const Decl *D, 446 LocationContext const *Parent, 447 const Stmt *S, 448 const CFGBlock *Blk, 449 unsigned Idx) { 450 return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx); 451 } 452 453 /// Discard all previously created AnalysisDeclContexts. 454 void clear(); 455 456 private: 457 friend class AnalysisDeclContext; 458 getLocationContextManager()459 LocationContextManager &getLocationContextManager() { 460 return LocContexts; 461 } 462 }; 463 464 } // end clang namespace 465 #endif 466