text: //== RegionStore.cpp - Field-sensitive store model --------------*- C++ -*--==//
  //
  //                     The LLVM Compiler Infrastructure
  //
  // This file is distributed under the University of Illinois Open Source
  // License. See LICENSE.TXT for details.
  //
  //===----------------------------------------------------------------------===//
  //
  // This file defines a basic region store model. In this model, we do have field
  // sensitivity. But we assume nothing about the heap shape. So recursive data
  // structures are largely ignored. Basically we do 1-limiting analysis.
  // Parameter pointers are assumed with no aliasing. Pointee objects of
  // parameters are created lazily.
  //
  //===----------------------------------------------------------------------===//
  
  #include "clang/AST/Attr.h"
  #include "clang/AST/CharUnits.h"
  #include "clang/Analysis/Analyses/LiveVariables.h"
  #include "clang/Analysis/AnalysisContext.h"
  #include "clang/Basic/TargetInfo.h"
  #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
  #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
  #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
  #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
  #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
  #include "llvm/ADT/ImmutableMap.h"
  #include "llvm/ADT/Optional.h"
  #include "llvm/Support/raw_ostream.h"
  #include <utility>
  
  using namespace clang;
  using namespace ento;
  
  //===----------------------------------------------------------------------===//
  // Representation of binding keys.
  //===----------------------------------------------------------------------===//
  
  namespace {
  class BindingKey {
  public:
    enum Kind { Default = 0x0, Direct = 0x1 };
  private:
    enum { Symbolic = 0x2 };
  
    llvm::PointerIntPair<const MemRegion *, 2> P;
    uint64_t Data;
  
    /// Create a key for a binding to region \p r, which has a symbolic offset
    /// from region \p Base.
    explicit BindingKey(const SubRegion *r, const SubRegion *Base, Kind k)
      : P(r, k | Symbolic), Data(reinterpret_cast<uintptr_t>(Base)) {
      assert(r && Base && "Must have known regions.");
      assert(getConcreteOffsetRegion() == Base && "Failed to store base region");
    }
  
    /// Create a key for a binding at \p offset from base region \p r.
    explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
      : P(r, k), Data(offset) {
      assert(r && "Must have known regions.");
      assert(getOffset() == offset && "Failed to store offset");
      assert((r == r->getBaseRegion() || isa<ObjCIvarRegion>(r)) && "Not a base");
    }
  public:
  
    bool isDirect() const { return P.getInt() & Direct; }
    bool hasSymbolicOffset() const { return P.getInt() & Symbolic; }
  
    const MemRegion *getRegion() const { return P.getPointer(); }
    uint64_t getOffset() const {
      assert(!hasSymbolicOffset());
      return Data;
    }
  
    const SubRegion *getConcreteOffsetRegion() const {
      assert(hasSymbolicOffset());
      return reinterpret_cast<const SubRegion *>(static_cast<uintptr_t>(Data));
    }
  
    const MemRegion *getBaseRegion() const {
      if (hasSymbolicOffset())
        return getConcreteOffsetRegion()->getBaseRegion();
      return getRegion()->getBaseRegion();
    }
  
    void Profile(llvm::FoldingSetNodeID& ID) const {
      ID.AddPointer(P.getOpaqueValue());
      ID.AddInteger(Data);
    }
  
    static BindingKey Make(const MemRegion *R, Kind k);
  
    bool operator<(const BindingKey &X) const {
      if (P.getOpaqueValue() < X.P.getOpaqueValue())
        return true;
      if (P.getOpaqueValue() > X.P.getOpaqueValue())
        return false;
      return Data < X.Data;
    }
  
    bool operator==(const BindingKey &X) const {
      return P.getOpaqueValue() == X.P.getOpaqueValue() &&
             Data == X.Data;
    }
  
    void dump() const;
  };
  } // end anonymous namespace
  
  BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
    const RegionOffset &RO = R->getAsOffset();
    if (RO.hasSymbolicOffset())
      return BindingKey(cast<SubRegion>(R), cast<SubRegion>(RO.getRegion()), k);
  
    return BindingKey(RO.getRegion(), RO.getOffset(), k);
  }
  
  namespace llvm {
    static inline
    raw_ostream &operator<<(raw_ostream &os, BindingKey K) {
      os << '(' << K.getRegion();
      if (!K.hasSymbolicOffset())
        os << ',' << K.getOffset();
      os << ',' << (K.isDirect() ? "direct" : "default")
         << ')';
      return os;
    }
  
    template <typename T> struct isPodLike;
    template <> struct isPodLike<BindingKey> {
      static const bool value = true;
    };
  } // end llvm namespace
  
  LLVM_DUMP_METHOD void BindingKey::dump() const { llvm::errs() << *this; }
  
  //===----------------------------------------------------------------------===//
  // Actual Store type.
  //===----------------------------------------------------------------------===//
  
  typedef llvm::ImmutableMap<BindingKey, SVal>    ClusterBindings;
  typedef llvm::ImmutableMapRef<BindingKey, SVal> ClusterBindingsRef;
  typedef std::pair<BindingKey, SVal> BindingPair;
  
  typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
          RegionBindings;
  
  namespace {
  class RegionBindingsRef : public llvm::ImmutableMapRef<const MemRegion *,
                                   ClusterBindings> {
    ClusterBindings::Factory *CBFactory;
  
  public:
    typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
            ParentTy;
  
    RegionBindingsRef(ClusterBindings::Factory &CBFactory,
                      const RegionBindings::TreeTy *T,
                      RegionBindings::TreeTy::Factory *F)
        : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(T, F),
          CBFactory(&CBFactory) {}
  
    RegionBindingsRef(const ParentTy &P, ClusterBindings::Factory &CBFactory)
        : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(P),
          CBFactory(&CBFactory) {}
  
    RegionBindingsRef add(key_type_ref K, data_type_ref D) const {
      return RegionBindingsRef(static_cast<const ParentTy *>(this)->add(K, D),
                               *CBFactory);
    }
  
    RegionBindingsRef remove(key_type_ref K) const {
      return RegionBindingsRef(static_cast<const ParentTy *>(this)->remove(K),
                               *CBFactory);
    }
  
    RegionBindingsRef addBinding(BindingKey K, SVal V) const;
  
    RegionBindingsRef addBinding(const MemRegion *R,
                                 BindingKey::Kind k, SVal V) const;
  
    const SVal *lookup(BindingKey K) const;
    const SVal *lookup(const MemRegion *R, BindingKey::Kind k) const;
    using llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>::lookup;
  
    RegionBindingsRef removeBinding(BindingKey K);
  
    RegionBindingsRef removeBinding(const MemRegion *R,
                                    BindingKey::Kind k);
  
    RegionBindingsRef removeBinding(const MemRegion *R) {
      return removeBinding(R, BindingKey::Direct).
             removeBinding(R, BindingKey::Default);
    }
  
    Optional<SVal> getDirectBinding(const MemRegion *R) const;
  
    /// getDefaultBinding - Returns an SVal* representing an optional default
    ///  binding associated with a region and its subregions.
    Optional<SVal> getDefaultBinding(const MemRegion *R) const;
  
    /// Return the internal tree as a Store.
    Store asStore() const {
      return asImmutableMap().getRootWithoutRetain();
    }
  
    void dump(raw_ostream &OS, const char *nl) const {
     for (iterator I = begin(), E = end(); I != E; ++I) {
       const ClusterBindings &Cluster = I.getData();
       for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
            CI != CE; ++CI) {
         OS << ' ' << CI.getKey() << " : " << CI.getData() << nl;
       }
       OS << nl;
     }
    }
  
    LLVM_DUMP_METHOD void dump() const { dump(llvm::errs(), "\n"); }
  };
  } // end anonymous namespace
  
  typedef const RegionBindingsRef& RegionBindingsConstRef;
  
  Optional<SVal> RegionBindingsRef::getDirectBinding(const MemRegion *R) const {
    return Optional<SVal>::create(lookup(R, BindingKey::Direct));
  }
  
  Optional<SVal> RegionBindingsRef::getDefaultBinding(const MemRegion *R) const {
    if (R->isBoundable())
      if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R))
        if (TR->getValueType()->isUnionType())
          return UnknownVal();
  
    return Optional<SVal>::create(lookup(R, BindingKey::Default));
  }
  
  RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K, SVal V) const {
    const MemRegion *Base = K.getBaseRegion();
  
    const ClusterBindings *ExistingCluster = lookup(Base);
    ClusterBindings Cluster =
        (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
  
    ClusterBindings NewCluster = CBFactory->add(Cluster, K, V);
    return add(Base, NewCluster);
  }
  
  
  RegionBindingsRef RegionBindingsRef::addBinding(const MemRegion *R,
                                                  BindingKey::Kind k,
                                                  SVal V) const {
    return addBinding(BindingKey::Make(R, k), V);
  }
  
  const SVal *RegionBindingsRef::lookup(BindingKey K) const {
    const ClusterBindings *Cluster = lookup(K.getBaseRegion());
    if (!Cluster)
      return nullptr;
    return Cluster->lookup(K);
  }
  
  const SVal *RegionBindingsRef::lookup(const MemRegion *R,
                                        BindingKey::Kind k) const {
    return lookup(BindingKey::Make(R, k));
  }
  
  RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
    const MemRegion *Base = K.getBaseRegion();
    const ClusterBindings *Cluster = lookup(Base);
    if (!Cluster)
      return *this;
  
    ClusterBindings NewCluster = CBFactory->remove(*Cluster, K);
    if (NewCluster.isEmpty())
      return remove(Base);
    return add(Base, NewCluster);
  }
  
  RegionBindingsRef RegionBindingsRef::removeBinding(const MemRegion *R,
                                                  BindingKey::Kind k){
    return removeBinding(BindingKey::Make(R, k));
  }
  
  //===----------------------------------------------------------------------===//
  // Fine-grained control of RegionStoreManager.
  //===----------------------------------------------------------------------===//
  
  namespace {
  struct minimal_features_tag {};
  struct maximal_features_tag {};
  
  class RegionStoreFeatures {
    bool SupportsFields;
  public:
    RegionStoreFeatures(minimal_features_tag) :
      SupportsFields(false) {}
  
    RegionStoreFeatures(maximal_features_tag) :
      SupportsFields(true) {}
  
    void enableFields(bool t) { SupportsFields = t; }
  
    bool supportsFields() const { return SupportsFields; }
  };
  }
  
  //===----------------------------------------------------------------------===//
  // Main RegionStore logic.
  //===----------------------------------------------------------------------===//
  
  namespace {
  class invalidateRegionsWorker;
  
  class RegionStoreManager : public StoreManager {
  public:
    const RegionStoreFeatures Features;
  
    RegionBindings::Factory RBFactory;
    mutable ClusterBindings::Factory CBFactory;
  
    typedef std::vector<SVal> SValListTy;
  private:
    typedef llvm::DenseMap<const LazyCompoundValData *,
                           SValListTy> LazyBindingsMapTy;
    LazyBindingsMapTy LazyBindingsMap;
  
    /// The largest number of fields a struct can have and still be
    /// considered "small".
    ///
    /// This is currently used to decide whether or not it is worth "forcing" a
    /// LazyCompoundVal on bind.
    ///
    /// This is controlled by 'region-store-small-struct-limit' option.
    /// To disable all small-struct-dependent behavior, set the option to "0".
    unsigned SmallStructLimit;
  
    /// \brief A helper used to populate the work list with the given set of
    /// regions.
    void populateWorkList(invalidateRegionsWorker &W,
                          ArrayRef<SVal> Values,
                          InvalidatedRegions *TopLevelRegions);
  
  public:
    RegionStoreManager(ProgramStateManager& mgr, const RegionStoreFeatures &f)
      : StoreManager(mgr), Features(f),
        RBFactory(mgr.getAllocator()), CBFactory(mgr.getAllocator()),
        SmallStructLimit(0) {
      if (SubEngine *Eng = StateMgr.getOwningEngine()) {
        AnalyzerOptions &Options = Eng->getAnalysisManager().options;
        SmallStructLimit =
          Options.getOptionAsInteger("region-store-small-struct-limit", 2);
      }
    }
  
  
    /// setImplicitDefaultValue - Set the default binding for the provided
    ///  MemRegion to the value implicitly defined for compound literals when
    ///  the value is not specified.
    RegionBindingsRef setImplicitDefaultValue(RegionBindingsConstRef B,
                                              const MemRegion *R, QualType T);
  
    /// ArrayToPointer - Emulates the "decay" of an array to a pointer
    ///  type.  'Array' represents the lvalue of the array being decayed
    ///  to a pointer, and the returned SVal represents the decayed
    ///  version of that lvalue (i.e., a pointer to the first element of
    ///  the array).  This is called by ExprEngine when evaluating
    ///  casts from arrays to pointers.
    SVal ArrayToPointer(Loc Array, QualType ElementTy) override;
  
    StoreRef getInitialStore(const LocationContext *InitLoc) override {
      return StoreRef(RBFactory.getEmptyMap().getRootWithoutRetain(), *this);
    }
  
    //===-------------------------------------------------------------------===//
    // Binding values to regions.
    //===-------------------------------------------------------------------===//
    RegionBindingsRef invalidateGlobalRegion(MemRegion::Kind K,
                                             const Expr *Ex,
                                             unsigned Count,
                                             const LocationContext *LCtx,
                                             RegionBindingsRef B,
                                             InvalidatedRegions *Invalidated);
  
    StoreRef invalidateRegions(Store store,
                               ArrayRef<SVal> Values,
                               const Expr *E, unsigned Count,
                               const LocationContext *LCtx,
                               const CallEvent *Call,
                               InvalidatedSymbols &IS,
                               RegionAndSymbolInvalidationTraits &ITraits,
                               InvalidatedRegions *Invalidated,
                               InvalidatedRegions *InvalidatedTopLevel) override;
  
    bool scanReachableSymbols(Store S, const MemRegion *R,
                              ScanReachableSymbols &Callbacks) override;
  
    RegionBindingsRef removeSubRegionBindings(RegionBindingsConstRef B,
                                              const SubRegion *R);
  
  public: // Part of public interface to class.
  
    StoreRef Bind(Store store, Loc LV, SVal V) override {
      return StoreRef(bind(getRegionBindings(store), LV, V).asStore(), *this);
    }
  
    RegionBindingsRef bind(RegionBindingsConstRef B, Loc LV, SVal V);
  
    // BindDefault is only used to initialize a region with a default value.
    StoreRef BindDefault(Store store, const MemRegion *R, SVal V) override {
      RegionBindingsRef B = getRegionBindings(store);
      assert(!B.lookup(R, BindingKey::Direct));
  
      BindingKey Key = BindingKey::Make(R, BindingKey::Default);
      if (B.lookup(Key)) {
        const SubRegion *SR = cast<SubRegion>(R);
        assert(SR->getAsOffset().getOffset() ==
               SR->getSuperRegion()->getAsOffset().getOffset() &&
               "A default value must come from a super-region");
        B = removeSubRegionBindings(B, SR);
      } else {
        B = B.addBinding(Key, V);
      }
  
      return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);
    }
  
    /// Attempt to extract the fields of \p LCV and bind them to the struct region
    /// \p R.
    ///
    /// This path is used when it seems advantageous to "force" loading the values
    /// within a LazyCompoundVal to bind memberwise to the struct region, rather
    /// than using a Default binding at the base of the entire region. This is a
    /// heuristic attempting to avoid building long chains of LazyCompoundVals.
    ///
    /// \returns The updated store bindings, or \c None if binding non-lazily
    ///          would be too expensive.
    Optional<RegionBindingsRef> tryBindSmallStruct(RegionBindingsConstRef B,
                                                   const TypedValueRegion *R,
                                                   const RecordDecl *RD,
                                                   nonloc::LazyCompoundVal LCV);
  
    /// BindStruct - Bind a compound value to a structure.
    RegionBindingsRef bindStruct(RegionBindingsConstRef B,
                                 const TypedValueRegion* R, SVal V);
  
    /// BindVector - Bind a compound value to a vector.
    RegionBindingsRef bindVector(RegionBindingsConstRef B,
                                 const TypedValueRegion* R, SVal V);
  
    RegionBindingsRef bindArray(RegionBindingsConstRef B,
                                const TypedValueRegion* R,
                                SVal V);
  
    /// Clears out all bindings in the given region and assigns a new value
    /// as a Default binding.
    RegionBindingsRef bindAggregate(RegionBindingsConstRef B,
                                    const TypedRegion *R,
                                    SVal DefaultVal);
  
    /// \brief Create a new store with the specified binding removed.
    /// \param ST the original store, that is the basis for the new store.
    /// \param L the location whose binding should be removed.
    StoreRef killBinding(Store ST, Loc L) override;
  
    void incrementReferenceCount(Store store) override {
      getRegionBindings(store).manualRetain();
    }
  
    /// If the StoreManager supports it, decrement the reference count of
    /// the specified Store object.  If the reference count hits 0, the memory
    /// associated with the object is recycled.
    void decrementReferenceCount(Store store) override {
      getRegionBindings(store).manualRelease();
    }
  
    bool includedInBindings(Store store, const MemRegion *region) const override;
  
    /// \brief Return the value bound to specified location in a given state.
    ///
    /// The high level logic for this method is this:
    /// getBinding (L)
    ///   if L has binding
    ///     return L's binding
    ///   else if L is in killset
    ///     return unknown
    ///   else
    ///     if L is on stack or heap
    ///       return undefined
    ///     else
    ///       return symbolic
    SVal getBinding(Store S, Loc L, QualType T) override {
      return getBinding(getRegionBindings(S), L, T);
    }
  
    SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
  
    SVal getBindingForElement(RegionBindingsConstRef B, const ElementRegion *R);
  
    SVal getBindingForField(RegionBindingsConstRef B, const FieldRegion *R);
  
    SVal getBindingForObjCIvar(RegionBindingsConstRef B, const ObjCIvarRegion *R);
  
    SVal getBindingForVar(RegionBindingsConstRef B, const VarRegion *R);
  
    SVal getBindingForLazySymbol(const TypedValueRegion *R);
  
    SVal getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
                                           const TypedValueRegion *R,
                                           QualType Ty);
  
    SVal getLazyBinding(const SubRegion *LazyBindingRegion,
                        RegionBindingsRef LazyBinding);
  
    /// Get bindings for the values in a struct and return a CompoundVal, used
    /// when doing struct copy:
    /// struct s x, y;
    /// x = y;
    /// y's value is retrieved by this method.
    SVal getBindingForStruct(RegionBindingsConstRef B, const TypedValueRegion *R);
    SVal getBindingForArray(RegionBindingsConstRef B, const TypedValueRegion *R);
    NonLoc createLazyBinding(RegionBindingsConstRef B, const TypedValueRegion *R);
  
    /// Used to lazily generate derived symbols for bindings that are defined
    /// implicitly by default bindings in a super region.
    ///
    /// Note that callers may need to specially handle LazyCompoundVals, which
    /// are returned as is in case the caller needs to treat them differently.
    Optional<SVal> getBindingForDerivedDefaultValue(RegionBindingsConstRef B,
                                                    const MemRegion *superR,
                                                    const TypedValueRegion *R,
                                                    QualType Ty);
  
    /// Get the state and region whose binding this region \p R corresponds to.
    ///
    /// If there is no lazy binding for \p R, the returned value will have a null
    /// \c second. Note that a null pointer can represents a valid Store.
    std::pair<Store, const SubRegion *>
    findLazyBinding(RegionBindingsConstRef B, const SubRegion *R,
                    const SubRegion *originalRegion);
  
    /// Returns the cached set of interesting SVals contained within a lazy
    /// binding.
    ///
    /// The precise value of "interesting" is determined for the purposes of
    /// RegionStore's internal analysis. It must always contain all regions and
    /// symbols, but may omit constants and other kinds of SVal.
    const SValListTy &getInterestingValues(nonloc::LazyCompoundVal LCV);
  
    //===------------------------------------------------------------------===//
    // State pruning.
    //===------------------------------------------------------------------===//
  
    /// removeDeadBindings - Scans the RegionStore of 'state' for dead values.
    ///  It returns a new Store with these values removed.
    StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
                                SymbolReaper& SymReaper) override;
  
    //===------------------------------------------------------------------===//
    // Region "extents".
    //===------------------------------------------------------------------===//
  
    // FIXME: This method will soon be eliminated; see the note in Store.h.
    DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,
                                           const MemRegion* R,
                                           QualType EleTy) override;
  
    //===------------------------------------------------------------------===//
    // Utility methods.
    //===------------------------------------------------------------------===//
  
    RegionBindingsRef getRegionBindings(Store store) const {
      return RegionBindingsRef(CBFactory,
                               static_cast<const RegionBindings::TreeTy*>(store),
                               RBFactory.getTreeFactory());
    }
  
    void print(Store store, raw_ostream &Out, const char* nl,
               const char *sep) override;
  
    void iterBindings(Store store, BindingsHandler& f) override {
      RegionBindingsRef B = getRegionBindings(store);
      for (RegionBindingsRef::iterator I = B.begin(), E = B.end(); I != E; ++I) {
        const ClusterBindings &Cluster = I.getData();
        for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
             CI != CE; ++CI) {
          const BindingKey &K = CI.getKey();
          if (!K.isDirect())
            continue;
          if (const SubRegion *R = dyn_cast<SubRegion>(K.getRegion())) {
            // FIXME: Possibly incorporate the offset?
            if (!f.HandleBinding(*this, store, R, CI.getData()))
              return;
          }
        }
      }
    }
  };
  
  } // end anonymous namespace
  
  //===----------------------------------------------------------------------===//
  // RegionStore creation.
  //===----------------------------------------------------------------------===//
  
  std::unique_ptr<StoreManager>
  ento::CreateRegionStoreManager(ProgramStateManager &StMgr) {
    RegionStoreFeatures F = maximal_features_tag();
    return llvm::make_unique<RegionStoreManager>(StMgr, F);
  }
  
  std::unique_ptr<StoreManager>
  ento::CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr) {
    RegionStoreFeatures F = minimal_features_tag();
    F.enableFields(true);
    return llvm::make_unique<RegionStoreManager>(StMgr, F);
  }
  
  
  //===----------------------------------------------------------------------===//
  // Region Cluster analysis.
  //===----------------------------------------------------------------------===//
  
  namespace {
  /// Used to determine which global regions are automatically included in the
  /// initial worklist of a ClusterAnalysis.
  enum GlobalsFilterKind {
    /// Don't include any global regions.
    GFK_None,
    /// Only include system globals.
    GFK_SystemOnly,
    /// Include all global regions.
    GFK_All
  };
  
  template <typename DERIVED>
  class ClusterAnalysis  {
  protected:
    typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
    typedef const MemRegion * WorkListElement;
    typedef SmallVector<WorkListElement, 10> WorkList;
  
    llvm::SmallPtrSet<const ClusterBindings *, 16> Visited;
  
    WorkList WL;
  
    RegionStoreManager &RM;
    ASTContext &Ctx;
    SValBuilder &svalBuilder;
  
    RegionBindingsRef B;
  
  
  protected:
    const ClusterBindings *getCluster(const MemRegion *R) {
      return B.lookup(R);
    }
  
    /// Returns true if all clusters in the given memspace should be initially
    /// included in the cluster analysis. Subclasses may provide their
    /// own implementation.
    bool includeEntireMemorySpace(const MemRegion *Base) {
      return false;
    }
  
  public:
    ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
                    RegionBindingsRef b)
        : RM(rm), Ctx(StateMgr.getContext()),
          svalBuilder(StateMgr.getSValBuilder()), B(std::move(b)) {}
  
    RegionBindingsRef getRegionBindings() const { return B; }
  
    bool isVisited(const MemRegion *R) {
      return Visited.count(getCluster(R));
    }
  
    void GenerateClusters() {
      // Scan the entire set of bindings and record the region clusters.
      for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
           RI != RE; ++RI){
        const MemRegion *Base = RI.getKey();
  
        const ClusterBindings &Cluster = RI.getData();
        assert(!Cluster.isEmpty() && "Empty clusters should be removed");
        static_cast<DERIVED*>(this)->VisitAddedToCluster(Base, Cluster);
  
        // If the base's memspace should be entirely invalidated, add the cluster
        // to the workspace up front.
        if (static_cast<DERIVED*>(this)->includeEntireMemorySpace(Base))
          AddToWorkList(WorkListElement(Base), &Cluster);
      }
    }
  
    bool AddToWorkList(WorkListElement E, const ClusterBindings *C) {
      if (C && !Visited.insert(C).second)
        return false;
      WL.push_back(E);
      return true;
    }
  
    bool AddToWorkList(const MemRegion *R) {
      return static_cast<DERIVED*>(this)->AddToWorkList(R);
    }
  
    void RunWorkList() {
      while (!WL.empty()) {
        WorkListElement E = WL.pop_back_val();
        const MemRegion *BaseR = E;
  
        static_cast<DERIVED*>(this)->VisitCluster(BaseR, getCluster(BaseR));
      }
    }
  
    void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C) {}
    void VisitCluster(const MemRegion *baseR, const ClusterBindings *C) {}
  
    void VisitCluster(const MemRegion *BaseR, const ClusterBindings *C,
                      bool Flag) {
      static_cast<DERIVED*>(this)->VisitCluster(BaseR, C);
    }
  };
  }
  
  //===----------------------------------------------------------------------===//
  // Binding invalidation.
  //===----------------------------------------------------------------------===//
  
  bool RegionStoreManager::scanReachableSymbols(Store S, const MemRegion *R,
                                                ScanReachableSymbols &Callbacks) {
    assert(R == R->getBaseRegion() && "Should only be called for base regions");
    RegionBindingsRef B = getRegionBindings(S);
    const ClusterBindings *Cluster = B.lookup(R);
  
    if (!Cluster)
      return true;
  
    for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
         RI != RE; ++RI) {
      if (!Callbacks.scan(RI.getData()))
        return false;
    }
  
    return true;
  }
  
  static inline bool isUnionField(const FieldRegion *FR) {
    return FR->getDecl()->getParent()->isUnion();
  }
  
  typedef SmallVector<const FieldDecl *, 8> FieldVector;
  
  static void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields) {
    assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
  
    const MemRegion *Base = K.getConcreteOffsetRegion();
    const MemRegion *R = K.getRegion();
  
    while (R != Base) {
      if (const FieldRegion *FR = dyn_cast<FieldRegion>(R))
        if (!isUnionField(FR))
          Fields.push_back(FR->getDecl());
  
      R = cast<SubRegion>(R)->getSuperRegion();
    }
  }
  
  static bool isCompatibleWithFields(BindingKey K, const FieldVector &Fields) {
    assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
  
    if (Fields.empty())
      return true;
  
    FieldVector FieldsInBindingKey;
    getSymbolicOffsetFields(K, FieldsInBindingKey);
  
    ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
    if (Delta >= 0)
      return std::equal(FieldsInBindingKey.begin() + Delta,
                        FieldsInBindingKey.end(),
                        Fields.begin());
    else
      return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
                        Fields.begin() - Delta);
  }
  
  /// Collects all bindings in \p Cluster that may refer to bindings within
  /// \p Top.
  ///
  /// Each binding is a pair whose \c first is the key (a BindingKey) and whose
  /// \c second is the value (an SVal).
  ///
  /// The \p IncludeAllDefaultBindings parameter specifies whether to include
  /// default bindings that may extend beyond \p Top itself, e.g. if \p Top is
  /// an aggregate within a larger aggregate with a default binding.
  static void
  collectSubRegionBindings(SmallVectorImpl<BindingPair> &Bindings,
                           SValBuilder &SVB, const ClusterBindings &Cluster,
                           const SubRegion *Top, BindingKey TopKey,
                           bool IncludeAllDefaultBindings) {
    FieldVector FieldsInSymbolicSubregions;
    if (TopKey.hasSymbolicOffset()) {
      getSymbolicOffsetFields(TopKey, FieldsInSymbolicSubregions);
      Top = cast<SubRegion>(TopKey.getConcreteOffsetRegion());
      TopKey = BindingKey::Make(Top, BindingKey::Default);
    }
  
    // Find the length (in bits) of the region being invalidated.
    uint64_t Length = UINT64_MAX;
    SVal Extent = Top->getExtent(SVB);
    if (Optional<nonloc::ConcreteInt> ExtentCI =
            Extent.getAs<nonloc::ConcreteInt>()) {
      const llvm::APSInt &ExtentInt = ExtentCI->getValue();
      assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
      // Extents are in bytes but region offsets are in bits. Be careful!
      Length = ExtentInt.getLimitedValue() * SVB.getContext().getCharWidth();
    } else if (const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
      if (FR->getDecl()->isBitField())
        Length = FR->getDecl()->getBitWidthValue(SVB.getContext());
    }
  
    for (ClusterBindings::iterator I = Cluster.begin(), E = Cluster.end();
         I != E; ++I) {
      BindingKey NextKey = I.getKey();
      if (NextKey.getRegion() == TopKey.getRegion()) {
        // FIXME: This doesn't catch the case where we're really invalidating a
        // region with a symbolic offset. Example:
        //      R: points[i].y
        //   Next: points[0].x
  
        if (NextKey.getOffset() > TopKey.getOffset() &&
            NextKey.getOffset() - TopKey.getOffset() < Length) {
          // Case 1: The next binding is inside the region we're invalidating.
          // Include it.
          Bindings.push_back(*I);
  
        } else if (NextKey.getOffset() == TopKey.getOffset()) {
          // Case 2: The next binding is at the same offset as the region we're
          // invalidating. In this case, we need to leave default bindings alone,
          // since they may be providing a default value for a regions beyond what
          // we're invalidating.
          // FIXME: This is probably incorrect; consider invalidating an outer
          // struct whose first field is bound to a LazyCompoundVal.
          if (IncludeAllDefaultBindings || NextKey.isDirect())
            Bindings.push_back(*I);
        }
  
      } else if (NextKey.hasSymbolicOffset()) {
        const MemRegion *Base = NextKey.getConcreteOffsetRegion();
        if (Top->isSubRegionOf(Base)) {
          // Case 3: The next key is symbolic and we just changed something within
          // its concrete region. We don't know if the binding is still valid, so
          // we'll be conservative and include it.
          if (IncludeAllDefaultBindings || NextKey.isDirect())
            if (isCompatibleWithFields(NextKey, FieldsInSymbolicSubregions))
              Bindings.push_back(*I);
        } else if (const SubRegion *BaseSR = dyn_cast<SubRegion>(Base)) {
          // Case 4: The next key is symbolic, but we changed a known
          // super-region. In this case the binding is certainly included.
          if (Top == Base || BaseSR->isSubRegionOf(Top))
            if (isCompatibleWithFields(NextKey, FieldsInSymbolicSubregions))
              Bindings.push_back(*I);
        }
      }
    }
  }
  
  static void
  collectSubRegionBindings(SmallVectorImpl<BindingPair> &Bindings,
                           SValBuilder &SVB, const ClusterBindings &Cluster,
                           const SubRegion *Top, bool IncludeAllDefaultBindings) {
    collectSubRegionBindings(Bindings, SVB, Cluster, Top,
                             BindingKey::Make(Top, BindingKey::Default),
                             IncludeAllDefaultBindings);
  }
  
  RegionBindingsRef
  RegionStoreManager::removeSubRegionBindings(RegionBindingsConstRef B,
                                              const SubRegion *Top) {
    BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
    const MemRegion *ClusterHead = TopKey.getBaseRegion();
  
    if (Top == ClusterHead) {
      // We can remove an entire cluster's bindings all in one go.
      return B.remove(Top);
    }
  
    const ClusterBindings *Cluster = B.lookup(ClusterHead);
    if (!Cluster) {
      // If we're invalidating a region with a symbolic offset, we need to make
      // sure we don't treat the base region as uninitialized anymore.
      if (TopKey.hasSymbolicOffset()) {
        const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
        return B.addBinding(Concrete, BindingKey::Default, UnknownVal());
      }
      return B;
    }
  
    SmallVector<BindingPair, 32> Bindings;
    collectSubRegionBindings(Bindings, svalBuilder, *Cluster, Top, TopKey,
                             /*IncludeAllDefaultBindings=*/false);
  
    ClusterBindingsRef Result(*Cluster, CBFactory);
    for (SmallVectorImpl<BindingPair>::const_iterator I = Bindings.begin(),
                                                      E = Bindings.end();
         I != E; ++I)
      Result = Result.remove(I->first);
  
    // If we're invalidating a region with a symbolic offset, we need to make sure
    // we don't treat the base region as uninitialized anymore.
    // FIXME: This isn't very precise; see the example in
    // collectSubRegionBindings.
    if (TopKey.hasSymbolicOffset()) {
      const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
      Result = Result.add(BindingKey::Make(Concrete, BindingKey::Default),
                          UnknownVal());
    }
  
    if (Result.isEmpty())
      return B.remove(ClusterHead);
    return B.add(ClusterHead, Result.asImmutableMap());
  }
  
  namespace {
  class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker>
  {
    const Expr *Ex;
    unsigned Count;
    const LocationContext *LCtx;
    InvalidatedSymbols &IS;
    RegionAndSymbolInvalidationTraits &ITraits;
    StoreManager::InvalidatedRegions *Regions;
    GlobalsFilterKind GlobalsFilter;
  public:
    invalidateRegionsWorker(RegionStoreManager &rm,
                            ProgramStateManager &stateMgr,
                            RegionBindingsRef b,
                            const Expr *ex, unsigned count,
                            const LocationContext *lctx,
                            InvalidatedSymbols &is,
                            RegionAndSymbolInvalidationTraits &ITraitsIn,
                            StoreManager::InvalidatedRegions *r,
                            GlobalsFilterKind GFK)
       : ClusterAnalysis<invalidateRegionsWorker>(rm, stateMgr, b),
         Ex(ex), Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
         GlobalsFilter(GFK) {}
  
    void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);
    void VisitBinding(SVal V);
  
    using ClusterAnalysis::AddToWorkList;
  
    bool AddToWorkList(const MemRegion *R);
  
    /// Returns true if all clusters in the memory space for \p Base should be
    /// be invalidated.
    bool includeEntireMemorySpace(const MemRegion *Base);
  
    /// Returns true if the memory space of the given region is one of the global
    /// regions specially included at the start of invalidation.
    bool isInitiallyIncludedGlobalRegion(const MemRegion *R);
  };
  }
  
  bool invalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
    bool doNotInvalidateSuperRegion = ITraits.hasTrait(
        R, RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
    const MemRegion *BaseR = doNotInvalidateSuperRegion ? R : R->getBaseRegion();
    return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
  }
  
  void invalidateRegionsWorker::VisitBinding(SVal V) {
    // A symbol?  Mark it touched by the invalidation.
    if (SymbolRef Sym = V.getAsSymbol())
      IS.insert(Sym);
  
    if (const MemRegion *R = V.getAsRegion()) {
      AddToWorkList(R);
      return;
    }
  
    // Is it a LazyCompoundVal?  All references get invalidated as well.
    if (Optional<nonloc::LazyCompoundVal> LCS =
            V.getAs<nonloc::LazyCompoundVal>()) {
  
      const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
  
      for (RegionStoreManager::SValListTy::const_iterator I = Vals.begin(),
                                                          E = Vals.end();
           I != E; ++I)
        VisitBinding(*I);
  
      return;
    }
  }
  
  void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
                                             const ClusterBindings *C) {
  
    bool PreserveRegionsContents =
        ITraits.hasTrait(baseR,
                         RegionAndSymbolInvalidationTraits::TK_PreserveContents);
  
    if (C) {
      for (ClusterBindings::iterator I = C->begin(), E = C->end(); I != E; ++I)
        VisitBinding(I.getData());
  
      // Invalidate regions contents.
      if (!PreserveRegionsContents)
        B = B.remove(baseR);
    }
  
    // BlockDataRegion?  If so, invalidate captured variables that are passed
    // by reference.
    if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
      for (BlockDataRegion::referenced_vars_iterator
           BI = BR->referenced_vars_begin(), BE = BR->referenced_vars_end() ;
           BI != BE; ++BI) {
        const VarRegion *VR = BI.getCapturedRegion();
        const VarDecl *VD = VR->getDecl();
        if (VD->hasAttr<BlocksAttr>() || !VD->hasLocalStorage()) {
          AddToWorkList(VR);
        }
        else if (Loc::isLocType(VR->getValueType())) {
          // Map the current bindings to a Store to retrieve the value
          // of the binding.  If that binding itself is a region, we should
          // invalidate that region.  This is because a block may capture
          // a pointer value, but the thing pointed by that pointer may
          // get invalidated.
          SVal V = RM.getBinding(B, loc::MemRegionVal(VR));
          if (Optional<Loc> L = V.getAs<Loc>()) {
            if (const MemRegion *LR = L->getAsRegion())
              AddToWorkList(LR);
          }
        }
      }
      return;
    }
  
    // Symbolic region?
    if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
      IS.insert(SR->getSymbol());
  
    // Nothing else should be done in the case when we preserve regions context.
    if (PreserveRegionsContents)
      return;
  
    // Otherwise, we have a normal data region. Record that we touched the region.
    if (Regions)
      Regions->push_back(baseR);
  
    if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
      // Invalidate the region by setting its default value to
      // conjured symbol. The type of the symbol is irrelevant.
      DefinedOrUnknownSVal V =
        svalBuilder.conjureSymbolVal(baseR, Ex, LCtx, Ctx.IntTy, Count);
      B = B.addBinding(baseR, BindingKey::Default, V);
      return;
    }
  
    if (!baseR->isBoundable())
      return;
  
    const TypedValueRegion *TR = cast<TypedValueRegion>(baseR);
    QualType T = TR->getValueType();
  
    if (isInitiallyIncludedGlobalRegion(baseR)) {
      // If the region is a global and we are invalidating all globals,
      // erasing the entry is good enough.  This causes all globals to be lazily
      // symbolicated from the same base symbol.
      return;
    }
  
    if (T->isStructureOrClassType()) {
      // Invalidate the region by setting its default value to
      // conjured symbol. The type of the symbol is irrelevant.
      DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(baseR, Ex, LCtx,
                                                            Ctx.IntTy, Count);
      B = B.addBinding(baseR, BindingKey::Default, V);
      return;
    }
  
    if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
      bool doNotInvalidateSuperRegion = ITraits.hasTrait(
          baseR,
          RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
  
      if (doNotInvalidateSuperRegion) {
        // We are not doing blank invalidation of the whole array region so we
        // have to manually invalidate each elements.
        Optional<uint64_t> NumElements;
  
        // Compute lower and upper offsets for region within array.
        if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
          NumElements = CAT->getSize().getZExtValue();
        if (!NumElements) // We are not dealing with a constant size array
          goto conjure_default;
        QualType ElementTy = AT->getElementType();
        uint64_t ElemSize = Ctx.getTypeSize(ElementTy);
        const RegionOffset &RO = baseR->getAsOffset();
        const MemRegion *SuperR = baseR->getBaseRegion();
        if (RO.hasSymbolicOffset()) {
          // If base region has a symbolic offset,
          // we revert to invalidating the super region.
          if (SuperR)
            AddToWorkList(SuperR);
          goto conjure_default;
        }
  
        uint64_t LowerOffset = RO.getOffset();
        uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
        bool UpperOverflow = UpperOffset < LowerOffset;
  
        // Invalidate regions which are within array boundaries,
        // or have a symbolic offset.
        if (!SuperR)
          goto conjure_default;
  
        const ClusterBindings *C = B.lookup(SuperR);
        if (!C)
          goto conjure_default;
  
        for (ClusterBindings::iterator I = C->begin(), E = C->end(); I != E;
             ++I) {
          const BindingKey &BK = I.getKey();
          Optional<uint64_t> ROffset =
              BK.hasSymbolicOffset() ? Optional<uint64_t>() : BK.getOffset();
  
          // Check offset is not symbolic and within array's boundaries.
          // Handles arrays of 0 elements and of 0-sized elements as well.
          if (!ROffset ||
              ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
               (UpperOverflow &&
                (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
               (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
            B = B.removeBinding(I.getKey());
            // Bound symbolic regions need to be invalidated for dead symbol
            // detection.
            SVal V = I.getData();
            const MemRegion *R = V.getAsRegion();
            if (R && isa<SymbolicRegion>(R))
              VisitBinding(V);
          }
        }
      }
    conjure_default:
        // Set the default value of the array to conjured symbol.
      DefinedOrUnknownSVal V =
      svalBuilder.conjureSymbolVal(baseR, Ex, LCtx,
                                       AT->getElementType(), Count);
      B = B.addBinding(baseR, BindingKey::Default, V);
      return;
    }
  
    DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(baseR, Ex, LCtx,
                                                          T,Count);
    assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
    B = B.addBinding(baseR, BindingKey::Direct, V);
  }
  
  bool invalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
      const MemRegion *R) {
    switch (GlobalsFilter) {
    case GFK_None:
      return false;
    case GFK_SystemOnly:
      return isa<GlobalSystemSpaceRegion>(R->getMemorySpace());
    case GFK_All:
      return isa<NonStaticGlobalSpaceRegion>(R->getMemorySpace());
    }
  
    llvm_unreachable("unknown globals filter");
  }
  
  bool invalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {
    if (isInitiallyIncludedGlobalRegion(Base))
      return true;
  
    const MemSpaceRegion *MemSpace = Base->getMemorySpace();
    return ITraits.hasTrait(MemSpace,
                            RegionAndSymbolInvalidationTraits::TK_EntireMemSpace);
  }
  
  RegionBindingsRef
  RegionStoreManager::invalidateGlobalRegion(MemRegion::Kind K,
                                             const Expr *Ex,
                                             unsigned Count,
                                             const LocationContext *LCtx,
                                             RegionBindingsRef B,
                                             InvalidatedRegions *Invalidated) {
    // Bind the globals memory space to a new symbol that we will use to derive
    // the bindings for all globals.
    const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);
    SVal V = svalBuilder.conjureSymbolVal(/* SymbolTag = */ (const void*) GS, Ex, LCtx,
                                          /* type does not matter */ Ctx.IntTy,
                                          Count);
  
    B = B.removeBinding(GS)
         .addBinding(BindingKey::Make(GS, BindingKey::Default), V);
  
    // Even if there are no bindings in the global scope, we still need to
    // record that we touched it.
    if (Invalidated)
      Invalidated->push_back(GS);
  
    return B;
  }
  
  void RegionStoreManager::populateWorkList(invalidateRegionsWorker &W,
                                            ArrayRef<SVal> Values,
                                            InvalidatedRegions *TopLevelRegions) {
    for (ArrayRef<SVal>::iterator I = Values.begin(),
                                  E = Values.end(); I != E; ++I) {
      SVal V = *I;
      if (Optional<nonloc::LazyCompoundVal> LCS =
          V.getAs<nonloc::LazyCompoundVal>()) {
  
        const SValListTy &Vals = getInterestingValues(*LCS);
  
        for (SValListTy::const_iterator I = Vals.begin(),
                                        E = Vals.end(); I != E; ++I) {
          // Note: the last argument is false here because these are
          // non-top-level regions.
          if (const MemRegion *R = (*I).getAsRegion())
            W.AddToWorkList(R);
        }
        continue;
      }
  
      if (const MemRegion *R = V.getAsRegion()) {
        if (TopLevelRegions)
          TopLevelRegions->push_back(R);
        W.AddToWorkList(R);
        continue;
      }
    }
  }
  
  StoreRef
  RegionStoreManager::invalidateRegions(Store store,
                                       ArrayRef<SVal> Values,
                                       const Expr *Ex, unsigned Count,
                                       const LocationContext *LCtx,
                                       const CallEvent *Call,
                                       InvalidatedSymbols &IS,
                                       RegionAndSymbolInvalidationTraits &ITraits,
                                       InvalidatedRegions *TopLevelRegions,
                                       InvalidatedRegions *Invalidated) {
    GlobalsFilterKind GlobalsFilter;
    if (Call) {
      if (Call->isInSystemHeader())
        GlobalsFilter = GFK_SystemOnly;
      else
        GlobalsFilter = GFK_All;
    } else {
      GlobalsFilter = GFK_None;
    }
  
    RegionBindingsRef B = getRegionBindings(store);
    invalidateRegionsWorker W(*this, StateMgr, B, Ex, Count, LCtx, IS, ITraits,
                              Invalidated, GlobalsFilter);
  
    // Scan the bindings and generate the clusters.
    W.GenerateClusters();
  
    // Add the regions to the worklist.
    populateWorkList(W, Values, TopLevelRegions);
  
    W.RunWorkList();
  
    // Return the new bindings.
    B = W.getRegionBindings();
  
    // For calls, determine which global regions should be invalidated and
    // invalidate them. (Note that function-static and immutable globals are never
    // invalidated by this.)
    // TODO: This could possibly be more precise with modules.
    switch (GlobalsFilter) {
    case GFK_All:
      B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind,
                                 Ex, Count, LCtx, B, Invalidated);
      // FALLTHROUGH
    case GFK_SystemOnly:
      B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
                                 Ex, Count, LCtx, B, Invalidated);
      // FALLTHROUGH
    case GFK_None:
      break;
    }
  
    return StoreRef(B.asStore(), *this);
  }
  
  //===----------------------------------------------------------------------===//
  // Extents for regions.
  //===----------------------------------------------------------------------===//
  
  DefinedOrUnknownSVal
  RegionStoreManager::getSizeInElements(ProgramStateRef state,
                                        const MemRegion *R,
                                        QualType EleTy) {
    SVal Size = cast<SubRegion>(R)->getExtent(svalBuilder);
    const llvm::APSInt *SizeInt = svalBuilder.getKnownValue(state, Size);
    if (!SizeInt)
      return UnknownVal();
  
    CharUnits RegionSize = CharUnits::fromQuantity(SizeInt->getSExtValue());
  
    if (Ctx.getAsVariableArrayType(EleTy)) {
      // FIXME: We need to track extra state to properly record the size
      // of VLAs.  Returning UnknownVal here, however, is a stop-gap so that
      // we don't have a divide-by-zero below.
      return UnknownVal();
    }
  
    CharUnits EleSize = Ctx.getTypeSizeInChars(EleTy);
  
    // If a variable is reinterpreted as a type that doesn't fit into a larger
    // type evenly, round it down.
    // This is a signed value, since it's used in arithmetic with signed indices.
    return svalBuilder.makeIntVal(RegionSize / EleSize, false);
  }
  
  //===----------------------------------------------------------------------===//
  // Location and region casting.
  //===----------------------------------------------------------------------===//
  
  /// ArrayToPointer - Emulates the "decay" of an array to a pointer
  ///  type.  'Array' represents the lvalue of the array being decayed
  ///  to a pointer, and the returned SVal represents the decayed
  ///  version of that lvalue (i.e., a pointer to the first element of
  ///  the array).  This is called by ExprEngine when evaluating casts
  ///  from arrays to pointers.
  SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) {
    if (!Array.getAs<loc::MemRegionVal>())
      return UnknownVal();
  
    const MemRegion* R = Array.castAs<loc::MemRegionVal>().getRegion();
    NonLoc ZeroIdx = svalBuilder.makeZeroArrayIndex();
    return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));
  }
  
  //===----------------------------------------------------------------------===//
  // Loading values from regions.
  //===----------------------------------------------------------------------===//
  
  SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T) {
    assert(!L.getAs<UnknownVal>() && "location unknown");
    assert(!L.getAs<UndefinedVal>() && "location undefined");
  
    // For access to concrete addresses, return UnknownVal.  Checks
    // for null dereferences (and similar errors) are done by checkers, not
    // the Store.
    // FIXME: We can consider lazily symbolicating such memory, but we really
    // should defer this when we can reason easily about symbolicating arrays
    // of bytes.
    if (L.getAs<loc::ConcreteInt>()) {
      return UnknownVal();
    }
    if (!L.getAs<loc::MemRegionVal>()) {
      return UnknownVal();
    }
  
    const MemRegion *MR = L.castAs<loc::MemRegionVal>().getRegion();
  
    if (isa<BlockDataRegion>(MR)) {
      return UnknownVal();
    }
  
    if (isa<AllocaRegion>(MR) ||
        isa<SymbolicRegion>(MR) ||
        isa<CodeTextRegion>(MR)) {
      if (T.isNull()) {
        if (const TypedRegion *TR = dyn_cast<TypedRegion>(MR))
          T = TR->getLocationType();
        else {
          const SymbolicRegion *SR = cast<SymbolicRegion>(MR);
          T = SR->getSymbol()->getType();
        }
      }
      MR = GetElementZeroRegion(MR, T);
    }
  
    // FIXME: Perhaps this method should just take a 'const MemRegion*' argument
    //  instead of 'Loc', and have the other Loc cases handled at a higher level.
    const TypedValueRegion *R = cast<TypedValueRegion>(MR);
    QualType RTy = R->getValueType();
  
    // FIXME: we do not yet model the parts of a complex type, so treat the
    // whole thing as "unknown".
    if (RTy->isAnyComplexType())
      return UnknownVal();
  
    // FIXME: We should eventually handle funny addressing.  e.g.:
    //
    //   int x = ...;
    //   int *p = &x;
    //   char *q = (char*) p;
    //   char c = *q;  // returns the first byte of 'x'.
    //
    // Such funny addressing will occur due to layering of regions.
    if (RTy->isStructureOrClassType())
      return getBindingForStruct(B, R);
  
    // FIXME: Handle unions.
    if (RTy->isUnionType())
      return createLazyBinding(B, R);
  
    if (RTy->isArrayType()) {
      if (RTy->isConstantArrayType())
        return getBindingForArray(B, R);
      else
        return UnknownVal();
    }
  
    // FIXME: handle Vector types.
    if (RTy->isVectorType())
      return UnknownVal();
  
    if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
      return CastRetrievedVal(getBindingForField(B, FR), FR, T, false);
  
    if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
      // FIXME: Here we actually perform an implicit conversion from the loaded
      // value to the element type.  Eventually we want to compose these values
      // more intelligently.  For example, an 'element' can encompass multiple
      // bound regions (e.g., several bound bytes), or could be a subset of
      // a larger value.
      return CastRetrievedVal(getBindingForElement(B, ER), ER, T, false);
    }
  
    if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
      // FIXME: Here we actually perform an implicit conversion from the loaded
      // value to the ivar type.  What we should model is stores to ivars
      // that blow past the extent of the ivar.  If the address of the ivar is
      // reinterpretted, it is possible we stored a different value that could
      // fit within the ivar.  Either we need to cast these when storing them
      // or reinterpret them lazily (as we do here).
      return CastRetrievedVal(getBindingForObjCIvar(B, IVR), IVR, T, false);
    }
  
    if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
      // FIXME: Here we actually perform an implicit conversion from the loaded
      // value to the variable type.  What we should model is stores to variables
      // that blow past the extent of the variable.  If the address of the
      // variable is reinterpretted, it is possible we stored a different value
      // that could fit within the variable.  Either we need to cast these when
      // storing them or reinterpret them lazily (as we do here).
      return CastRetrievedVal(getBindingForVar(B, VR), VR, T, false);
    }
  
    const SVal *V = B.lookup(R, BindingKey::Direct);
  
    // Check if the region has a binding.
    if (V)
      return *V;
  
    // The location does not have a bound value.  This means that it has
    // the value it had upon its creation and/or entry to the analyzed
    // function/method.  These are either symbolic values or 'undefined'.
    if (R->hasStackNonParametersStorage()) {
      // All stack variables are considered to have undefined values
      // upon creation.  All heap allocated blocks are considered to
      // have undefined values as well unless they are explicitly bound
      // to specific values.
      return UndefinedVal();
    }
  
    // All other values are symbolic.
    return svalBuilder.getRegionValueSymbolVal(R);
  }
  
  static QualType getUnderlyingType(const SubRegion *R) {
    QualType RegionTy;
    if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R))
      RegionTy = TVR->getValueType();
  
    if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
      RegionTy = SR->getSymbol()->getType();
  
    return RegionTy;
  }
  
  /// Checks to see if store \p B has a lazy binding for region \p R.
  ///
  /// If \p AllowSubregionBindings is \c false, a lazy binding will be rejected
  /// if there are additional bindings within \p R.
  ///
  /// Note that unlike RegionStoreManager::findLazyBinding, this will not search
  /// for lazy bindings for super-regions of \p R.
  static Optional<nonloc::LazyCompoundVal>
  getExistingLazyBinding(SValBuilder &SVB, RegionBindingsConstRef B,
                         const SubRegion *R, bool AllowSubregionBindings) {
    Optional<SVal> V = B.getDefaultBinding(R);
    if (!V)
      return None;
  
    Optional<nonloc::LazyCompoundVal> LCV = V->getAs<nonloc::LazyCompoundVal>();
    if (!LCV)
      return None;
  
    // If the LCV is for a subregion, the types might not match, and we shouldn't
    // reuse the binding.
    QualType RegionTy = getUnderlyingType(R);
    if (!RegionTy.isNull() &&
        !RegionTy->isVoidPointerType()) {
      QualType SourceRegionTy = LCV->getRegion()->getValueType();
      if (!SVB.getContext().hasSameUnqualifiedType(RegionTy, SourceRegionTy))
        return None;
    }
  
    if (!AllowSubregionBindings) {
      // If there are any other bindings within this region, we shouldn't reuse
      // the top-level binding.
      SmallVector<BindingPair, 16> Bindings;
      collectSubRegionBindings(Bindings, SVB, *B.lookup(R->getBaseRegion()), R,
                               /*IncludeAllDefaultBindings=*/true);
      if (Bindings.size() > 1)
        return None;
    }
  
    return *LCV;
  }
  
  
  std::pair<Store, const SubRegion *>
  RegionStoreManager::findLazyBinding(RegionBindingsConstRef B,
                                     const SubRegion *R,
                                     const SubRegion *originalRegion) {
    if (originalRegion != R) {
      if (Optional<nonloc::LazyCompoundVal> V =
            getExistingLazyBinding(svalBuilder, B, R, true))
        return std::make_pair(V->getStore(), V->getRegion());
    }
  
    typedef std::pair<Store, const SubRegion *> StoreRegionPair;
    StoreRegionPair Result = StoreRegionPair();
  
    if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
      Result = findLazyBinding(B, cast<SubRegion>(ER->getSuperRegion()),
                               originalRegion);
  
      if (Result.second)
        Result.second = MRMgr.getElementRegionWithSuper(ER, Result.second);
  
    } else if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
      Result = findLazyBinding(B, cast<SubRegion>(FR->getSuperRegion()),
                                         originalRegion);
  
      if (Result.second)
        Result.second = MRMgr.getFieldRegionWithSuper(FR, Result.second);
  
    } else if (const CXXBaseObjectRegion *BaseReg =
                 dyn_cast<CXXBaseObjectRegion>(R)) {
      // C++ base object region is another kind of region that we should blast
      // through to look for lazy compound value. It is like a field region.
      Result = findLazyBinding(B, cast<SubRegion>(BaseReg->getSuperRegion()),
                               originalRegion);
  
      if (Result.second)
        Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
                                                              Result.second);
    }
  
    return Result;
  }
  
  SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
                                                const ElementRegion* R) {
    // We do not currently model bindings of the CompoundLiteralregion.
    if (isa<CompoundLiteralRegion>(R->getBaseRegion()))
      return UnknownVal();
  
    // Check if the region has a binding.
    if (const Optional<SVal> &V = B.getDirectBinding(R))
      return *V;
  
    const MemRegion* superR = R->getSuperRegion();
  
    // Check if the region is an element region of a string literal.
    if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {
      // FIXME: Handle loads from strings where the literal is treated as
      // an integer, e.g., *((unsigned int*)"hello")
      QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType();
      if (!Ctx.hasSameUnqualifiedType(T, R->getElementType()))
        return UnknownVal();
  
      const StringLiteral *Str = StrR->getStringLiteral();
      SVal Idx = R->getIndex();
      if (Optional<nonloc::ConcreteInt> CI = Idx.getAs<nonloc::ConcreteInt>()) {
        int64_t i = CI->getValue().getSExtValue();
        // Abort on string underrun.  This can be possible by arbitrary
        // clients of getBindingForElement().
        if (i < 0)
          return UndefinedVal();
        int64_t length = Str->getLength();
        // Technically, only i == length is guaranteed to be null.
        // However, such overflows should be caught before reaching this point;
        // the only time such an access would be made is if a string literal was
        // used to initialize a larger array.
        char c = (i >= length) ? '\0' : Str->getCodeUnit(i);
        return svalBuilder.makeIntVal(c, T);
      }
    }
  
    // Check for loads from a code text region.  For such loads, just give up.
    if (isa<CodeTextRegion>(superR))
      return UnknownVal();
  
    // Handle the case where we are indexing into a larger scalar object.
    // For example, this handles:
    //   int x = ...
    //   char *y = &x;
    //   return *y;
    // FIXME: This is a hack, and doesn't do anything really intelligent yet.
    const RegionRawOffset &O = R->getAsArrayOffset();
  
    // If we cannot reason about the offset, return an unknown value.
    if (!O.getRegion())
      return UnknownVal();
  
    if (const TypedValueRegion *baseR =
          dyn_cast_or_null<TypedValueRegion>(O.getRegion())) {
      QualType baseT = baseR->getValueType();
      if (baseT->isScalarType()) {
        QualType elemT = R->getElementType();
        if (elemT->isScalarType()) {
          if (Ctx.getTypeSizeInChars(baseT) >= Ctx.getTypeSizeInChars(elemT)) {
            if (const Optional<SVal> &V = B.getDirectBinding(superR)) {
              if (SymbolRef parentSym = V->getAsSymbol())
                return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
  
              if (V->isUnknownOrUndef())
                return *V;
              // Other cases: give up.  We are indexing into a larger object
              // that has some value, but we don't know how to handle that yet.
              return UnknownVal();
            }
          }
        }
      }
    }
    return getBindingForFieldOrElementCommon(B, R, R->getElementType());
  }
  
  SVal RegionStoreManager::getBindingForField(RegionBindingsConstRef B,
                                              const FieldRegion* R) {
  
    // Check if the region has a binding.
    if (const Optional<SVal> &V = B.getDirectBinding(R))
      return *V;
  
    QualType Ty = R->getValueType();
    return getBindingForFieldOrElementCommon(B, R, Ty);
  }
  
  Optional<SVal>
  RegionStoreManager::getBindingForDerivedDefaultValue(RegionBindingsConstRef B,
                                                       const MemRegion *superR,
                                                       const TypedValueRegion *R,
                                                       QualType Ty) {
  
    if (const Optional<SVal> &D = B.getDefaultBinding(superR)) {
      const SVal &val = D.getValue();
      if (SymbolRef parentSym = val.getAsSymbol())
        return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
  
      if (val.isZeroConstant())
        return svalBuilder.makeZeroVal(Ty);
  
      if (val.isUnknownOrUndef())
        return val;
  
      // Lazy bindings are usually handled through getExistingLazyBinding().
      // We should unify these two code paths at some point.
      if (val.getAs<nonloc::LazyCompoundVal>() ||
          val.getAs<nonloc::CompoundVal>())
        return val;
  
      llvm_unreachable("Unknown default value");
    }
  
    return None;
  }
  
  SVal RegionStoreManager::getLazyBinding(const SubRegion *LazyBindingRegion,
                                          RegionBindingsRef LazyBinding) {
    SVal Result;
    if (const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
      Result = getBindingForElement(LazyBinding, ER);
    else
      Result = getBindingForField(LazyBinding,
                                  cast<FieldRegion>(LazyBindingRegion));
  
    // FIXME: This is a hack to deal with RegionStore's inability to distinguish a
    // default value for /part/ of an aggregate from a default value for the
    // /entire/ aggregate. The most common case of this is when struct Outer
    // has as its first member a struct Inner, which is copied in from a stack
    // variable. In this case, even if the Outer's default value is symbolic, 0,
    // or unknown, it gets overridden by the Inner's default value of undefined.
    //
    // This is a general problem -- if the Inner is zero-initialized, the Outer
    // will now look zero-initialized. The proper way to solve this is with a
    // new version of RegionStore that tracks the extent of a binding as well
    // as the offset.
    //
    // This hack only takes care of the undefined case because that can very
    // quickly result in a warning.
    if (Result.isUndef())
      Result = UnknownVal();
  
    return Result;
  }
  
  SVal
  RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
                                                        const TypedValueRegion *R,
                                                        QualType Ty) {
  
    // At this point we have already checked in either getBindingForElement or
    // getBindingForField if 'R' has a direct binding.
  
    // Lazy binding?
    Store lazyBindingStore = nullptr;
    const SubRegion *lazyBindingRegion = nullptr;
    std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
    if (lazyBindingRegion)
      return getLazyBinding(lazyBindingRegion,
                            getRegionBindings(lazyBindingStore));
  
    // Record whether or not we see a symbolic index.  That can completely
    // be out of scope of our lookup.
    bool hasSymbolicIndex = false;
  
    // FIXME: This is a hack to deal with RegionStore's inability to distinguish a
    // default value for /part/ of an aggregate from a default value for the
    // /entire/ aggregate. The most common case of this is when struct Outer
    // has as its first member a struct Inner, which is copied in from a stack
    // variable. In this case, even if the Outer's default value is symbolic, 0,
    // or unknown, it gets overridden by the Inner's default value of undefined.
    //
    // This is a general problem -- if the Inner is zero-initialized, the Outer
    // will now look zero-initialized. The proper way to solve this is with a
    // new version of RegionStore that tracks the extent of a binding as well
    // as the offset.
    //
    // This hack only takes care of the undefined case because that can very
    // quickly result in a warning.
    bool hasPartialLazyBinding = false;
  
    const SubRegion *SR = dyn_cast<SubRegion>(R);
    while (SR) {
      const MemRegion *Base = SR->getSuperRegion();
      if (Optional<SVal> D = getBindingForDerivedDefaultValue(B, Base, R, Ty)) {
        if (D->getAs<nonloc::LazyCompoundVal>()) {
          hasPartialLazyBinding = true;
          break;
        }
  
        return *D;
      }
  
      if (const ElementRegion *ER = dyn_cast<ElementRegion>(Base)) {
        NonLoc index = ER->getIndex();
        if (!index.isConstant())
          hasSymbolicIndex = true;
      }
  
      // If our super region is a field or element itself, walk up the region
      // hierarchy to see if there is a default value installed in an ancestor.
      SR = dyn_cast<SubRegion>(Base);
    }
  
    if (R->hasStackNonParametersStorage()) {
      if (isa<ElementRegion>(R)) {
        // Currently we don't reason specially about Clang-style vectors.  Check
        // if superR is a vector and if so return Unknown.
        if (const TypedValueRegion *typedSuperR =
              dyn_cast<TypedValueRegion>(R->getSuperRegion())) {
          if (typedSuperR->getValueType()->isVectorType())
            return UnknownVal();
        }
      }
  
      // FIXME: We also need to take ElementRegions with symbolic indexes into
      // account.  This case handles both directly accessing an ElementRegion
      // with a symbolic offset, but also fields within an element with
      // a symbolic offset.
      if (hasSymbolicIndex)
        return UnknownVal();
  
      if (!hasPartialLazyBinding)
        return UndefinedVal();
    }
  
    // All other values are symbolic.
    return svalBuilder.getRegionValueSymbolVal(R);
  }
  
  SVal RegionStoreManager::getBindingForObjCIvar(RegionBindingsConstRef B,
                                                 const ObjCIvarRegion* R) {
    // Check if the region has a binding.
    if (const Optional<SVal> &V = B.getDirectBinding(R))
      return *V;
  
    const MemRegion *superR = R->getSuperRegion();
  
    // Check if the super region has a default binding.
    if (const Optional<SVal> &V = B.getDefaultBinding(superR)) {
      if (SymbolRef parentSym = V->getAsSymbol())
        return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
  
      // Other cases: give up.
      return UnknownVal();
    }
  
    return getBindingForLazySymbol(R);
  }
  
  SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B,
                                            const VarRegion *R) {
  
    // Check if the region has a binding.
    if (const Optional<SVal> &V = B.getDirectBinding(R))
      return *V;
  
    // Lazily derive a value for the VarRegion.
    const VarDecl *VD = R->getDecl();
    const MemSpaceRegion *MS = R->getMemorySpace();
  
    // Arguments are always symbolic.
    if (isa<StackArgumentsSpaceRegion>(MS))
      return svalBuilder.getRegionValueSymbolVal(R);
  
    // Is 'VD' declared constant?  If so, retrieve the constant value.
    if (VD->getType().isConstQualified())
      if (const Expr *Init = VD->getInit())
        if (Optional<SVal> V = svalBuilder.getConstantVal(Init))
          return *V;
  
    // This must come after the check for constants because closure-captured
    // constant variables may appear in UnknownSpaceRegion.
    if (isa<UnknownSpaceRegion>(MS))
      return svalBuilder.getRegionValueSymbolVal(R);
  
    if (isa<GlobalsSpaceRegion>(MS)) {
      QualType T = VD->getType();
  
      // Function-scoped static variables are default-initialized to 0; if they
      // have an initializer, it would have been processed by now.
      // FIXME: This is only true when we're starting analysis from main().
      // We're losing a lot of coverage here.
      if (isa<StaticGlobalSpaceRegion>(MS))
        return svalBuilder.makeZeroVal(T);
  
      if (Optional<SVal> V = getBindingForDerivedDefaultValue(B, MS, R, T)) {
        assert(!V->getAs<nonloc::LazyCompoundVal>());
        return V.getValue();
      }
  
      return svalBuilder.getRegionValueSymbolVal(R);
    }
  
    return UndefinedVal();
  }
  
  SVal RegionStoreManager::getBindingForLazySymbol(const TypedValueRegion *R) {
    // All other values are symbolic.
    return svalBuilder.getRegionValueSymbolVal(R);
  }
  
  const RegionStoreManager::SValListTy &
  RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
    // First, check the cache.
    LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.getCVData());
    if (I != LazyBindingsMap.end())
      return I->second;
  
    // If we don't have a list of values cached, start constructing it.
    SValListTy List;
  
    const SubRegion *LazyR = LCV.getRegion();
    RegionBindingsRef B = getRegionBindings(LCV.getStore());
  
    // If this region had /no/ bindings at the time, there are no interesting
    // values to return.
    const ClusterBindings *Cluster = B.lookup(LazyR->getBaseRegion());
    if (!Cluster)
      return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
  
    SmallVector<BindingPair, 32> Bindings;
    collectSubRegionBindings(Bindings, svalBuilder, *Cluster, LazyR,
                             /*IncludeAllDefaultBindings=*/true);
    for (SmallVectorImpl<BindingPair>::const_iterator I = Bindings.begin(),
                                                      E = Bindings.end();
         I != E; ++I) {
      SVal V = I->second;
      if (V.isUnknownOrUndef() || V.isConstant())
        continue;
  
      if (Optional<nonloc::LazyCompoundVal> InnerLCV =
              V.getAs<nonloc::LazyCompoundVal>()) {
        const SValListTy &InnerList = getInterestingValues(*InnerLCV);
        List.insert(List.end(), InnerList.begin(), InnerList.end());
        continue;
      }
  
      List.push_back(V);
    }
  
    return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
  }
  
  NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B,
                                               const TypedValueRegion *R) {
    if (Optional<nonloc::LazyCompoundVal> V =
          getExistingLazyBinding(svalBuilder, B, R, false))
      return *V;
  
    return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R);
  }
  
  static bool isRecordEmpty(const RecordDecl *RD) {
    if (!RD->field_empty())
      return false;
    if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD))
      return CRD->getNumBases() == 0;
    return true;
  }
  
  SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B,
                                               const TypedValueRegion *R) {
    const RecordDecl *RD = R->getValueType()->castAs<RecordType>()->getDecl();
    if (!RD->getDefinition() || isRecordEmpty(RD))
      return UnknownVal();
  
    return createLazyBinding(B, R);
  }
  
  SVal RegionStoreManager::getBindingForArray(RegionBindingsConstRef B,
                                              const TypedValueRegion *R) {
    assert(Ctx.getAsConstantArrayType(R->getValueType()) &&
           "Only constant array types can have compound bindings.");
  
    return createLazyBinding(B, R);
  }
  
  bool RegionStoreManager::includedInBindings(Store store,
                                              const MemRegion *region) const {
    RegionBindingsRef B = getRegionBindings(store);
    region = region->getBaseRegion();
  
    // Quick path: if the base is the head of a cluster, the region is live.
    if (B.lookup(region))
      return true;
  
    // Slow path: if the region is the VALUE of any binding, it is live.
    for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
      const ClusterBindings &Cluster = RI.getData();
      for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
           CI != CE; ++CI) {
        const SVal &D = CI.getData();
        if (const MemRegion *R = D.getAsRegion())
          if (R->getBaseRegion() == region)
            return true;
      }
    }
  
    return false;
  }
  
  //===----------------------------------------------------------------------===//
  // Binding values to regions.
  //===----------------------------------------------------------------------===//
  
  StoreRef RegionStoreManager::killBinding(Store ST, Loc L) {
    if (Optional<loc::MemRegionVal> LV = L.getAs<loc::MemRegionVal>())
      if (const MemRegion* R = LV->getRegion())
        return StoreRef(getRegionBindings(ST).removeBinding(R)
                                             .asImmutableMap()
                                             .getRootWithoutRetain(),
                        *this);
  
    return StoreRef(ST, *this);
  }
  
  RegionBindingsRef
  RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) {
    if (L.getAs<loc::ConcreteInt>())
      return B;
  
    // If we get here, the location should be a region.
    const MemRegion *R = L.castAs<loc::MemRegionVal>().getRegion();
  
    // Check if the region is a struct region.
    if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
      QualType Ty = TR->getValueType();
      if (Ty->isArrayType())
        return bindArray(B, TR, V);
      if (Ty->isStructureOrClassType())
        return bindStruct(B, TR, V);
      if (Ty->isVectorType())
        return bindVector(B, TR, V);
      if (Ty->isUnionType())
        return bindAggregate(B, TR, V);
    }
  
    if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
      // Binding directly to a symbolic region should be treated as binding
      // to element 0.
      QualType T = SR->getSymbol()->getType();
      if (T->isAnyPointerType() || T->isReferenceType())
        T = T->getPointeeType();
  
      R = GetElementZeroRegion(SR, T);
    }
  
    // Clear out bindings that may overlap with this binding.
    RegionBindingsRef NewB = removeSubRegionBindings(B, cast<SubRegion>(R));
    return NewB.addBinding(BindingKey::Make(R, BindingKey::Direct), V);
  }
  
  RegionBindingsRef
  RegionStoreManager::setImplicitDefaultValue(RegionBindingsConstRef B,
                                              const MemRegion *R,
                                              QualType T) {
    SVal V;
  
    if (Loc::isLocType(T))
      V = svalBuilder.makeNull();
    else if (T->isIntegralOrEnumerationType())
      V = svalBuilder.makeZeroVal(T);
    else if (T->isStructureOrClassType() || T->isArrayType()) {
      // Set the default value to a zero constant when it is a structure
      // or array.  The type doesn't really matter.
      V = svalBuilder.makeZeroVal(Ctx.IntTy);
    }
    else {
      // We can't represent values of this type, but we still need to set a value
      // to record that the region has been initialized.
      // If this assertion ever fires, a new case should be added above -- we
      // should know how to default-initialize any value we can symbolicate.
      assert(!SymbolManager::canSymbolicate(T) && "This type is representable");
      V = UnknownVal();
    }
  
    return B.addBinding(R, BindingKey::Default, V);
  }
  
  RegionBindingsRef
  RegionStoreManager::bindArray(RegionBindingsConstRef B,
                                const TypedValueRegion* R,
                                SVal Init) {
  
    const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
    QualType ElementTy = AT->getElementType();
    Optional<uint64_t> Size;
  
    if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
      Size = CAT->getSize().getZExtValue();
  
    // Check if the init expr is a string literal.
    if (Optional<loc::MemRegionVal> MRV = Init.getAs<loc::MemRegionVal>()) {
      const StringRegion *S = cast<StringRegion>(MRV->getRegion());
  
      // Treat the string as a lazy compound value.
      StoreRef store(B.asStore(), *this);
      nonloc::LazyCompoundVal LCV = svalBuilder.makeLazyCompoundVal(store, S)
          .castAs<nonloc::LazyCompoundVal>();
      return bindAggregate(B, R, LCV);
    }
  
    // Handle lazy compound values.
    if (Init.getAs<nonloc::LazyCompoundVal>())
      return bindAggregate(B, R, Init);
  
    if (Init.isUnknown())
      return bindAggregate(B, R, UnknownVal());
  
    // Remaining case: explicit compound values.
    const nonloc::CompoundVal& CV = Init.castAs<nonloc::CompoundVal>();
    nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
    uint64_t i = 0;
  
    RegionBindingsRef NewB(B);
  
    for (; Size.hasValue() ? i < Size.getValue() : true ; ++i, ++VI) {
      // The init list might be shorter than the array length.
      if (VI == VE)
        break;
  
      const NonLoc &Idx = svalBuilder.makeArrayIndex(i);
      const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
  
      if (ElementTy->isStructureOrClassType())
        NewB = bindStruct(NewB, ER, *VI);
      else if (ElementTy->isArrayType())
        NewB = bindArray(NewB, ER, *VI);
      else
        NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
    }
  
    // If the init list is shorter than the array length, set the
    // array default value.
    if (Size.hasValue() && i < Size.getValue())
      NewB = setImplicitDefaultValue(NewB, R, ElementTy);
  
    return NewB;
  }
  
  RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B,
                                                   const TypedValueRegion* R,
                                                   SVal V) {
    QualType T = R->getValueType();
    assert(T->isVectorType());
    const VectorType *VT = T->getAs<VectorType>(); // Use getAs for typedefs.
  
    // Handle lazy compound values and symbolic values.
    if (V.getAs<nonloc::LazyCompoundVal>() || V.getAs<nonloc::SymbolVal>())
      return bindAggregate(B, R, V);
  
    // We may get non-CompoundVal accidentally due to imprecise cast logic or
    // that we are binding symbolic struct value. Kill the field values, and if
    // the value is symbolic go and bind it as a "default" binding.
    if (!V.getAs<nonloc::CompoundVal>()) {
      return bindAggregate(B, R, UnknownVal());
    }
  
    QualType ElemType = VT->getElementType();
    nonloc::CompoundVal CV = V.castAs<nonloc::CompoundVal>();
    nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
    unsigned index = 0, numElements = VT->getNumElements();
    RegionBindingsRef NewB(B);
  
    for ( ; index != numElements ; ++index) {
      if (VI == VE)
        break;
  
      NonLoc Idx = svalBuilder.makeArrayIndex(index);
      const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
  
      if (ElemType->isArrayType())
        NewB = bindArray(NewB, ER, *VI);
      else if (ElemType->isStructureOrClassType())
        NewB = bindStruct(NewB, ER, *VI);
      else
        NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
    }
    return NewB;
  }
  
  Optional<RegionBindingsRef>
  RegionStoreManager::tryBindSmallStruct(RegionBindingsConstRef B,
                                         const TypedValueRegion *R,
                                         const RecordDecl *RD,
                                         nonloc::LazyCompoundVal LCV) {
    FieldVector Fields;
  
    if (const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD))
      if (Class->getNumBases() != 0 || Class->getNumVBases() != 0)
        return None;
  
    for (const auto *FD : RD->fields()) {
      if (FD->isUnnamedBitfield())
        continue;
  
      // If there are too many fields, or if any of the fields are aggregates,
      // just use the LCV as a default binding.
      if (Fields.size() == SmallStructLimit)
        return None;
  
      QualType Ty = FD->getType();
      if (!(Ty->isScalarType() || Ty->isReferenceType()))
        return None;
  
      Fields.push_back(FD);
    }
  
    RegionBindingsRef NewB = B;
  
    for (FieldVector::iterator I = Fields.begin(), E = Fields.end(); I != E; ++I){
      const FieldRegion *SourceFR = MRMgr.getFieldRegion(*I, LCV.getRegion());
      SVal V = getBindingForField(getRegionBindings(LCV.getStore()), SourceFR);
  
      const FieldRegion *DestFR = MRMgr.getFieldRegion(*I, R);
      NewB = bind(NewB, loc::MemRegionVal(DestFR), V);
    }
  
    return NewB;
  }
  
  RegionBindingsRef RegionStoreManager::bindStruct(RegionBindingsConstRef B,
                                                   const TypedValueRegion* R,
                                                   SVal V) {
    if (!Features.supportsFields())
      return B;
  
    QualType T = R->getValueType();
    assert(T->isStructureOrClassType());
  
    const RecordType* RT = T->getAs<RecordType>();
    const RecordDecl *RD = RT->getDecl();
  
    if (!RD->isCompleteDefinition())
      return B;
  
    // Handle lazy compound values and symbolic values.
    if (Optional<nonloc::LazyCompoundVal> LCV =
          V.getAs<nonloc::LazyCompoundVal>()) {
      if (Optional<RegionBindingsRef> NewB = tryBindSmallStruct(B, R, RD, *LCV))
        return *NewB;
      return bindAggregate(B, R, V);
    }
    if (V.getAs<nonloc::SymbolVal>())
      return bindAggregate(B, R, V);
  
    // We may get non-CompoundVal accidentally due to imprecise cast logic or
    // that we are binding symbolic struct value. Kill the field values, and if
    // the value is symbolic go and bind it as a "default" binding.
    if (V.isUnknown() || !V.getAs<nonloc::CompoundVal>())
      return bindAggregate(B, R, UnknownVal());
  
    const nonloc::CompoundVal& CV = V.castAs<nonloc::CompoundVal>();
    nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
  
    RecordDecl::field_iterator FI, FE;
    RegionBindingsRef NewB(B);
  
    for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) {
  
      if (VI == VE)
        break;
  
      // Skip any unnamed bitfields to stay in sync with the initializers.
      if (FI->isUnnamedBitfield())
        continue;
  
      QualType FTy = FI->getType();
      const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
  
      if (FTy->isArrayType())
        NewB = bindArray(NewB, FR, *VI);
      else if (FTy->isStructureOrClassType())
        NewB = bindStruct(NewB, FR, *VI);
      else
        NewB = bind(NewB, loc::MemRegionVal(FR), *VI);
      ++VI;
    }
  
    // There may be fewer values in the initialize list than the fields of struct.
    if (FI != FE) {
      NewB = NewB.addBinding(R, BindingKey::Default,
                             svalBuilder.makeIntVal(0, false));
    }
  
    return NewB;
  }
  
  RegionBindingsRef
  RegionStoreManager::bindAggregate(RegionBindingsConstRef B,
                                    const TypedRegion *R,
                                    SVal Val) {
    // Remove the old bindings, using 'R' as the root of all regions
    // we will invalidate. Then add the new binding.
    return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val);
  }
  
  //===----------------------------------------------------------------------===//
  // State pruning.
  //===----------------------------------------------------------------------===//
  
  namespace {
  class removeDeadBindingsWorker :
    public ClusterAnalysis<removeDeadBindingsWorker> {
    SmallVector<const SymbolicRegion*, 12> Postponed;
    SymbolReaper &SymReaper;
    const StackFrameContext *CurrentLCtx;
  
  public:
    removeDeadBindingsWorker(RegionStoreManager &rm,
                             ProgramStateManager &stateMgr,
                             RegionBindingsRef b, SymbolReaper &symReaper,
                             const StackFrameContext *LCtx)
      : ClusterAnalysis<removeDeadBindingsWorker>(rm, stateMgr, b),
        SymReaper(symReaper), CurrentLCtx(LCtx) {}
  
    // Called by ClusterAnalysis.
    void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C);
    void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);
    using ClusterAnalysis<removeDeadBindingsWorker>::VisitCluster;
  
    using ClusterAnalysis::AddToWorkList;
  
    bool AddToWorkList(const MemRegion *R);
  
    bool UpdatePostponed();
    void VisitBinding(SVal V);
  };
  }
  
  bool removeDeadBindingsWorker::AddToWorkList(const MemRegion *R) {
    const MemRegion *BaseR = R->getBaseRegion();
    return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
  }
  
  void removeDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
                                                     const ClusterBindings &C) {
  
    if (const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
      if (SymReaper.isLive(VR))
        AddToWorkList(baseR, &C);
  
      return;
    }
  
    if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
      if (SymReaper.isLive(SR->getSymbol()))
        AddToWorkList(SR, &C);
      else
        Postponed.push_back(SR);
  
      return;
    }
  
    if (isa<NonStaticGlobalSpaceRegion>(baseR)) {
      AddToWorkList(baseR, &C);
      return;
    }
  
    // CXXThisRegion in the current or parent location context is live.
    if (const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
      const StackArgumentsSpaceRegion *StackReg =
        cast<StackArgumentsSpaceRegion>(TR->getSuperRegion());
      const StackFrameContext *RegCtx = StackReg->getStackFrame();
      if (CurrentLCtx &&
          (RegCtx == CurrentLCtx || RegCtx->isParentOf(CurrentLCtx)))
        AddToWorkList(TR, &C);
    }
  }
  
  void removeDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
                                              const ClusterBindings *C) {
    if (!C)
      return;
  
    // Mark the symbol for any SymbolicRegion with live bindings as live itself.
    // This means we should continue to track that symbol.
    if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
      SymReaper.markLive(SymR->getSymbol());
  
    for (ClusterBindings::iterator I = C->begin(), E = C->end(); I != E; ++I) {
      // Element index of a binding key is live.
      SymReaper.markElementIndicesLive(I.getKey().getRegion());
  
      VisitBinding(I.getData());
    }
  }
  
  void removeDeadBindingsWorker::VisitBinding(SVal V) {
    // Is it a LazyCompoundVal?  All referenced regions are live as well.
    if (Optional<nonloc::LazyCompoundVal> LCS =
            V.getAs<nonloc::LazyCompoundVal>()) {
  
      const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
  
      for (RegionStoreManager::SValListTy::const_iterator I = Vals.begin(),
                                                          E = Vals.end();
           I != E; ++I)
        VisitBinding(*I);
  
      return;
    }
  
    // If V is a region, then add it to the worklist.
    if (const MemRegion *R = V.getAsRegion()) {
      AddToWorkList(R);
      SymReaper.markLive(R);
  
      // All regions captured by a block are also live.
      if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
        BlockDataRegion::referenced_vars_iterator I = BR->referenced_vars_begin(),
                                                  E = BR->referenced_vars_end();
        for ( ; I != E; ++I)
          AddToWorkList(I.getCapturedRegion());
      }
    }
  
  
    // Update the set of live symbols.
    for (SymExpr::symbol_iterator SI = V.symbol_begin(), SE = V.symbol_end();
         SI!=SE; ++SI)
      SymReaper.markLive(*SI);
  }
  
  bool removeDeadBindingsWorker::UpdatePostponed() {
    // See if any postponed SymbolicRegions are actually live now, after
    // having done a scan.
    bool changed = false;
  
    for (SmallVectorImpl<const SymbolicRegion*>::iterator
          I = Postponed.begin(), E = Postponed.end() ; I != E ; ++I) {
      if (const SymbolicRegion *SR = *I) {
        if (SymReaper.isLive(SR->getSymbol())) {
          changed |= AddToWorkList(SR);
          *I = nullptr;
        }
      }
    }
  
    return changed;
  }
  
  StoreRef RegionStoreManager::removeDeadBindings(Store store,
                                                  const StackFrameContext *LCtx,
                                                  SymbolReaper& SymReaper) {
    RegionBindingsRef B = getRegionBindings(store);
    removeDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
    W.GenerateClusters();
  
    // Enqueue the region roots onto the worklist.
    for (SymbolReaper::region_iterator I = SymReaper.region_begin(),
         E = SymReaper.region_end(); I != E; ++I) {
      W.AddToWorkList(*I);
    }
  
    do W.RunWorkList(); while (W.UpdatePostponed());
  
    // We have now scanned the store, marking reachable regions and symbols
    // as live.  We now remove all the regions that are dead from the store
    // as well as update DSymbols with the set symbols that are now dead.
    for (RegionBindingsRef::iterator I = B.begin(), E = B.end(); I != E; ++I) {
      const MemRegion *Base = I.getKey();
  
      // If the cluster has been visited, we know the region has been marked.
      if (W.isVisited(Base))
        continue;
  
      // Remove the dead entry.
      B = B.remove(Base);
  
      if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(Base))
        SymReaper.maybeDead(SymR->getSymbol());
  
      // Mark all non-live symbols that this binding references as dead.
      const ClusterBindings &Cluster = I.getData();
      for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
           CI != CE; ++CI) {
        SVal X = CI.getData();
        SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
        for (; SI != SE; ++SI)
          SymReaper.maybeDead(*SI);
      }
    }
  
    return StoreRef(B.asStore(), *this);
  }
  
  //===----------------------------------------------------------------------===//
  // Utility methods.
  //===----------------------------------------------------------------------===//
  
  void RegionStoreManager::print(Store store, raw_ostream &OS,
                                 const char* nl, const char *sep) {
    RegionBindingsRef B = getRegionBindings(store);
    OS << "Store (direct and default bindings), "
       << B.asStore()
       << " :" << nl;
    B.dump(OS, nl);
  }
  