15ffd83dbSDimitry Andric //===- AnalysisDeclContext.h - Context for path sensitivity -----*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 95ffd83dbSDimitry Andric /// \file 105ffd83dbSDimitry Andric /// This file defines AnalysisDeclContext, a class that manages the analysis 115ffd83dbSDimitry Andric /// context data for context sensitive and path sensitive analysis. 125ffd83dbSDimitry Andric /// It also defines the helper classes to model entering, leaving or inlining 135ffd83dbSDimitry Andric /// function calls. 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H 180b57cec5SDimitry Andric #define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #include "clang/AST/DeclBase.h" 210b57cec5SDimitry Andric #include "clang/Analysis/BodyFarm.h" 220b57cec5SDimitry Andric #include "clang/Analysis/CFG.h" 230b57cec5SDimitry Andric #include "clang/Analysis/CodeInjector.h" 240b57cec5SDimitry Andric #include "clang/Basic/LLVM.h" 250b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 260b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h" 270b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 280b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 290b57cec5SDimitry Andric #include "llvm/Support/Allocator.h" 300b57cec5SDimitry Andric #include <functional> 310b57cec5SDimitry Andric #include <memory> 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace clang { 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric class AnalysisDeclContextManager; 360b57cec5SDimitry Andric class ASTContext; 370b57cec5SDimitry Andric class BlockDecl; 380b57cec5SDimitry Andric class BlockInvocationContext; 390b57cec5SDimitry Andric class CFGReverseBlockReachabilityAnalysis; 400b57cec5SDimitry Andric class CFGStmtMap; 410b57cec5SDimitry Andric class ImplicitParamDecl; 420b57cec5SDimitry Andric class LocationContext; 430b57cec5SDimitry Andric class LocationContextManager; 440b57cec5SDimitry Andric class ParentMap; 450b57cec5SDimitry Andric class StackFrameContext; 460b57cec5SDimitry Andric class Stmt; 470b57cec5SDimitry Andric class VarDecl; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric /// The base class of a hierarchy of objects representing analyses tied 500b57cec5SDimitry Andric /// to AnalysisDeclContext. 510b57cec5SDimitry Andric class ManagedAnalysis { 520b57cec5SDimitry Andric protected: 530b57cec5SDimitry Andric ManagedAnalysis() = default; 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric public: 560b57cec5SDimitry Andric virtual ~ManagedAnalysis(); 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric // Subclasses need to implement: 590b57cec5SDimitry Andric // 600b57cec5SDimitry Andric // static const void *getTag(); 610b57cec5SDimitry Andric // 620b57cec5SDimitry Andric // Which returns a fixed pointer address to distinguish classes of 630b57cec5SDimitry Andric // analysis objects. They also need to implement: 640b57cec5SDimitry Andric // 650b57cec5SDimitry Andric // static [Derived*] create(AnalysisDeclContext &Ctx); 660b57cec5SDimitry Andric // 670b57cec5SDimitry Andric // which creates the analysis object given an AnalysisDeclContext. 680b57cec5SDimitry Andric }; 690b57cec5SDimitry Andric 705ffd83dbSDimitry Andric /// AnalysisDeclContext contains the context data for the function, method 715ffd83dbSDimitry Andric /// or block under analysis. 720b57cec5SDimitry Andric class AnalysisDeclContext { 735ffd83dbSDimitry Andric // Backpoint to the AnalysisManager object that created this 745ffd83dbSDimitry Andric // AnalysisDeclContext. This may be null. 755ffd83dbSDimitry Andric AnalysisDeclContextManager *ADCMgr; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric const Decl *const D; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric std::unique_ptr<CFG> cfg, completeCFG; 800b57cec5SDimitry Andric std::unique_ptr<CFGStmtMap> cfgStmtMap; 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric CFG::BuildOptions cfgBuildOptions; 830b57cec5SDimitry Andric CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs = nullptr; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric bool builtCFG = false; 860b57cec5SDimitry Andric bool builtCompleteCFG = false; 870b57cec5SDimitry Andric std::unique_ptr<ParentMap> PM; 880b57cec5SDimitry Andric std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric llvm::BumpPtrAllocator A; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric llvm::DenseMap<const BlockDecl *, void *> *ReferencedBlockVars = nullptr; 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric void *ManagedAnalyses = nullptr; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric public: 975ffd83dbSDimitry Andric AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D); 980b57cec5SDimitry Andric 995ffd83dbSDimitry Andric AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D, 1000b57cec5SDimitry Andric const CFG::BuildOptions &BuildOptions); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric ~AnalysisDeclContext(); 1030b57cec5SDimitry Andric getASTContext()1040b57cec5SDimitry Andric ASTContext &getASTContext() const { return D->getASTContext(); } 1055ffd83dbSDimitry Andric getDecl()1060b57cec5SDimitry Andric const Decl *getDecl() const { return D; } 1070b57cec5SDimitry Andric getManager()1085ffd83dbSDimitry Andric AnalysisDeclContextManager *getManager() const { return ADCMgr; } 1090b57cec5SDimitry Andric getCFGBuildOptions()1105ffd83dbSDimitry Andric CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; } 1110b57cec5SDimitry Andric getCFGBuildOptions()1120b57cec5SDimitry Andric const CFG::BuildOptions &getCFGBuildOptions() const { 1130b57cec5SDimitry Andric return cfgBuildOptions; 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1165ffd83dbSDimitry Andric /// \returns Whether we are adding exception handling edges from CallExprs. 1175ffd83dbSDimitry Andric /// If this is false, then try/catch statements and blocks reachable from them 1185ffd83dbSDimitry Andric /// can appear to be dead in the CFG, analysis passes must cope with that. getAddEHEdges()1190b57cec5SDimitry Andric bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } getUseUnoptimizedCFG()1200b57cec5SDimitry Andric bool getUseUnoptimizedCFG() const { 1210b57cec5SDimitry Andric return !cfgBuildOptions.PruneTriviallyFalseEdges; 1220b57cec5SDimitry Andric } getAddImplicitDtors()1230b57cec5SDimitry Andric bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } getAddInitializers()1240b57cec5SDimitry Andric bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; } 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric void registerForcedBlockExpression(const Stmt *stmt); 1270b57cec5SDimitry Andric const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); 1280b57cec5SDimitry Andric 1295ffd83dbSDimitry Andric /// \returns The body of the stored Decl \c D. 1300b57cec5SDimitry Andric Stmt *getBody() const; 1310b57cec5SDimitry Andric 1325ffd83dbSDimitry Andric /// \copydoc AnalysisDeclContext::getBody() 1330b57cec5SDimitry Andric /// \param[out] IsAutosynthesized Specifies if the body is auto-generated 1340b57cec5SDimitry Andric /// by the BodyFarm. 1350b57cec5SDimitry Andric Stmt *getBody(bool &IsAutosynthesized) const; 1360b57cec5SDimitry Andric 1375ffd83dbSDimitry Andric /// \returns Whether the body of the Decl \c D is generated by the BodyFarm. 1380b57cec5SDimitry Andric /// 1395ffd83dbSDimitry Andric /// \note The lookup is not free. We are going to call getBody behind 1400b57cec5SDimitry Andric /// the scenes. 1410b57cec5SDimitry Andric /// \sa getBody 1420b57cec5SDimitry Andric bool isBodyAutosynthesized() const; 1430b57cec5SDimitry Andric 1445ffd83dbSDimitry Andric /// \returns Whether the body of the Decl \c D is generated by the BodyFarm 1455ffd83dbSDimitry Andric /// from a model file. 1460b57cec5SDimitry Andric /// 1475ffd83dbSDimitry Andric /// \note The lookup is not free. We are going to call getBody behind 1480b57cec5SDimitry Andric /// the scenes. 1490b57cec5SDimitry Andric /// \sa getBody 1500b57cec5SDimitry Andric bool isBodyAutosynthesizedFromModelFile() const; 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric CFG *getCFG(); 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric CFGStmtMap *getCFGStmtMap(); 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis(); 1570b57cec5SDimitry Andric 1585ffd83dbSDimitry Andric /// \returns A version of the CFG without any edges pruned. 1590b57cec5SDimitry Andric CFG *getUnoptimizedCFG(); 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric void dumpCFG(bool ShowColors); 1620b57cec5SDimitry Andric 1635ffd83dbSDimitry Andric /// \returns Whether we have built a CFG for this analysis context. 1645ffd83dbSDimitry Andric /// 1655ffd83dbSDimitry Andric /// \note This doesn't correspond to whether or not a valid CFG exists, it 1660b57cec5SDimitry Andric /// corresponds to whether we *attempted* to build one. isCFGBuilt()1670b57cec5SDimitry Andric bool isCFGBuilt() const { return builtCFG; } 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric ParentMap &getParentMap(); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric using referenced_decls_iterator = const VarDecl *const *; 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric llvm::iterator_range<referenced_decls_iterator> 1740b57cec5SDimitry Andric getReferencedBlockVars(const BlockDecl *BD); 1750b57cec5SDimitry Andric 1765ffd83dbSDimitry Andric /// \returns The ImplicitParamDecl associated with \c self if this 1775ffd83dbSDimitry Andric /// AnalysisDeclContext wraps an ObjCMethodDecl or nullptr otherwise. 1780b57cec5SDimitry Andric const ImplicitParamDecl *getSelfDecl() const; 1790b57cec5SDimitry Andric 1805ffd83dbSDimitry Andric /// \copydoc LocationContextManager::getStackFrame() 1815ffd83dbSDimitry Andric const StackFrameContext *getStackFrame(LocationContext const *ParentLC, 182a7dea167SDimitry Andric const Stmt *S, const CFGBlock *Blk, 1835ffd83dbSDimitry Andric unsigned BlockCount, unsigned Index); 1840b57cec5SDimitry Andric 1855ffd83dbSDimitry Andric /// \copydoc LocationContextManager::getBlockInvocationContext() 1860b57cec5SDimitry Andric const BlockInvocationContext * 1875ffd83dbSDimitry Andric getBlockInvocationContext(const LocationContext *ParentLC, 1885ffd83dbSDimitry Andric const BlockDecl *BD, const void *Data); 1890b57cec5SDimitry Andric 1905ffd83dbSDimitry Andric /// \returns The specified analysis object, lazily running the analysis if 1915ffd83dbSDimitry Andric /// necessary or nullptr if the analysis could not run. getAnalysis()1925ffd83dbSDimitry Andric template <typename T> T *getAnalysis() { 1930b57cec5SDimitry Andric const void *tag = T::getTag(); 1945ffd83dbSDimitry Andric std::unique_ptr<ManagedAnalysis> &data = getAnalysisImpl(tag); 1955ffd83dbSDimitry Andric if (!data) 1960b57cec5SDimitry Andric data = T::create(*this); 1975ffd83dbSDimitry Andric return static_cast<T *>(data.get()); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2005ffd83dbSDimitry Andric /// \returns Whether the root namespace of \p D is the \c std C++ namespace. 2010b57cec5SDimitry Andric static bool isInStdNamespace(const Decl *D); 2020b57cec5SDimitry Andric 203fe6060f1SDimitry Andric static std::string getFunctionName(const Decl *D); 204fe6060f1SDimitry Andric 2050b57cec5SDimitry Andric private: 2065ffd83dbSDimitry Andric std::unique_ptr<ManagedAnalysis> &getAnalysisImpl(const void *tag); 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric LocationContextManager &getLocationContextManager(); 2090b57cec5SDimitry Andric }; 2100b57cec5SDimitry Andric 2115ffd83dbSDimitry Andric /// It wraps the AnalysisDeclContext to represent both the call stack with 2125ffd83dbSDimitry Andric /// the help of StackFrameContext and inside the function calls the 2135ffd83dbSDimitry Andric /// BlockInvocationContext. It is needed for context sensitive analysis to 2145ffd83dbSDimitry Andric /// model entering, leaving or inlining function calls. 2150b57cec5SDimitry Andric class LocationContext : public llvm::FoldingSetNode { 2160b57cec5SDimitry Andric public: 2175ffd83dbSDimitry Andric enum ContextKind { StackFrame, Block }; 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric private: 2200b57cec5SDimitry Andric ContextKind Kind; 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric // AnalysisDeclContext can't be const since some methods may modify its 2230b57cec5SDimitry Andric // member. 2240b57cec5SDimitry Andric AnalysisDeclContext *Ctx; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric const LocationContext *Parent; 2270b57cec5SDimitry Andric int64_t ID; 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric protected: LocationContext(ContextKind k,AnalysisDeclContext * ctx,const LocationContext * parent,int64_t ID)2300b57cec5SDimitry Andric LocationContext(ContextKind k, AnalysisDeclContext *ctx, 2315ffd83dbSDimitry Andric const LocationContext *parent, int64_t ID) 23281ad6265SDimitry Andric : Kind(k), Ctx(ctx), Parent(parent), ID(ID) { 23381ad6265SDimitry Andric assert(ctx); 23481ad6265SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric public: 2370b57cec5SDimitry Andric virtual ~LocationContext(); 2380b57cec5SDimitry Andric getKind()2390b57cec5SDimitry Andric ContextKind getKind() const { return Kind; } 2400b57cec5SDimitry Andric getID()2415ffd83dbSDimitry Andric int64_t getID() const { return ID; } 2420b57cec5SDimitry Andric 24381ad6265SDimitry Andric LLVM_ATTRIBUTE_RETURNS_NONNULL getAnalysisDeclContext()2440b57cec5SDimitry Andric AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; } 2450b57cec5SDimitry Andric 24681ad6265SDimitry Andric /// It might return null. getParent()2470b57cec5SDimitry Andric const LocationContext *getParent() const { return Parent; } 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric bool isParentOf(const LocationContext *LC) const; 2500b57cec5SDimitry Andric getDecl()2515ffd83dbSDimitry Andric const Decl *getDecl() const { return Ctx->getDecl(); } 2520b57cec5SDimitry Andric getCFG()2535ffd83dbSDimitry Andric CFG *getCFG() const { return Ctx->getCFG(); } 2540b57cec5SDimitry Andric getAnalysis()2555ffd83dbSDimitry Andric template <typename T> T *getAnalysis() const { return Ctx->getAnalysis<T>(); } 2560b57cec5SDimitry Andric getParentMap()2575ffd83dbSDimitry Andric const ParentMap &getParentMap() const { return Ctx->getParentMap(); } 2580b57cec5SDimitry Andric 2595ffd83dbSDimitry Andric /// \copydoc AnalysisDeclContext::getSelfDecl() getSelfDecl()2605ffd83dbSDimitry Andric const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); } 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric const StackFrameContext *getStackFrame() const; 2630b57cec5SDimitry Andric 2645ffd83dbSDimitry Andric /// \returns Whether the current LocationContext has no caller context. 2650b57cec5SDimitry Andric virtual bool inTopFrame() const; 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; 2680b57cec5SDimitry Andric 2695ffd83dbSDimitry Andric /// Prints out the call stack. 2705ffd83dbSDimitry Andric /// 2715ffd83dbSDimitry Andric /// \param Out The out stream. 2725ffd83dbSDimitry Andric LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const; 2730b57cec5SDimitry Andric 2745ffd83dbSDimitry Andric /// Prints out the call stack in \c json format. 2755ffd83dbSDimitry Andric /// 2765ffd83dbSDimitry Andric /// \param Out The out stream. 2775ffd83dbSDimitry Andric /// \param NL The newline. 2785ffd83dbSDimitry Andric /// \param Space The space count for indentation. 2795ffd83dbSDimitry Andric /// \param IsDot Whether the output format is \c dot. 2805ffd83dbSDimitry Andric /// \param printMoreInfoPerContext 2815ffd83dbSDimitry Andric /// A callback to print more information for each context, for example: 2825ffd83dbSDimitry Andric /// \code 2835ffd83dbSDimitry Andric /// [&](const LocationContext *LC) { LC->dump(); } 2845ffd83dbSDimitry Andric /// \endcode 2850b57cec5SDimitry Andric void printJson( 2860b57cec5SDimitry Andric raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0, 2870b57cec5SDimitry Andric bool IsDot = false, 2880b57cec5SDimitry Andric std::function<void(const LocationContext *)> printMoreInfoPerContext = 2890b57cec5SDimitry Andric [](const LocationContext *) {}) const; 2900b57cec5SDimitry Andric 2915ffd83dbSDimitry Andric LLVM_DUMP_METHOD void dump() const; 2920b57cec5SDimitry Andric 2935ffd83dbSDimitry Andric static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck, 2940b57cec5SDimitry Andric AnalysisDeclContext *ctx, 2955ffd83dbSDimitry Andric const LocationContext *parent, const void *data); 2960b57cec5SDimitry Andric }; 2970b57cec5SDimitry Andric 2985ffd83dbSDimitry Andric /// It represents a stack frame of the call stack (based on CallEvent). 2990b57cec5SDimitry Andric class StackFrameContext : public LocationContext { 3000b57cec5SDimitry Andric friend class LocationContextManager; 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric // The call site where this stack frame is established. 3030b57cec5SDimitry Andric const Stmt *CallSite; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric // The parent block of the call site. 3060b57cec5SDimitry Andric const CFGBlock *Block; 3070b57cec5SDimitry Andric 308a7dea167SDimitry Andric // The number of times the 'Block' has been visited. 309a7dea167SDimitry Andric // It allows discriminating between stack frames of the same call that is 310a7dea167SDimitry Andric // called multiple times in a loop. 311a7dea167SDimitry Andric const unsigned BlockCount; 312a7dea167SDimitry Andric 3130b57cec5SDimitry Andric // The index of the call site in the CFGBlock. 314a7dea167SDimitry Andric const unsigned Index; 3150b57cec5SDimitry Andric StackFrameContext(AnalysisDeclContext * ADC,const LocationContext * ParentLC,const Stmt * S,const CFGBlock * Block,unsigned BlockCount,unsigned Index,int64_t ID)3165ffd83dbSDimitry Andric StackFrameContext(AnalysisDeclContext *ADC, const LocationContext *ParentLC, 3175ffd83dbSDimitry Andric const Stmt *S, const CFGBlock *Block, unsigned BlockCount, 3185ffd83dbSDimitry Andric unsigned Index, int64_t ID) 3195ffd83dbSDimitry Andric : LocationContext(StackFrame, ADC, ParentLC, ID), CallSite(S), 3205ffd83dbSDimitry Andric Block(Block), BlockCount(BlockCount), Index(Index) {} 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric public: 3230b57cec5SDimitry Andric ~StackFrameContext() override = default; 3240b57cec5SDimitry Andric getCallSite()3250b57cec5SDimitry Andric const Stmt *getCallSite() const { return CallSite; } 3260b57cec5SDimitry Andric getCallSiteBlock()3270b57cec5SDimitry Andric const CFGBlock *getCallSiteBlock() const { return Block; } 3280b57cec5SDimitry Andric inTopFrame()3290b57cec5SDimitry Andric bool inTopFrame() const override { return getParent() == nullptr; } 3300b57cec5SDimitry Andric getIndex()3310b57cec5SDimitry Andric unsigned getIndex() const { return Index; } 3320b57cec5SDimitry Andric getCallSiteCFGElement()3335ffd83dbSDimitry Andric CFGElement getCallSiteCFGElement() const { return (*Block)[Index]; } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric void Profile(llvm::FoldingSetNodeID &ID) override; 3360b57cec5SDimitry Andric Profile(llvm::FoldingSetNodeID & ID,AnalysisDeclContext * ADC,const LocationContext * ParentLC,const Stmt * S,const CFGBlock * Block,unsigned BlockCount,unsigned Index)3375ffd83dbSDimitry Andric static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC, 3385ffd83dbSDimitry Andric const LocationContext *ParentLC, const Stmt *S, 3395ffd83dbSDimitry Andric const CFGBlock *Block, unsigned BlockCount, 3405ffd83dbSDimitry Andric unsigned Index) { 3415ffd83dbSDimitry Andric ProfileCommon(ID, StackFrame, ADC, ParentLC, S); 3425ffd83dbSDimitry Andric ID.AddPointer(Block); 3435ffd83dbSDimitry Andric ID.AddInteger(BlockCount); 3445ffd83dbSDimitry Andric ID.AddInteger(Index); 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric classof(const LocationContext * LC)3475ffd83dbSDimitry Andric static bool classof(const LocationContext *LC) { 3485ffd83dbSDimitry Andric return LC->getKind() == StackFrame; 3490b57cec5SDimitry Andric } 3500b57cec5SDimitry Andric }; 3510b57cec5SDimitry Andric 3525ffd83dbSDimitry Andric /// It represents a block invocation (based on BlockCall). 3530b57cec5SDimitry Andric class BlockInvocationContext : public LocationContext { 3540b57cec5SDimitry Andric friend class LocationContextManager; 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric const BlockDecl *BD; 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric // FIXME: Come up with a more type-safe way to model context-sensitivity. 3595ffd83dbSDimitry Andric const void *Data; 3600b57cec5SDimitry Andric BlockInvocationContext(AnalysisDeclContext * ADC,const LocationContext * ParentLC,const BlockDecl * BD,const void * Data,int64_t ID)3615ffd83dbSDimitry Andric BlockInvocationContext(AnalysisDeclContext *ADC, 3625ffd83dbSDimitry Andric const LocationContext *ParentLC, const BlockDecl *BD, 3635ffd83dbSDimitry Andric const void *Data, int64_t ID) 3645ffd83dbSDimitry Andric : LocationContext(Block, ADC, ParentLC, ID), BD(BD), Data(Data) {} 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric public: 3670b57cec5SDimitry Andric ~BlockInvocationContext() override = default; 3680b57cec5SDimitry Andric getBlockDecl()3690b57cec5SDimitry Andric const BlockDecl *getBlockDecl() const { return BD; } 3700b57cec5SDimitry Andric getData()3715ffd83dbSDimitry Andric const void *getData() const { return Data; } 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric void Profile(llvm::FoldingSetNodeID &ID) override; 3740b57cec5SDimitry Andric Profile(llvm::FoldingSetNodeID & ID,AnalysisDeclContext * ADC,const LocationContext * ParentLC,const BlockDecl * BD,const void * Data)3755ffd83dbSDimitry Andric static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC, 3765ffd83dbSDimitry Andric const LocationContext *ParentLC, const BlockDecl *BD, 3775ffd83dbSDimitry Andric const void *Data) { 3785ffd83dbSDimitry Andric ProfileCommon(ID, Block, ADC, ParentLC, BD); 3795ffd83dbSDimitry Andric ID.AddPointer(Data); 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric classof(const LocationContext * LC)3825ffd83dbSDimitry Andric static bool classof(const LocationContext *LC) { 3835ffd83dbSDimitry Andric return LC->getKind() == Block; 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric }; 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric class LocationContextManager { 3880b57cec5SDimitry Andric llvm::FoldingSet<LocationContext> Contexts; 3890b57cec5SDimitry Andric 3905ffd83dbSDimitry Andric // ID used for generating a new location context. 3910b57cec5SDimitry Andric int64_t NewID = 0; 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric public: 3940b57cec5SDimitry Andric ~LocationContextManager(); 3950b57cec5SDimitry Andric 3965ffd83dbSDimitry Andric /// Obtain a context of the call stack using its parent context. 3975ffd83dbSDimitry Andric /// 3985ffd83dbSDimitry Andric /// \param ADC The AnalysisDeclContext. 3995ffd83dbSDimitry Andric /// \param ParentLC The parent context of this newly created context. 4005ffd83dbSDimitry Andric /// \param S The call. 4015ffd83dbSDimitry Andric /// \param Block The basic block. 4025ffd83dbSDimitry Andric /// \param BlockCount The current count of entering into \p Blk. 4035ffd83dbSDimitry Andric /// \param Index The index of \p Blk. 4045ffd83dbSDimitry Andric /// \returns The context for \p D with parent context \p ParentLC. 4055ffd83dbSDimitry Andric const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC, 4065ffd83dbSDimitry Andric const LocationContext *ParentLC, 4075ffd83dbSDimitry Andric const Stmt *S, const CFGBlock *Block, 4085ffd83dbSDimitry Andric unsigned BlockCount, unsigned Index); 4090b57cec5SDimitry Andric 4105ffd83dbSDimitry Andric /// Obtain a context of the block invocation using its parent context. 4115ffd83dbSDimitry Andric /// 4125ffd83dbSDimitry Andric /// \param ADC The AnalysisDeclContext. 4135ffd83dbSDimitry Andric /// \param ParentLC The parent context of this newly created context. 4145ffd83dbSDimitry Andric /// \param BD The BlockDecl. 4155ffd83dbSDimitry Andric /// \param Data The raw data to store as part of the context. 4160b57cec5SDimitry Andric const BlockInvocationContext * 4175ffd83dbSDimitry Andric getBlockInvocationContext(AnalysisDeclContext *ADC, 4185ffd83dbSDimitry Andric const LocationContext *ParentLC, 4195ffd83dbSDimitry Andric const BlockDecl *BD, const void *Data); 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric /// Discard all previously created LocationContext objects. 4220b57cec5SDimitry Andric void clear(); 4230b57cec5SDimitry Andric }; 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric class AnalysisDeclContextManager { 4260b57cec5SDimitry Andric using ContextMap = 4270b57cec5SDimitry Andric llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric ContextMap Contexts; 4305ffd83dbSDimitry Andric LocationContextManager LocCtxMgr; 4310b57cec5SDimitry Andric CFG::BuildOptions cfgBuildOptions; 4320b57cec5SDimitry Andric 4335ffd83dbSDimitry Andric // Pointer to an interface that can provide function bodies for 4345ffd83dbSDimitry Andric // declarations from external source. 4350b57cec5SDimitry Andric std::unique_ptr<CodeInjector> Injector; 4360b57cec5SDimitry Andric 4375ffd83dbSDimitry Andric // A factory for creating and caching implementations for common 4385ffd83dbSDimitry Andric // methods during the analysis. 4390b57cec5SDimitry Andric BodyFarm FunctionBodyFarm; 4400b57cec5SDimitry Andric 4415ffd83dbSDimitry Andric // Flag to indicate whether or not bodies should be synthesized 4425ffd83dbSDimitry Andric // for well-known functions. 4430b57cec5SDimitry Andric bool SynthesizeBodies; 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric public: 4465ffd83dbSDimitry Andric AnalysisDeclContextManager( 4475ffd83dbSDimitry Andric ASTContext &ASTCtx, bool useUnoptimizedCFG = false, 4485ffd83dbSDimitry Andric bool addImplicitDtors = false, bool addInitializers = false, 4495ffd83dbSDimitry Andric bool addTemporaryDtors = false, bool addLifetime = false, 4505ffd83dbSDimitry Andric bool addLoopExit = false, bool addScopes = false, 4515ffd83dbSDimitry Andric bool synthesizeBodies = false, bool addStaticInitBranches = false, 4525ffd83dbSDimitry Andric bool addCXXNewAllocator = true, bool addRichCXXConstructors = true, 4535ffd83dbSDimitry Andric bool markElidedCXXConstructors = true, bool addVirtualBaseBranches = true, 4540b57cec5SDimitry Andric CodeInjector *injector = nullptr); 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric AnalysisDeclContext *getContext(const Decl *D); 4570b57cec5SDimitry Andric getUseUnoptimizedCFG()4580b57cec5SDimitry Andric bool getUseUnoptimizedCFG() const { 4590b57cec5SDimitry Andric return !cfgBuildOptions.PruneTriviallyFalseEdges; 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric getCFGBuildOptions()4625ffd83dbSDimitry Andric CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; } 4630b57cec5SDimitry Andric 4645ffd83dbSDimitry Andric /// \returns Whether faux bodies should be synthesized for known functions. synthesizeBodies()4650b57cec5SDimitry Andric bool synthesizeBodies() const { return SynthesizeBodies; } 4660b57cec5SDimitry Andric 4675ffd83dbSDimitry Andric /// Obtain the beginning context of the analysis. 4685ffd83dbSDimitry Andric /// 4695ffd83dbSDimitry Andric /// \returns The top level stack frame for \p D. getStackFrame(const Decl * D)4700b57cec5SDimitry Andric const StackFrameContext *getStackFrame(const Decl *D) { 4715ffd83dbSDimitry Andric return LocCtxMgr.getStackFrame(getContext(D), nullptr, nullptr, nullptr, 0, 4725ffd83dbSDimitry Andric 0); 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4755ffd83dbSDimitry Andric /// \copydoc LocationContextManager::getStackFrame() getStackFrame(AnalysisDeclContext * ADC,const LocationContext * Parent,const Stmt * S,const CFGBlock * Block,unsigned BlockCount,unsigned Index)4765ffd83dbSDimitry Andric const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC, 477a7dea167SDimitry Andric const LocationContext *Parent, 4785ffd83dbSDimitry Andric const Stmt *S, const CFGBlock *Block, 4795ffd83dbSDimitry Andric unsigned BlockCount, unsigned Index) { 4805ffd83dbSDimitry Andric return LocCtxMgr.getStackFrame(ADC, Parent, S, Block, BlockCount, Index); 4810b57cec5SDimitry Andric } 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric BodyFarm &getBodyFarm(); 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric /// Discard all previously created AnalysisDeclContexts. 4860b57cec5SDimitry Andric void clear(); 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric private: 4890b57cec5SDimitry Andric friend class AnalysisDeclContext; 4900b57cec5SDimitry Andric getLocationContextManager()4915ffd83dbSDimitry Andric LocationContextManager &getLocationContextManager() { return LocCtxMgr; } 4920b57cec5SDimitry Andric }; 4930b57cec5SDimitry Andric 4940b57cec5SDimitry Andric } // namespace clang 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric #endif // LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H 497