Home | History | Annotate | Download | only in PathSensitive
      1 //== Store.h - Interface for maps from Locations to Values ------*- C++ -*--==//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file defined the types Store and StoreManager.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
     15 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
     16 
     17 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
     18 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
     19 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
     20 #include "llvm/ADT/DenseSet.h"
     21 
     22 namespace clang {
     23 
     24 class Stmt;
     25 class Expr;
     26 class ObjCIvarDecl;
     27 class CXXBasePath;
     28 class StackFrameContext;
     29 
     30 namespace ento {
     31 
     32 class CallEvent;
     33 class ProgramState;
     34 class ProgramStateManager;
     35 class ScanReachableSymbols;
     36 
     37 typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
     38 
     39 class StoreManager {
     40 protected:
     41   SValBuilder &svalBuilder;
     42   ProgramStateManager &StateMgr;
     43 
     44   /// MRMgr - Manages region objects associated with this StoreManager.
     45   MemRegionManager &MRMgr;
     46   ASTContext &Ctx;
     47 
     48   StoreManager(ProgramStateManager &stateMgr);
     49 
     50 public:
     51   virtual ~StoreManager() {}
     52 
     53   /// Return the value bound to specified location in a given state.
     54   /// \param[in] store The analysis state.
     55   /// \param[in] loc The symbolic memory location.
     56   /// \param[in] T An optional type that provides a hint indicating the
     57   ///   expected type of the returned value.  This is used if the value is
     58   ///   lazily computed.
     59   /// \return The value bound to the location \c loc.
     60   virtual SVal getBinding(Store store, Loc loc, QualType T = QualType()) = 0;
     61 
     62   /// Return the default value bound to a region in a given store. The default
     63   /// binding is the value of sub-regions that were not initialized separately
     64   /// from their base region. For example, if the structure is zero-initialized
     65   /// upon construction, this method retrieves the concrete zero value, even if
     66   /// some or all fields were later overwritten manually. Default binding may be
     67   /// an unknown, undefined, concrete, or symbolic value.
     68   /// \param[in] store The store in which to make the lookup.
     69   /// \param[in] R The region to find the default binding for.
     70   /// \return The default value bound to the region in the store, if a default
     71   /// binding exists.
     72   virtual Optional<SVal> getDefaultBinding(Store store, const MemRegion *R) = 0;
     73 
     74   /// Return the default value bound to a LazyCompoundVal. The default binding
     75   /// is used to represent the value of any fields or elements within the
     76   /// structure represented by the LazyCompoundVal which were not initialized
     77   /// explicitly separately from the whole structure. Default binding may be an
     78   /// unknown, undefined, concrete, or symbolic value.
     79   /// \param[in] lcv The lazy compound value.
     80   /// \return The default value bound to the LazyCompoundVal \c lcv, if a
     81   /// default binding exists.
     82   Optional<SVal> getDefaultBinding(nonloc::LazyCompoundVal lcv) {
     83     return getDefaultBinding(lcv.getStore(), lcv.getRegion());
     84   }
     85 
     86   /// Return a state with the specified value bound to the given location.
     87   /// \param[in] store The analysis state.
     88   /// \param[in] loc The symbolic memory location.
     89   /// \param[in] val The value to bind to location \c loc.
     90   /// \return A pointer to a ProgramState object that contains the same
     91   ///   bindings as \c state with the addition of having the value specified
     92   ///   by \c val bound to the location given for \c loc.
     93   virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0;
     94 
     95   virtual StoreRef BindDefault(Store store, const MemRegion *R, SVal V);
     96 
     97   /// \brief Create a new store with the specified binding removed.
     98   /// \param ST the original store, that is the basis for the new store.
     99   /// \param L the location whose binding should be removed.
    100   virtual StoreRef killBinding(Store ST, Loc L) = 0;
    101 
    102   /// getInitialStore - Returns the initial "empty" store representing the
    103   ///  value bindings upon entry to an analyzed function.
    104   virtual StoreRef getInitialStore(const LocationContext *InitLoc) = 0;
    105 
    106   /// getRegionManager - Returns the internal RegionManager object that is
    107   ///  used to query and manipulate MemRegion objects.
    108   MemRegionManager& getRegionManager() { return MRMgr; }
    109 
    110   virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) {
    111     return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
    112   }
    113 
    114   Loc getLValueCompoundLiteral(const CompoundLiteralExpr *CL,
    115                                const LocationContext *LC) {
    116     return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC));
    117   }
    118 
    119   virtual SVal getLValueIvar(const ObjCIvarDecl *decl, SVal base);
    120 
    121   virtual SVal getLValueField(const FieldDecl *D, SVal Base) {
    122     return getLValueFieldOrIvar(D, Base);
    123   }
    124 
    125   virtual SVal getLValueElement(QualType elementType, NonLoc offset, SVal Base);
    126 
    127   // FIXME: This should soon be eliminated altogether; clients should deal with
    128   // region extents directly.
    129   virtual DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,
    130                                                  const MemRegion *region,
    131                                                  QualType EleTy) {
    132     return UnknownVal();
    133   }
    134 
    135   /// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit
    136   ///  conversions between arrays and pointers.
    137   virtual SVal ArrayToPointer(Loc Array, QualType ElementTy) = 0;
    138 
    139   /// Evaluates a chain of derived-to-base casts through the path specified in
    140   /// \p Cast.
    141   SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast);
    142 
    143   /// Evaluates a chain of derived-to-base casts through the specified path.
    144   SVal evalDerivedToBase(SVal Derived, const CXXBasePath &CastPath);
    145 
    146   /// Evaluates a derived-to-base cast through a single level of derivation.
    147   SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType,
    148                          bool IsVirtual);
    149 
    150   /// \brief Attempts to do a down cast. Used to model BaseToDerived and C++
    151   ///        dynamic_cast.
    152   /// The callback may result in the following 3 scenarios:
    153   ///  - Successful cast (ex: derived is subclass of base).
    154   ///  - Failed cast (ex: derived is definitely not a subclass of base).
    155   ///    The distinction of this case from the next one is necessary to model
    156   ///    dynamic_cast.
    157   ///  - We don't know (base is a symbolic region and we don't have
    158   ///    enough info to determine if the cast will succeed at run time).
    159   /// The function returns an SVal representing the derived class; it's
    160   /// valid only if Failed flag is set to false.
    161   SVal attemptDownCast(SVal Base, QualType DerivedPtrType, bool &Failed);
    162 
    163   const ElementRegion *GetElementZeroRegion(const SubRegion *R, QualType T);
    164 
    165   /// castRegion - Used by ExprEngine::VisitCast to handle casts from
    166   ///  a MemRegion* to a specific location type.  'R' is the region being
    167   ///  casted and 'CastToTy' the result type of the cast.
    168   const MemRegion *castRegion(const MemRegion *region, QualType CastToTy);
    169 
    170   virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
    171                                       SymbolReaper& SymReaper) = 0;
    172 
    173   virtual bool includedInBindings(Store store,
    174                                   const MemRegion *region) const = 0;
    175 
    176   /// If the StoreManager supports it, increment the reference count of
    177   /// the specified Store object.
    178   virtual void incrementReferenceCount(Store store) {}
    179 
    180   /// If the StoreManager supports it, decrement the reference count of
    181   /// the specified Store object.  If the reference count hits 0, the memory
    182   /// associated with the object is recycled.
    183   virtual void decrementReferenceCount(Store store) {}
    184 
    185   typedef SmallVector<const MemRegion *, 8> InvalidatedRegions;
    186 
    187   /// invalidateRegions - Clears out the specified regions from the store,
    188   ///  marking their values as unknown. Depending on the store, this may also
    189   ///  invalidate additional regions that may have changed based on accessing
    190   ///  the given regions. Optionally, invalidates non-static globals as well.
    191   /// \param[in] store The initial store
    192   /// \param[in] Values The values to invalidate.
    193   /// \param[in] E The current statement being evaluated. Used to conjure
    194   ///   symbols to mark the values of invalidated regions.
    195   /// \param[in] Count The current block count. Used to conjure
    196   ///   symbols to mark the values of invalidated regions.
    197   /// \param[in] Call The call expression which will be used to determine which
    198   ///   globals should get invalidated.
    199   /// \param[in,out] IS A set to fill with any symbols that are no longer
    200   ///   accessible. Pass \c NULL if this information will not be used.
    201   /// \param[in] ITraits Information about invalidation for a particular
    202   ///   region/symbol.
    203   /// \param[in,out] InvalidatedTopLevel A vector to fill with regions
    204   ////  explicitly being invalidated. Pass \c NULL if this
    205   ///   information will not be used.
    206   /// \param[in,out] Invalidated A vector to fill with any regions being
    207   ///   invalidated. This should include any regions explicitly invalidated
    208   ///   even if they do not currently have bindings. Pass \c NULL if this
    209   ///   information will not be used.
    210   virtual StoreRef invalidateRegions(Store store,
    211                                   ArrayRef<SVal> Values,
    212                                   const Expr *E, unsigned Count,
    213                                   const LocationContext *LCtx,
    214                                   const CallEvent *Call,
    215                                   InvalidatedSymbols &IS,
    216                                   RegionAndSymbolInvalidationTraits &ITraits,
    217                                   InvalidatedRegions *InvalidatedTopLevel,
    218                                   InvalidatedRegions *Invalidated) = 0;
    219 
    220   /// enterStackFrame - Let the StoreManager to do something when execution
    221   /// engine is about to execute into a callee.
    222   StoreRef enterStackFrame(Store store,
    223                            const CallEvent &Call,
    224                            const StackFrameContext *CalleeCtx);
    225 
    226   /// Finds the transitive closure of symbols within the given region.
    227   ///
    228   /// Returns false if the visitor aborted the scan.
    229   virtual bool scanReachableSymbols(Store S, const MemRegion *R,
    230                                     ScanReachableSymbols &Visitor) = 0;
    231 
    232   virtual void print(Store store, raw_ostream &Out,
    233                      const char* nl, const char *sep) = 0;
    234 
    235   class BindingsHandler {
    236   public:
    237     virtual ~BindingsHandler();
    238     virtual bool HandleBinding(StoreManager& SMgr, Store store,
    239                                const MemRegion *region, SVal val) = 0;
    240   };
    241 
    242   class FindUniqueBinding :
    243   public BindingsHandler {
    244     SymbolRef Sym;
    245     const MemRegion* Binding;
    246     bool First;
    247 
    248   public:
    249     FindUniqueBinding(SymbolRef sym)
    250       : Sym(sym), Binding(nullptr), First(true) {}
    251 
    252     bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
    253                        SVal val) override;
    254     explicit operator bool() { return First && Binding; }
    255     const MemRegion *getRegion() { return Binding; }
    256   };
    257 
    258   /// iterBindings - Iterate over the bindings in the Store.
    259   virtual void iterBindings(Store store, BindingsHandler& f) = 0;
    260 
    261 protected:
    262   const ElementRegion *MakeElementRegion(const SubRegion *baseRegion,
    263                                          QualType pointeeTy,
    264                                          uint64_t index = 0);
    265 
    266   /// CastRetrievedVal - Used by subclasses of StoreManager to implement
    267   ///  implicit casts that arise from loads from regions that are reinterpreted
    268   ///  as another region.
    269   SVal CastRetrievedVal(SVal val, const TypedValueRegion *region,
    270                         QualType castTy, bool performTestOnly = true);
    271 
    272 private:
    273   SVal getLValueFieldOrIvar(const Decl *decl, SVal base);
    274 };
    275 
    276 
    277 inline StoreRef::StoreRef(Store store, StoreManager & smgr)
    278   : store(store), mgr(smgr) {
    279   if (store)
    280     mgr.incrementReferenceCount(store);
    281 }
    282 
    283 inline StoreRef::StoreRef(const StoreRef &sr)
    284   : store(sr.store), mgr(sr.mgr)
    285 {
    286   if (store)
    287     mgr.incrementReferenceCount(store);
    288 }
    289 
    290 inline StoreRef::~StoreRef() {
    291   if (store)
    292     mgr.decrementReferenceCount(store);
    293 }
    294 
    295 inline StoreRef &StoreRef::operator=(StoreRef const &newStore) {
    296   assert(&newStore.mgr == &mgr);
    297   if (store != newStore.store) {
    298     mgr.incrementReferenceCount(newStore.store);
    299     mgr.decrementReferenceCount(store);
    300     store = newStore.getStore();
    301   }
    302   return *this;
    303 }
    304 
    305 // FIXME: Do we need to pass ProgramStateManager anymore?
    306 std::unique_ptr<StoreManager>
    307 CreateRegionStoreManager(ProgramStateManager &StMgr);
    308 std::unique_ptr<StoreManager>
    309 CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr);
    310 
    311 } // end GR namespace
    312 
    313 } // end clang namespace
    314 
    315 #endif
    316