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: 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 104 ASTContext &getASTContext() const { return D->getASTContext(); } 105 const Decl *getDecl() const { return D; } 106 107 /// Return the AnalysisDeclContextManager (if any) that created 108 /// this AnalysisDeclContext. 109 AnalysisDeclContextManager *getManager() const { 110 return Manager; 111 } 112 113 /// Return the build options used to construct the CFG. 114 CFG::BuildOptions &getCFGBuildOptions() { 115 return cfgBuildOptions; 116 } 117 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. 126 bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } 127 bool getUseUnoptimizedCFG() const { 128 return !cfgBuildOptions.PruneTriviallyFalseEdges; 129 } 130 bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } 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. 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> 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: 220 LocationContext(ContextKind k, AnalysisDeclContext *ctx, 221 const LocationContext *parent) 222 : Kind(k), Ctx(ctx), Parent(parent) {} 223 224 public: 225 virtual ~LocationContext(); 226 227 ContextKind getKind() const { return Kind; } 228 229 AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; } 230 231 const LocationContext *getParent() const { return Parent; } 232 233 bool isParentOf(const LocationContext *LC) const; 234 235 const Decl *getDecl() const { return getAnalysisDeclContext()->getDecl(); } 236 237 CFG *getCFG() const { return getAnalysisDeclContext()->getCFG(); } 238 239 template <typename T> 240 T *getAnalysis() const { 241 return getAnalysisDeclContext()->getAnalysis<T>(); 242 } 243 244 ParentMap &getParentMap() const { 245 return getAnalysisDeclContext()->getParentMap(); 246 } 247 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 void dumpStack(raw_ostream &OS, StringRef Indent = "") const; 260 LLVM_ATTRIBUTE_USED void dumpStack() const; 261 262 public: 263 static void ProfileCommon(llvm::FoldingSetNodeID &ID, 264 ContextKind ck, 265 AnalysisDeclContext *ctx, 266 const LocationContext *parent, 267 const void *data); 268 }; 269 270 class StackFrameContext : public LocationContext { 271 // The callsite where this stack frame is established. 272 const Stmt *CallSite; 273 274 // The parent block of the callsite. 275 const CFGBlock *Block; 276 277 // The index of the callsite in the CFGBlock. 278 unsigned Index; 279 280 friend class LocationContextManager; 281 StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent, 282 const Stmt *s, const CFGBlock *blk, 283 unsigned idx) 284 : LocationContext(StackFrame, ctx, parent), CallSite(s), 285 Block(blk), Index(idx) {} 286 287 public: 288 ~StackFrameContext() {} 289 290 const Stmt *getCallSite() const { return CallSite; } 291 292 const CFGBlock *getCallSiteBlock() const { return Block; } 293 294 /// Return true if the current LocationContext has no caller context. 295 virtual bool inTopFrame() const { return getParent() == 0; } 296 297 unsigned getIndex() const { return Index; } 298 299 void Profile(llvm::FoldingSetNodeID &ID); 300 301 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, 302 const LocationContext *parent, const Stmt *s, 303 const CFGBlock *blk, unsigned idx) { 304 ProfileCommon(ID, StackFrame, ctx, parent, s); 305 ID.AddPointer(blk); 306 ID.AddInteger(idx); 307 } 308 309 static bool classof(const LocationContext *Ctx) { 310 return Ctx->getKind() == StackFrame; 311 } 312 }; 313 314 class ScopeContext : public LocationContext { 315 const Stmt *Enter; 316 317 friend class LocationContextManager; 318 ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent, 319 const Stmt *s) 320 : LocationContext(Scope, ctx, parent), Enter(s) {} 321 322 public: 323 ~ScopeContext() {} 324 325 void Profile(llvm::FoldingSetNodeID &ID); 326 327 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, 328 const LocationContext *parent, const Stmt *s) { 329 ProfileCommon(ID, Scope, ctx, parent, s); 330 } 331 332 static bool classof(const LocationContext *Ctx) { 333 return Ctx->getKind() == Scope; 334 } 335 }; 336 337 class BlockInvocationContext : public LocationContext { 338 const BlockDecl *BD; 339 340 // FIXME: Come up with a more type-safe way to model context-sensitivity. 341 const void *ContextData; 342 343 friend class LocationContextManager; 344 345 BlockInvocationContext(AnalysisDeclContext *ctx, 346 const LocationContext *parent, 347 const BlockDecl *bd, const void *contextData) 348 : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {} 349 350 public: 351 ~BlockInvocationContext() {} 352 353 const BlockDecl *getBlockDecl() const { return BD; } 354 355 const void *getContextData() const { return ContextData; } 356 357 void Profile(llvm::FoldingSetNodeID &ID); 358 359 static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx, 360 const LocationContext *parent, const BlockDecl *bd, 361 const void *contextData) { 362 ProfileCommon(ID, Block, ctx, parent, bd); 363 ID.AddPointer(contextData); 364 } 365 366 static bool classof(const LocationContext *Ctx) { 367 return Ctx->getKind() == Block; 368 } 369 }; 370 371 class LocationContextManager { 372 llvm::FoldingSet<LocationContext> Contexts; 373 public: 374 ~LocationContextManager(); 375 376 const StackFrameContext *getStackFrame(AnalysisDeclContext *ctx, 377 const LocationContext *parent, 378 const Stmt *s, 379 const CFGBlock *blk, unsigned idx); 380 381 const ScopeContext *getScope(AnalysisDeclContext *ctx, 382 const LocationContext *parent, 383 const Stmt *s); 384 385 const BlockInvocationContext * 386 getBlockInvocationContext(AnalysisDeclContext *ctx, 387 const LocationContext *parent, 388 const BlockDecl *BD, 389 const void *ContextData); 390 391 /// Discard all previously created LocationContext objects. 392 void clear(); 393 private: 394 template <typename LOC, typename DATA> 395 const LOC *getLocationContext(AnalysisDeclContext *ctx, 396 const LocationContext *parent, 397 const DATA *d); 398 }; 399 400 class AnalysisDeclContextManager { 401 typedef llvm::DenseMap<const Decl*, AnalysisDeclContext*> ContextMap; 402 403 ContextMap Contexts; 404 LocationContextManager LocContexts; 405 CFG::BuildOptions cfgBuildOptions; 406 407 /// Flag to indicate whether or not bodies should be synthesized 408 /// for well-known functions. 409 bool SynthesizeBodies; 410 411 public: 412 AnalysisDeclContextManager(bool useUnoptimizedCFG = false, 413 bool addImplicitDtors = false, 414 bool addInitializers = false, 415 bool addTemporaryDtors = false, 416 bool synthesizeBodies = false, 417 bool addStaticInitBranches = false); 418 419 ~AnalysisDeclContextManager(); 420 421 AnalysisDeclContext *getContext(const Decl *D); 422 423 bool getUseUnoptimizedCFG() const { 424 return !cfgBuildOptions.PruneTriviallyFalseEdges; 425 } 426 427 CFG::BuildOptions &getCFGBuildOptions() { 428 return cfgBuildOptions; 429 } 430 431 /// Return true if faux bodies should be synthesized for well-known 432 /// functions. 433 bool synthesizeBodies() const { return SynthesizeBodies; } 434 435 const StackFrameContext *getStackFrame(AnalysisDeclContext *Ctx, 436 LocationContext const *Parent, 437 const Stmt *S, 438 const CFGBlock *Blk, 439 unsigned Idx) { 440 return LocContexts.getStackFrame(Ctx, Parent, S, Blk, Idx); 441 } 442 443 // Get the top level stack frame. 444 const StackFrameContext *getStackFrame(const Decl *D) { 445 return LocContexts.getStackFrame(getContext(D), 0, 0, 0, 0); 446 } 447 448 // Get a stack frame with parent. 449 StackFrameContext const *getStackFrame(const Decl *D, 450 LocationContext const *Parent, 451 const Stmt *S, 452 const CFGBlock *Blk, 453 unsigned Idx) { 454 return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx); 455 } 456 457 /// Discard all previously created AnalysisDeclContexts. 458 void clear(); 459 460 private: 461 friend class AnalysisDeclContext; 462 463 LocationContextManager &getLocationContextManager() { 464 return LocContexts; 465 } 466 }; 467 468 } // end clang namespace 469 #endif 470