Example #1
0
SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {

  bool isLocType = Loc::isLocType(castTy);

  if (val.getAs<nonloc::PointerToMember>())
    return val;

  if (Optional<nonloc::LocAsInteger> LI = val.getAs<nonloc::LocAsInteger>()) {
    if (isLocType)
      return LI->getLoc();

    // FIXME: Correctly support promotions/truncations.
    unsigned castSize = Context.getTypeSize(castTy);
    if (castSize == LI->getNumBits())
      return val;
    return makeLocAsInteger(LI->getLoc(), castSize);
  }

  if (const SymExpr *se = val.getAsSymbolicExpression()) {
    QualType T = Context.getCanonicalType(se->getType());
    // If types are the same or both are integers, ignore the cast.
    // FIXME: Remove this hack when we support symbolic truncation/extension.
    // HACK: If both castTy and T are integers, ignore the cast.  This is
    // not a permanent solution.  Eventually we want to precisely handle
    // extension/truncation of symbolic integers.  This prevents us from losing
    // precision when we assign 'x = y' and 'y' is symbolic and x and y are
    // different integer types.
   if (haveSameType(T, castTy))
      return val;

    if (!isLocType)
      return makeNonLoc(se, T, castTy);
    return UnknownVal();
  }

  // If value is a non-integer constant, produce unknown.
  if (!val.getAs<nonloc::ConcreteInt>())
    return UnknownVal();

  // Handle casts to a boolean type.
  if (castTy->isBooleanType()) {
    bool b = val.castAs<nonloc::ConcreteInt>().getValue().getBoolValue();
    return makeTruthVal(b, castTy);
  }

  // Only handle casts from integers to integers - if val is an integer constant
  // being cast to a non-integer type, produce unknown.
  if (!isLocType && !castTy->isIntegralOrEnumerationType())
    return UnknownVal();

  llvm::APSInt i = val.castAs<nonloc::ConcreteInt>().getValue();
  BasicVals.getAPSIntType(castTy).apply(i);

  if (isLocType)
    return makeIntLocVal(i);
  else
    return makeIntVal(i);
}
SVal SimpleSValBuilder::evalCastFromNonLoc(NonLoc val, QualType castTy) {

  bool isLocType = Loc::isLocType(castTy);

  if (nonloc::LocAsInteger *LI = dyn_cast<nonloc::LocAsInteger>(&val)) {
    if (isLocType)
      return LI->getLoc();

    // FIXME: Correctly support promotions/truncations.
    unsigned castSize = Context.getTypeSize(castTy);
    if (castSize == LI->getNumBits())
      return val;
    return makeLocAsInteger(LI->getLoc(), castSize);
  }

  if (const SymExpr *se = val.getAsSymbolicExpression()) {
    QualType T = Context.getCanonicalType(se->getType(Context));
    if (T == Context.getCanonicalType(castTy))
      return val;
    
    // FIXME: Remove this hack when we support symbolic truncation/extension.
    // HACK: If both castTy and T are integers, ignore the cast.  This is
    // not a permanent solution.  Eventually we want to precisely handle
    // extension/truncation of symbolic integers.  This prevents us from losing
    // precision when we assign 'x = y' and 'y' is symbolic and x and y are
    // different integer types.
    if (T->isIntegerType() && castTy->isIntegerType())
      return val;

    return UnknownVal();
  }

  if (!isa<nonloc::ConcreteInt>(val))
    return UnknownVal();

  // Only handle casts from integers to integers.
  if (!isLocType && !castTy->isIntegerType())
    return UnknownVal();

  llvm::APSInt i = cast<nonloc::ConcreteInt>(val).getValue();
  i.setIsUnsigned(castTy->isUnsignedIntegerOrEnumerationType() || 
                  Loc::isLocType(castTy));
  i = i.extOrTrunc(Context.getTypeSize(castTy));

  if (isLocType)
    return makeIntLocVal(i);
  else
    return makeIntVal(i);
}