Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:25

0001 //===- AnalysisDeclContext.h - Context for path sensitivity -----*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 /// \file
0010 /// This file defines AnalysisDeclContext, a class that manages the analysis
0011 /// context data for context sensitive and path sensitive analysis.
0012 /// It also defines the helper classes to model entering, leaving or inlining
0013 /// function calls.
0014 //
0015 //===----------------------------------------------------------------------===//
0016 
0017 #ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
0018 #define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H
0019 
0020 #include "clang/AST/DeclBase.h"
0021 #include "clang/Analysis/BodyFarm.h"
0022 #include "clang/Analysis/CFG.h"
0023 #include "clang/Analysis/CodeInjector.h"
0024 #include "clang/Basic/LLVM.h"
0025 #include "llvm/ADT/DenseMap.h"
0026 #include "llvm/ADT/FoldingSet.h"
0027 #include "llvm/ADT/StringRef.h"
0028 #include "llvm/ADT/iterator_range.h"
0029 #include "llvm/Support/Allocator.h"
0030 #include <functional>
0031 #include <memory>
0032 
0033 namespace clang {
0034 
0035 class AnalysisDeclContextManager;
0036 class ASTContext;
0037 class BlockDecl;
0038 class BlockInvocationContext;
0039 class CFGReverseBlockReachabilityAnalysis;
0040 class CFGStmtMap;
0041 class ImplicitParamDecl;
0042 class LocationContext;
0043 class LocationContextManager;
0044 class ParentMap;
0045 class StackFrameContext;
0046 class Stmt;
0047 class VarDecl;
0048 
0049 /// The base class of a hierarchy of objects representing analyses tied
0050 /// to AnalysisDeclContext.
0051 class ManagedAnalysis {
0052 protected:
0053   ManagedAnalysis() = default;
0054 
0055 public:
0056   virtual ~ManagedAnalysis();
0057 
0058   // Subclasses need to implement:
0059   //
0060   //  static const void *getTag();
0061   //
0062   // Which returns a fixed pointer address to distinguish classes of
0063   // analysis objects.  They also need to implement:
0064   //
0065   //  static [Derived*] create(AnalysisDeclContext &Ctx);
0066   //
0067   // which creates the analysis object given an AnalysisDeclContext.
0068 };
0069 
0070 /// AnalysisDeclContext contains the context data for the function, method
0071 /// or block under analysis.
0072 class AnalysisDeclContext {
0073   // Backpoint to the AnalysisManager object that created this
0074   // AnalysisDeclContext. This may be null.
0075   AnalysisDeclContextManager *ADCMgr;
0076 
0077   const Decl *const D;
0078 
0079   std::unique_ptr<CFG> cfg, completeCFG;
0080   std::unique_ptr<CFGStmtMap> cfgStmtMap;
0081 
0082   CFG::BuildOptions cfgBuildOptions;
0083   CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs = nullptr;
0084 
0085   bool builtCFG = false;
0086   bool builtCompleteCFG = false;
0087   std::unique_ptr<ParentMap> PM;
0088   std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA;
0089 
0090   llvm::BumpPtrAllocator A;
0091 
0092   llvm::DenseMap<const BlockDecl *, void *> *ReferencedBlockVars = nullptr;
0093 
0094   void *ManagedAnalyses = nullptr;
0095 
0096 public:
0097   AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D);
0098 
0099   AnalysisDeclContext(AnalysisDeclContextManager *Mgr, const Decl *D,
0100                       const CFG::BuildOptions &BuildOptions);
0101 
0102   ~AnalysisDeclContext();
0103 
0104   ASTContext &getASTContext() const { return D->getASTContext(); }
0105 
0106   const Decl *getDecl() const { return D; }
0107 
0108   AnalysisDeclContextManager *getManager() const { return ADCMgr; }
0109 
0110   CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; }
0111 
0112   const CFG::BuildOptions &getCFGBuildOptions() const {
0113     return cfgBuildOptions;
0114   }
0115 
0116   /// \returns Whether we are adding exception handling edges from CallExprs.
0117   /// If this is false, then try/catch statements and blocks reachable from them
0118   /// can appear to be dead in the CFG, analysis passes must cope with that.
0119   bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; }
0120   bool getUseUnoptimizedCFG() const {
0121     return !cfgBuildOptions.PruneTriviallyFalseEdges;
0122   }
0123   bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; }
0124   bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; }
0125 
0126   void registerForcedBlockExpression(const Stmt *stmt);
0127   const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt);
0128 
0129   /// \returns The body of the stored Decl \c D.
0130   Stmt *getBody() const;
0131 
0132   /// \copydoc AnalysisDeclContext::getBody()
0133   /// \param[out] IsAutosynthesized Specifies if the body is auto-generated
0134   ///             by the BodyFarm.
0135   Stmt *getBody(bool &IsAutosynthesized) const;
0136 
0137   /// \returns Whether the body of the Decl \c D is generated by the BodyFarm.
0138   ///
0139   /// \note The lookup is not free. We are going to call getBody behind
0140   /// the scenes.
0141   /// \sa getBody
0142   bool isBodyAutosynthesized() const;
0143 
0144   /// \returns Whether the body of the Decl \c D is generated by the BodyFarm
0145   /// from a model file.
0146   ///
0147   /// \note The lookup is not free. We are going to call getBody behind
0148   /// the scenes.
0149   /// \sa getBody
0150   bool isBodyAutosynthesizedFromModelFile() const;
0151 
0152   CFG *getCFG();
0153 
0154   CFGStmtMap *getCFGStmtMap();
0155 
0156   CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis();
0157 
0158   /// \returns A version of the CFG without any edges pruned.
0159   CFG *getUnoptimizedCFG();
0160 
0161   void dumpCFG(bool ShowColors);
0162 
0163   /// \returns Whether we have built a CFG for this analysis context.
0164   ///
0165   /// \note This doesn't correspond to whether or not a valid CFG exists, it
0166   /// corresponds to whether we *attempted* to build one.
0167   bool isCFGBuilt() const { return builtCFG; }
0168 
0169   ParentMap &getParentMap();
0170 
0171   using referenced_decls_iterator = const VarDecl *const *;
0172 
0173   llvm::iterator_range<referenced_decls_iterator>
0174   getReferencedBlockVars(const BlockDecl *BD);
0175 
0176   /// \returns The ImplicitParamDecl associated with \c self if this
0177   /// AnalysisDeclContext wraps an ObjCMethodDecl or nullptr otherwise.
0178   const ImplicitParamDecl *getSelfDecl() const;
0179 
0180   /// \copydoc LocationContextManager::getStackFrame()
0181   const StackFrameContext *getStackFrame(LocationContext const *ParentLC,
0182                                          const Stmt *S, const CFGBlock *Blk,
0183                                          unsigned BlockCount, unsigned Index);
0184 
0185   /// \copydoc LocationContextManager::getBlockInvocationContext()
0186   const BlockInvocationContext *
0187   getBlockInvocationContext(const LocationContext *ParentLC,
0188                             const BlockDecl *BD, const void *Data);
0189 
0190   /// \returns The specified analysis object, lazily running the analysis if
0191   /// necessary or nullptr if the analysis could not run.
0192   template <typename T> T *getAnalysis() {
0193     const void *tag = T::getTag();
0194     std::unique_ptr<ManagedAnalysis> &data = getAnalysisImpl(tag);
0195     if (!data)
0196       data = T::create(*this);
0197     return static_cast<T *>(data.get());
0198   }
0199 
0200   /// \returns Whether the root namespace of \p D is the \c std C++ namespace.
0201   static bool isInStdNamespace(const Decl *D);
0202 
0203   static std::string getFunctionName(const Decl *D);
0204 
0205 private:
0206   std::unique_ptr<ManagedAnalysis> &getAnalysisImpl(const void *tag);
0207 
0208   LocationContextManager &getLocationContextManager();
0209 };
0210 
0211 /// It wraps the AnalysisDeclContext to represent both the call stack with
0212 /// the help of StackFrameContext and inside the function calls the
0213 /// BlockInvocationContext. It is needed for context sensitive analysis to
0214 /// model entering, leaving or inlining function calls.
0215 class LocationContext : public llvm::FoldingSetNode {
0216 public:
0217   enum ContextKind { StackFrame, Block };
0218 
0219 private:
0220   ContextKind Kind;
0221 
0222   // AnalysisDeclContext can't be const since some methods may modify its
0223   // member.
0224   AnalysisDeclContext *Ctx;
0225 
0226   const LocationContext *Parent;
0227   int64_t ID;
0228 
0229 protected:
0230   LocationContext(ContextKind k, AnalysisDeclContext *ctx,
0231                   const LocationContext *parent, int64_t ID)
0232       : Kind(k), Ctx(ctx), Parent(parent), ID(ID) {
0233     assert(ctx);
0234   }
0235 
0236 public:
0237   virtual ~LocationContext();
0238 
0239   ContextKind getKind() const { return Kind; }
0240 
0241   int64_t getID() const { return ID; }
0242 
0243   LLVM_ATTRIBUTE_RETURNS_NONNULL
0244   AnalysisDeclContext *getAnalysisDeclContext() const { return Ctx; }
0245 
0246   /// It might return null.
0247   const LocationContext *getParent() const { return Parent; }
0248 
0249   bool isParentOf(const LocationContext *LC) const;
0250 
0251   const Decl *getDecl() const { return Ctx->getDecl(); }
0252 
0253   CFG *getCFG() const { return Ctx->getCFG(); }
0254 
0255   template <typename T> T *getAnalysis() const { return Ctx->getAnalysis<T>(); }
0256 
0257   const ParentMap &getParentMap() const { return Ctx->getParentMap(); }
0258 
0259   /// \copydoc AnalysisDeclContext::getSelfDecl()
0260   const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); }
0261 
0262   const StackFrameContext *getStackFrame() const;
0263 
0264   /// \returns Whether the current LocationContext has no caller context.
0265   virtual bool inTopFrame() const;
0266 
0267   virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
0268 
0269   /// Prints out the call stack.
0270   ///
0271   /// \param Out The out stream.
0272   LLVM_DUMP_METHOD void dumpStack(raw_ostream &Out) const;
0273 
0274   /// Prints out the call stack in \c json format.
0275   ///
0276   /// \param Out   The out stream.
0277   /// \param NL    The newline.
0278   /// \param Space The space count for indentation.
0279   /// \param IsDot Whether the output format is \c dot.
0280   /// \param printMoreInfoPerContext
0281   /// A callback to print more information for each context, for example:
0282   /// \code
0283   ///   [&](const LocationContext *LC) { LC->dump(); }
0284   /// \endcode
0285   void printJson(
0286       raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0,
0287       bool IsDot = false,
0288       std::function<void(const LocationContext *)> printMoreInfoPerContext =
0289           [](const LocationContext *) {}) const;
0290 
0291   LLVM_DUMP_METHOD void dump() const;
0292 
0293   static void ProfileCommon(llvm::FoldingSetNodeID &ID, ContextKind ck,
0294                             AnalysisDeclContext *ctx,
0295                             const LocationContext *parent, const void *data);
0296 };
0297 
0298 /// It represents a stack frame of the call stack (based on CallEvent).
0299 class StackFrameContext : public LocationContext {
0300   friend class LocationContextManager;
0301 
0302   // The call site where this stack frame is established.
0303   const Stmt *CallSite;
0304 
0305   // The parent block of the call site.
0306   const CFGBlock *Block;
0307 
0308   // The number of times the 'Block' has been visited.
0309   // It allows discriminating between stack frames of the same call that is
0310   // called multiple times in a loop.
0311   const unsigned BlockCount;
0312 
0313   // The index of the call site in the CFGBlock.
0314   const unsigned Index;
0315 
0316   StackFrameContext(AnalysisDeclContext *ADC, const LocationContext *ParentLC,
0317                     const Stmt *S, const CFGBlock *Block, unsigned BlockCount,
0318                     unsigned Index, int64_t ID)
0319       : LocationContext(StackFrame, ADC, ParentLC, ID), CallSite(S),
0320         Block(Block), BlockCount(BlockCount), Index(Index) {}
0321 
0322 public:
0323   ~StackFrameContext() override = default;
0324 
0325   const Stmt *getCallSite() const { return CallSite; }
0326 
0327   const CFGBlock *getCallSiteBlock() const { return Block; }
0328 
0329   bool inTopFrame() const override { return getParent() == nullptr; }
0330 
0331   unsigned getIndex() const { return Index; }
0332 
0333   CFGElement getCallSiteCFGElement() const { return (*Block)[Index]; }
0334 
0335   void Profile(llvm::FoldingSetNodeID &ID) override;
0336 
0337   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
0338                       const LocationContext *ParentLC, const Stmt *S,
0339                       const CFGBlock *Block, unsigned BlockCount,
0340                       unsigned Index) {
0341     ProfileCommon(ID, StackFrame, ADC, ParentLC, S);
0342     ID.AddPointer(Block);
0343     ID.AddInteger(BlockCount);
0344     ID.AddInteger(Index);
0345   }
0346 
0347   static bool classof(const LocationContext *LC) {
0348     return LC->getKind() == StackFrame;
0349   }
0350 };
0351 
0352 /// It represents a block invocation (based on BlockCall).
0353 class BlockInvocationContext : public LocationContext {
0354   friend class LocationContextManager;
0355 
0356   const BlockDecl *BD;
0357 
0358   // FIXME: Come up with a more type-safe way to model context-sensitivity.
0359   const void *Data;
0360 
0361   BlockInvocationContext(AnalysisDeclContext *ADC,
0362                          const LocationContext *ParentLC, const BlockDecl *BD,
0363                          const void *Data, int64_t ID)
0364       : LocationContext(Block, ADC, ParentLC, ID), BD(BD), Data(Data) {}
0365 
0366 public:
0367   ~BlockInvocationContext() override = default;
0368 
0369   const BlockDecl *getBlockDecl() const { return BD; }
0370 
0371   const void *getData() const { return Data; }
0372 
0373   void Profile(llvm::FoldingSetNodeID &ID) override;
0374 
0375   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ADC,
0376                       const LocationContext *ParentLC, const BlockDecl *BD,
0377                       const void *Data) {
0378     ProfileCommon(ID, Block, ADC, ParentLC, BD);
0379     ID.AddPointer(Data);
0380   }
0381 
0382   static bool classof(const LocationContext *LC) {
0383     return LC->getKind() == Block;
0384   }
0385 };
0386 
0387 class LocationContextManager {
0388   llvm::FoldingSet<LocationContext> Contexts;
0389 
0390   // ID used for generating a new location context.
0391   int64_t NewID = 0;
0392 
0393 public:
0394   ~LocationContextManager();
0395 
0396   /// Obtain a context of the call stack using its parent context.
0397   ///
0398   /// \param ADC        The AnalysisDeclContext.
0399   /// \param ParentLC   The parent context of this newly created context.
0400   /// \param S          The call.
0401   /// \param Block      The basic block.
0402   /// \param BlockCount The current count of entering into \p Blk.
0403   /// \param Index      The index of \p Blk.
0404   /// \returns The context for \p D with parent context \p ParentLC.
0405   const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
0406                                          const LocationContext *ParentLC,
0407                                          const Stmt *S, const CFGBlock *Block,
0408                                          unsigned BlockCount, unsigned Index);
0409 
0410   /// Obtain a context of the block invocation using its parent context.
0411   ///
0412   /// \param ADC      The AnalysisDeclContext.
0413   /// \param ParentLC The parent context of this newly created context.
0414   /// \param BD       The BlockDecl.
0415   /// \param Data     The raw data to store as part of the context.
0416   const BlockInvocationContext *
0417   getBlockInvocationContext(AnalysisDeclContext *ADC,
0418                             const LocationContext *ParentLC,
0419                             const BlockDecl *BD, const void *Data);
0420 
0421   /// Discard all previously created LocationContext objects.
0422   void clear();
0423 };
0424 
0425 class AnalysisDeclContextManager {
0426   using ContextMap =
0427       llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>;
0428 
0429   ContextMap Contexts;
0430   LocationContextManager LocCtxMgr;
0431   CFG::BuildOptions cfgBuildOptions;
0432 
0433   // Pointer to an interface that can provide function bodies for
0434   // declarations from external source.
0435   std::unique_ptr<CodeInjector> Injector;
0436 
0437   // A factory for creating and caching implementations for common
0438   // methods during the analysis.
0439   BodyFarm FunctionBodyFarm;
0440 
0441   // Flag to indicate whether or not bodies should be synthesized
0442   // for well-known functions.
0443   bool SynthesizeBodies;
0444 
0445 public:
0446   AnalysisDeclContextManager(
0447       ASTContext &ASTCtx, bool useUnoptimizedCFG = false,
0448       bool addImplicitDtors = false, bool addInitializers = false,
0449       bool addTemporaryDtors = false, bool addLifetime = false,
0450       bool addLoopExit = false, bool addScopes = false,
0451       bool synthesizeBodies = false, bool addStaticInitBranches = false,
0452       bool addCXXNewAllocator = true, bool addRichCXXConstructors = true,
0453       bool markElidedCXXConstructors = true, bool addVirtualBaseBranches = true,
0454       CodeInjector *injector = nullptr);
0455 
0456   AnalysisDeclContext *getContext(const Decl *D);
0457 
0458   bool getUseUnoptimizedCFG() const {
0459     return !cfgBuildOptions.PruneTriviallyFalseEdges;
0460   }
0461 
0462   CFG::BuildOptions &getCFGBuildOptions() { return cfgBuildOptions; }
0463 
0464   /// \returns Whether faux bodies should be synthesized for known functions.
0465   bool synthesizeBodies() const { return SynthesizeBodies; }
0466 
0467   /// Obtain the beginning context of the analysis.
0468   ///
0469   /// \returns The top level stack frame for \p D.
0470   const StackFrameContext *getStackFrame(const Decl *D) {
0471     return LocCtxMgr.getStackFrame(getContext(D), nullptr, nullptr, nullptr, 0,
0472                                    0);
0473   }
0474 
0475   /// \copydoc LocationContextManager::getStackFrame()
0476   const StackFrameContext *getStackFrame(AnalysisDeclContext *ADC,
0477                                          const LocationContext *Parent,
0478                                          const Stmt *S, const CFGBlock *Block,
0479                                          unsigned BlockCount, unsigned Index) {
0480     return LocCtxMgr.getStackFrame(ADC, Parent, S, Block, BlockCount, Index);
0481   }
0482 
0483   BodyFarm &getBodyFarm();
0484 
0485   /// Discard all previously created AnalysisDeclContexts.
0486   void clear();
0487 
0488 private:
0489   friend class AnalysisDeclContext;
0490 
0491   LocationContextManager &getLocationContextManager() { return LocCtxMgr; }
0492 };
0493 
0494 } // namespace clang
0495 
0496 #endif // LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H