forked from OSchip/llvm-project
PR15383: When -fsanitize=float-cast-overflow checks a float-to-int conversion,
it wasn't taking into account that the float should be truncated *before* the range check happens. Thus (unsigned)-0.99 and (unsigned char)255.9 have defined behavior and should not be trapped. llvm-svn: 177362
This commit is contained in:
parent
fc9aad6436
commit
4af40c4083
|
@ -585,7 +585,7 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc,
|
|||
} else {
|
||||
// Floating-point to integer or floating-point to floating-point. This has
|
||||
// undefined behavior if the source is +-Inf, NaN, or doesn't fit into the
|
||||
// destination type.
|
||||
// destination type (after truncation to an integer for float-to-integer).
|
||||
const llvm::fltSemantics &SrcSema =
|
||||
CGF.getContext().getFloatTypeSemantics(OrigSrcType);
|
||||
APFloat MaxSrc(SrcSema, APFloat::uninitialized);
|
||||
|
@ -600,14 +600,22 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc,
|
|||
APFloat::opOverflow)
|
||||
// Don't need an overflow check for lower bound. Just check for
|
||||
// -Inf/NaN.
|
||||
MinSrc = APFloat::getLargest(SrcSema, true);
|
||||
MinSrc = APFloat::getInf(SrcSema, true);
|
||||
else
|
||||
// Find the largest value which is too small to represent (before
|
||||
// truncation toward zero).
|
||||
MinSrc.subtract(APFloat(SrcSema, 1), APFloat::rmTowardNegative);
|
||||
|
||||
APSInt Max = APSInt::getMaxValue(Width, Unsigned);
|
||||
if (MaxSrc.convertFromAPInt(Max, !Unsigned, APFloat::rmTowardZero) &
|
||||
APFloat::opOverflow)
|
||||
// Don't need an overflow check for upper bound. Just check for
|
||||
// +Inf/NaN.
|
||||
MaxSrc = APFloat::getLargest(SrcSema, false);
|
||||
MaxSrc = APFloat::getInf(SrcSema, false);
|
||||
else
|
||||
// Find the smallest value which is too large to represent (before
|
||||
// truncation toward zero).
|
||||
MaxSrc.add(APFloat(SrcSema, 1), APFloat::rmTowardPositive);
|
||||
} else {
|
||||
const llvm::fltSemantics &DstSema =
|
||||
CGF.getContext().getFloatTypeSemantics(DstType);
|
||||
|
@ -634,11 +642,19 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc,
|
|||
MaxSrc.convert(Sema, APFloat::rmTowardZero, &IsInexact);
|
||||
}
|
||||
|
||||
llvm::Value *GE =
|
||||
Builder.CreateFCmpOGE(Src, llvm::ConstantFP::get(VMContext, MinSrc));
|
||||
llvm::Value *LE =
|
||||
Builder.CreateFCmpOLE(Src, llvm::ConstantFP::get(VMContext, MaxSrc));
|
||||
Check = Builder.CreateAnd(GE, LE);
|
||||
if (isa<llvm::IntegerType>(DstTy)) {
|
||||
llvm::Value *GE =
|
||||
Builder.CreateFCmpOGT(Src, llvm::ConstantFP::get(VMContext, MinSrc));
|
||||
llvm::Value *LE =
|
||||
Builder.CreateFCmpOLT(Src, llvm::ConstantFP::get(VMContext, MaxSrc));
|
||||
Check = Builder.CreateAnd(GE, LE);
|
||||
} else {
|
||||
llvm::Value *GE =
|
||||
Builder.CreateFCmpOGE(Src, llvm::ConstantFP::get(VMContext, MinSrc));
|
||||
llvm::Value *LE =
|
||||
Builder.CreateFCmpOLE(Src, llvm::ConstantFP::get(VMContext, MaxSrc));
|
||||
Check = Builder.CreateAnd(GE, LE);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Provide a SourceLocation.
|
||||
|
|
|
@ -285,13 +285,13 @@ void int_fp16_overflow(int n, __fp16 *p) {
|
|||
// CHECK: @float_int_overflow
|
||||
// CHECK-TRAP: @float_int_overflow
|
||||
int float_int_overflow(float f) {
|
||||
// CHECK: %[[GE:.*]] = fcmp oge float %[[F:.*]], 0xC1E0000000000000
|
||||
// CHECK: %[[LE:.*]] = fcmp ole float %[[F]], 0x41DFFFFFE0000000
|
||||
// CHECK: %[[GE:.*]] = fcmp ogt float %[[F:.*]], 0xC1E0000020000000
|
||||
// CHECK: %[[LE:.*]] = fcmp olt float %[[F]], 0x41E0000000000000
|
||||
// CHECK: and i1 %[[GE]], %[[LE]]
|
||||
// CHECK: call void @__ubsan_handle_float_cast_overflow(
|
||||
|
||||
// CHECK-TRAP: %[[GE:.*]] = fcmp oge float %[[F:.*]], 0xC1E0000000000000
|
||||
// CHECK-TRAP: %[[LE:.*]] = fcmp ole float %[[F]], 0x41DFFFFFE0000000
|
||||
// CHECK-TRAP: %[[GE:.*]] = fcmp ogt float %[[F:.*]], 0xC1E0000020000000
|
||||
// CHECK-TRAP: %[[LE:.*]] = fcmp olt float %[[F]], 0x41E0000000000000
|
||||
// CHECK-TRAP: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]]
|
||||
// CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]]
|
||||
|
||||
|
@ -303,13 +303,13 @@ int float_int_overflow(float f) {
|
|||
// CHECK: @float_uint_overflow
|
||||
// CHECK-TRAP: @float_uint_overflow
|
||||
unsigned float_uint_overflow(float f) {
|
||||
// CHECK: %[[GE:.*]] = fcmp oge float %[[F:.*]], 0.{{0*}}e+00
|
||||
// CHECK: %[[LE:.*]] = fcmp ole float %[[F]], 0x41EFFFFFE0000000
|
||||
// CHECK: %[[GE:.*]] = fcmp ogt float %[[F:.*]], -1.{{0*}}e+00
|
||||
// CHECK: %[[LE:.*]] = fcmp olt float %[[F]], 0x41F0000000000000
|
||||
// CHECK: and i1 %[[GE]], %[[LE]]
|
||||
// CHECK: call void @__ubsan_handle_float_cast_overflow(
|
||||
|
||||
// CHECK-TRAP: %[[GE:.*]] = fcmp oge float %[[F:.*]], 0.{{0*}}e+00
|
||||
// CHECK-TRAP: %[[LE:.*]] = fcmp ole float %[[F]], 0x41EFFFFFE0000000
|
||||
// CHECK-TRAP: %[[GE:.*]] = fcmp ogt float %[[F:.*]], -1.{{0*}}e+00
|
||||
// CHECK-TRAP: %[[LE:.*]] = fcmp olt float %[[F]], 0x41F0000000000000
|
||||
// CHECK-TRAP: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]]
|
||||
// CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]]
|
||||
|
||||
|
@ -321,13 +321,13 @@ unsigned float_uint_overflow(float f) {
|
|||
// CHECK: @fp16_char_overflow
|
||||
// CHECK-TRAP: @fp16_char_overflow
|
||||
signed char fp16_char_overflow(__fp16 *p) {
|
||||
// CHECK: %[[GE:.*]] = fcmp oge float %[[F:.*]], -1.28{{0*}}e+02
|
||||
// CHECK: %[[LE:.*]] = fcmp ole float %[[F]], 1.27{{0*}}e+02
|
||||
// CHECK: %[[GE:.*]] = fcmp ogt float %[[F:.*]], -1.29{{0*}}e+02
|
||||
// CHECK: %[[LE:.*]] = fcmp olt float %[[F]], 1.28{{0*}}e+02
|
||||
// CHECK: and i1 %[[GE]], %[[LE]]
|
||||
// CHECK: call void @__ubsan_handle_float_cast_overflow(
|
||||
|
||||
// CHECK-TRAP: %[[GE:.*]] = fcmp oge float %[[F:.*]], -1.28{{0*}}e+02
|
||||
// CHECK-TRAP: %[[LE:.*]] = fcmp ole float %[[F]], 1.27{{0*}}e+02
|
||||
// CHECK-TRAP: %[[GE:.*]] = fcmp ogt float %[[F:.*]], -1.29{{0*}}e+02
|
||||
// CHECK-TRAP: %[[LE:.*]] = fcmp olt float %[[F]], 1.28{{0*}}e+02
|
||||
// CHECK-TRAP: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]]
|
||||
// CHECK-TRAP-NEXT: br i1 %[[INBOUNDS]]
|
||||
|
||||
|
|
Loading…
Reference in New Issue