Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:09

0001 //===- Store.h - Interface for maps from Locations to Values ----*- 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 //  This file defined the types Store and StoreManager.
0010 //
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
0014 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
0015 
0016 #include "clang/AST/Type.h"
0017 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
0018 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
0019 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
0020 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
0021 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
0022 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
0023 #include "clang/Basic/LLVM.h"
0024 #include "llvm/ADT/ArrayRef.h"
0025 #include "llvm/ADT/DenseSet.h"
0026 #include "llvm/ADT/SmallVector.h"
0027 #include <cassert>
0028 #include <cstdint>
0029 #include <memory>
0030 #include <optional>
0031 
0032 namespace clang {
0033 
0034 class ASTContext;
0035 class CastExpr;
0036 class CompoundLiteralExpr;
0037 class CXXBasePath;
0038 class Decl;
0039 class Expr;
0040 class LocationContext;
0041 class ObjCIvarDecl;
0042 class StackFrameContext;
0043 
0044 namespace ento {
0045 
0046 class CallEvent;
0047 class ProgramStateManager;
0048 class ScanReachableSymbols;
0049 class SymbolReaper;
0050 
0051 using InvalidatedSymbols = llvm::DenseSet<SymbolRef>;
0052 
0053 class StoreManager {
0054 protected:
0055   SValBuilder &svalBuilder;
0056   ProgramStateManager &StateMgr;
0057 
0058   /// MRMgr - Manages region objects associated with this StoreManager.
0059   MemRegionManager &MRMgr;
0060   ASTContext &Ctx;
0061 
0062   StoreManager(ProgramStateManager &stateMgr);
0063 
0064 public:
0065   virtual ~StoreManager() = default;
0066 
0067   /// Return the value bound to specified location in a given state.
0068   /// \param[in] store The store in which to make the lookup.
0069   /// \param[in] loc The symbolic memory location.
0070   /// \param[in] T An optional type that provides a hint indicating the
0071   ///   expected type of the returned value.  This is used if the value is
0072   ///   lazily computed.
0073   /// \return The value bound to the location \c loc.
0074   virtual SVal getBinding(Store store, Loc loc, QualType T = QualType()) = 0;
0075 
0076   /// Return the default value bound to a region in a given store. The default
0077   /// binding is the value of sub-regions that were not initialized separately
0078   /// from their base region. For example, if the structure is zero-initialized
0079   /// upon construction, this method retrieves the concrete zero value, even if
0080   /// some or all fields were later overwritten manually. Default binding may be
0081   /// an unknown, undefined, concrete, or symbolic value.
0082   /// \param[in] store The store in which to make the lookup.
0083   /// \param[in] R The region to find the default binding for.
0084   /// \return The default value bound to the region in the store, if a default
0085   /// binding exists.
0086   virtual std::optional<SVal> getDefaultBinding(Store store,
0087                                                 const MemRegion *R) = 0;
0088 
0089   /// Return the default value bound to a LazyCompoundVal. The default binding
0090   /// is used to represent the value of any fields or elements within the
0091   /// structure represented by the LazyCompoundVal which were not initialized
0092   /// explicitly separately from the whole structure. Default binding may be an
0093   /// unknown, undefined, concrete, or symbolic value.
0094   /// \param[in] lcv The lazy compound value.
0095   /// \return The default value bound to the LazyCompoundVal \c lcv, if a
0096   /// default binding exists.
0097   std::optional<SVal> getDefaultBinding(nonloc::LazyCompoundVal lcv) {
0098     return getDefaultBinding(lcv.getStore(), lcv.getRegion());
0099   }
0100 
0101   /// Return a store with the specified value bound to the given location.
0102   /// \param[in] store The store in which to make the binding.
0103   /// \param[in] loc The symbolic memory location.
0104   /// \param[in] val The value to bind to location \c loc.
0105   /// \return A StoreRef object that contains the same
0106   ///   bindings as \c store with the addition of having the value specified
0107   ///   by \c val bound to the location given for \c loc.
0108   virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0;
0109 
0110   /// Return a store with the specified value bound to all sub-regions of the
0111   /// region. The region must not have previous bindings. If you need to
0112   /// invalidate existing bindings, consider invalidateRegions().
0113   virtual StoreRef BindDefaultInitial(Store store, const MemRegion *R,
0114                                       SVal V) = 0;
0115 
0116   /// Return a store with in which all values within the given region are
0117   /// reset to zero. This method is allowed to overwrite previous bindings.
0118   virtual StoreRef BindDefaultZero(Store store, const MemRegion *R) = 0;
0119 
0120   /// Create a new store with the specified binding removed.
0121   /// \param ST the original store, that is the basis for the new store.
0122   /// \param L the location whose binding should be removed.
0123   virtual StoreRef killBinding(Store ST, Loc L) = 0;
0124 
0125   /// getInitialStore - Returns the initial "empty" store representing the
0126   ///  value bindings upon entry to an analyzed function.
0127   virtual StoreRef getInitialStore(const LocationContext *InitLoc) = 0;
0128 
0129   /// getRegionManager - Returns the internal RegionManager object that is
0130   ///  used to query and manipulate MemRegion objects.
0131   MemRegionManager& getRegionManager() { return MRMgr; }
0132 
0133   SValBuilder& getSValBuilder() { return svalBuilder; }
0134 
0135   virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) {
0136     return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
0137   }
0138 
0139   Loc getLValueCompoundLiteral(const CompoundLiteralExpr *CL,
0140                                const LocationContext *LC) {
0141     return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC));
0142   }
0143 
0144   virtual SVal getLValueIvar(const ObjCIvarDecl *decl, SVal base);
0145 
0146   virtual SVal getLValueField(const FieldDecl *D, SVal Base) {
0147     return getLValueFieldOrIvar(D, Base);
0148   }
0149 
0150   virtual SVal getLValueElement(QualType elementType, NonLoc offset, SVal Base);
0151 
0152   /// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit
0153   ///  conversions between arrays and pointers.
0154   virtual SVal ArrayToPointer(Loc Array, QualType ElementTy) = 0;
0155 
0156   /// Evaluates a chain of derived-to-base casts through the path specified in
0157   /// \p Cast.
0158   SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast);
0159 
0160   /// Evaluates a chain of derived-to-base casts through the specified path.
0161   SVal evalDerivedToBase(SVal Derived, const CXXBasePath &CastPath);
0162 
0163   /// Evaluates a derived-to-base cast through a single level of derivation.
0164   SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType,
0165                          bool IsVirtual);
0166 
0167   /// Attempts to do a down cast. Used to model BaseToDerived and C++
0168   ///        dynamic_cast.
0169   /// The callback may result in the following 3 scenarios:
0170   ///  - Successful cast (ex: derived is subclass of base).
0171   ///  - Failed cast (ex: derived is definitely not a subclass of base).
0172   ///    The distinction of this case from the next one is necessary to model
0173   ///    dynamic_cast.
0174   ///  - We don't know (base is a symbolic region and we don't have
0175   ///    enough info to determine if the cast will succeed at run time).
0176   /// The function returns an optional with SVal representing the derived class
0177   /// in case of a successful cast and `std::nullopt` otherwise.
0178   std::optional<SVal> evalBaseToDerived(SVal Base, QualType DerivedPtrType);
0179 
0180   const ElementRegion *GetElementZeroRegion(const SubRegion *R, QualType T);
0181 
0182   /// castRegion - Used by ExprEngine::VisitCast to handle casts from
0183   ///  a MemRegion* to a specific location type.  'R' is the region being
0184   ///  casted and 'CastToTy' the result type of the cast.
0185   std::optional<const MemRegion *> castRegion(const MemRegion *region,
0186                                               QualType CastToTy);
0187 
0188   virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
0189                                       SymbolReaper &SymReaper) = 0;
0190 
0191   virtual bool includedInBindings(Store store,
0192                                   const MemRegion *region) const = 0;
0193 
0194   /// If the StoreManager supports it, increment the reference count of
0195   /// the specified Store object.
0196   virtual void incrementReferenceCount(Store store) {}
0197 
0198   /// If the StoreManager supports it, decrement the reference count of
0199   /// the specified Store object.  If the reference count hits 0, the memory
0200   /// associated with the object is recycled.
0201   virtual void decrementReferenceCount(Store store) {}
0202 
0203   using InvalidatedRegions = SmallVector<const MemRegion *, 8>;
0204 
0205   /// invalidateRegions - Clears out the specified regions from the store,
0206   ///  marking their values as unknown. Depending on the store, this may also
0207   ///  invalidate additional regions that may have changed based on accessing
0208   ///  the given regions. If \p Call is non-null, then this also invalidates
0209   ///  non-static globals (but if \p Call is from a system header, then this is
0210   ///  limited to globals declared in system headers).
0211   ///
0212   /// Instead of calling this method directly, you should probably use
0213   /// \c ProgramState::invalidateRegions, which calls this and then ensures that
0214   /// the relevant checker callbacks are triggered.
0215   ///
0216   /// \param[in] store The initial store.
0217   /// \param[in] Values The values to invalidate.
0218   /// \param[in] S The current statement being evaluated. Used to conjure
0219   ///   symbols to mark the values of invalidated regions.
0220   /// \param[in] Count The current block count. Used to conjure
0221   ///   symbols to mark the values of invalidated regions.
0222   /// \param[in] Call The call expression which will be used to determine which
0223   ///   globals should get invalidated.
0224   /// \param[in,out] IS A set to fill with any symbols that are no longer
0225   ///   accessible. Pass \c NULL if this information will not be used.
0226   /// \param[in] ITraits Information about invalidation for a particular
0227   ///   region/symbol.
0228   /// \param[in,out] InvalidatedTopLevel A vector to fill with regions
0229   ////  explicitly being invalidated. Pass \c NULL if this
0230   ///   information will not be used.
0231   /// \param[in,out] Invalidated A vector to fill with any regions being
0232   ///   invalidated. This should include any regions explicitly invalidated
0233   ///   even if they do not currently have bindings. Pass \c NULL if this
0234   ///   information will not be used.
0235   virtual StoreRef invalidateRegions(
0236       Store store, ArrayRef<SVal> Values, const Stmt *S, unsigned Count,
0237       const LocationContext *LCtx, const CallEvent *Call,
0238       InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits,
0239       InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) = 0;
0240 
0241   /// enterStackFrame - Let the StoreManager to do something when execution
0242   /// engine is about to execute into a callee.
0243   StoreRef enterStackFrame(Store store,
0244                            const CallEvent &Call,
0245                            const StackFrameContext *CalleeCtx);
0246 
0247   /// Finds the transitive closure of symbols within the given region.
0248   ///
0249   /// Returns false if the visitor aborted the scan.
0250   virtual bool scanReachableSymbols(Store S, const MemRegion *R,
0251                                     ScanReachableSymbols &Visitor) = 0;
0252 
0253   virtual void printJson(raw_ostream &Out, Store S, const char *NL,
0254                          unsigned int Space, bool IsDot) const = 0;
0255 
0256   class BindingsHandler {
0257   public:
0258     virtual ~BindingsHandler();
0259 
0260     /// \return whether the iteration should continue.
0261     virtual bool HandleBinding(StoreManager& SMgr, Store store,
0262                                const MemRegion *region, SVal val) = 0;
0263   };
0264 
0265   class FindUniqueBinding : public BindingsHandler {
0266     SymbolRef Sym;
0267     const MemRegion* Binding = nullptr;
0268     bool First = true;
0269 
0270   public:
0271     FindUniqueBinding(SymbolRef sym) : Sym(sym) {}
0272 
0273     explicit operator bool() { return First && Binding; }
0274 
0275     bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
0276                        SVal val) override;
0277     const MemRegion *getRegion() { return Binding; }
0278   };
0279 
0280   /// iterBindings - Iterate over the bindings in the Store.
0281   virtual void iterBindings(Store store, BindingsHandler& f) = 0;
0282 
0283 protected:
0284   const ElementRegion *MakeElementRegion(const SubRegion *baseRegion,
0285                                          QualType pointeeTy,
0286                                          uint64_t index = 0);
0287 
0288 private:
0289   SVal getLValueFieldOrIvar(const Decl *decl, SVal base);
0290 };
0291 
0292 inline StoreRef::StoreRef(Store store, StoreManager & smgr)
0293     : store(store), mgr(smgr) {
0294   if (store)
0295     mgr.incrementReferenceCount(store);
0296 }
0297 
0298 inline StoreRef::StoreRef(const StoreRef &sr)
0299     : store(sr.store), mgr(sr.mgr)
0300 {
0301   if (store)
0302     mgr.incrementReferenceCount(store);
0303 }
0304 
0305 inline StoreRef::~StoreRef() {
0306   if (store)
0307     mgr.decrementReferenceCount(store);
0308 }
0309 
0310 inline StoreRef &StoreRef::operator=(StoreRef const &newStore) {
0311   assert(&newStore.mgr == &mgr);
0312   if (store != newStore.store) {
0313     mgr.incrementReferenceCount(newStore.store);
0314     mgr.decrementReferenceCount(store);
0315     store = newStore.getStore();
0316   }
0317   return *this;
0318 }
0319 
0320 // FIXME: Do we need to pass ProgramStateManager anymore?
0321 std::unique_ptr<StoreManager>
0322 CreateRegionStoreManager(ProgramStateManager &StMgr);
0323 
0324 } // namespace ento
0325 
0326 } // namespace clang
0327 
0328 #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H