//== 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/AnalysisDeclContext.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 {
    // FIXME: The offsets of empty bases can be tricky because of
    // of the so called "empty base class optimization".
    // If a base class has been optimized out
    // we should not try to create a binding, otherwise we should.
    // Unfortunately, at the moment ASTRecordLayout doesn't expose
    // the actual sizes of the empty bases
    // and trying to infer them from offsets/alignments
    // seems to be error-prone and non-trivial because of the trailing padding.
    // As a temporary mitigation we don't create bindings for empty bases.
    if (R->getKind() == MemRegion::CXXBaseObjectRegionKind &&
        cast<CXXBaseObjectRegion>(R)->getDecl()->isEmpty())
      return StoreRef(store, *this);

    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);
  }

  Optional<SVal> getDefaultBinding(Store S, const MemRegion *R) override {
    RegionBindingsRef B = getRegionBindings(S);
    // Default bindings are always applied over a base region so look up the
    // base region's default binding, otherwise the lookup will fail when R
    // is at an offset from R->getBaseRegion().
    return B.getDefaultBinding(R->getBaseRegion());
  }

  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::ConcreteInt>())
    return Array;

  if (!Array.getAs<loc::MemRegionVal>())
    return UnknownVal();

  const SubRegion *R =
      cast<SubRegion>(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<TypedValueRegion>(MR)) {
    if (T.isNull()) {
      if (const TypedRegion *TR = dyn_cast<TypedRegion>(MR))
        T = TR->getLocationType()->getPointeeType();
      else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
        T = SR->getSymbol()->getType()->getPointeeType();
      else if (isa<AllocaRegion>(MR))
        T = Ctx.VoidTy;
    }
    assert(!T.isNull() && "Unable to auto-detect binding type!");
    if (T->isVoidType()) {
      // When trying to dereference a void pointer, read the first byte.
      T = Ctx.CharTy;
    }
    MR = GetElementZeroRegion(cast<SubRegion>(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 literal. If so, bind the rvalue instead.
  // FIXME: It's not responsibility of the Store to transform this lvalue
  // to rvalue. ExprEngine or maybe even CFG should do this before binding.
  if (Optional<loc::MemRegionVal> MRV = Init.getAs<loc::MemRegionVal>()) {
    SVal V = getBinding(B.asStore(), *MRV, R->getValueType());
    return bindAggregate(B, R, V);
  }

  // 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);
}
