//===-- DataflowEnvironment.cpp ---------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines an Environment class that is used by dataflow analyses
//  that run over Control-Flow Graphs (CFGs) to keep track of the state of the
//  program at given program points.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/FlowSensitive/ASTOps.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <memory>
#include <utility>

#define DEBUG_TYPE "dataflow"

namespace clang {
namespace dataflow {

// FIXME: convert these to parameters of the analysis or environment. Current
// settings have been experimentaly validated, but only for a particular
// analysis.
static constexpr int MaxCompositeValueDepth = 3;
static constexpr int MaxCompositeValueSize = 1000;

/// Returns a map consisting of key-value entries that are present in both maps.
static llvm::DenseMap<const ValueDecl *, StorageLocation *> intersectDeclToLoc(
    const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc1,
    const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc2) {
  llvm::DenseMap<const ValueDecl *, StorageLocation *> Result;
  for (auto &Entry : DeclToLoc1) {
    auto It = DeclToLoc2.find(Entry.first);
    if (It != DeclToLoc2.end() && Entry.second == It->second)
      Result.insert({Entry.first, Entry.second});
  }
  return Result;
}

// Performs a join on either `ExprToLoc` or `ExprToVal`.
// The maps must be consistent in the sense that any entries for the same
// expression must map to the same location / value. This is the case if we are
// performing a join for control flow within a full-expression (which is the
// only case when this function should be used).
template <typename MapT>
static MapT joinExprMaps(const MapT &Map1, const MapT &Map2) {
  MapT Result = Map1;

  for (const auto &Entry : Map2) {
    [[maybe_unused]] auto [It, Inserted] = Result.insert(Entry);
    // If there was an existing entry, its value should be the same as for the
    // entry we were trying to insert.
    assert(It->second == Entry.second);
  }

  return Result;
}

// Whether to consider equivalent two values with an unknown relation.
//
// FIXME: this function is a hack enabling unsoundness to support
// convergence. Once we have widening support for the reference/pointer and
// struct built-in models, this should be unconditionally `false` (and inlined
// as such at its call sites).
static bool equateUnknownValues(Value::Kind K) {
  switch (K) {
  case Value::Kind::Integer:
  case Value::Kind::Pointer:
    return true;
  default:
    return false;
  }
}

static bool compareDistinctValues(QualType Type, Value &Val1,
                                  const Environment &Env1, Value &Val2,
                                  const Environment &Env2,
                                  Environment::ValueModel &Model) {
  // Note: Potentially costly, but, for booleans, we could check whether both
  // can be proven equivalent in their respective environments.

  // FIXME: move the reference/pointers logic from `areEquivalentValues` to here
  // and implement separate, join/widen specific handling for
  // reference/pointers.
  switch (Model.compare(Type, Val1, Env1, Val2, Env2)) {
  case ComparisonResult::Same:
    return true;
  case ComparisonResult::Different:
    return false;
  case ComparisonResult::Unknown:
    return equateUnknownValues(Val1.getKind());
  }
  llvm_unreachable("All cases covered in switch");
}

/// Attempts to join distinct values `Val1` and `Val2` in `Env1` and `Env2`,
/// respectively, of the same type `Type`. Joining generally produces a single
/// value that (soundly) approximates the two inputs, although the actual
/// meaning depends on `Model`.
static Value *joinDistinctValues(QualType Type, Value &Val1,
                                 const Environment &Env1, Value &Val2,
                                 const Environment &Env2,
                                 Environment &JoinedEnv,
                                 Environment::ValueModel &Model) {
  // Join distinct boolean values preserving information about the constraints
  // in the respective path conditions.
  if (isa<BoolValue>(&Val1) && isa<BoolValue>(&Val2)) {
    // FIXME: Checking both values should be unnecessary, since they should have
    // a consistent shape.  However, right now we can end up with BoolValue's in
    // integer-typed variables due to our incorrect handling of
    // boolean-to-integer casts (we just propagate the BoolValue to the result
    // of the cast). So, a join can encounter an integer in one branch but a
    // bool in the other.
    // For example:
    // ```
    // std::optional<bool> o;
    // int x;
    // if (o.has_value())
    //   x = o.value();
    // ```
    auto &Expr1 = cast<BoolValue>(Val1).formula();
    auto &Expr2 = cast<BoolValue>(Val2).formula();
    auto &A = JoinedEnv.arena();
    auto &JoinedVal = A.makeAtomRef(A.makeAtom());
    JoinedEnv.assume(
        A.makeOr(A.makeAnd(A.makeAtomRef(Env1.getFlowConditionToken()),
                           A.makeEquals(JoinedVal, Expr1)),
                 A.makeAnd(A.makeAtomRef(Env2.getFlowConditionToken()),
                           A.makeEquals(JoinedVal, Expr2))));
    return &A.makeBoolValue(JoinedVal);
  }

  Value *JoinedVal = JoinedEnv.createValue(Type);
  if (JoinedVal)
    Model.join(Type, Val1, Env1, Val2, Env2, *JoinedVal, JoinedEnv);

  return JoinedVal;
}

static WidenResult widenDistinctValues(QualType Type, Value &Prev,
                                       const Environment &PrevEnv,
                                       Value &Current, Environment &CurrentEnv,
                                       Environment::ValueModel &Model) {
  // Boolean-model widening.
  if (isa<BoolValue>(Prev) && isa<BoolValue>(Current)) {
    // FIXME: Checking both values should be unnecessary, but we can currently
    // end up with `BoolValue`s in integer-typed variables. See comment in
    // `joinDistinctValues()` for details.
    auto &PrevBool = cast<BoolValue>(Prev);
    auto &CurBool = cast<BoolValue>(Current);

    if (isa<TopBoolValue>(Prev))
      // Safe to return `Prev` here, because Top is never dependent on the
      // environment.
      return {&Prev, LatticeEffect::Unchanged};

    // We may need to widen to Top, but before we do so, check whether both
    // values are implied to be either true or false in the current environment.
    // In that case, we can simply return a literal instead.
    bool TruePrev = PrevEnv.proves(PrevBool.formula());
    bool TrueCur = CurrentEnv.proves(CurBool.formula());
    if (TruePrev && TrueCur)
      return {&CurrentEnv.getBoolLiteralValue(true), LatticeEffect::Unchanged};
    if (!TruePrev && !TrueCur &&
        PrevEnv.proves(PrevEnv.arena().makeNot(PrevBool.formula())) &&
        CurrentEnv.proves(CurrentEnv.arena().makeNot(CurBool.formula())))
      return {&CurrentEnv.getBoolLiteralValue(false), LatticeEffect::Unchanged};

    return {&CurrentEnv.makeTopBoolValue(), LatticeEffect::Changed};
  }

  // FIXME: Add other built-in model widening.

  // Custom-model widening.
  if (auto Result = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
    return *Result;

  return {&Current, equateUnknownValues(Prev.getKind())
                        ? LatticeEffect::Unchanged
                        : LatticeEffect::Changed};
}

// Returns whether the values in `Map1` and `Map2` compare equal for those
// keys that `Map1` and `Map2` have in common.
template <typename Key>
static bool compareKeyToValueMaps(const llvm::MapVector<Key, Value *> &Map1,
                                  const llvm::MapVector<Key, Value *> &Map2,
                                  const Environment &Env1,
                                  const Environment &Env2,
                                  Environment::ValueModel &Model) {
  for (auto &Entry : Map1) {
    Key K = Entry.first;
    assert(K != nullptr);

    Value *Val = Entry.second;
    assert(Val != nullptr);

    auto It = Map2.find(K);
    if (It == Map2.end())
      continue;
    assert(It->second != nullptr);

    if (!areEquivalentValues(*Val, *It->second) &&
        !compareDistinctValues(K->getType(), *Val, Env1, *It->second, Env2,
                               Model))
      return false;
  }

  return true;
}

// Perform a join on two `LocToVal` maps.
static llvm::MapVector<const StorageLocation *, Value *>
joinLocToVal(const llvm::MapVector<const StorageLocation *, Value *> &LocToVal,
             const llvm::MapVector<const StorageLocation *, Value *> &LocToVal2,
             const Environment &Env1, const Environment &Env2,
             Environment &JoinedEnv, Environment::ValueModel &Model) {
  llvm::MapVector<const StorageLocation *, Value *> Result;
  for (auto &Entry : LocToVal) {
    const StorageLocation *Loc = Entry.first;
    assert(Loc != nullptr);

    Value *Val = Entry.second;
    assert(Val != nullptr);

    auto It = LocToVal2.find(Loc);
    if (It == LocToVal2.end())
      continue;
    assert(It->second != nullptr);

    if (Value *JoinedVal = Environment::joinValues(
            Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) {
      Result.insert({Loc, JoinedVal});
    }
  }

  return Result;
}

// Perform widening on either `LocToVal` or `ExprToVal`. `Key` must be either
// `const StorageLocation *` or `const Expr *`.
template <typename Key>
static llvm::MapVector<Key, Value *>
widenKeyToValueMap(const llvm::MapVector<Key, Value *> &CurMap,
                   const llvm::MapVector<Key, Value *> &PrevMap,
                   Environment &CurEnv, const Environment &PrevEnv,
                   Environment::ValueModel &Model, LatticeEffect &Effect) {
  llvm::MapVector<Key, Value *> WidenedMap;
  for (auto &Entry : CurMap) {
    Key K = Entry.first;
    assert(K != nullptr);

    Value *Val = Entry.second;
    assert(Val != nullptr);

    auto PrevIt = PrevMap.find(K);
    if (PrevIt == PrevMap.end())
      continue;
    assert(PrevIt->second != nullptr);

    if (areEquivalentValues(*Val, *PrevIt->second)) {
      WidenedMap.insert({K, Val});
      continue;
    }

    auto [WidenedVal, ValEffect] = widenDistinctValues(
        K->getType(), *PrevIt->second, PrevEnv, *Val, CurEnv, Model);
    WidenedMap.insert({K, WidenedVal});
    if (ValEffect == LatticeEffect::Changed)
      Effect = LatticeEffect::Changed;
  }

  return WidenedMap;
}

namespace {

// Visitor that builds a map from record prvalues to result objects.
// For each result object that it encounters, it propagates the storage location
// of the result object to all record prvalues that can initialize it.
class ResultObjectVisitor : public AnalysisASTVisitor {
public:
  // `ResultObjectMap` will be filled with a map from record prvalues to result
  // object. If this visitor will traverse a function that returns a record by
  // value, `LocForRecordReturnVal` is the location to which this record should
  // be written; otherwise, it is null.
  explicit ResultObjectVisitor(
      llvm::DenseMap<const Expr *, RecordStorageLocation *> &ResultObjectMap,
      RecordStorageLocation *LocForRecordReturnVal,
      DataflowAnalysisContext &DACtx)
      : ResultObjectMap(ResultObjectMap),
        LocForRecordReturnVal(LocForRecordReturnVal), DACtx(DACtx) {}

  // Traverse all member and base initializers of `Ctor`. This function is not
  // called by `RecursiveASTVisitor`; it should be called manually if we are
  // analyzing a constructor. `ThisPointeeLoc` is the storage location that
  // `this` points to.
  void traverseConstructorInits(const CXXConstructorDecl *Ctor,
                                RecordStorageLocation *ThisPointeeLoc) {
    assert(ThisPointeeLoc != nullptr);
    for (const CXXCtorInitializer *Init : Ctor->inits()) {
      Expr *InitExpr = Init->getInit();
      if (FieldDecl *Field = Init->getMember();
          Field != nullptr && Field->getType()->isRecordType()) {
        PropagateResultObject(InitExpr, cast<RecordStorageLocation>(
                                            ThisPointeeLoc->getChild(*Field)));
      } else if (Init->getBaseClass()) {
        PropagateResultObject(InitExpr, ThisPointeeLoc);
      }

      // Ensure that any result objects within `InitExpr` (e.g. temporaries)
      // are also propagated to the prvalues that initialize them.
      TraverseStmt(InitExpr);

      // If this is a `CXXDefaultInitExpr`, also propagate any result objects
      // within the default expression.
      if (auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(InitExpr))
        TraverseStmt(DefaultInit->getExpr());
    }
  }

  bool VisitVarDecl(VarDecl *VD) override {
    if (VD->getType()->isRecordType() && VD->hasInit())
      PropagateResultObject(
          VD->getInit(),
          &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*VD)));
    return true;
  }

  bool VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE) override {
    if (MTE->getType()->isRecordType())
      PropagateResultObject(
          MTE->getSubExpr(),
          &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*MTE)));
    return true;
  }

  bool VisitReturnStmt(ReturnStmt *Return) override {
    Expr *RetValue = Return->getRetValue();
    if (RetValue != nullptr && RetValue->getType()->isRecordType() &&
        RetValue->isPRValue())
      PropagateResultObject(RetValue, LocForRecordReturnVal);
    return true;
  }

  bool VisitExpr(Expr *E) override {
    // Clang's AST can have record-type prvalues without a result object -- for
    // example as full-expressions contained in a compound statement or as
    // arguments of call expressions. We notice this if we get here and a
    // storage location has not yet been associated with `E`. In this case,
    // treat this as if it was a `MaterializeTemporaryExpr`.
    if (E->isPRValue() && E->getType()->isRecordType() &&
        !ResultObjectMap.contains(E))
      PropagateResultObject(
          E, &cast<RecordStorageLocation>(DACtx.getStableStorageLocation(*E)));
    return true;
  }

  void
  PropagateResultObjectToRecordInitList(const RecordInitListHelper &InitList,
                                        RecordStorageLocation *Loc) {
    for (auto [Base, Init] : InitList.base_inits()) {
      assert(Base->getType().getCanonicalType() ==
             Init->getType().getCanonicalType());

      // Storage location for the base class is the same as that of the
      // derived class because we "flatten" the object hierarchy and put all
      // fields in `RecordStorageLocation` of the derived class.
      PropagateResultObject(Init, Loc);
    }

    for (auto [Field, Init] : InitList.field_inits()) {
      // Fields of non-record type are handled in
      // `TransferVisitor::VisitInitListExpr()`.
      if (Field->getType()->isRecordType())
        PropagateResultObject(
            Init, cast<RecordStorageLocation>(Loc->getChild(*Field)));
    }
  }

  // Assigns `Loc` as the result object location of `E`, then propagates the
  // location to all lower-level prvalues that initialize the same object as
  // `E` (or one of its base classes or member variables).
  void PropagateResultObject(Expr *E, RecordStorageLocation *Loc) {
    if (!E->isPRValue() || !E->getType()->isRecordType()) {
      assert(false);
      // Ensure we don't propagate the result object if we hit this in a
      // release build.
      return;
    }

    ResultObjectMap[E] = Loc;

    // The following AST node kinds are "original initializers": They are the
    // lowest-level AST node that initializes a given object, and nothing
    // below them can initialize the same object (or part of it).
    if (isa<CXXConstructExpr>(E) || isa<CallExpr>(E) || isa<LambdaExpr>(E) ||
        isa<CXXDefaultArgExpr>(E) || isa<CXXStdInitializerListExpr>(E) ||
        isa<AtomicExpr>(E) || isa<CXXInheritedCtorInitExpr>(E) ||
        // We treat `BuiltinBitCastExpr` as an "original initializer" too as
        // it may not even be casting from a record type -- and even if it is,
        // the two objects are in general of unrelated type.
        isa<BuiltinBitCastExpr>(E)) {
      return;
    }
    if (auto *Op = dyn_cast<BinaryOperator>(E);
        Op && Op->getOpcode() == BO_Cmp) {
      // Builtin `<=>` returns a `std::strong_ordering` object.
      return;
    }

    if (auto *InitList = dyn_cast<InitListExpr>(E)) {
      if (!InitList->isSemanticForm())
        return;
      if (InitList->isTransparent()) {
        PropagateResultObject(InitList->getInit(0), Loc);
        return;
      }

      PropagateResultObjectToRecordInitList(RecordInitListHelper(InitList),
                                            Loc);
      return;
    }

    if (auto *ParenInitList = dyn_cast<CXXParenListInitExpr>(E)) {
      PropagateResultObjectToRecordInitList(RecordInitListHelper(ParenInitList),
                                            Loc);
      return;
    }

    if (auto *Op = dyn_cast<BinaryOperator>(E); Op && Op->isCommaOp()) {
      PropagateResultObject(Op->getRHS(), Loc);
      return;
    }

    if (auto *Cond = dyn_cast<AbstractConditionalOperator>(E)) {
      PropagateResultObject(Cond->getTrueExpr(), Loc);
      PropagateResultObject(Cond->getFalseExpr(), Loc);
      return;
    }

    if (auto *SE = dyn_cast<StmtExpr>(E)) {
      PropagateResultObject(cast<Expr>(SE->getSubStmt()->body_back()), Loc);
      return;
    }

    if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(E)) {
      PropagateResultObject(DIE->getExpr(), Loc);
      return;
    }

    // All other expression nodes that propagate a record prvalue should have
    // exactly one child.
    SmallVector<Stmt *, 1> Children(E->child_begin(), E->child_end());
    LLVM_DEBUG({
      if (Children.size() != 1)
        E->dump();
    });
    assert(Children.size() == 1);
    for (Stmt *S : Children)
      PropagateResultObject(cast<Expr>(S), Loc);
  }

private:
  llvm::DenseMap<const Expr *, RecordStorageLocation *> &ResultObjectMap;
  RecordStorageLocation *LocForRecordReturnVal;
  DataflowAnalysisContext &DACtx;
};

} // namespace

void Environment::initialize() {
  if (InitialTargetStmt == nullptr)
    return;

  if (InitialTargetFunc == nullptr) {
    initFieldsGlobalsAndFuncs(getReferencedDecls(*InitialTargetStmt));
    ResultObjectMap =
        std::make_shared<PrValueToResultObject>(buildResultObjectMap(
            DACtx, InitialTargetStmt, getThisPointeeStorageLocation(),
            /*LocForRecordReturnValue=*/nullptr));
    return;
  }

  initFieldsGlobalsAndFuncs(getReferencedDecls(*InitialTargetFunc));

  for (const auto *ParamDecl : InitialTargetFunc->parameters()) {
    assert(ParamDecl != nullptr);
    setStorageLocation(*ParamDecl, createObject(*ParamDecl, nullptr));
  }

  if (InitialTargetFunc->getReturnType()->isRecordType())
    LocForRecordReturnVal = &cast<RecordStorageLocation>(
        createStorageLocation(InitialTargetFunc->getReturnType()));

  if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(InitialTargetFunc)) {
    auto *Parent = MethodDecl->getParent();
    assert(Parent != nullptr);

    if (Parent->isLambda()) {
      for (const auto &Capture : Parent->captures()) {
        if (Capture.capturesVariable()) {
          const auto *VarDecl = Capture.getCapturedVar();
          assert(VarDecl != nullptr);
          setStorageLocation(*VarDecl, createObject(*VarDecl, nullptr));
        } else if (Capture.capturesThis()) {
          if (auto *Ancestor = InitialTargetFunc->getNonClosureAncestor()) {
            const auto *SurroundingMethodDecl = cast<CXXMethodDecl>(Ancestor);
            QualType ThisPointeeType =
                SurroundingMethodDecl->getFunctionObjectParameterType();
            setThisPointeeStorageLocation(
                cast<RecordStorageLocation>(createObject(ThisPointeeType)));
          } else if (auto *FieldBeingInitialized =
                         dyn_cast<FieldDecl>(Parent->getLambdaContextDecl())) {
            // This is in a field initializer, rather than a method.
            const RecordDecl *RD = FieldBeingInitialized->getParent();
            const ASTContext &Ctx = RD->getASTContext();
            CanQualType T = Ctx.getCanonicalTagType(RD);
            setThisPointeeStorageLocation(
                cast<RecordStorageLocation>(createObject(T)));
          } else {
            assert(false && "Unexpected this-capturing lambda context.");
          }
        }
      }
    } else if (MethodDecl->isImplicitObjectMemberFunction()) {
      QualType ThisPointeeType = MethodDecl->getFunctionObjectParameterType();
      auto &ThisLoc =
          cast<RecordStorageLocation>(createStorageLocation(ThisPointeeType));
      setThisPointeeStorageLocation(ThisLoc);
      // Initialize fields of `*this` with values, but only if we're not
      // analyzing a constructor; after all, it's the constructor's job to do
      // this (and we want to be able to test that).
      if (!isa<CXXConstructorDecl>(MethodDecl))
        initializeFieldsWithValues(ThisLoc);
    }
  }

  // We do this below the handling of `CXXMethodDecl` above so that we can
  // be sure that the storage location for `this` has been set.
  ResultObjectMap =
      std::make_shared<PrValueToResultObject>(buildResultObjectMap(
          DACtx, InitialTargetFunc, getThisPointeeStorageLocation(),
          LocForRecordReturnVal));
}

// FIXME: Add support for resetting globals after function calls to enable the
// implementation of sound analyses.

void Environment::initFieldsGlobalsAndFuncs(const ReferencedDecls &Referenced) {
  // These have to be added before the lines that follow to ensure that
  // `create*` work correctly for structs.
  DACtx->addModeledFields(Referenced.Fields);

  for (const VarDecl *D : Referenced.Globals) {
    if (getStorageLocation(*D) != nullptr)
      continue;

    // We don't run transfer functions on the initializers of global variables,
    // so they won't be associated with a value or storage location. We
    // therefore intentionally don't pass an initializer to `createObject()`; in
    // particular, this ensures that `createObject()` will initialize the fields
    // of record-type variables with values.
    setStorageLocation(*D, createObject(*D, nullptr));
  }

  for (const FunctionDecl *FD : Referenced.Functions) {
    if (getStorageLocation(*FD) != nullptr)
      continue;
    auto &Loc = createStorageLocation(*FD);
    setStorageLocation(*FD, Loc);
  }
}

Environment Environment::fork() const {
  Environment Copy(*this);
  Copy.FlowConditionToken = DACtx->forkFlowCondition(FlowConditionToken);
  return Copy;
}

bool Environment::canDescend(unsigned MaxDepth,
                             const FunctionDecl *Callee) const {
  return CallStack.size() < MaxDepth && !llvm::is_contained(CallStack, Callee);
}

Environment Environment::pushCall(const CallExpr *Call) const {
  Environment Env(*this);

  if (const auto *MethodCall = dyn_cast<CXXMemberCallExpr>(Call)) {
    if (const Expr *Arg = MethodCall->getImplicitObjectArgument()) {
      if (!isa<CXXThisExpr>(Arg))
        Env.ThisPointeeLoc =
            cast<RecordStorageLocation>(getStorageLocation(*Arg));
      // Otherwise (when the argument is `this`), retain the current
      // environment's `ThisPointeeLoc`.
    }
  }

  if (Call->getType()->isRecordType() && Call->isPRValue())
    Env.LocForRecordReturnVal = &Env.getResultObjectLocation(*Call);

  Env.pushCallInternal(Call->getDirectCallee(),
                       llvm::ArrayRef(Call->getArgs(), Call->getNumArgs()));

  return Env;
}

Environment Environment::pushCall(const CXXConstructExpr *Call) const {
  Environment Env(*this);

  Env.ThisPointeeLoc = &Env.getResultObjectLocation(*Call);
  Env.LocForRecordReturnVal = &Env.getResultObjectLocation(*Call);

  Env.pushCallInternal(Call->getConstructor(),
                       llvm::ArrayRef(Call->getArgs(), Call->getNumArgs()));

  return Env;
}

void Environment::pushCallInternal(const FunctionDecl *FuncDecl,
                                   ArrayRef<const Expr *> Args) {
  // Canonicalize to the definition of the function. This ensures that we're
  // putting arguments into the same `ParamVarDecl`s` that the callee will later
  // be retrieving them from.
  assert(FuncDecl->getDefinition() != nullptr);
  FuncDecl = FuncDecl->getDefinition();

  CallStack.push_back(FuncDecl);

  initFieldsGlobalsAndFuncs(getReferencedDecls(*FuncDecl));

  const auto *ParamIt = FuncDecl->param_begin();

  // FIXME: Parameters don't always map to arguments 1:1; examples include
  // overloaded operators implemented as member functions, and parameter packs.
  for (unsigned ArgIndex = 0; ArgIndex < Args.size(); ++ParamIt, ++ArgIndex) {
    assert(ParamIt != FuncDecl->param_end());
    const VarDecl *Param = *ParamIt;
    setStorageLocation(*Param, createObject(*Param, Args[ArgIndex]));
  }

  ResultObjectMap = std::make_shared<PrValueToResultObject>(
      buildResultObjectMap(DACtx, FuncDecl, getThisPointeeStorageLocation(),
                           LocForRecordReturnVal));
}

void Environment::popCall(const CallExpr *Call, const Environment &CalleeEnv) {
  // We ignore some entries of `CalleeEnv`:
  // - `DACtx` because is already the same in both
  // - We don't want the callee's `DeclCtx`, `ReturnVal`, `ReturnLoc` or
  //   `ThisPointeeLoc` because they don't apply to us.
  // - `DeclToLoc`, `ExprToLoc`, and `ExprToVal` capture information from the
  //   callee's local scope, so when popping that scope, we do not propagate
  //   the maps.
  this->LocToVal = std::move(CalleeEnv.LocToVal);
  this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);

  if (Call->isGLValue()) {
    if (CalleeEnv.ReturnLoc != nullptr)
      setStorageLocation(*Call, *CalleeEnv.ReturnLoc);
  } else if (!Call->getType()->isVoidType()) {
    if (CalleeEnv.ReturnVal != nullptr)
      setValue(*Call, *CalleeEnv.ReturnVal);
  }
}

void Environment::popCall(const CXXConstructExpr *Call,
                          const Environment &CalleeEnv) {
  // See also comment in `popCall(const CallExpr *, const Environment &)` above.
  this->LocToVal = std::move(CalleeEnv.LocToVal);
  this->FlowConditionToken = std::move(CalleeEnv.FlowConditionToken);
}

bool Environment::equivalentTo(const Environment &Other,
                               Environment::ValueModel &Model) const {
  assert(DACtx == Other.DACtx);

  if (ReturnVal != Other.ReturnVal)
    return false;

  if (ReturnLoc != Other.ReturnLoc)
    return false;

  if (LocForRecordReturnVal != Other.LocForRecordReturnVal)
    return false;

  if (ThisPointeeLoc != Other.ThisPointeeLoc)
    return false;

  if (DeclToLoc != Other.DeclToLoc)
    return false;

  if (ExprToLoc != Other.ExprToLoc)
    return false;

  if (!compareKeyToValueMaps(ExprToVal, Other.ExprToVal, *this, Other, Model))
    return false;

  if (!compareKeyToValueMaps(LocToVal, Other.LocToVal, *this, Other, Model))
    return false;

  return true;
}

LatticeEffect Environment::widen(const Environment &PrevEnv,
                                 Environment::ValueModel &Model) {
  assert(DACtx == PrevEnv.DACtx);
  assert(ReturnVal == PrevEnv.ReturnVal);
  assert(ReturnLoc == PrevEnv.ReturnLoc);
  assert(LocForRecordReturnVal == PrevEnv.LocForRecordReturnVal);
  assert(ThisPointeeLoc == PrevEnv.ThisPointeeLoc);
  assert(CallStack == PrevEnv.CallStack);
  assert(ResultObjectMap == PrevEnv.ResultObjectMap);
  assert(InitialTargetFunc == PrevEnv.InitialTargetFunc);
  assert(InitialTargetStmt == PrevEnv.InitialTargetStmt);

  auto Effect = LatticeEffect::Unchanged;

  // By the API, `PrevEnv` is a previous version of the environment for the same
  // block, so we have some guarantees about its shape. In particular, it will
  // be the result of a join or widen operation on previous values for this
  // block. For `DeclToLoc`, `ExprToVal`, and `ExprToLoc`, join guarantees that
  // these maps are subsets of the maps in `PrevEnv`. So, as long as we maintain
  // this property here, we don't need change their current values to widen.
  assert(DeclToLoc.size() <= PrevEnv.DeclToLoc.size());
  assert(ExprToVal.size() <= PrevEnv.ExprToVal.size());
  assert(ExprToLoc.size() <= PrevEnv.ExprToLoc.size());

  ExprToVal = widenKeyToValueMap(ExprToVal, PrevEnv.ExprToVal, *this, PrevEnv,
                                 Model, Effect);

  LocToVal = widenKeyToValueMap(LocToVal, PrevEnv.LocToVal, *this, PrevEnv,
                                Model, Effect);
  if (DeclToLoc.size() != PrevEnv.DeclToLoc.size() ||
      ExprToLoc.size() != PrevEnv.ExprToLoc.size() ||
      ExprToVal.size() != PrevEnv.ExprToVal.size() ||
      LocToVal.size() != PrevEnv.LocToVal.size())
    Effect = LatticeEffect::Changed;

  return Effect;
}

Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
                              Environment::ValueModel &Model,
                              ExprJoinBehavior ExprBehavior) {
  assert(EnvA.DACtx == EnvB.DACtx);
  assert(EnvA.LocForRecordReturnVal == EnvB.LocForRecordReturnVal);
  assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc);
  assert(EnvA.CallStack == EnvB.CallStack);
  assert(EnvA.ResultObjectMap == EnvB.ResultObjectMap);
  assert(EnvA.InitialTargetFunc == EnvB.InitialTargetFunc);
  assert(EnvA.InitialTargetStmt == EnvB.InitialTargetStmt);

  Environment JoinedEnv(*EnvA.DACtx);

  JoinedEnv.CallStack = EnvA.CallStack;
  JoinedEnv.ResultObjectMap = EnvA.ResultObjectMap;
  JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal;
  JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;
  JoinedEnv.InitialTargetFunc = EnvA.InitialTargetFunc;
  JoinedEnv.InitialTargetStmt = EnvA.InitialTargetStmt;

  const FunctionDecl *Func = EnvA.getCurrentFunc();
  if (!Func) {
    JoinedEnv.ReturnVal = nullptr;
  } else {
    JoinedEnv.ReturnVal =
        joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal,
                   EnvB, JoinedEnv, Model);
  }

  if (EnvA.ReturnLoc == EnvB.ReturnLoc)
    JoinedEnv.ReturnLoc = EnvA.ReturnLoc;
  else
    JoinedEnv.ReturnLoc = nullptr;

  JoinedEnv.DeclToLoc = intersectDeclToLoc(EnvA.DeclToLoc, EnvB.DeclToLoc);

  // FIXME: update join to detect backedges and simplify the flow condition
  // accordingly.
  JoinedEnv.FlowConditionToken = EnvA.DACtx->joinFlowConditions(
      EnvA.FlowConditionToken, EnvB.FlowConditionToken);

  JoinedEnv.LocToVal =
      joinLocToVal(EnvA.LocToVal, EnvB.LocToVal, EnvA, EnvB, JoinedEnv, Model);

  if (ExprBehavior == KeepExprState) {
    JoinedEnv.ExprToVal = joinExprMaps(EnvA.ExprToVal, EnvB.ExprToVal);
    JoinedEnv.ExprToLoc = joinExprMaps(EnvA.ExprToLoc, EnvB.ExprToLoc);
  }

  return JoinedEnv;
}

Value *Environment::joinValues(QualType Ty, Value *Val1,
                               const Environment &Env1, Value *Val2,
                               const Environment &Env2, Environment &JoinedEnv,
                               Environment::ValueModel &Model) {
  if (Val1 == nullptr || Val2 == nullptr)
    // We can't say anything about the joined value -- even if one of the values
    // is non-null, we don't want to simply propagate it, because it would be
    // too specific: Because the other value is null, that means we have no
    // information at all about the value (i.e. the value is unconstrained).
    return nullptr;

  if (areEquivalentValues(*Val1, *Val2))
    // Arbitrarily return one of the two values.
    return Val1;

  return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model);
}

StorageLocation &Environment::createStorageLocation(QualType Type) {
  return DACtx->createStorageLocation(Type);
}

StorageLocation &Environment::createStorageLocation(const ValueDecl &D) {
  // Evaluated declarations are always assigned the same storage locations to
  // ensure that the environment stabilizes across loop iterations. Storage
  // locations for evaluated declarations are stored in the analysis context.
  return DACtx->getStableStorageLocation(D);
}

StorageLocation &Environment::createStorageLocation(const Expr &E) {
  // Evaluated expressions are always assigned the same storage locations to
  // ensure that the environment stabilizes across loop iterations. Storage
  // locations for evaluated expressions are stored in the analysis context.
  return DACtx->getStableStorageLocation(E);
}

void Environment::setStorageLocation(const ValueDecl &D, StorageLocation &Loc) {
  assert(!DeclToLoc.contains(&D));
  // The only kinds of declarations that may have a "variable" storage location
  // are declarations of reference type and `BindingDecl`. For all other
  // declaration, the storage location should be the stable storage location
  // returned by `createStorageLocation()`.
  assert(D.getType()->isReferenceType() || isa<BindingDecl>(D) ||
         &Loc == &createStorageLocation(D));
  DeclToLoc[&D] = &Loc;
}

StorageLocation *Environment::getStorageLocation(const ValueDecl &D) const {
  auto It = DeclToLoc.find(&D);
  if (It == DeclToLoc.end())
    return nullptr;

  StorageLocation *Loc = It->second;

  return Loc;
}

void Environment::removeDecl(const ValueDecl &D) { DeclToLoc.erase(&D); }

void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) {
  // `DeclRefExpr`s to builtin function types aren't glvalues, for some reason,
  // but we still want to be able to associate a `StorageLocation` with them,
  // so allow these as an exception.
  assert(E.isGLValue() ||
         E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
  const Expr &CanonE = ignoreCFGOmittedNodes(E);
  assert(!ExprToLoc.contains(&CanonE));
  ExprToLoc[&CanonE] = &Loc;
}

StorageLocation *Environment::getStorageLocation(const Expr &E) const {
  // See comment in `setStorageLocation()`.
  assert(E.isGLValue() ||
         E.getType()->isSpecificBuiltinType(BuiltinType::BuiltinFn));
  auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
  return It == ExprToLoc.end() ? nullptr : &*It->second;
}

RecordStorageLocation &
Environment::getResultObjectLocation(const Expr &RecordPRValue) const {
  assert(RecordPRValue.getType()->isRecordType());
  assert(RecordPRValue.isPRValue());

  assert(ResultObjectMap != nullptr);
  RecordStorageLocation *Loc = ResultObjectMap->lookup(&RecordPRValue);
  assert(Loc != nullptr);
  // In release builds, use the "stable" storage location if the map lookup
  // failed.
  if (Loc == nullptr)
    return cast<RecordStorageLocation>(
        DACtx->getStableStorageLocation(RecordPRValue));
  return *Loc;
}

PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) {
  return DACtx->getOrCreateNullPointerValue(PointeeType);
}

void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc,
                                             QualType Type) {
  llvm::DenseSet<QualType> Visited;
  int CreatedValuesCount = 0;
  initializeFieldsWithValues(Loc, Type, Visited, 0, CreatedValuesCount);
  if (CreatedValuesCount > MaxCompositeValueSize) {
    llvm::errs() << "Attempting to initialize a huge value of type: " << Type
                 << '\n';
  }
}

void Environment::setValue(const StorageLocation &Loc, Value &Val) {
  // Records should not be associated with values.
  assert(!isa<RecordStorageLocation>(Loc));
  LocToVal[&Loc] = &Val;
}

void Environment::setValue(const Expr &E, Value &Val) {
  const Expr &CanonE = ignoreCFGOmittedNodes(E);

  assert(CanonE.isPRValue());
  // Records should not be associated with values.
  assert(!CanonE.getType()->isRecordType());
  ExprToVal[&CanonE] = &Val;
}

Value *Environment::getValue(const StorageLocation &Loc) const {
  // Records should not be associated with values.
  assert(!isa<RecordStorageLocation>(Loc));
  return LocToVal.lookup(&Loc);
}

Value *Environment::getValue(const ValueDecl &D) const {
  auto *Loc = getStorageLocation(D);
  if (Loc == nullptr)
    return nullptr;
  return getValue(*Loc);
}

Value *Environment::getValue(const Expr &E) const {
  // Records should not be associated with values.
  assert(!E.getType()->isRecordType());

  if (E.isPRValue()) {
    auto It = ExprToVal.find(&ignoreCFGOmittedNodes(E));
    return It == ExprToVal.end() ? nullptr : It->second;
  }

  auto It = ExprToLoc.find(&ignoreCFGOmittedNodes(E));
  if (It == ExprToLoc.end())
    return nullptr;
  return getValue(*It->second);
}

Value *Environment::createValue(QualType Type) {
  llvm::DenseSet<QualType> Visited;
  int CreatedValuesCount = 0;
  Value *Val = createValueUnlessSelfReferential(Type, Visited, /*Depth=*/0,
                                                CreatedValuesCount);
  if (CreatedValuesCount > MaxCompositeValueSize) {
    llvm::errs() << "Attempting to initialize a huge value of type: " << Type
                 << '\n';
  }
  return Val;
}

Value *Environment::createValueUnlessSelfReferential(
    QualType Type, llvm::DenseSet<QualType> &Visited, int Depth,
    int &CreatedValuesCount) {
  assert(!Type.isNull());
  assert(!Type->isReferenceType());
  assert(!Type->isRecordType());

  // Allow unlimited fields at depth 1; only cap at deeper nesting levels.
  if ((Depth > 1 && CreatedValuesCount > MaxCompositeValueSize) ||
      Depth > MaxCompositeValueDepth)
    return nullptr;

  if (Type->isBooleanType()) {
    CreatedValuesCount++;
    return &makeAtomicBoolValue();
  }

  if (Type->isIntegerType()) {
    // FIXME: consider instead `return nullptr`, given that we do nothing useful
    // with integers, and so distinguishing them serves no purpose, but could
    // prevent convergence.
    CreatedValuesCount++;
    return &arena().create<IntegerValue>();
  }

  if (Type->isPointerType()) {
    CreatedValuesCount++;
    QualType PointeeType = Type->getPointeeType();
    StorageLocation &PointeeLoc =
        createLocAndMaybeValue(PointeeType, Visited, Depth, CreatedValuesCount);

    return &arena().create<PointerValue>(PointeeLoc);
  }

  return nullptr;
}

StorageLocation &
Environment::createLocAndMaybeValue(QualType Ty,
                                    llvm::DenseSet<QualType> &Visited,
                                    int Depth, int &CreatedValuesCount) {
  if (!Visited.insert(Ty.getCanonicalType()).second)
    return createStorageLocation(Ty.getNonReferenceType());
  auto EraseVisited = llvm::make_scope_exit(
      [&Visited, Ty] { Visited.erase(Ty.getCanonicalType()); });

  Ty = Ty.getNonReferenceType();

  if (Ty->isRecordType()) {
    auto &Loc = cast<RecordStorageLocation>(createStorageLocation(Ty));
    initializeFieldsWithValues(Loc, Ty, Visited, Depth, CreatedValuesCount);
    return Loc;
  }

  StorageLocation &Loc = createStorageLocation(Ty);

  if (Value *Val = createValueUnlessSelfReferential(Ty, Visited, Depth,
                                                    CreatedValuesCount))
    setValue(Loc, *Val);

  return Loc;
}

void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc,
                                             QualType Type,
                                             llvm::DenseSet<QualType> &Visited,
                                             int Depth,
                                             int &CreatedValuesCount) {
  auto initField = [&](QualType FieldType, StorageLocation &FieldLoc) {
    if (FieldType->isRecordType()) {
      auto &FieldRecordLoc = cast<RecordStorageLocation>(FieldLoc);
      initializeFieldsWithValues(FieldRecordLoc, FieldRecordLoc.getType(),
                                 Visited, Depth + 1, CreatedValuesCount);
    } else {
      if (getValue(FieldLoc) != nullptr)
        return;
      if (!Visited.insert(FieldType.getCanonicalType()).second)
        return;
      if (Value *Val = createValueUnlessSelfReferential(
              FieldType, Visited, Depth + 1, CreatedValuesCount))
        setValue(FieldLoc, *Val);
      Visited.erase(FieldType.getCanonicalType());
    }
  };

  for (const FieldDecl *Field : DACtx->getModeledFields(Type)) {
    assert(Field != nullptr);
    QualType FieldType = Field->getType();

    if (FieldType->isReferenceType()) {
      Loc.setChild(*Field,
                   &createLocAndMaybeValue(FieldType, Visited, Depth + 1,
                                           CreatedValuesCount));
    } else {
      StorageLocation *FieldLoc = Loc.getChild(*Field);
      assert(FieldLoc != nullptr);
      initField(FieldType, *FieldLoc);
    }
  }
  for (const auto &[FieldName, FieldType] : DACtx->getSyntheticFields(Type)) {
    // Synthetic fields cannot have reference type, so we don't need to deal
    // with this case.
    assert(!FieldType->isReferenceType());
    initField(FieldType, Loc.getSyntheticField(FieldName));
  }
}

StorageLocation &Environment::createObjectInternal(const ValueDecl *D,
                                                   QualType Ty,
                                                   const Expr *InitExpr) {
  if (Ty->isReferenceType()) {
    // Although variables of reference type always need to be initialized, it
    // can happen that we can't see the initializer, so `InitExpr` may still
    // be null.
    if (InitExpr) {
      if (auto *InitExprLoc = getStorageLocation(*InitExpr))
        return *InitExprLoc;
    }

    // Even though we have an initializer, we might not get an
    // InitExprLoc, for example if the InitExpr is a CallExpr for which we
    // don't have a function body. In this case, we just invent a storage
    // location and value -- it's the best we can do.
    return createObjectInternal(D, Ty.getNonReferenceType(), nullptr);
  }

  StorageLocation &Loc =
      D ? createStorageLocation(*D) : createStorageLocation(Ty);

  if (Ty->isRecordType()) {
    auto &RecordLoc = cast<RecordStorageLocation>(Loc);
    if (!InitExpr)
      initializeFieldsWithValues(RecordLoc);
  } else {
    Value *Val = nullptr;
    if (InitExpr)
      // In the (few) cases where an expression is intentionally
      // "uninterpreted", `InitExpr` is not associated with a value.  There are
      // two ways to handle this situation: propagate the status, so that
      // uninterpreted initializers result in uninterpreted variables, or
      // provide a default value. We choose the latter so that later refinements
      // of the variable can be used for reasoning about the surrounding code.
      // For this reason, we let this case be handled by the `createValue()`
      // call below.
      //
      // FIXME. If and when we interpret all language cases, change this to
      // assert that `InitExpr` is interpreted, rather than supplying a
      // default value (assuming we don't update the environment API to return
      // references).
      Val = getValue(*InitExpr);
    if (!Val)
      Val = createValue(Ty);
    if (Val)
      setValue(Loc, *Val);
  }

  return Loc;
}

void Environment::assume(const Formula &F) {
  DACtx->addFlowConditionConstraint(FlowConditionToken, F);
}

bool Environment::proves(const Formula &F) const {
  return DACtx->flowConditionImplies(FlowConditionToken, F);
}

bool Environment::allows(const Formula &F) const {
  return DACtx->flowConditionAllows(FlowConditionToken, F);
}

void Environment::dump(raw_ostream &OS) const {
  llvm::DenseMap<const StorageLocation *, std::string> LocToName;
  if (LocForRecordReturnVal != nullptr)
    LocToName[LocForRecordReturnVal] = "(returned record)";
  if (ThisPointeeLoc != nullptr)
    LocToName[ThisPointeeLoc] = "this";

  OS << "DeclToLoc:\n";
  for (auto [D, L] : DeclToLoc) {
    auto Iter = LocToName.insert({L, D->getNameAsString()}).first;
    OS << "  [" << Iter->second << ", " << L << "]\n";
  }
  OS << "ExprToLoc:\n";
  for (auto [E, L] : ExprToLoc)
    OS << "  [" << E << ", " << L << "]\n";

  OS << "ExprToVal:\n";
  for (auto [E, V] : ExprToVal)
    OS << "  [" << E << ", " << V << ": " << *V << "]\n";

  OS << "LocToVal:\n";
  for (auto [L, V] : LocToVal) {
    OS << "  [" << L;
    if (auto Iter = LocToName.find(L); Iter != LocToName.end())
      OS << " (" << Iter->second << ")";
    OS << ", " << V << ": " << *V << "]\n";
  }

  if (const FunctionDecl *Func = getCurrentFunc()) {
    if (Func->getReturnType()->isReferenceType()) {
      OS << "ReturnLoc: " << ReturnLoc;
      if (auto Iter = LocToName.find(ReturnLoc); Iter != LocToName.end())
        OS << " (" << Iter->second << ")";
      OS << "\n";
    } else if (Func->getReturnType()->isRecordType() ||
               isa<CXXConstructorDecl>(Func)) {
      OS << "LocForRecordReturnVal: " << LocForRecordReturnVal << "\n";
    } else if (!Func->getReturnType()->isVoidType()) {
      if (ReturnVal == nullptr)
        OS << "ReturnVal: nullptr\n";
      else
        OS << "ReturnVal: " << *ReturnVal << "\n";
    }

    if (isa<CXXMethodDecl>(Func)) {
      OS << "ThisPointeeLoc: " << ThisPointeeLoc << "\n";
    }
  }

  OS << "\n";
  DACtx->dumpFlowCondition(FlowConditionToken, OS);
}

void Environment::dump() const { dump(llvm::dbgs()); }

Environment::PrValueToResultObject Environment::buildResultObjectMap(
    DataflowAnalysisContext *DACtx, const FunctionDecl *FuncDecl,
    RecordStorageLocation *ThisPointeeLoc,
    RecordStorageLocation *LocForRecordReturnVal) {
  assert(FuncDecl->doesThisDeclarationHaveABody());

  PrValueToResultObject Map = buildResultObjectMap(
      DACtx, FuncDecl->getBody(), ThisPointeeLoc, LocForRecordReturnVal);

  ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx);
  if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(FuncDecl))
    Visitor.traverseConstructorInits(Ctor, ThisPointeeLoc);

  return Map;
}

Environment::PrValueToResultObject Environment::buildResultObjectMap(
    DataflowAnalysisContext *DACtx, Stmt *S,
    RecordStorageLocation *ThisPointeeLoc,
    RecordStorageLocation *LocForRecordReturnVal) {
  PrValueToResultObject Map;
  ResultObjectVisitor Visitor(Map, LocForRecordReturnVal, *DACtx);
  Visitor.TraverseStmt(S);
  return Map;
}

RecordStorageLocation *getImplicitObjectLocation(const CXXMemberCallExpr &MCE,
                                                 const Environment &Env) {
  Expr *ImplicitObject = MCE.getImplicitObjectArgument();
  if (ImplicitObject == nullptr)
    return nullptr;
  if (ImplicitObject->getType()->isPointerType()) {
    if (auto *Val = Env.get<PointerValue>(*ImplicitObject))
      return &cast<RecordStorageLocation>(Val->getPointeeLoc());
    return nullptr;
  }
  return cast_or_null<RecordStorageLocation>(
      Env.getStorageLocation(*ImplicitObject));
}

RecordStorageLocation *getBaseObjectLocation(const MemberExpr &ME,
                                             const Environment &Env) {
  Expr *Base = ME.getBase();
  if (Base == nullptr)
    return nullptr;
  if (ME.isArrow()) {
    if (auto *Val = Env.get<PointerValue>(*Base))
      return &cast<RecordStorageLocation>(Val->getPointeeLoc());
    return nullptr;
  }
  return Env.get<RecordStorageLocation>(*Base);
}

} // namespace dataflow
} // namespace clang
