r177362 - PR15383: When -fsanitize=float-cast-overflow checks a float-to-int conversion,

Richard Smith richard-llvm at metafoo.co.uk
Mon Mar 18 17:01:12 PDT 2013


Author: rsmith
Date: Mon Mar 18 19:01:12 2013
New Revision: 177362

URL: http://llvm.org/viewvc/llvm-project?rev=177362&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/test/CodeGen/catch-undef-behavior.c

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=177362&r1=177361&r2=177362&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Mar 18 19:01:12 2013
@@ -585,7 +585,7 @@ void ScalarExprEmitter::EmitFloatConvers
   } 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::EmitFloatConvers
           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::EmitFloatConvers
       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.

Modified: cfe/trunk/test/CodeGen/catch-undef-behavior.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/catch-undef-behavior.c?rev=177362&r1=177361&r2=177362&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/catch-undef-behavior.c (original)
+++ cfe/trunk/test/CodeGen/catch-undef-behavior.c Mon Mar 18 19:01:12 2013
@@ -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]]
 





More information about the cfe-commits mailing list