//===- 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/Analysis/AnalysisDeclContext.h"
#include "clang/Basic/LLVM.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.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/SValVisitor.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() {}

SValBuilder::SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
                         ProgramStateManager &stateMgr)
    : Context(context), BasicVals(context, alloc),
      SymMgr(context, BasicVals, alloc), MemMgr(context, alloc),
      StateMgr(stateMgr),
      AnOpts(
          stateMgr.getOwningEngine().getAnalysisManager().getAnalyzerOptions()),
      ArrayIndexTy(context.LongLongTy),
      ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}

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

  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::SymbolVal 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::SymbolVal 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::SymbolVal 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, UnaryOperator::Opcode op,
                               QualType type) {
  assert(operand);
  assert(!Loc::isLocType(type));
  return nonloc::SymbolVal(SymMgr.getUnarySymExpr(operand, op, type));
}

nonloc::SymbolVal SValBuilder::makeNonLoc(const SymExpr *operand,
                                          QualType fromTy, QualType toTy) {
  assert(operand);
  assert(!Loc::isLocType(toTy));
  if (fromTy == toTy)
    return operand;
  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();
  return getConjuredHeapSymbolVal(E, LCtx, T, VisitCount);
}

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

  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, type, 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, FieldDecl, 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);
}

Optional<loc::MemRegionVal>
SValBuilder::getCastedMemRegionVal(const MemRegion *R, QualType Ty) {
  if (auto OptR = StateMgr.getStoreManager().castRegion(R, Ty))
    return loc::MemRegionVal(*OptR);
  return None;
}

/// 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 makeNullWithType(E->getType());

  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 makeNullWithType(E->getType());

    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 = AnOpts.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::evalMinus(NonLoc X) {
  switch (X.getSubKind()) {
  case nonloc::ConcreteIntKind:
    return makeIntVal(-X.castAs<nonloc::ConcreteInt>().getValue());
  case nonloc::SymbolValKind:
    return makeNonLoc(X.castAs<nonloc::SymbolVal>().getSymbol(), UO_Minus,
                      X.getType(Context));
  default:
    return UnknownVal();
  }
}

SVal SValBuilder::evalComplement(NonLoc X) {
  switch (X.getSubKind()) {
  case nonloc::ConcreteIntKind:
    return makeIntVal(~X.castAs<nonloc::ConcreteInt>().getValue());
  case nonloc::SymbolValKind:
    return makeNonLoc(X.castAs<nonloc::SymbolVal>().getSymbol(), UO_Not,
                      X.getType(Context));
  default:
    return UnknownVal();
  }
}

SVal SValBuilder::evalUnaryOp(ProgramStateRef state, UnaryOperator::Opcode opc,
                 SVal operand, QualType type) {
  auto OpN = operand.getAs<NonLoc>();
  if (!OpN)
    return UnknownVal();

  if (opc == UO_Minus)
    return evalMinus(*OpN);
  if (opc == UO_Not)
    return evalComplement(*OpN);
  llvm_unreachable("Unexpected unary operator");
}

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 (isa<nonloc::LazyCompoundVal>(lhs) || isa<nonloc::LazyCompoundVal>(rhs)) {
    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 (const Optional<Loc> RV = rhs.getAs<Loc>()) {
    const auto IsCommutative = [](BinaryOperatorKind Op) {
      return Op == BO_Mul || Op == BO_Add || Op == BO_And || Op == BO_Xor ||
             Op == BO_Or;
    };

    if (IsCommutative(op)) {
      // Swap operands.
      return evalBinOpLN(state, op, *RV, lhs.castAs<NonLoc>(), type);
    }

    // If the right operand is a concrete int location then we have nothing
    // better but to treat it as a simple nonloc.
    if (auto RV = rhs.getAs<loc::ConcreteInt>()) {
      const nonloc::ConcreteInt RhsAsLoc = makeIntVal(RV->getValue());
      return evalBinOpNN(state, op, lhs.castAs<NonLoc>(), RhsAsLoc, 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.
    return makeNonLoc(se, originalTy, castTy);
  }
  return evalCast(val, castTy, originalTy);
}

//===----------------------------------------------------------------------===//
// Cast method.
// `evalCast` and its helper `EvalCastVisitor`
//===----------------------------------------------------------------------===//

namespace {
class EvalCastVisitor : public SValVisitor<EvalCastVisitor, SVal> {
private:
  SValBuilder &VB;
  ASTContext &Context;
  QualType CastTy, OriginalTy;

public:
  EvalCastVisitor(SValBuilder &VB, QualType CastTy, QualType OriginalTy)
      : VB(VB), Context(VB.getContext()), CastTy(CastTy),
        OriginalTy(OriginalTy) {}

  SVal Visit(SVal V) {
    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;
    }
    return SValVisitor::Visit(V);
  }
  SVal VisitUndefinedVal(UndefinedVal V) { return V; }
  SVal VisitUnknownVal(UnknownVal V) { return V; }
  SVal VisitLocConcreteInt(loc::ConcreteInt V) {
    // Pointer to bool.
    if (CastTy->isBooleanType())
      return VB.makeTruthVal(V.getValue().getBoolValue(), CastTy);

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

    // Pointer to any pointer.
    if (Loc::isLocType(CastTy)) {
      llvm::APSInt Value = V.getValue();
      VB.getBasicValueFactory().getAPSIntType(CastTy).apply(Value);
      return loc::ConcreteInt(VB.getBasicValueFactory().getValue(Value));
    }

    // Pointer to whatever else.
    return UnknownVal();
  }
  SVal VisitLocGotoLabel(loc::GotoLabel V) {
    // Pointer to bool.
    if (CastTy->isBooleanType())
      // Labels are always true.
      return VB.makeTruthVal(true, CastTy);

    // Pointer to integer.
    if (CastTy->isIntegralOrEnumerationType()) {
      const unsigned BitWidth = Context.getIntWidth(CastTy);
      return VB.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();
  }
  SVal VisitLocMemRegionVal(loc::MemRegionVal V) {
    // 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(
                VB.getSymbolManager().getExtentSymbol(FTR));

      if (const SymbolicRegion *SymR = R->getSymbolicBase()) {
        SymbolRef Sym = SymR->getSymbol();
        QualType Ty = Sym->getType();
        // This change is needed for architectures with varying
        // pointer widths. See the amdgcn opencl reproducer with
        // this change as an example: solver-sym-simplification-ptr-bool.cl
        if (!Ty->isReferenceType())
          return VB.makeNonLoc(
              Sym, BO_NE, VB.getBasicValueFactory().getZeroWithTypeSize(Ty),
              CastTy);
      }
      // Non-symbolic memory regions are always true.
      return VB.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 = VB.getStateManager().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 VB.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();

            auto HasSameUnqualifiedPointeeType = [](QualType ty1,
                                                    QualType ty2) {
              return ty1->getPointeeType().getCanonicalType().getTypePtr() ==
                     ty2->getPointeeType().getCanonicalType().getTypePtr();
            };
            if (!HasSameUnqualifiedPointeeType(SRTy, CastTy)) {
              if (auto OptMemRegV = VB.getCastedMemRegionVal(SR, CastTy))
                return *OptMemRegV;
            }
          }
        }
        // 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 (auto OptMemRegV = VB.getCastedMemRegionVal(ER, CastTy))
            return *OptMemRegV;
        }

        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 VB.getStateManager().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 (auto OptMemRegV = VB.getCastedMemRegionVal(R, CastTy))
        return *OptMemRegV;
    }

    // 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 VisitNonLocCompoundVal(nonloc::CompoundVal V) {
    // Compound to whatever.
    return UnknownVal();
  }
  SVal VisitNonLocConcreteInt(nonloc::ConcreteInt V) {
    auto CastedValue = [V, this]() {
      llvm::APSInt Value = V.getValue();
      VB.getBasicValueFactory().getAPSIntType(CastTy).apply(Value);
      return Value;
    };

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

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

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

    // Pointer to whatever else.
    return UnknownVal();
  }
  SVal VisitNonLocLazyCompoundVal(nonloc::LazyCompoundVal V) {
    // LazyCompound to whatever.
    return UnknownVal();
  }
  SVal VisitNonLocLocAsInteger(nonloc::LocAsInteger V) {
    Loc L = V.getLoc();

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

    const bool IsUnknownOriginalType = OriginalTy.isNull();
    // Pointer as integer to pointer.
    if (!IsUnknownOriginalType && Loc::isLocType(CastTy) &&
        OriginalTy->isIntegralOrEnumerationType()) {
      if (const MemRegion *R = L.getAsRegion())
        if (auto OptMemRegV = VB.getCastedMemRegionVal(R, CastTy))
          return *OptMemRegV;
      return L;
    }

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

      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 (auto OptMemRegV = VB.getCastedMemRegionVal(R, CastTy))
          return *OptMemRegV;
      }
    } else {
      if (Loc::isLocType(CastTy)) {
        if (IsUnknownOriginalType)
          return VisitLocMemRegionVal(loc::MemRegionVal(R));
        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 VB.makeLocAsInteger(L, CastSize);
      }
    }

    // Pointer as integer to whatever else.
    return UnknownVal();
  }
  SVal VisitNonLocSymbolVal(nonloc::SymbolVal V) {
    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 = VB.getBasicValueFactory();
        return VB.makeNonLoc(SE, BO_NE, BVF.getValue(0, SE->getType()), CastTy);
      }
    } else {
      // Symbol to integer, float.
      QualType T = Context.getCanonicalType(SE->getType());

      // Produce SymbolCast if CastTy and T are different integers.
      // NOTE: In the end the type of SymbolCast shall be equal to CastTy.
      if (T->isIntegralOrUnscopedEnumerationType() &&
          CastTy->isIntegralOrUnscopedEnumerationType()) {
        AnalyzerOptions &Opts = VB.getStateManager()
                                    .getOwningEngine()
                                    .getAnalysisManager()
                                    .getAnalyzerOptions();
        // If appropriate option is disabled, ignore the cast.
        // NOTE: ShouldSupportSymbolicIntegerCasts is `false` by default.
        if (!Opts.ShouldSupportSymbolicIntegerCasts)
          return V;
        return simplifySymbolCast(V, CastTy);
      }
      if (!Loc::isLocType(CastTy))
        if (!IsUnknownOriginalType || !CastTy->isFloatingType() ||
            T->isFloatingType())
          return VB.makeNonLoc(SE, T, CastTy);
    }

    // Symbol to pointer and whatever else.
    return UnknownVal();
  }
  SVal VisitNonLocPointerToMember(nonloc::PointerToMember V) {
    // Member pointer to whatever.
    return V;
  }

  /// Reduce cast expression by removing redundant intermediate casts.
  /// E.g.
  /// - (char)(short)(int x) -> (char)(int x)
  /// - (int)(int x) -> int x
  ///
  /// \param V -- SymbolVal, which pressumably contains SymbolCast or any symbol
  /// that is applicable for cast operation.
  /// \param CastTy -- QualType, which `V` shall be cast to.
  /// \return SVal with simplified cast expression.
  /// \note: Currently only support integral casts.
  nonloc::SymbolVal simplifySymbolCast(nonloc::SymbolVal V, QualType CastTy) {
    // We use seven conditions to recognize a simplification case.
    // For the clarity let `CastTy` be `C`, SE->getType() - `T`, root type -
    // `R`, prefix `u` for unsigned, `s` for signed, no prefix - any sign: E.g.
    // (char)(short)(uint x)
    //      ( sC )( sT  )( uR  x)
    //
    // C === R (the same type)
    //  (char)(char x) -> (char x)
    //  (long)(long x) -> (long x)
    // Note: Comparisons operators below are for bit width.
    // C == T
    //  (short)(short)(int x) -> (short)(int x)
    //  (int)(long)(char x) -> (int)(char x) (sizeof(long) == sizeof(int))
    //  (long)(ullong)(char x) -> (long)(char x) (sizeof(long) ==
    //  sizeof(ullong))
    // C < T
    //  (short)(int)(char x) -> (short)(char x)
    //  (char)(int)(short x) -> (char)(short x)
    //  (short)(int)(short x) -> (short x)
    // C > T > uR
    //  (int)(short)(uchar x) -> (int)(uchar x)
    //  (uint)(short)(uchar x) -> (uint)(uchar x)
    //  (int)(ushort)(uchar x) -> (int)(uchar x)
    // C > sT > sR
    //  (int)(short)(char x) -> (int)(char x)
    //  (uint)(short)(char x) -> (uint)(char x)
    // C > sT == sR
    //  (int)(char)(char x) -> (int)(char x)
    //  (uint)(short)(short x) -> (uint)(short x)
    // C > uT == uR
    //  (int)(uchar)(uchar x) -> (int)(uchar x)
    //  (uint)(ushort)(ushort x) -> (uint)(ushort x)
    //  (llong)(ulong)(uint x) -> (llong)(uint x) (sizeof(ulong) ==
    //  sizeof(uint))

    SymbolRef SE = V.getSymbol();
    QualType T = Context.getCanonicalType(SE->getType());

    if (T == CastTy)
      return V;

    if (!isa<SymbolCast>(SE))
      return VB.makeNonLoc(SE, T, CastTy);

    SymbolRef RootSym = cast<SymbolCast>(SE)->getOperand();
    QualType RT = RootSym->getType().getCanonicalType();

    // FIXME support simplification from non-integers.
    if (!RT->isIntegralOrEnumerationType())
      return VB.makeNonLoc(SE, T, CastTy);

    BasicValueFactory &BVF = VB.getBasicValueFactory();
    APSIntType CTy = BVF.getAPSIntType(CastTy);
    APSIntType TTy = BVF.getAPSIntType(T);

    const auto WC = CTy.getBitWidth();
    const auto WT = TTy.getBitWidth();

    if (WC <= WT) {
      const bool isSameType = (RT == CastTy);
      if (isSameType)
        return nonloc::SymbolVal(RootSym);
      return VB.makeNonLoc(RootSym, RT, CastTy);
    }

    APSIntType RTy = BVF.getAPSIntType(RT);
    const auto WR = RTy.getBitWidth();
    const bool UT = TTy.isUnsigned();
    const bool UR = RTy.isUnsigned();

    if (((WT > WR) && (UR || !UT)) || ((WT == WR) && (UT == UR)))
      return VB.makeNonLoc(RootSym, RT, CastTy);

    return VB.makeNonLoc(SE, T, CastTy);
  }
};
} // end anonymous namespace

/// 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) {
  EvalCastVisitor TRV{*this, CastTy, OriginalTy};
  return TRV.Visit(V);
}
