// SimpleSValBuilder.cpp - A basic SValBuilder -----------------------*- 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 SimpleSValBuilder, a basic implementation of SValBuilder.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"

using namespace clang;
using namespace ento;

namespace {
class SimpleSValBuilder : public SValBuilder {
public:
  SimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
                    ProgramStateManager &stateMgr)
      : SValBuilder(alloc, context, stateMgr) {}
  ~SimpleSValBuilder() override {}

  SVal evalMinus(NonLoc val) override;
  SVal evalComplement(NonLoc val) override;
  SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op,
                   NonLoc lhs, NonLoc rhs, QualType resultTy) override;
  SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op,
                   Loc lhs, Loc rhs, QualType resultTy) override;
  SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op,
                   Loc lhs, NonLoc rhs, QualType resultTy) override;

  /// getKnownValue - evaluates a given SVal. If the SVal has only one possible
  ///  (integer) value, that value is returned. Otherwise, returns NULL.
  const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal V) override;

  /// Recursively descends into symbolic expressions and replaces symbols
  /// with their known values (in the sense of the getKnownValue() method).
  SVal simplifySVal(ProgramStateRef State, SVal V) override;

  SVal MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op,
                     const llvm::APSInt &RHS, QualType resultTy);
};
} // end anonymous namespace

SValBuilder *ento::createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
                                           ASTContext &context,
                                           ProgramStateManager &stateMgr) {
  return new SimpleSValBuilder(alloc, context, stateMgr);
}

//===----------------------------------------------------------------------===//
// Transfer function for unary operators.
//===----------------------------------------------------------------------===//

SVal SimpleSValBuilder::evalMinus(NonLoc val) {
  switch (val.getSubKind()) {
  case nonloc::ConcreteIntKind:
    return val.castAs<nonloc::ConcreteInt>().evalMinus(*this);
  default:
    return UnknownVal();
  }
}

SVal SimpleSValBuilder::evalComplement(NonLoc X) {
  switch (X.getSubKind()) {
  case nonloc::ConcreteIntKind:
    return X.castAs<nonloc::ConcreteInt>().evalComplement(*this);
  default:
    return UnknownVal();
  }
}

//===----------------------------------------------------------------------===//
// Transfer function for binary operators.
//===----------------------------------------------------------------------===//

SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS,
                                    BinaryOperator::Opcode op,
                                    const llvm::APSInt &RHS,
                                    QualType resultTy) {
  bool isIdempotent = false;

  // Check for a few special cases with known reductions first.
  switch (op) {
  default:
    // We can't reduce this case; just treat it normally.
    break;
  case BO_Mul:
    // a*0 and a*1
    if (RHS == 0)
      return makeIntVal(0, resultTy);
    else if (RHS == 1)
      isIdempotent = true;
    break;
  case BO_Div:
    // a/0 and a/1
    if (RHS == 0)
      // This is also handled elsewhere.
      return UndefinedVal();
    else if (RHS == 1)
      isIdempotent = true;
    break;
  case BO_Rem:
    // a%0 and a%1
    if (RHS == 0)
      // This is also handled elsewhere.
      return UndefinedVal();
    else if (RHS == 1)
      return makeIntVal(0, resultTy);
    break;
  case BO_Add:
  case BO_Sub:
  case BO_Shl:
  case BO_Shr:
  case BO_Xor:
    // a+0, a-0, a<<0, a>>0, a^0
    if (RHS == 0)
      isIdempotent = true;
    break;
  case BO_And:
    // a&0 and a&(~0)
    if (RHS == 0)
      return makeIntVal(0, resultTy);
    else if (RHS.isAllOnes())
      isIdempotent = true;
    break;
  case BO_Or:
    // a|0 and a|(~0)
    if (RHS == 0)
      isIdempotent = true;
    else if (RHS.isAllOnes()) {
      const llvm::APSInt &Result = BasicVals.Convert(resultTy, RHS);
      return nonloc::ConcreteInt(Result);
    }
    break;
  }

  // Idempotent ops (like a*1) can still change the type of an expression.
  // Wrap the LHS up in a NonLoc again and let evalCast do the
  // dirty work.
  if (isIdempotent)
    return evalCast(nonloc::SymbolVal(LHS), resultTy, QualType{});

  // If we reach this point, the expression cannot be simplified.
  // Make a SymbolVal for the entire expression, after converting the RHS.
  const llvm::APSInt *ConvertedRHS = &RHS;
  if (BinaryOperator::isComparisonOp(op)) {
    // We're looking for a type big enough to compare the symbolic value
    // with the given constant.
    // FIXME: This is an approximation of Sema::UsualArithmeticConversions.
    ASTContext &Ctx = getContext();
    QualType SymbolType = LHS->getType();
    uint64_t ValWidth = RHS.getBitWidth();
    uint64_t TypeWidth = Ctx.getTypeSize(SymbolType);

    if (ValWidth < TypeWidth) {
      // If the value is too small, extend it.
      ConvertedRHS = &BasicVals.Convert(SymbolType, RHS);
    } else if (ValWidth == TypeWidth) {
      // If the value is signed but the symbol is unsigned, do the comparison
      // in unsigned space. [C99 6.3.1.8]
      // (For the opposite case, the value is already unsigned.)
      if (RHS.isSigned() && !SymbolType->isSignedIntegerOrEnumerationType())
        ConvertedRHS = &BasicVals.Convert(SymbolType, RHS);
    }
  } else
    ConvertedRHS = &BasicVals.Convert(resultTy, RHS);

  return makeNonLoc(LHS, op, *ConvertedRHS, resultTy);
}

// See if Sym is known to be a relation Rel with Bound.
static bool isInRelation(BinaryOperator::Opcode Rel, SymbolRef Sym,
                         llvm::APSInt Bound, ProgramStateRef State) {
  SValBuilder &SVB = State->getStateManager().getSValBuilder();
  SVal Result =
      SVB.evalBinOpNN(State, Rel, nonloc::SymbolVal(Sym),
                      nonloc::ConcreteInt(Bound), SVB.getConditionType());
  if (auto DV = Result.getAs<DefinedSVal>()) {
    return !State->assume(*DV, false);
  }
  return false;
}

// See if Sym is known to be within [min/4, max/4], where min and max
// are the bounds of the symbol's integral type. With such symbols,
// some manipulations can be performed without the risk of overflow.
// assume() doesn't cause infinite recursion because we should be dealing
// with simpler symbols on every recursive call.
static bool isWithinConstantOverflowBounds(SymbolRef Sym,
                                           ProgramStateRef State) {
  SValBuilder &SVB = State->getStateManager().getSValBuilder();
  BasicValueFactory &BV = SVB.getBasicValueFactory();

  QualType T = Sym->getType();
  assert(T->isSignedIntegerOrEnumerationType() &&
         "This only works with signed integers!");
  APSIntType AT = BV.getAPSIntType(T);

  llvm::APSInt Max = AT.getMaxValue() / AT.getValue(4), Min = -Max;
  return isInRelation(BO_LE, Sym, Max, State) &&
         isInRelation(BO_GE, Sym, Min, State);
}

// Same for the concrete integers: see if I is within [min/4, max/4].
static bool isWithinConstantOverflowBounds(llvm::APSInt I) {
  APSIntType AT(I);
  assert(!AT.isUnsigned() &&
         "This only works with signed integers!");

  llvm::APSInt Max = AT.getMaxValue() / AT.getValue(4), Min = -Max;
  return (I <= Max) && (I >= -Max);
}

static std::pair<SymbolRef, llvm::APSInt>
decomposeSymbol(SymbolRef Sym, BasicValueFactory &BV) {
  if (const auto *SymInt = dyn_cast<SymIntExpr>(Sym))
    if (BinaryOperator::isAdditiveOp(SymInt->getOpcode()))
      return std::make_pair(SymInt->getLHS(),
                            (SymInt->getOpcode() == BO_Add) ?
                            (SymInt->getRHS()) :
                            (-SymInt->getRHS()));

  // Fail to decompose: "reduce" the problem to the "$x + 0" case.
  return std::make_pair(Sym, BV.getValue(0, Sym->getType()));
}

// Simplify "(LSym + LInt) Op (RSym + RInt)" assuming all values are of the
// same signed integral type and no overflows occur (which should be checked
// by the caller).
static NonLoc doRearrangeUnchecked(ProgramStateRef State,
                                   BinaryOperator::Opcode Op,
                                   SymbolRef LSym, llvm::APSInt LInt,
                                   SymbolRef RSym, llvm::APSInt RInt) {
  SValBuilder &SVB = State->getStateManager().getSValBuilder();
  BasicValueFactory &BV = SVB.getBasicValueFactory();
  SymbolManager &SymMgr = SVB.getSymbolManager();

  QualType SymTy = LSym->getType();
  assert(SymTy == RSym->getType() &&
         "Symbols are not of the same type!");
  assert(APSIntType(LInt) == BV.getAPSIntType(SymTy) &&
         "Integers are not of the same type as symbols!");
  assert(APSIntType(RInt) == BV.getAPSIntType(SymTy) &&
         "Integers are not of the same type as symbols!");

  QualType ResultTy;
  if (BinaryOperator::isComparisonOp(Op))
    ResultTy = SVB.getConditionType();
  else if (BinaryOperator::isAdditiveOp(Op))
    ResultTy = SymTy;
  else
    llvm_unreachable("Operation not suitable for unchecked rearrangement!");

  // FIXME: Can we use assume() without getting into an infinite recursion?
  if (LSym == RSym)
    return SVB.evalBinOpNN(State, Op, nonloc::ConcreteInt(LInt),
                           nonloc::ConcreteInt(RInt), ResultTy)
        .castAs<NonLoc>();

  SymbolRef ResultSym = nullptr;
  BinaryOperator::Opcode ResultOp;
  llvm::APSInt ResultInt;
  if (BinaryOperator::isComparisonOp(Op)) {
    // Prefer comparing to a non-negative number.
    // FIXME: Maybe it'd be better to have consistency in
    // "$x - $y" vs. "$y - $x" because those are solver's keys.
    if (LInt > RInt) {
      ResultSym = SymMgr.getSymSymExpr(RSym, BO_Sub, LSym, SymTy);
      ResultOp = BinaryOperator::reverseComparisonOp(Op);
      ResultInt = LInt - RInt; // Opposite order!
    } else {
      ResultSym = SymMgr.getSymSymExpr(LSym, BO_Sub, RSym, SymTy);
      ResultOp = Op;
      ResultInt = RInt - LInt; // Opposite order!
    }
  } else {
    ResultSym = SymMgr.getSymSymExpr(LSym, Op, RSym, SymTy);
    ResultInt = (Op == BO_Add) ? (LInt + RInt) : (LInt - RInt);
    ResultOp = BO_Add;
    // Bring back the cosmetic difference.
    if (ResultInt < 0) {
      ResultInt = -ResultInt;
      ResultOp = BO_Sub;
    } else if (ResultInt == 0) {
      // Shortcut: Simplify "$x + 0" to "$x".
      return nonloc::SymbolVal(ResultSym);
    }
  }
  const llvm::APSInt &PersistentResultInt = BV.getValue(ResultInt);
  return nonloc::SymbolVal(
      SymMgr.getSymIntExpr(ResultSym, ResultOp, PersistentResultInt, ResultTy));
}

// Rearrange if symbol type matches the result type and if the operator is a
// comparison operator, both symbol and constant must be within constant
// overflow bounds.
static bool shouldRearrange(ProgramStateRef State, BinaryOperator::Opcode Op,
                            SymbolRef Sym, llvm::APSInt Int, QualType Ty) {
  return Sym->getType() == Ty &&
    (!BinaryOperator::isComparisonOp(Op) ||
     (isWithinConstantOverflowBounds(Sym, State) &&
      isWithinConstantOverflowBounds(Int)));
}

static Optional<NonLoc> tryRearrange(ProgramStateRef State,
                                     BinaryOperator::Opcode Op, NonLoc Lhs,
                                     NonLoc Rhs, QualType ResultTy) {
  ProgramStateManager &StateMgr = State->getStateManager();
  SValBuilder &SVB = StateMgr.getSValBuilder();

  // We expect everything to be of the same type - this type.
  QualType SingleTy;

  // FIXME: After putting complexity threshold to the symbols we can always
  //        rearrange additive operations but rearrange comparisons only if
  //        option is set.
  if (!SVB.getAnalyzerOptions().ShouldAggressivelySimplifyBinaryOperation)
    return None;

  SymbolRef LSym = Lhs.getAsSymbol();
  if (!LSym)
    return None;

  if (BinaryOperator::isComparisonOp(Op)) {
    SingleTy = LSym->getType();
    if (ResultTy != SVB.getConditionType())
      return None;
    // Initialize SingleTy later with a symbol's type.
  } else if (BinaryOperator::isAdditiveOp(Op)) {
    SingleTy = ResultTy;
    if (LSym->getType() != SingleTy)
      return None;
  } else {
    // Don't rearrange other operations.
    return None;
  }

  assert(!SingleTy.isNull() && "We should have figured out the type by now!");

  // Rearrange signed symbolic expressions only
  if (!SingleTy->isSignedIntegerOrEnumerationType())
    return None;

  SymbolRef RSym = Rhs.getAsSymbol();
  if (!RSym || RSym->getType() != SingleTy)
    return None;

  BasicValueFactory &BV = State->getBasicVals();
  llvm::APSInt LInt, RInt;
  std::tie(LSym, LInt) = decomposeSymbol(LSym, BV);
  std::tie(RSym, RInt) = decomposeSymbol(RSym, BV);
  if (!shouldRearrange(State, Op, LSym, LInt, SingleTy) ||
      !shouldRearrange(State, Op, RSym, RInt, SingleTy))
    return None;

  // We know that no overflows can occur anymore.
  return doRearrangeUnchecked(State, Op, LSym, LInt, RSym, RInt);
}

SVal SimpleSValBuilder::evalBinOpNN(ProgramStateRef state,
                                  BinaryOperator::Opcode op,
                                  NonLoc lhs, NonLoc rhs,
                                  QualType resultTy)  {
  NonLoc InputLHS = lhs;
  NonLoc InputRHS = rhs;

  // Constraints may have changed since the creation of a bound SVal. Check if
  // the values can be simplified based on those new constraints.
  SVal simplifiedLhs = simplifySVal(state, lhs);
  SVal simplifiedRhs = simplifySVal(state, rhs);
  if (auto simplifiedLhsAsNonLoc = simplifiedLhs.getAs<NonLoc>())
    lhs = *simplifiedLhsAsNonLoc;
  if (auto simplifiedRhsAsNonLoc = simplifiedRhs.getAs<NonLoc>())
    rhs = *simplifiedRhsAsNonLoc;

  // Handle trivial case where left-side and right-side are the same.
  if (lhs == rhs)
    switch (op) {
      default:
        break;
      case BO_EQ:
      case BO_LE:
      case BO_GE:
        return makeTruthVal(true, resultTy);
      case BO_LT:
      case BO_GT:
      case BO_NE:
        return makeTruthVal(false, resultTy);
      case BO_Xor:
      case BO_Sub:
        if (resultTy->isIntegralOrEnumerationType())
          return makeIntVal(0, resultTy);
        return evalCast(makeIntVal(0, /*isUnsigned=*/false), resultTy,
                        QualType{});
      case BO_Or:
      case BO_And:
        return evalCast(lhs, resultTy, QualType{});
    }

  while (1) {
    switch (lhs.getSubKind()) {
    default:
      return makeSymExprValNN(op, lhs, rhs, resultTy);
    case nonloc::PointerToMemberKind: {
      assert(rhs.getSubKind() == nonloc::PointerToMemberKind &&
             "Both SVals should have pointer-to-member-type");
      auto LPTM = lhs.castAs<nonloc::PointerToMember>(),
           RPTM = rhs.castAs<nonloc::PointerToMember>();
      auto LPTMD = LPTM.getPTMData(), RPTMD = RPTM.getPTMData();
      switch (op) {
        case BO_EQ:
          return makeTruthVal(LPTMD == RPTMD, resultTy);
        case BO_NE:
          return makeTruthVal(LPTMD != RPTMD, resultTy);
        default:
          return UnknownVal();
      }
    }
    case nonloc::LocAsIntegerKind: {
      Loc lhsL = lhs.castAs<nonloc::LocAsInteger>().getLoc();
      switch (rhs.getSubKind()) {
        case nonloc::LocAsIntegerKind:
          // FIXME: at the moment the implementation
          // of modeling "pointers as integers" is not complete.
          if (!BinaryOperator::isComparisonOp(op))
            return UnknownVal();
          return evalBinOpLL(state, op, lhsL,
                             rhs.castAs<nonloc::LocAsInteger>().getLoc(),
                             resultTy);
        case nonloc::ConcreteIntKind: {
          // FIXME: at the moment the implementation
          // of modeling "pointers as integers" is not complete.
          if (!BinaryOperator::isComparisonOp(op))
            return UnknownVal();
          // Transform the integer into a location and compare.
          // FIXME: This only makes sense for comparisons. If we want to, say,
          // add 1 to a LocAsInteger, we'd better unpack the Loc and add to it,
          // then pack it back into a LocAsInteger.
          llvm::APSInt i = rhs.castAs<nonloc::ConcreteInt>().getValue();
          // If the region has a symbolic base, pay attention to the type; it
          // might be coming from a non-default address space. For non-symbolic
          // regions it doesn't matter that much because such comparisons would
          // most likely evaluate to concrete false anyway. FIXME: We might
          // still need to handle the non-comparison case.
          if (SymbolRef lSym = lhs.getAsLocSymbol(true))
            BasicVals.getAPSIntType(lSym->getType()).apply(i);
          else
            BasicVals.getAPSIntType(Context.VoidPtrTy).apply(i);
          return evalBinOpLL(state, op, lhsL, makeLoc(i), resultTy);
        }
        default:
          switch (op) {
            case BO_EQ:
              return makeTruthVal(false, resultTy);
            case BO_NE:
              return makeTruthVal(true, resultTy);
            default:
              // This case also handles pointer arithmetic.
              return makeSymExprValNN(op, InputLHS, InputRHS, resultTy);
          }
      }
    }
    case nonloc::ConcreteIntKind: {
      llvm::APSInt LHSValue = lhs.castAs<nonloc::ConcreteInt>().getValue();

      // If we're dealing with two known constants, just perform the operation.
      if (const llvm::APSInt *KnownRHSValue = getKnownValue(state, rhs)) {
        llvm::APSInt RHSValue = *KnownRHSValue;
        if (BinaryOperator::isComparisonOp(op)) {
          // We're looking for a type big enough to compare the two values.
          // FIXME: This is not correct. char + short will result in a promotion
          // to int. Unfortunately we have lost types by this point.
          APSIntType CompareType = std::max(APSIntType(LHSValue),
                                            APSIntType(RHSValue));
          CompareType.apply(LHSValue);
          CompareType.apply(RHSValue);
        } else if (!BinaryOperator::isShiftOp(op)) {
          APSIntType IntType = BasicVals.getAPSIntType(resultTy);
          IntType.apply(LHSValue);
          IntType.apply(RHSValue);
        }

        const llvm::APSInt *Result =
          BasicVals.evalAPSInt(op, LHSValue, RHSValue);
        if (!Result)
          return UndefinedVal();

        return nonloc::ConcreteInt(*Result);
      }

      // Swap the left and right sides and flip the operator if doing so
      // allows us to better reason about the expression (this is a form
      // of expression canonicalization).
      // While we're at it, catch some special cases for non-commutative ops.
      switch (op) {
      case BO_LT:
      case BO_GT:
      case BO_LE:
      case BO_GE:
        op = BinaryOperator::reverseComparisonOp(op);
        LLVM_FALLTHROUGH;
      case BO_EQ:
      case BO_NE:
      case BO_Add:
      case BO_Mul:
      case BO_And:
      case BO_Xor:
      case BO_Or:
        std::swap(lhs, rhs);
        continue;
      case BO_Shr:
        // (~0)>>a
        if (LHSValue.isAllOnes() && LHSValue.isSigned())
          return evalCast(lhs, resultTy, QualType{});
        LLVM_FALLTHROUGH;
      case BO_Shl:
        // 0<<a and 0>>a
        if (LHSValue == 0)
          return evalCast(lhs, resultTy, QualType{});
        return makeSymExprValNN(op, InputLHS, InputRHS, resultTy);
      case BO_Div:
        // 0 / x == 0
      case BO_Rem:
        // 0 % x == 0
        if (LHSValue == 0)
          return makeZeroVal(resultTy);
        LLVM_FALLTHROUGH;
      default:
        return makeSymExprValNN(op, InputLHS, InputRHS, resultTy);
      }
    }
    case nonloc::SymbolValKind: {
      // We only handle LHS as simple symbols or SymIntExprs.
      SymbolRef Sym = lhs.castAs<nonloc::SymbolVal>().getSymbol();

      // LHS is a symbolic expression.
      if (const SymIntExpr *symIntExpr = dyn_cast<SymIntExpr>(Sym)) {

        // Is this a logical not? (!x is represented as x == 0.)
        if (op == BO_EQ && rhs.isZeroConstant()) {
          // We know how to negate certain expressions. Simplify them here.

          BinaryOperator::Opcode opc = symIntExpr->getOpcode();
          switch (opc) {
          default:
            // We don't know how to negate this operation.
            // Just handle it as if it were a normal comparison to 0.
            break;
          case BO_LAnd:
          case BO_LOr:
            llvm_unreachable("Logical operators handled by branching logic.");
          case BO_Assign:
          case BO_MulAssign:
          case BO_DivAssign:
          case BO_RemAssign:
          case BO_AddAssign:
          case BO_SubAssign:
          case BO_ShlAssign:
          case BO_ShrAssign:
          case BO_AndAssign:
          case BO_XorAssign:
          case BO_OrAssign:
          case BO_Comma:
            llvm_unreachable("'=' and ',' operators handled by ExprEngine.");
          case BO_PtrMemD:
          case BO_PtrMemI:
            llvm_unreachable("Pointer arithmetic not handled here.");
          case BO_LT:
          case BO_GT:
          case BO_LE:
          case BO_GE:
          case BO_EQ:
          case BO_NE:
            assert(resultTy->isBooleanType() ||
                   resultTy == getConditionType());
            assert(symIntExpr->getType()->isBooleanType() ||
                   getContext().hasSameUnqualifiedType(symIntExpr->getType(),
                                                       getConditionType()));
            // Negate the comparison and make a value.
            opc = BinaryOperator::negateComparisonOp(opc);
            return makeNonLoc(symIntExpr->getLHS(), opc,
                symIntExpr->getRHS(), resultTy);
          }
        }

        // For now, only handle expressions whose RHS is a constant.
        if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs)) {
          // If both the LHS and the current expression are additive,
          // fold their constants and try again.
          if (BinaryOperator::isAdditiveOp(op)) {
            BinaryOperator::Opcode lop = symIntExpr->getOpcode();
            if (BinaryOperator::isAdditiveOp(lop)) {
              // Convert the two constants to a common type, then combine them.

              // resultTy may not be the best type to convert to, but it's
              // probably the best choice in expressions with mixed type
              // (such as x+1U+2LL). The rules for implicit conversions should
              // choose a reasonable type to preserve the expression, and will
              // at least match how the value is going to be used.
              APSIntType IntType = BasicVals.getAPSIntType(resultTy);
              const llvm::APSInt &first = IntType.convert(symIntExpr->getRHS());
              const llvm::APSInt &second = IntType.convert(*RHSValue);

              const llvm::APSInt *newRHS;
              if (lop == op)
                newRHS = BasicVals.evalAPSInt(BO_Add, first, second);
              else
                newRHS = BasicVals.evalAPSInt(BO_Sub, first, second);

              assert(newRHS && "Invalid operation despite common type!");
              rhs = nonloc::ConcreteInt(*newRHS);
              lhs = nonloc::SymbolVal(symIntExpr->getLHS());
              op = lop;
              continue;
            }
          }

          // Otherwise, make a SymIntExpr out of the expression.
          return MakeSymIntVal(symIntExpr, op, *RHSValue, resultTy);
        }
      }

      // Is the RHS a constant?
      if (const llvm::APSInt *RHSValue = getKnownValue(state, rhs))
        return MakeSymIntVal(Sym, op, *RHSValue, resultTy);

      if (Optional<NonLoc> V = tryRearrange(state, op, lhs, rhs, resultTy))
        return *V;

      // Give up -- this is not a symbolic expression we can handle.
      return makeSymExprValNN(op, InputLHS, InputRHS, resultTy);
    }
    }
  }
}

static SVal evalBinOpFieldRegionFieldRegion(const FieldRegion *LeftFR,
                                            const FieldRegion *RightFR,
                                            BinaryOperator::Opcode op,
                                            QualType resultTy,
                                            SimpleSValBuilder &SVB) {
  // Only comparisons are meaningful here!
  if (!BinaryOperator::isComparisonOp(op))
    return UnknownVal();

  // Next, see if the two FRs have the same super-region.
  // FIXME: This doesn't handle casts yet, and simply stripping the casts
  // doesn't help.
  if (LeftFR->getSuperRegion() != RightFR->getSuperRegion())
    return UnknownVal();

  const FieldDecl *LeftFD = LeftFR->getDecl();
  const FieldDecl *RightFD = RightFR->getDecl();
  const RecordDecl *RD = LeftFD->getParent();

  // Make sure the two FRs are from the same kind of record. Just in case!
  // FIXME: This is probably where inheritance would be a problem.
  if (RD != RightFD->getParent())
    return UnknownVal();

  // We know for sure that the two fields are not the same, since that
  // would have given us the same SVal.
  if (op == BO_EQ)
    return SVB.makeTruthVal(false, resultTy);
  if (op == BO_NE)
    return SVB.makeTruthVal(true, resultTy);

  // Iterate through the fields and see which one comes first.
  // [C99 6.7.2.1.13] "Within a structure object, the non-bit-field
  // members and the units in which bit-fields reside have addresses that
  // increase in the order in which they are declared."
  bool leftFirst = (op == BO_LT || op == BO_LE);
  for (const auto *I : RD->fields()) {
    if (I == LeftFD)
      return SVB.makeTruthVal(leftFirst, resultTy);
    if (I == RightFD)
      return SVB.makeTruthVal(!leftFirst, resultTy);
  }

  llvm_unreachable("Fields not found in parent record's definition");
}

// FIXME: all this logic will change if/when we have MemRegion::getLocation().
SVal SimpleSValBuilder::evalBinOpLL(ProgramStateRef state,
                                  BinaryOperator::Opcode op,
                                  Loc lhs, Loc rhs,
                                  QualType resultTy) {
  // Only comparisons and subtractions are valid operations on two pointers.
  // See [C99 6.5.5 through 6.5.14] or [C++0x 5.6 through 5.15].
  // However, if a pointer is casted to an integer, evalBinOpNN may end up
  // calling this function with another operation (PR7527). We don't attempt to
  // model this for now, but it could be useful, particularly when the
  // "location" is actually an integer value that's been passed through a void*.
  if (!(BinaryOperator::isComparisonOp(op) || op == BO_Sub))
    return UnknownVal();

  // Special cases for when both sides are identical.
  if (lhs == rhs) {
    switch (op) {
    default:
      llvm_unreachable("Unimplemented operation for two identical values");
    case BO_Sub:
      return makeZeroVal(resultTy);
    case BO_EQ:
    case BO_LE:
    case BO_GE:
      return makeTruthVal(true, resultTy);
    case BO_NE:
    case BO_LT:
    case BO_GT:
      return makeTruthVal(false, resultTy);
    }
  }

  switch (lhs.getSubKind()) {
  default:
    llvm_unreachable("Ordering not implemented for this Loc.");

  case loc::GotoLabelKind:
    // The only thing we know about labels is that they're non-null.
    if (rhs.isZeroConstant()) {
      switch (op) {
      default:
        break;
      case BO_Sub:
        return evalCast(lhs, resultTy, QualType{});
      case BO_EQ:
      case BO_LE:
      case BO_LT:
        return makeTruthVal(false, resultTy);
      case BO_NE:
      case BO_GT:
      case BO_GE:
        return makeTruthVal(true, resultTy);
      }
    }
    // There may be two labels for the same location, and a function region may
    // have the same address as a label at the start of the function (depending
    // on the ABI).
    // FIXME: we can probably do a comparison against other MemRegions, though.
    // FIXME: is there a way to tell if two labels refer to the same location?
    return UnknownVal();

  case loc::ConcreteIntKind: {
    // If one of the operands is a symbol and the other is a constant,
    // build an expression for use by the constraint manager.
    if (SymbolRef rSym = rhs.getAsLocSymbol()) {
      // We can only build expressions with symbols on the left,
      // so we need a reversible operator.
      if (!BinaryOperator::isComparisonOp(op) || op == BO_Cmp)
        return UnknownVal();

      const llvm::APSInt &lVal = lhs.castAs<loc::ConcreteInt>().getValue();
      op = BinaryOperator::reverseComparisonOp(op);
      return makeNonLoc(rSym, op, lVal, resultTy);
    }

    // If both operands are constants, just perform the operation.
    if (Optional<loc::ConcreteInt> rInt = rhs.getAs<loc::ConcreteInt>()) {
      SVal ResultVal =
          lhs.castAs<loc::ConcreteInt>().evalBinOp(BasicVals, op, *rInt);
      if (Optional<NonLoc> Result = ResultVal.getAs<NonLoc>())
        return evalCast(*Result, resultTy, QualType{});

      assert(!ResultVal.getAs<Loc>() && "Loc-Loc ops should not produce Locs");
      return UnknownVal();
    }

    // Special case comparisons against NULL.
    // This must come after the test if the RHS is a symbol, which is used to
    // build constraints. The address of any non-symbolic region is guaranteed
    // to be non-NULL, as is any label.
    assert(rhs.getAs<loc::MemRegionVal>() || rhs.getAs<loc::GotoLabel>());
    if (lhs.isZeroConstant()) {
      switch (op) {
      default:
        break;
      case BO_EQ:
      case BO_GT:
      case BO_GE:
        return makeTruthVal(false, resultTy);
      case BO_NE:
      case BO_LT:
      case BO_LE:
        return makeTruthVal(true, resultTy);
      }
    }

    // Comparing an arbitrary integer to a region or label address is
    // completely unknowable.
    return UnknownVal();
  }
  case loc::MemRegionValKind: {
    if (Optional<loc::ConcreteInt> rInt = rhs.getAs<loc::ConcreteInt>()) {
      // If one of the operands is a symbol and the other is a constant,
      // build an expression for use by the constraint manager.
      if (SymbolRef lSym = lhs.getAsLocSymbol(true)) {
        if (BinaryOperator::isComparisonOp(op))
          return MakeSymIntVal(lSym, op, rInt->getValue(), resultTy);
        return UnknownVal();
      }
      // Special case comparisons to NULL.
      // This must come after the test if the LHS is a symbol, which is used to
      // build constraints. The address of any non-symbolic region is guaranteed
      // to be non-NULL.
      if (rInt->isZeroConstant()) {
        if (op == BO_Sub)
          return evalCast(lhs, resultTy, QualType{});

        if (BinaryOperator::isComparisonOp(op)) {
          QualType boolType = getContext().BoolTy;
          NonLoc l = evalCast(lhs, boolType, QualType{}).castAs<NonLoc>();
          NonLoc r = makeTruthVal(false, boolType).castAs<NonLoc>();
          return evalBinOpNN(state, op, l, r, resultTy);
        }
      }

      // Comparing a region to an arbitrary integer is completely unknowable.
      return UnknownVal();
    }

    // Get both values as regions, if possible.
    const MemRegion *LeftMR = lhs.getAsRegion();
    assert(LeftMR && "MemRegionValKind SVal doesn't have a region!");

    const MemRegion *RightMR = rhs.getAsRegion();
    if (!RightMR)
      // The RHS is probably a label, which in theory could address a region.
      // FIXME: we can probably make a more useful statement about non-code
      // regions, though.
      return UnknownVal();

    const MemRegion *LeftBase = LeftMR->getBaseRegion();
    const MemRegion *RightBase = RightMR->getBaseRegion();
    const MemSpaceRegion *LeftMS = LeftBase->getMemorySpace();
    const MemSpaceRegion *RightMS = RightBase->getMemorySpace();
    const MemSpaceRegion *UnknownMS = MemMgr.getUnknownRegion();

    // If the two regions are from different known memory spaces they cannot be
    // equal. Also, assume that no symbolic region (whose memory space is
    // unknown) is on the stack.
    if (LeftMS != RightMS &&
        ((LeftMS != UnknownMS && RightMS != UnknownMS) ||
         (isa<StackSpaceRegion>(LeftMS) || isa<StackSpaceRegion>(RightMS)))) {
      switch (op) {
      default:
        return UnknownVal();
      case BO_EQ:
        return makeTruthVal(false, resultTy);
      case BO_NE:
        return makeTruthVal(true, resultTy);
      }
    }

    // If both values wrap regions, see if they're from different base regions.
    // Note, heap base symbolic regions are assumed to not alias with
    // each other; for example, we assume that malloc returns different address
    // on each invocation.
    // FIXME: ObjC object pointers always reside on the heap, but currently
    // we treat their memory space as unknown, because symbolic pointers
    // to ObjC objects may alias. There should be a way to construct
    // possibly-aliasing heap-based regions. For instance, MacOSXApiChecker
    // guesses memory space for ObjC object pointers manually instead of
    // relying on us.
    if (LeftBase != RightBase &&
        ((!isa<SymbolicRegion>(LeftBase) && !isa<SymbolicRegion>(RightBase)) ||
         (isa<HeapSpaceRegion>(LeftMS) || isa<HeapSpaceRegion>(RightMS))) ){
      switch (op) {
      default:
        return UnknownVal();
      case BO_EQ:
        return makeTruthVal(false, resultTy);
      case BO_NE:
        return makeTruthVal(true, resultTy);
      }
    }

    // Handle special cases for when both regions are element regions.
    const ElementRegion *RightER = dyn_cast<ElementRegion>(RightMR);
    const ElementRegion *LeftER = dyn_cast<ElementRegion>(LeftMR);
    if (RightER && LeftER) {
      // Next, see if the two ERs have the same super-region and matching types.
      // FIXME: This should do something useful even if the types don't match,
      // though if both indexes are constant the RegionRawOffset path will
      // give the correct answer.
      if (LeftER->getSuperRegion() == RightER->getSuperRegion() &&
          LeftER->getElementType() == RightER->getElementType()) {
        // Get the left index and cast it to the correct type.
        // If the index is unknown or undefined, bail out here.
        SVal LeftIndexVal = LeftER->getIndex();
        Optional<NonLoc> LeftIndex = LeftIndexVal.getAs<NonLoc>();
        if (!LeftIndex)
          return UnknownVal();
        LeftIndexVal = evalCast(*LeftIndex, ArrayIndexTy, QualType{});
        LeftIndex = LeftIndexVal.getAs<NonLoc>();
        if (!LeftIndex)
          return UnknownVal();

        // Do the same for the right index.
        SVal RightIndexVal = RightER->getIndex();
        Optional<NonLoc> RightIndex = RightIndexVal.getAs<NonLoc>();
        if (!RightIndex)
          return UnknownVal();
        RightIndexVal = evalCast(*RightIndex, ArrayIndexTy, QualType{});
        RightIndex = RightIndexVal.getAs<NonLoc>();
        if (!RightIndex)
          return UnknownVal();

        // Actually perform the operation.
        // evalBinOpNN expects the two indexes to already be the right type.
        return evalBinOpNN(state, op, *LeftIndex, *RightIndex, resultTy);
      }
    }

    // Special handling of the FieldRegions, even with symbolic offsets.
    const FieldRegion *RightFR = dyn_cast<FieldRegion>(RightMR);
    const FieldRegion *LeftFR = dyn_cast<FieldRegion>(LeftMR);
    if (RightFR && LeftFR) {
      SVal R = evalBinOpFieldRegionFieldRegion(LeftFR, RightFR, op, resultTy,
                                               *this);
      if (!R.isUnknown())
        return R;
    }

    // Compare the regions using the raw offsets.
    RegionOffset LeftOffset = LeftMR->getAsOffset();
    RegionOffset RightOffset = RightMR->getAsOffset();

    if (LeftOffset.getRegion() != nullptr &&
        LeftOffset.getRegion() == RightOffset.getRegion() &&
        !LeftOffset.hasSymbolicOffset() && !RightOffset.hasSymbolicOffset()) {
      int64_t left = LeftOffset.getOffset();
      int64_t right = RightOffset.getOffset();

      switch (op) {
        default:
          return UnknownVal();
        case BO_LT:
          return makeTruthVal(left < right, resultTy);
        case BO_GT:
          return makeTruthVal(left > right, resultTy);
        case BO_LE:
          return makeTruthVal(left <= right, resultTy);
        case BO_GE:
          return makeTruthVal(left >= right, resultTy);
        case BO_EQ:
          return makeTruthVal(left == right, resultTy);
        case BO_NE:
          return makeTruthVal(left != right, resultTy);
      }
    }

    // At this point we're not going to get a good answer, but we can try
    // conjuring an expression instead.
    SymbolRef LHSSym = lhs.getAsLocSymbol();
    SymbolRef RHSSym = rhs.getAsLocSymbol();
    if (LHSSym && RHSSym)
      return makeNonLoc(LHSSym, op, RHSSym, resultTy);

    // If we get here, we have no way of comparing the regions.
    return UnknownVal();
  }
  }
}

SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
                                    BinaryOperator::Opcode op, Loc lhs,
                                    NonLoc rhs, QualType resultTy) {
  if (op >= BO_PtrMemD && op <= BO_PtrMemI) {
    if (auto PTMSV = rhs.getAs<nonloc::PointerToMember>()) {
      if (PTMSV->isNullMemberPointer())
        return UndefinedVal();

      auto getFieldLValue = [&](const auto *FD) -> SVal {
        SVal Result = lhs;

        for (const auto &I : *PTMSV)
          Result = StateMgr.getStoreManager().evalDerivedToBase(
              Result, I->getType(), I->isVirtual());

        return state->getLValue(FD, Result);
      };

      if (const auto *FD = PTMSV->getDeclAs<FieldDecl>()) {
        return getFieldLValue(FD);
      }
      if (const auto *FD = PTMSV->getDeclAs<IndirectFieldDecl>()) {
        return getFieldLValue(FD);
      }
    }

    return rhs;
  }

  assert(!BinaryOperator::isComparisonOp(op) &&
         "arguments to comparison ops must be of the same type");

  // Special case: rhs is a zero constant.
  if (rhs.isZeroConstant())
    return lhs;

  // Perserve the null pointer so that it can be found by the DerefChecker.
  if (lhs.isZeroConstant())
    return lhs;

  // We are dealing with pointer arithmetic.

  // Handle pointer arithmetic on constant values.
  if (Optional<nonloc::ConcreteInt> rhsInt = rhs.getAs<nonloc::ConcreteInt>()) {
    if (Optional<loc::ConcreteInt> lhsInt = lhs.getAs<loc::ConcreteInt>()) {
      const llvm::APSInt &leftI = lhsInt->getValue();
      assert(leftI.isUnsigned());
      llvm::APSInt rightI(rhsInt->getValue(), /* isUnsigned */ true);

      // Convert the bitwidth of rightI.  This should deal with overflow
      // since we are dealing with concrete values.
      rightI = rightI.extOrTrunc(leftI.getBitWidth());

      // Offset the increment by the pointer size.
      llvm::APSInt Multiplicand(rightI.getBitWidth(), /* isUnsigned */ true);
      QualType pointeeType = resultTy->getPointeeType();
      Multiplicand = getContext().getTypeSizeInChars(pointeeType).getQuantity();
      rightI *= Multiplicand;

      // Compute the adjusted pointer.
      switch (op) {
        case BO_Add:
          rightI = leftI + rightI;
          break;
        case BO_Sub:
          rightI = leftI - rightI;
          break;
        default:
          llvm_unreachable("Invalid pointer arithmetic operation");
      }
      return loc::ConcreteInt(getBasicValueFactory().getValue(rightI));
    }
  }

  // Handle cases where 'lhs' is a region.
  if (const MemRegion *region = lhs.getAsRegion()) {
    rhs = convertToArrayIndex(rhs).castAs<NonLoc>();
    SVal index = UnknownVal();
    const SubRegion *superR = nullptr;
    // We need to know the type of the pointer in order to add an integer to it.
    // Depending on the type, different amount of bytes is added.
    QualType elementType;

    if (const ElementRegion *elemReg = dyn_cast<ElementRegion>(region)) {
      assert(op == BO_Add || op == BO_Sub);
      index = evalBinOpNN(state, op, elemReg->getIndex(), rhs,
                          getArrayIndexType());
      superR = cast<SubRegion>(elemReg->getSuperRegion());
      elementType = elemReg->getElementType();
    }
    else if (isa<SubRegion>(region)) {
      assert(op == BO_Add || op == BO_Sub);
      index = (op == BO_Add) ? rhs : evalMinus(rhs);
      superR = cast<SubRegion>(region);
      // TODO: Is this actually reliable? Maybe improving our MemRegion
      // hierarchy to provide typed regions for all non-void pointers would be
      // better. For instance, we cannot extend this towards LocAsInteger
      // operations, where result type of the expression is integer.
      if (resultTy->isAnyPointerType())
        elementType = resultTy->getPointeeType();
    }

    // Represent arithmetic on void pointers as arithmetic on char pointers.
    // It is fine when a TypedValueRegion of char value type represents
    // a void pointer. Note that arithmetic on void pointers is a GCC extension.
    if (elementType->isVoidType())
      elementType = getContext().CharTy;

    if (Optional<NonLoc> indexV = index.getAs<NonLoc>()) {
      return loc::MemRegionVal(MemMgr.getElementRegion(elementType, *indexV,
                                                       superR, getContext()));
    }
  }
  return UnknownVal();
}

const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
                                                   SVal V) {
  V = simplifySVal(state, V);
  if (V.isUnknownOrUndef())
    return nullptr;

  if (Optional<loc::ConcreteInt> X = V.getAs<loc::ConcreteInt>())
    return &X->getValue();

  if (Optional<nonloc::ConcreteInt> X = V.getAs<nonloc::ConcreteInt>())
    return &X->getValue();

  if (SymbolRef Sym = V.getAsSymbol())
    return state->getConstraintManager().getSymVal(state, Sym);

  return nullptr;
}

SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
  // For now, this function tries to constant-fold symbols inside a
  // nonloc::SymbolVal, and does nothing else. More simplifications should
  // be possible, such as constant-folding an index in an ElementRegion.

  class Simplifier : public FullSValVisitor<Simplifier, SVal> {
    ProgramStateRef State;
    SValBuilder &SVB;

    // Cache results for the lifetime of the Simplifier. Results change every
    // time new constraints are added to the program state, which is the whole
    // point of simplifying, and for that very reason it's pointless to maintain
    // the same cache for the duration of the whole analysis.
    llvm::DenseMap<SymbolRef, SVal> Cached;

    static bool isUnchanged(SymbolRef Sym, SVal Val) {
      return Sym == Val.getAsSymbol();
    }

    SVal cache(SymbolRef Sym, SVal V) {
      Cached[Sym] = V;
      return V;
    }

    SVal skip(SymbolRef Sym) {
      return cache(Sym, SVB.makeSymbolVal(Sym));
    }

    // Return the known const value for the Sym if available, or return Undef
    // otherwise.
    SVal getConst(SymbolRef Sym) {
      const llvm::APSInt *Const =
          State->getConstraintManager().getSymVal(State, Sym);
      if (Const)
        return Loc::isLocType(Sym->getType()) ? (SVal)SVB.makeIntLocVal(*Const)
                                              : (SVal)SVB.makeIntVal(*Const);
      return UndefinedVal();
    }

    SVal getConstOrVisit(SymbolRef Sym) {
      const SVal Ret = getConst(Sym);
      if (Ret.isUndef())
        return Visit(Sym);
      return Ret;
    }

  public:
    Simplifier(ProgramStateRef State)
        : State(State), SVB(State->getStateManager().getSValBuilder()) {}

    SVal VisitSymbolData(const SymbolData *S) {
      // No cache here.
      if (const llvm::APSInt *I =
              SVB.getKnownValue(State, SVB.makeSymbolVal(S)))
        return Loc::isLocType(S->getType()) ? (SVal)SVB.makeIntLocVal(*I)
                                            : (SVal)SVB.makeIntVal(*I);
      return SVB.makeSymbolVal(S);
    }

    // TODO: Support SymbolCast.

    SVal VisitSymIntExpr(const SymIntExpr *S) {
      auto I = Cached.find(S);
      if (I != Cached.end())
        return I->second;

      SVal LHS = getConstOrVisit(S->getLHS());
      if (isUnchanged(S->getLHS(), LHS))
        return skip(S);

      SVal RHS;
      // By looking at the APSInt in the right-hand side of S, we cannot
      // figure out if it should be treated as a Loc or as a NonLoc.
      // So make our guess by recalling that we cannot multiply pointers
      // or compare a pointer to an integer.
      if (Loc::isLocType(S->getLHS()->getType()) &&
          BinaryOperator::isComparisonOp(S->getOpcode())) {
        // The usual conversion of $sym to &SymRegion{$sym}, as they have
        // the same meaning for Loc-type symbols, but the latter form
        // is preferred in SVal computations for being Loc itself.
        if (SymbolRef Sym = LHS.getAsSymbol()) {
          assert(Loc::isLocType(Sym->getType()));
          LHS = SVB.makeLoc(Sym);
        }
        RHS = SVB.makeIntLocVal(S->getRHS());
      } else {
        RHS = SVB.makeIntVal(S->getRHS());
      }

      return cache(
          S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()));
    }

    SVal VisitIntSymExpr(const IntSymExpr *S) {
      auto I = Cached.find(S);
      if (I != Cached.end())
        return I->second;

      SVal RHS = getConstOrVisit(S->getRHS());
      if (isUnchanged(S->getRHS(), RHS))
        return skip(S);

      SVal LHS = SVB.makeIntVal(S->getLHS());
      return cache(
          S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()));
    }

    SVal VisitSymSymExpr(const SymSymExpr *S) {
      auto I = Cached.find(S);
      if (I != Cached.end())
        return I->second;

      // For now don't try to simplify mixed Loc/NonLoc expressions
      // because they often appear from LocAsInteger operations
      // and we don't know how to combine a LocAsInteger
      // with a concrete value.
      if (Loc::isLocType(S->getLHS()->getType()) !=
          Loc::isLocType(S->getRHS()->getType()))
        return skip(S);

      SVal LHS = getConstOrVisit(S->getLHS());
      SVal RHS = getConstOrVisit(S->getRHS());

      if (isUnchanged(S->getLHS(), LHS) && isUnchanged(S->getRHS(), RHS))
        return skip(S);

      return cache(
          S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()));
    }

    SVal VisitSymExpr(SymbolRef S) { return nonloc::SymbolVal(S); }

    SVal VisitMemRegion(const MemRegion *R) { return loc::MemRegionVal(R); }

    SVal VisitNonLocSymbolVal(nonloc::SymbolVal V) {
      // Simplification is much more costly than computing complexity.
      // For high complexity, it may be not worth it.
      return Visit(V.getSymbol());
    }

    SVal VisitSVal(SVal V) { return V; }
  };

  // A crude way of preventing this function from calling itself from evalBinOp.
  static bool isReentering = false;
  if (isReentering)
    return V;

  isReentering = true;
  SVal SimplifiedV = Simplifier(State).Visit(V);
  isReentering = false;

  return SimplifiedV;
}
