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