Home | History | Annotate | Download | only in Float
      1 // RUN: %clangxx -fsanitize=float-cast-overflow %s -o %t
      2 // RUN: %run %t _
      3 // RUN: %env_ubsan_opts=print_summary=1:report_error_type=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0
      4 // RUN: %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-1
      5 // RUN: %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-2
      6 // RUN: %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK-3
      7 // RUN: %run %t 4 2>&1 | FileCheck %s --check-prefix=CHECK-4
      8 // RUN: %run %t 5 2>&1 | FileCheck %s --check-prefix=CHECK-5
      9 // RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-6
     10 // FIXME: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-7
     11 // FIXME: not %run %t 8 2>&1 | FileCheck %s --check-prefix=CHECK-8
     12 // RUN: not %run %t 9 2>&1 | FileCheck %s --check-prefix=CHECK-9
     13 
     14 // This test assumes float and double are IEEE-754 single- and double-precision.
     15 
     16 #if defined(__APPLE__)
     17 # include <machine/endian.h>
     18 # define BYTE_ORDER __DARWIN_BYTE_ORDER
     19 # define BIG_ENDIAN __DARWIN_BIG_ENDIAN
     20 # define LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN
     21 #elif defined(__FreeBSD__)
     22 # include <sys/endian.h>
     23 # define BYTE_ORDER _BYTE_ORDER
     24 # define BIG_ENDIAN _BIG_ENDIAN
     25 # define LITTLE_ENDIAN _LITTLE_ENDIAN
     26 #elif defined(_WIN32)
     27 # define BYTE_ORDER 0
     28 # define BIG_ENDIAN 1
     29 # define LITTLE_ENDIAN 0
     30 #else
     31 # include <endian.h>
     32 # define BYTE_ORDER __BYTE_ORDER
     33 # define BIG_ENDIAN __BIG_ENDIAN
     34 # define LITTLE_ENDIAN __LITTLE_ENDIAN
     35 #endif  // __APPLE__
     36 #include <stdint.h>
     37 #include <stdio.h>
     38 #include <string.h>
     39 
     40 float Inf;
     41 float NaN;
     42 
     43 int main(int argc, char **argv) {
     44   float MaxFloatRepresentableAsInt = 0x7fffff80;
     45   (int)MaxFloatRepresentableAsInt; // ok
     46   (int)-MaxFloatRepresentableAsInt; // ok
     47 
     48   float MinFloatRepresentableAsInt = -0x7fffffff - 1;
     49   (int)MinFloatRepresentableAsInt; // ok
     50 
     51   float MaxFloatRepresentableAsUInt = 0xffffff00u;
     52   (unsigned int)MaxFloatRepresentableAsUInt; // ok
     53 
     54 #ifdef __SIZEOF_INT128__
     55   unsigned __int128 FloatMaxAsUInt128 = -((unsigned __int128)1 << 104);
     56   (void)(float)FloatMaxAsUInt128; // ok
     57 #endif
     58 
     59   float NearlyMinusOne = -0.99999;
     60   unsigned Zero = NearlyMinusOne; // ok
     61 
     62   // Build a '+Inf'.
     63 #if BYTE_ORDER == LITTLE_ENDIAN
     64   char InfVal[] = { 0x00, 0x00, 0x80, 0x7f };
     65 #else
     66   char InfVal[] = { 0x7f, 0x80, 0x00, 0x00 };
     67 #endif
     68   float Inf;
     69   memcpy(&Inf, InfVal, 4);
     70 
     71   // Build a 'NaN'.
     72 #if BYTE_ORDER == LITTLE_ENDIAN
     73   char NaNVal[] = { 0x01, 0x00, 0x80, 0x7f };
     74 #else
     75   char NaNVal[] = { 0x7f, 0x80, 0x00, 0x01 };
     76 #endif
     77   float NaN;
     78   memcpy(&NaN, NaNVal, 4);
     79 
     80   double DblInf = (double)Inf; // ok
     81 
     82   switch (argv[1][0]) {
     83     // FIXME: Produce a source location for these checks and test for it here.
     84 
     85     // Floating point -> integer overflow.
     86   case '0': {
     87     // Note that values between 0x7ffffe00 and 0x80000000 may or may not
     88     // successfully round-trip, depending on the rounding mode.
     89     // CHECK-0: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: value 2.14748{{.*}} is outside the range of representable values of type 'int'
     90     static int test_int = MaxFloatRepresentableAsInt + 0x80;
     91     // CHECK-0: SUMMARY: {{.*}}Sanitizer: float-cast-overflow {{.*}}cast-overflow.cpp:[[@LINE-1]]
     92     return 0;
     93     }
     94   case '1': {
     95     // CHECK-1: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: value -2.14748{{.*}} is outside the range of representable values of type 'int'
     96     static int test_int = MinFloatRepresentableAsInt - 0x100;
     97     return 0;
     98   }
     99   case '2': {
    100     // CHECK-2: {{.*}}cast-overflow.cpp:[[@LINE+2]]:37: runtime error: value -1 is outside the range of representable values of type 'unsigned int'
    101     volatile float f = -1.0;
    102     volatile unsigned u = (unsigned)f;
    103     return 0;
    104   }
    105   case '3': {
    106     // CHECK-3: {{.*}}cast-overflow.cpp:[[@LINE+1]]:37: runtime error: value 4.2949{{.*}} is outside the range of representable values of type 'unsigned int'
    107     static int test_int = (unsigned)(MaxFloatRepresentableAsUInt + 0x100);
    108     return 0;
    109   }
    110 
    111   case '4': {
    112     // CHECK-4: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: value {{.*}} is outside the range of representable values of type 'int'
    113     static int test_int = Inf;
    114     return 0;
    115   }
    116   case '5': {
    117     // CHECK-5: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: value {{.*}} is outside the range of representable values of type 'int'
    118     static int test_int = NaN;
    119     return 0;
    120   }
    121 
    122     // Integer -> floating point overflow.
    123   case '6': {
    124     // CHECK-6: cast-overflow.cpp:[[@LINE+2]]:{{34: runtime error: value 0xffffff00000000000000000000000001 is outside the range of representable values of type 'float'| __int128 not supported}}
    125 #if defined(__SIZEOF_INT128__) && !defined(_WIN32)
    126     static int test_int = (float)(FloatMaxAsUInt128 + 1);
    127     return 0;
    128 #else
    129     // Print the same line as the check above. That way the test is robust to
    130     // line changes around it
    131     printf("%s:%d: __int128 not supported", __FILE__, __LINE__ - 5);
    132     return 0;
    133 #endif
    134   }
    135   // FIXME: The backend cannot lower __fp16 operations on x86 yet.
    136   //case '7':
    137   //  (__fp16)65504; // ok
    138   //  // CHECK-7: runtime error: value 65505 is outside the range of representable values of type '__fp16'
    139   //  return (__fp16)65505;
    140 
    141     // Floating point -> floating point overflow.
    142   case '8':
    143     // CHECK-8: {{.*}}cast-overflow.cpp:[[@LINE+1]]:19: runtime error: value 1e+39 is outside the range of representable values of type 'float'
    144     return (float)1e39;
    145   case '9':
    146     volatile long double ld = 300.0;
    147     // CHECK-9: {{.*}}cast-overflow.cpp:[[@LINE+1]]:14: runtime error: value 300 is outside the range of representable values of type 'char'
    148     char c = ld;
    149     return c;
    150   }
    151 }
    152