Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 1 | // RUN: %clangxx -fsanitize=float-cast-overflow %s -o %t |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 2 | // RUN: %run %t _ |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 3 | // RUN: %env_ubsan_opts=print_summary=1:report_error_type=1 %run %t 0 2>&1 | FileCheck %s --check-prefix=CHECK-0 |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 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 |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 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 |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 13 | |
| 14 | // This test assumes float and double are IEEE-754 single- and double-precision. |
| 15 | |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 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 |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 26 | #elif defined(_WIN32) |
| 27 | # define BYTE_ORDER 0 |
| 28 | # define BIG_ENDIAN 1 |
| 29 | # define LITTLE_ENDIAN 0 |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 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__ |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 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'. |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 63 | #if BYTE_ORDER == LITTLE_ENDIAN |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 64 | char InfVal[] = { 0x00, 0x00, 0x80, 0x7f }; |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 65 | #else |
| 66 | char InfVal[] = { 0x7f, 0x80, 0x00, 0x00 }; |
| 67 | #endif |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 68 | float Inf; |
| 69 | memcpy(&Inf, InfVal, 4); |
| 70 | |
| 71 | // Build a 'NaN'. |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 72 | #if BYTE_ORDER == LITTLE_ENDIAN |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 73 | char NaNVal[] = { 0x01, 0x00, 0x80, 0x7f }; |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 74 | #else |
| 75 | char NaNVal[] = { 0x7f, 0x80, 0x00, 0x01 }; |
| 76 | #endif |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 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. |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 86 | case '0': { |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 87 | // Note that values between 0x7ffffe00 and 0x80000000 may or may not |
| 88 | // successfully round-trip, depending on the rounding mode. |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 89 | // CHECK-0: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: value 2.14748{{.*}} is outside the range of representable values of type 'int' |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 90 | static int test_int = MaxFloatRepresentableAsInt + 0x80; |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 91 | // CHECK-0: SUMMARY: {{.*}}Sanitizer: float-cast-overflow {{.*}}cast-overflow.cpp:[[@LINE-1]] |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 92 | return 0; |
| 93 | } |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 94 | case '1': { |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 95 | // CHECK-1: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: value -2.14748{{.*}} is outside the range of representable values of type 'int' |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 96 | static int test_int = MinFloatRepresentableAsInt - 0x100; |
| 97 | return 0; |
| 98 | } |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 99 | case '2': { |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 100 | // CHECK-2: {{.*}}cast-overflow.cpp:[[@LINE+2]]:37: runtime error: value -1 is outside the range of representable values of type 'unsigned int' |
Stephen Hines | 6d18623 | 2014-11-26 17:56:19 -0800 | [diff] [blame] | 101 | volatile float f = -1.0; |
| 102 | volatile unsigned u = (unsigned)f; |
| 103 | return 0; |
| 104 | } |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 105 | case '3': { |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 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' |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 107 | static int test_int = (unsigned)(MaxFloatRepresentableAsUInt + 0x100); |
| 108 | return 0; |
| 109 | } |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 110 | |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 111 | case '4': { |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 112 | // CHECK-4: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: value {{.*}} is outside the range of representable values of type 'int' |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 113 | static int test_int = Inf; |
| 114 | return 0; |
| 115 | } |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 116 | case '5': { |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 117 | // CHECK-5: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: value {{.*}} is outside the range of representable values of type 'int' |
Pirama Arumuga Nainar | cdce50b | 2015-07-01 12:26:56 -0700 | [diff] [blame] | 118 | static int test_int = NaN; |
| 119 | return 0; |
| 120 | } |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 121 | |
| 122 | // Integer -> floating point overflow. |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 123 | case '6': { |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 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) |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 126 | static int test_int = (float)(FloatMaxAsUInt128 + 1); |
| 127 | return 0; |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 128 | #else |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 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); |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 132 | return 0; |
| 133 | #endif |
Pirama Arumuga Nainar | 259f706 | 2015-05-06 11:49:53 -0700 | [diff] [blame] | 134 | } |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 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': |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 143 | // CHECK-8: {{.*}}cast-overflow.cpp:[[@LINE+1]]:19: runtime error: value 1e+39 is outside the range of representable values of type 'float' |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 144 | return (float)1e39; |
| 145 | case '9': |
| 146 | volatile long double ld = 300.0; |
Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 147 | // CHECK-9: {{.*}}cast-overflow.cpp:[[@LINE+1]]:14: runtime error: value 300 is outside the range of representable values of type 'char' |
Stephen Hines | 2d1fdb2 | 2014-05-28 23:58:16 -0700 | [diff] [blame] | 148 | char c = ld; |
| 149 | return c; |
| 150 | } |
| 151 | } |