Beispiel #1
0
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.isAllOnesValue())
      isIdempotent = true;
    break;
  case BO_Or:
    // a|0 and a|(~0)
    if (RHS == 0)
      isIdempotent = true;
    else if (RHS.isAllOnesValue()) {
      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 evalCastFromNonLoc do the
  // dirty work.
  if (isIdempotent)
      return evalCastFromNonLoc(nonloc::SymbolVal(LHS), resultTy);

  // 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);
}
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.isAllOnesValue())
      isIdempotent = true;
    break;
  case BO_Or:
    // a|0 and a|(~0)
    if (RHS == 0)
      isIdempotent = true;
    else if (RHS.isAllOnesValue()) {
      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 evalCastFromNonLoc do the
  // dirty work.
  if (isIdempotent) {
    if (SymbolRef LHSSym = dyn_cast<SymbolData>(LHS))
      return evalCastFromNonLoc(nonloc::SymbolVal(LHSSym), resultTy);
    return evalCastFromNonLoc(nonloc::SymExprVal(LHS), resultTy);
  }

  // If we reach this point, the expression cannot be simplified.
  // Make a SymExprVal for the entire thing.
  return makeNonLoc(LHS, op, RHS, resultTy);
}