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); }