//===- SValBuilder.cpp - Basic class for all SValBuilder implementations --===//
//
// 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 SValBuilder, the base class for all (complete) SValBuilder
//  implementations.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/Type.h"
#include "clang/Basic/LLVM.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include <cassert>
#include <tuple>

using namespace clang;
using namespace ento;

//===----------------------------------------------------------------------===//
// Basic SVal creation.
//===----------------------------------------------------------------------===//

void SValBuilder::anchor() {}

DefinedOrUnknownSVal SValBuilder::makeZeroVal(QualType type) {
  if (Loc::isLocType(type))
    return makeNull();

  if (type->isIntegralOrEnumerationType())
    return makeIntVal(0, type);

  if (type->isArrayType() || type->isRecordType() || type->isVectorType() ||
      type->isAnyComplexType())
    return makeCompoundVal(type, BasicVals.getEmptySValList());

  // FIXME: Handle floats.
  return UnknownVal();
}

NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
                                const llvm::APSInt& rhs, QualType type) {
  // The Environment ensures we always get a persistent APSInt in
  // BasicValueFactory, so we don't need to get the APSInt from
  // BasicValueFactory again.
  assert(lhs);
  assert(!Loc::isLocType(type));
  return nonloc::SymbolVal(SymMgr.getSymIntExpr(lhs, op, rhs, type));
}

NonLoc SValBuilder::makeNonLoc(const llvm::APSInt& lhs,
                               BinaryOperator::Opcode op, const SymExpr *rhs,
                               QualType type) {
  assert(rhs);
  assert(!Loc::isLocType(type));
  return nonloc::SymbolVal(SymMgr.getIntSymExpr(lhs, op, rhs, type));
}

NonLoc SValBuilder::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
                               const SymExpr *rhs, QualType type) {
  assert(lhs && rhs);
  assert(!Loc::isLocType(type));
  return nonloc::SymbolVal(SymMgr.getSymSymExpr(lhs, op, rhs, type));
}

NonLoc SValBuilder::makeNonLoc(const SymExpr *operand,
                               QualType fromTy, QualType toTy) {
  assert(operand);
  assert(!Loc::isLocType(toTy));
  return nonloc::SymbolVal(SymMgr.getCastSymbol(operand, fromTy, toTy));
}

SVal SValBuilder::convertToArrayIndex(SVal val) {
  if (val.isUnknownOrUndef())
    return val;

  // Common case: we have an appropriately sized integer.
  if (Optional<nonloc::ConcreteInt> CI = val.getAs<nonloc::ConcreteInt>()) {
    const llvm::APSInt& I = CI->getValue();
    if (I.getBitWidth() == ArrayIndexWidth && I.isSigned())
      return val;
  }

  return evalCast(val, ArrayIndexTy, QualType{});
}

nonloc::ConcreteInt SValBuilder::makeBoolVal(const CXXBoolLiteralExpr *boolean){
  return makeTruthVal(boolean->getValue());
}

DefinedOrUnknownSVal
SValBuilder::getRegionValueSymbolVal(const TypedValueRegion *region) {
  QualType T = region->getValueType();

  if (T->isNullPtrType())
    return makeZeroVal(T);

  if (!SymbolManager::canSymbolicate(T))
    return UnknownVal();

  SymbolRef sym = SymMgr.getRegionValueSymbol(region);

  if (Loc::isLocType(T))
    return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));

  return nonloc::SymbolVal(sym);
}

DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag,
                                                   const Expr *Ex,
                                                   const LocationContext *LCtx,
                                                   unsigned Count) {
  QualType T = Ex->getType();

  if (T->isNullPtrType())
    return makeZeroVal(T);

  // Compute the type of the result. If the expression is not an R-value, the
  // result should be a location.
  QualType ExType = Ex->getType();
  if (Ex->isGLValue())
    T = LCtx->getAnalysisDeclContext()->getASTContext().getPointerType(ExType);

  return conjureSymbolVal(SymbolTag, Ex, LCtx, T, Count);
}

DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag,
                                                   const Expr *expr,
                                                   const LocationContext *LCtx,
                                                   QualType type,
                                                   unsigned count) {
  if (type->isNullPtrType())
    return makeZeroVal(type);

  if (!SymbolManager::canSymbolicate(type))
    return UnknownVal();

  SymbolRef sym = SymMgr.conjureSymbol(expr, LCtx, type, count, symbolTag);

  if (Loc::isLocType(type))
    return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));

  return nonloc::SymbolVal(sym);
}

DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt,
                                                   const LocationContext *LCtx,
                                                   QualType type,
                                                   unsigned visitCount) {
  if (type->isNullPtrType())
    return makeZeroVal(type);

  if (!SymbolManager::canSymbolicate(type))
    return UnknownVal();

  SymbolRef sym = SymMgr.conjureSymbol(stmt, LCtx, type, visitCount);

  if (Loc::isLocType(type))
    return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));

  return nonloc::SymbolVal(sym);
}

DefinedOrUnknownSVal
SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
                                      const LocationContext *LCtx,
                                      unsigned VisitCount) {
  QualType T = E->getType();
  assert(Loc::isLocType(T));
  assert(SymbolManager::canSymbolicate(T));
  if (T->isNullPtrType())
    return makeZeroVal(T);

  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount);
  return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
}

DefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag,
                                              const MemRegion *region,
                                              const Expr *expr, QualType type,
                                              const LocationContext *LCtx,
                                              unsigned count) {
  assert(SymbolManager::canSymbolicate(type) && "Invalid metadata symbol type");

  SymbolRef sym =
      SymMgr.getMetadataSymbol(region, expr, type, LCtx, count, symbolTag);

  if (Loc::isLocType(type))
    return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));

  return nonloc::SymbolVal(sym);
}

DefinedOrUnknownSVal
SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol,
                                             const TypedValueRegion *region) {
  QualType T = region->getValueType();

  if (T->isNullPtrType())
    return makeZeroVal(T);

  if (!SymbolManager::canSymbolicate(T))
    return UnknownVal();

  SymbolRef sym = SymMgr.getDerivedSymbol(parentSymbol, region);

  if (Loc::isLocType(T))
    return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));

  return nonloc::SymbolVal(sym);
}

DefinedSVal SValBuilder::getMemberPointer(const NamedDecl *ND) {
  assert(!ND || isa<CXXMethodDecl>(ND) || isa<FieldDecl>(ND) ||
         isa<IndirectFieldDecl>(ND));

  if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
    // Sema treats pointers to static member functions as have function pointer
    // type, so return a function pointer for the method.
    // We don't need to play a similar trick for static member fields
    // because these are represented as plain VarDecls and not FieldDecls
    // in the AST.
    if (MD->isStatic())
      return getFunctionPointer(MD);
  }

  return nonloc::PointerToMember(ND);
}

DefinedSVal SValBuilder::getFunctionPointer(const FunctionDecl *func) {
  return loc::MemRegionVal(MemMgr.getFunctionCodeRegion(func));
}

DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block,
                                         CanQualType locTy,
                                         const LocationContext *locContext,
                                         unsigned blockCount) {
  const BlockCodeRegion *BC =
    MemMgr.getBlockCodeRegion(block, locTy, locContext->getAnalysisDeclContext());
  const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, locContext,
                                                        blockCount);
  return loc::MemRegionVal(BD);
}

/// Return a memory region for the 'this' object reference.
loc::MemRegionVal SValBuilder::getCXXThis(const CXXMethodDecl *D,
                                          const StackFrameContext *SFC) {
  return loc::MemRegionVal(
      getRegionManager().getCXXThisRegion(D->getThisType(), SFC));
}

/// Return a memory region for the 'this' object reference.
loc::MemRegionVal SValBuilder::getCXXThis(const CXXRecordDecl *D,
                                          const StackFrameContext *SFC) {
  const Type *T = D->getTypeForDecl();
  QualType PT = getContext().getPointerType(QualType(T, 0));
  return loc::MemRegionVal(getRegionManager().getCXXThisRegion(PT, SFC));
}

Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
  E = E->IgnoreParens();

  switch (E->getStmtClass()) {
  // Handle expressions that we treat differently from the AST's constant
  // evaluator.
  case Stmt::AddrLabelExprClass:
    return makeLoc(cast<AddrLabelExpr>(E));

  case Stmt::CXXScalarValueInitExprClass:
  case Stmt::ImplicitValueInitExprClass:
    return makeZeroVal(E->getType());

  case Stmt::ObjCStringLiteralClass: {
    const auto *SL = cast<ObjCStringLiteral>(E);
    return makeLoc(getRegionManager().getObjCStringRegion(SL));
  }

  case Stmt::StringLiteralClass: {
    const auto *SL = cast<StringLiteral>(E);
    return makeLoc(getRegionManager().getStringRegion(SL));
  }

  case Stmt::PredefinedExprClass: {
    const auto *PE = cast<PredefinedExpr>(E);
    assert(PE->getFunctionName() &&
           "Since we analyze only instantiated functions, PredefinedExpr "
           "should have a function name.");
    return makeLoc(getRegionManager().getStringRegion(PE->getFunctionName()));
  }

  // Fast-path some expressions to avoid the overhead of going through the AST's
  // constant evaluator
  case Stmt::CharacterLiteralClass: {
    const auto *C = cast<CharacterLiteral>(E);
    return makeIntVal(C->getValue(), C->getType());
  }

  case Stmt::CXXBoolLiteralExprClass:
    return makeBoolVal(cast<CXXBoolLiteralExpr>(E));

  case Stmt::TypeTraitExprClass: {
    const auto *TE = cast<TypeTraitExpr>(E);
    return makeTruthVal(TE->getValue(), TE->getType());
  }

  case Stmt::IntegerLiteralClass:
    return makeIntVal(cast<IntegerLiteral>(E));

  case Stmt::ObjCBoolLiteralExprClass:
    return makeBoolVal(cast<ObjCBoolLiteralExpr>(E));

  case Stmt::CXXNullPtrLiteralExprClass:
    return makeNull();

  case Stmt::CStyleCastExprClass:
  case Stmt::CXXFunctionalCastExprClass:
  case Stmt::CXXConstCastExprClass:
  case Stmt::CXXReinterpretCastExprClass:
  case Stmt::CXXStaticCastExprClass:
  case Stmt::ImplicitCastExprClass: {
    const auto *CE = cast<CastExpr>(E);
    switch (CE->getCastKind()) {
    default:
      break;
    case CK_ArrayToPointerDecay:
    case CK_IntegralToPointer:
    case CK_NoOp:
    case CK_BitCast: {
      const Expr *SE = CE->getSubExpr();
      Optional<SVal> Val = getConstantVal(SE);
      if (!Val)
        return None;
      return evalCast(*Val, CE->getType(), SE->getType());
    }
    }
    // FALLTHROUGH
    LLVM_FALLTHROUGH;
  }

  // If we don't have a special case, fall back to the AST's constant evaluator.
  default: {
    // Don't try to come up with a value for materialized temporaries.
    if (E->isGLValue())
      return None;

    ASTContext &Ctx = getContext();
    Expr::EvalResult Result;
    if (E->EvaluateAsInt(Result, Ctx))
      return makeIntVal(Result.Val.getInt());

    if (Loc::isLocType(E->getType()))
      if (E->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull))
        return makeNull();

    return None;
  }
  }
}

SVal SValBuilder::makeSymExprValNN(BinaryOperator::Opcode Op,
                                   NonLoc LHS, NonLoc RHS,
                                   QualType ResultTy) {
  SymbolRef symLHS = LHS.getAsSymbol();
  SymbolRef symRHS = RHS.getAsSymbol();

  // TODO: When the Max Complexity is reached, we should conjure a symbol
  // instead of generating an Unknown value and propagate the taint info to it.
  const unsigned MaxComp = StateMgr.getOwningEngine()
                               .getAnalysisManager()
                               .options.MaxSymbolComplexity;

  if (symLHS && symRHS &&
      (symLHS->computeComplexity() + symRHS->computeComplexity()) <  MaxComp)
    return makeNonLoc(symLHS, Op, symRHS, ResultTy);

  if (symLHS && symLHS->computeComplexity() < MaxComp)
    if (Optional<nonloc::ConcreteInt> rInt = RHS.getAs<nonloc::ConcreteInt>())
      return makeNonLoc(symLHS, Op, rInt->getValue(), ResultTy);

  if (symRHS && symRHS->computeComplexity() < MaxComp)
    if (Optional<nonloc::ConcreteInt> lInt = LHS.getAs<nonloc::ConcreteInt>())
      return makeNonLoc(lInt->getValue(), Op, symRHS, ResultTy);

  return UnknownVal();
}

SVal SValBuilder::evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
                            SVal lhs, SVal rhs, QualType type) {
  if (lhs.isUndef() || rhs.isUndef())
    return UndefinedVal();

  if (lhs.isUnknown() || rhs.isUnknown())
    return UnknownVal();

  if (lhs.getAs<nonloc::LazyCompoundVal>() ||
      rhs.getAs<nonloc::LazyCompoundVal>()) {
    return UnknownVal();
  }

  if (op == BinaryOperatorKind::BO_Cmp) {
    // We can't reason about C++20 spaceship operator yet.
    //
    // FIXME: Support C++20 spaceship operator.
    //        The main problem here is that the result is not integer.
    return UnknownVal();
  }

  if (Optional<Loc> LV = lhs.getAs<Loc>()) {
    if (Optional<Loc> RV = rhs.getAs<Loc>())
      return evalBinOpLL(state, op, *LV, *RV, type);

    return evalBinOpLN(state, op, *LV, rhs.castAs<NonLoc>(), type);
  }

  if (Optional<Loc> RV = rhs.getAs<Loc>()) {
    // Support pointer arithmetic where the addend is on the left
    // and the pointer on the right.
    assert(op == BO_Add);

    // Commute the operands.
    return evalBinOpLN(state, op, *RV, lhs.castAs<NonLoc>(), type);
  }

  return evalBinOpNN(state, op, lhs.castAs<NonLoc>(), rhs.castAs<NonLoc>(),
                     type);
}

ConditionTruthVal SValBuilder::areEqual(ProgramStateRef state, SVal lhs,
                                        SVal rhs) {
  return state->isNonNull(evalEQ(state, lhs, rhs));
}

SVal SValBuilder::evalEQ(ProgramStateRef state, SVal lhs, SVal rhs) {
  return evalBinOp(state, BO_EQ, lhs, rhs, getConditionType());
}

DefinedOrUnknownSVal SValBuilder::evalEQ(ProgramStateRef state,
                                         DefinedOrUnknownSVal lhs,
                                         DefinedOrUnknownSVal rhs) {
  return evalEQ(state, static_cast<SVal>(lhs), static_cast<SVal>(rhs))
      .castAs<DefinedOrUnknownSVal>();
}

/// Recursively check if the pointer types are equal modulo const, volatile,
/// and restrict qualifiers. Also, assume that all types are similar to 'void'.
/// Assumes the input types are canonical.
static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy,
                                                         QualType FromTy) {
  while (Context.UnwrapSimilarTypes(ToTy, FromTy)) {
    Qualifiers Quals1, Quals2;
    ToTy = Context.getUnqualifiedArrayType(ToTy, Quals1);
    FromTy = Context.getUnqualifiedArrayType(FromTy, Quals2);

    // Make sure that non-cvr-qualifiers the other qualifiers (e.g., address
    // spaces) are identical.
    Quals1.removeCVRQualifiers();
    Quals2.removeCVRQualifiers();
    if (Quals1 != Quals2)
      return false;
  }

  // If we are casting to void, the 'From' value can be used to represent the
  // 'To' value.
  //
  // FIXME: Doing this after unwrapping the types doesn't make any sense. A
  // cast from 'int**' to 'void**' is not special in the way that a cast from
  // 'int*' to 'void*' is.
  if (ToTy->isVoidType())
    return true;

  if (ToTy != FromTy)
    return false;

  return true;
}

// Handles casts of type CK_IntegralCast.
// At the moment, this function will redirect to evalCast, except when the range
// of the original value is known to be greater than the max of the target type.
SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val,
                                   QualType castTy, QualType originalTy) {
  // No truncations if target type is big enough.
  if (getContext().getTypeSize(castTy) >= getContext().getTypeSize(originalTy))
    return evalCast(val, castTy, originalTy);

  SymbolRef se = val.getAsSymbol();
  if (!se) // Let evalCast handle non symbolic expressions.
    return evalCast(val, castTy, originalTy);

  // Find the maximum value of the target type.
  APSIntType ToType(getContext().getTypeSize(castTy),
                    castTy->isUnsignedIntegerType());
  llvm::APSInt ToTypeMax = ToType.getMaxValue();
  NonLoc ToTypeMaxVal =
      makeIntVal(ToTypeMax.isUnsigned() ? ToTypeMax.getZExtValue()
                                        : ToTypeMax.getSExtValue(),
                 castTy)
          .castAs<NonLoc>();
  // Check the range of the symbol being casted against the maximum value of the
  // target type.
  NonLoc FromVal = val.castAs<NonLoc>();
  QualType CmpTy = getConditionType();
  NonLoc CompVal =
      evalBinOpNN(state, BO_LE, FromVal, ToTypeMaxVal, CmpTy).castAs<NonLoc>();
  ProgramStateRef IsNotTruncated, IsTruncated;
  std::tie(IsNotTruncated, IsTruncated) = state->assume(CompVal);
  if (!IsNotTruncated && IsTruncated) {
    // Symbol is truncated so we evaluate it as a cast.
    NonLoc CastVal = makeNonLoc(se, originalTy, castTy);
    return CastVal;
  }
  return evalCast(val, castTy, originalTy);
}

//===----------------------------------------------------------------------===//
// Cast methods.
// `evalCast` is the main method
// `evalCastKind` and `evalCastSubKind` are helpers
//===----------------------------------------------------------------------===//

/// Cast a given SVal to another SVal using given QualType's.
/// \param V -- SVal that should be casted.
/// \param CastTy -- QualType that V should be casted according to.
/// \param OriginalTy -- QualType which is associated to V. It provides
/// additional information about what type the cast performs from.
/// \returns the most appropriate casted SVal.
/// Note: Many cases don't use an exact OriginalTy. It can be extracted
/// from SVal or the cast can performs unconditionaly. Always pass OriginalTy!
/// It can be crucial in certain cases and generates different results.
/// FIXME: If `OriginalTy.isNull()` is true, then cast performs based on CastTy
/// only. This behavior is uncertain and should be improved.
SVal SValBuilder::evalCast(SVal V, QualType CastTy, QualType OriginalTy) {
  if (CastTy.isNull())
    return V;

  CastTy = Context.getCanonicalType(CastTy);

  const bool IsUnknownOriginalType = OriginalTy.isNull();
  if (!IsUnknownOriginalType) {
    OriginalTy = Context.getCanonicalType(OriginalTy);

    if (CastTy == OriginalTy)
      return V;

    // FIXME: Move this check to the most appropriate
    // evalCastKind/evalCastSubKind function. For const casts, casts to void,
    // just propagate the value.
    if (!CastTy->isVariableArrayType() && !OriginalTy->isVariableArrayType())
      if (shouldBeModeledWithNoOp(Context, Context.getPointerType(CastTy),
                                  Context.getPointerType(OriginalTy)))
        return V;
  }

  // Cast SVal according to kinds.
  switch (V.getBaseKind()) {
  case SVal::UndefinedValKind:
    return evalCastKind(V.castAs<UndefinedVal>(), CastTy, OriginalTy);
  case SVal::UnknownValKind:
    return evalCastKind(V.castAs<UnknownVal>(), CastTy, OriginalTy);
  case SVal::LocKind:
    return evalCastKind(V.castAs<Loc>(), CastTy, OriginalTy);
  case SVal::NonLocKind:
    return evalCastKind(V.castAs<NonLoc>(), CastTy, OriginalTy);
  }

  llvm_unreachable("Unknown SVal kind");
}

SVal SValBuilder::evalCastKind(UndefinedVal V, QualType CastTy,
                               QualType OriginalTy) {
  return V;
}

SVal SValBuilder::evalCastKind(UnknownVal V, QualType CastTy,
                               QualType OriginalTy) {
  return V;
}

SVal SValBuilder::evalCastKind(Loc V, QualType CastTy, QualType OriginalTy) {
  switch (V.getSubKind()) {
  case loc::ConcreteIntKind:
    return evalCastSubKind(V.castAs<loc::ConcreteInt>(), CastTy, OriginalTy);
  case loc::GotoLabelKind:
    return evalCastSubKind(V.castAs<loc::GotoLabel>(), CastTy, OriginalTy);
  case loc::MemRegionValKind:
    return evalCastSubKind(V.castAs<loc::MemRegionVal>(), CastTy, OriginalTy);
  }

  llvm_unreachable("Unknown SVal kind");
}

SVal SValBuilder::evalCastKind(NonLoc V, QualType CastTy, QualType OriginalTy) {
  switch (V.getSubKind()) {
  case nonloc::CompoundValKind:
    return evalCastSubKind(V.castAs<nonloc::CompoundVal>(), CastTy, OriginalTy);
  case nonloc::ConcreteIntKind:
    return evalCastSubKind(V.castAs<nonloc::ConcreteInt>(), CastTy, OriginalTy);
  case nonloc::LazyCompoundValKind:
    return evalCastSubKind(V.castAs<nonloc::LazyCompoundVal>(), CastTy,
                           OriginalTy);
  case nonloc::LocAsIntegerKind:
    return evalCastSubKind(V.castAs<nonloc::LocAsInteger>(), CastTy,
                           OriginalTy);
  case nonloc::SymbolValKind:
    return evalCastSubKind(V.castAs<nonloc::SymbolVal>(), CastTy, OriginalTy);
  case nonloc::PointerToMemberKind:
    return evalCastSubKind(V.castAs<nonloc::PointerToMember>(), CastTy,
                           OriginalTy);
  }

  llvm_unreachable("Unknown SVal kind");
}

SVal SValBuilder::evalCastSubKind(loc::ConcreteInt V, QualType CastTy,
                                  QualType OriginalTy) {
  // Pointer to bool.
  if (CastTy->isBooleanType())
    return makeTruthVal(V.getValue().getBoolValue(), CastTy);

  // Pointer to integer.
  if (CastTy->isIntegralOrEnumerationType()) {
    llvm::APSInt Value = V.getValue();
    BasicVals.getAPSIntType(CastTy).apply(Value);
    return makeIntVal(Value);
  }

  // Pointer to any pointer.
  if (Loc::isLocType(CastTy))
    return V;

  // Pointer to whatever else.
  return UnknownVal();
}

SVal SValBuilder::evalCastSubKind(loc::GotoLabel V, QualType CastTy,
                                  QualType OriginalTy) {
  // Pointer to bool.
  if (CastTy->isBooleanType())
    // Labels are always true.
    return makeTruthVal(true, CastTy);

  // Pointer to integer.
  if (CastTy->isIntegralOrEnumerationType()) {
    const unsigned BitWidth = Context.getIntWidth(CastTy);
    return makeLocAsInteger(V, BitWidth);
  }

  const bool IsUnknownOriginalType = OriginalTy.isNull();
  if (!IsUnknownOriginalType) {
    // Array to pointer.
    if (isa<ArrayType>(OriginalTy))
      if (CastTy->isPointerType() || CastTy->isReferenceType())
        return UnknownVal();
  }

  // Pointer to any pointer.
  if (Loc::isLocType(CastTy))
    return V;

  // Pointer to whatever else.
  return UnknownVal();
}

static bool hasSameUnqualifiedPointeeType(QualType ty1, QualType ty2) {
  return ty1->getPointeeType().getCanonicalType().getTypePtr() ==
         ty2->getPointeeType().getCanonicalType().getTypePtr();
}

SVal SValBuilder::evalCastSubKind(loc::MemRegionVal V, QualType CastTy,
                                  QualType OriginalTy) {
  // Pointer to bool.
  if (CastTy->isBooleanType()) {
    const MemRegion *R = V.getRegion();
    if (const FunctionCodeRegion *FTR = dyn_cast<FunctionCodeRegion>(R))
      if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(FTR->getDecl()))
        if (FD->isWeak())
          // FIXME: Currently we are using an extent symbol here,
          // because there are no generic region address metadata
          // symbols to use, only content metadata.
          return nonloc::SymbolVal(SymMgr.getExtentSymbol(FTR));

    if (const SymbolicRegion *SymR = R->getSymbolicBase())
      return makeNonLoc(SymR->getSymbol(), BO_NE,
                        BasicVals.getZeroWithPtrWidth(), CastTy);
    // Non-symbolic memory regions are always true.
    return makeTruthVal(true, CastTy);
  }

  const bool IsUnknownOriginalType = OriginalTy.isNull();
  // Try to cast to array
  const auto *ArrayTy =
      IsUnknownOriginalType
          ? nullptr
          : dyn_cast<ArrayType>(OriginalTy.getCanonicalType());

  // Pointer to integer.
  if (CastTy->isIntegralOrEnumerationType()) {
    SVal Val = V;
    // Array to integer.
    if (ArrayTy) {
      // We will always decay to a pointer.
      QualType ElemTy = ArrayTy->getElementType();
      Val = StateMgr.ArrayToPointer(V, ElemTy);
      // FIXME: Keep these here for now in case we decide soon that we
      // need the original decayed type.
      //    QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
      //    QualType pointerTy = C.getPointerType(elemTy);
    }
    const unsigned BitWidth = Context.getIntWidth(CastTy);
    return makeLocAsInteger(Val.castAs<Loc>(), BitWidth);
  }

  // Pointer to pointer.
  if (Loc::isLocType(CastTy)) {

    if (IsUnknownOriginalType) {
      // When retrieving symbolic pointer and expecting a non-void pointer,
      // wrap them into element regions of the expected type if necessary.
      // It is necessary to make sure that the retrieved value makes sense,
      // because there's no other cast in the AST that would tell us to cast
      // it to the correct pointer type. We might need to do that for non-void
      // pointers as well.
      // FIXME: We really need a single good function to perform casts for us
      // correctly every time we need it.
      const MemRegion *R = V.getRegion();
      if (CastTy->isPointerType() && !CastTy->isVoidPointerType()) {
        if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
          QualType SRTy = SR->getSymbol()->getType();
          if (!hasSameUnqualifiedPointeeType(SRTy, CastTy)) {
            R = StateMgr.getStoreManager().castRegion(SR, CastTy);
            return loc::MemRegionVal(R);
          }
        }
      }
      // Next fixes pointer dereference using type different from its initial
      // one. See PR37503 and PR49007 for details.
      if (const auto *ER = dyn_cast<ElementRegion>(R)) {
        if ((R = StateMgr.getStoreManager().castRegion(ER, CastTy)))
          return loc::MemRegionVal(R);
      }

      return V;
    }

    if (OriginalTy->isIntegralOrEnumerationType() ||
        OriginalTy->isBlockPointerType() || OriginalTy->isFunctionPointerType())
      return V;

    // Array to pointer.
    if (ArrayTy) {
      // Are we casting from an array to a pointer?  If so just pass on
      // the decayed value.
      if (CastTy->isPointerType() || CastTy->isReferenceType()) {
        // We will always decay to a pointer.
        QualType ElemTy = ArrayTy->getElementType();
        return StateMgr.ArrayToPointer(V, ElemTy);
      }
      // Are we casting from an array to an integer?  If so, cast the decayed
      // pointer value to an integer.
      assert(CastTy->isIntegralOrEnumerationType());
    }

    // Other pointer to pointer.
    assert(Loc::isLocType(OriginalTy) || OriginalTy->isFunctionType() ||
           CastTy->isReferenceType());

    // We get a symbolic function pointer for a dereference of a function
    // pointer, but it is of function type. Example:

    //  struct FPRec {
    //    void (*my_func)(int * x);
    //  };
    //
    //  int bar(int x);
    //
    //  int f1_a(struct FPRec* foo) {
    //    int x;
    //    (*foo->my_func)(&x);
    //    return bar(x)+1; // no-warning
    //  }

    // Get the result of casting a region to a different type.
    const MemRegion *R = V.getRegion();
    if ((R = StateMgr.getStoreManager().castRegion(R, CastTy)))
      return loc::MemRegionVal(R);
  }

  // Pointer to whatever else.
  // FIXME: There can be gross cases where one casts the result of a
  // function (that returns a pointer) to some other value that happens to
  // fit within that pointer value.  We currently have no good way to model
  // such operations.  When this happens, the underlying operation is that
  // the caller is reasoning about bits.  Conceptually we are layering a
  // "view" of a location on top of those bits.  Perhaps we need to be more
  // lazy about mutual possible views, even on an SVal?  This may be
  // necessary for bit-level reasoning as well.
  return UnknownVal();
}

SVal SValBuilder::evalCastSubKind(nonloc::CompoundVal V, QualType CastTy,
                                  QualType OriginalTy) {
  // Compound to whatever.
  return UnknownVal();
}

SVal SValBuilder::evalCastSubKind(nonloc::ConcreteInt V, QualType CastTy,
                                  QualType OriginalTy) {
  auto CastedValue = [V, CastTy, this]() {
    llvm::APSInt Value = V.getValue();
    BasicVals.getAPSIntType(CastTy).apply(Value);
    return Value;
  };

  // Integer to bool.
  if (CastTy->isBooleanType())
    return makeTruthVal(V.getValue().getBoolValue(), CastTy);

  // Integer to pointer.
  if (CastTy->isIntegralOrEnumerationType())
    return makeIntVal(CastedValue());

  // Integer to pointer.
  if (Loc::isLocType(CastTy))
    return makeIntLocVal(CastedValue());

  // Pointer to whatever else.
  return UnknownVal();
}

SVal SValBuilder::evalCastSubKind(nonloc::LazyCompoundVal V, QualType CastTy,
                                  QualType OriginalTy) {
  // Compound to whatever.
  return UnknownVal();
}

SVal SValBuilder::evalCastSubKind(nonloc::LocAsInteger V, QualType CastTy,
                                  QualType OriginalTy) {
  Loc L = V.getLoc();

  // Pointer as integer to bool.
  if (CastTy->isBooleanType())
    // Pass to Loc function.
    return evalCastKind(L, CastTy, OriginalTy);

  const bool IsUnknownOriginalType = OriginalTy.isNull();
  // Pointer as integer to pointer.
  if (!IsUnknownOriginalType && Loc::isLocType(CastTy) &&
      OriginalTy->isIntegralOrEnumerationType()) {
    if (const MemRegion *R = L.getAsRegion())
      if ((R = StateMgr.getStoreManager().castRegion(R, CastTy)))
        return loc::MemRegionVal(R);
    return L;
  }

  // Pointer as integer with region to integer/pointer.
  const MemRegion *R = L.getAsRegion();
  if (!IsUnknownOriginalType && R) {
    if (CastTy->isIntegralOrEnumerationType())
      return evalCastSubKind(loc::MemRegionVal(R), CastTy, OriginalTy);

    if (Loc::isLocType(CastTy)) {
      assert(Loc::isLocType(OriginalTy) || OriginalTy->isFunctionType() ||
             CastTy->isReferenceType());
      // Delegate to store manager to get the result of casting a region to a
      // different type. If the MemRegion* returned is NULL, this expression
      // Evaluates to UnknownVal.
      if ((R = StateMgr.getStoreManager().castRegion(R, CastTy)))
        return loc::MemRegionVal(R);
    }
  } else {
    if (Loc::isLocType(CastTy)) {
      if (IsUnknownOriginalType)
        return evalCastSubKind(loc::MemRegionVal(R), CastTy, OriginalTy);
      return L;
    }

    SymbolRef SE = nullptr;
    if (R) {
      if (const SymbolicRegion *SR =
              dyn_cast<SymbolicRegion>(R->StripCasts())) {
        SE = SR->getSymbol();
      }
    }

    if (!CastTy->isFloatingType() || !SE || SE->getType()->isFloatingType()) {
      // FIXME: Correctly support promotions/truncations.
      const unsigned CastSize = Context.getIntWidth(CastTy);
      if (CastSize == V.getNumBits())
        return V;

      return makeLocAsInteger(L, CastSize);
    }
  }

  // Pointer as integer to whatever else.
  return UnknownVal();
}

SVal SValBuilder::evalCastSubKind(nonloc::SymbolVal V, QualType CastTy,
                                  QualType OriginalTy) {
  SymbolRef SE = V.getSymbol();

  const bool IsUnknownOriginalType = OriginalTy.isNull();
  // Symbol to bool.
  if (!IsUnknownOriginalType && CastTy->isBooleanType()) {
    // Non-float to bool.
    if (Loc::isLocType(OriginalTy) ||
        OriginalTy->isIntegralOrEnumerationType() ||
        OriginalTy->isMemberPointerType()) {
      BasicValueFactory &BVF = getBasicValueFactory();
      return makeNonLoc(SE, BO_NE, BVF.getValue(0, SE->getType()), CastTy);
    }
  } else {
    // Symbol to integer, float.
    QualType T = Context.getCanonicalType(SE->getType());
    // If types are the same or both are integers, ignore the cast.
    // FIXME: Remove this hack when we support symbolic truncation/extension.
    // HACK: If both castTy and T are integers, ignore the cast.  This is
    // not a permanent solution.  Eventually we want to precisely handle
    // extension/truncation of symbolic integers.  This prevents us from losing
    // precision when we assign 'x = y' and 'y' is symbolic and x and y are
    // different integer types.
    if (haveSameType(T, CastTy))
      return V;
    if (!Loc::isLocType(CastTy))
      if (!IsUnknownOriginalType || !CastTy->isFloatingType() ||
          T->isFloatingType())
        return makeNonLoc(SE, T, CastTy);
  }

  // Symbol to pointer and whatever else.
  return UnknownVal();
}

SVal SValBuilder::evalCastSubKind(nonloc::PointerToMember V, QualType CastTy,
                                  QualType OriginalTy) {
  // Member pointer to whatever.
  return V;
}
