158 lines · cpp
1// RUN: %clangxx -fsanitize=float-cast-overflow %s -o %t2// 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-04// RUN: %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-15// RUN: %run %t 2 2>&1 | FileCheck %s --check-prefix=CHECK-26// RUN: %run %t 3 2>&1 | FileCheck %s --check-prefix=CHECK-37// RUN: %run %t 4 2>&1 | FileCheck %s --check-prefix=CHECK-48// RUN: %run %t 5 2>&1 | FileCheck %s --check-prefix=CHECK-59// RUN: %run %t 6 2>&1 | FileCheck %s --check-prefix=CHECK-610// RUN: %run %t 7 2>&1 | FileCheck %s --check-prefix=CHECK-711 12// This test assumes float and double are IEEE-754 single- and double-precision.13 14#if defined(__APPLE__)15# include <machine/endian.h>16# define BYTE_ORDER __DARWIN_BYTE_ORDER17# define BIG_ENDIAN __DARWIN_BIG_ENDIAN18# define LITTLE_ENDIAN __DARWIN_LITTLE_ENDIAN19#elif defined(__FreeBSD__) || defined(__NetBSD__)20# include <sys/endian.h>21# ifndef BYTE_ORDER22# define BYTE_ORDER _BYTE_ORDER23# endif24# ifndef BIG_ENDIAN25# define BIG_ENDIAN _BIG_ENDIAN26# endif27# ifndef LITTLE_ENDIAN28# define LITTLE_ENDIAN _LITTLE_ENDIAN29# endif30#elif defined(__sun__) && defined(__svr4__)31// Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h.32# include <sys/types.h>33# define BIG_ENDIAN 432134# define LITTLE_ENDIAN 123435# if defined(_BIG_ENDIAN)36# define BYTE_ORDER BIG_ENDIAN37# else38# define BYTE_ORDER LITTLE_ENDIAN39# endif40#elif defined(_WIN32)41# define BYTE_ORDER 042# define BIG_ENDIAN 143# define LITTLE_ENDIAN 044#else45# include <endian.h>46# define BYTE_ORDER __BYTE_ORDER47# define BIG_ENDIAN __BIG_ENDIAN48# define LITTLE_ENDIAN __LITTLE_ENDIAN49#endif // __APPLE__50#include <stdint.h>51#include <stdio.h>52#include <string.h>53 54float Inf;55float NaN;56 57int main(int argc, char **argv) {58 float MaxFloatRepresentableAsInt = 0x7fffff80;59 (int)MaxFloatRepresentableAsInt; // ok60 (int)-MaxFloatRepresentableAsInt; // ok61 62 float MinFloatRepresentableAsInt = -0x7fffffff - 1;63 (int)MinFloatRepresentableAsInt; // ok64 65 float MaxFloatRepresentableAsUInt = 0xffffff00u;66 (unsigned int)MaxFloatRepresentableAsUInt; // ok67 68#ifdef __SIZEOF_INT128__69 unsigned __int128 FloatMaxAsUInt128 = -((unsigned __int128)1 << 104);70 (void)(float)FloatMaxAsUInt128; // ok71#endif72 73 float NearlyMinusOne = -0.99999;74 unsigned Zero = NearlyMinusOne; // ok75 76 // Build a '+Inf'.77#if BYTE_ORDER == LITTLE_ENDIAN78 unsigned char InfVal[] = {0x00, 0x00, 0x80, 0x7f};79#else80 unsigned char InfVal[] = {0x7f, 0x80, 0x00, 0x00};81#endif82 float Inf;83 memcpy(&Inf, InfVal, 4);84 85 // Build a 'NaN'.86#if BYTE_ORDER == LITTLE_ENDIAN87 unsigned char NaNVal[] = {0x01, 0x00, 0x80, 0x7f};88#else89 unsigned char NaNVal[] = {0x7f, 0x80, 0x00, 0x01};90#endif91 float NaN;92 memcpy(&NaN, NaNVal, 4);93 94 double DblInf = (double)Inf; // ok95 96 switch (argv[1][0]) {97 // FIXME: Produce a source location for these checks and test for it here.98 99 // Floating point -> integer overflow.100 case '0': {101 // Note that values between 0x7ffffe00 and 0x80000000 may or may not102 // successfully round-trip, depending on the rounding mode.103 // CHECK-0: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: 2.14748{{.*}} is outside the range of representable values of type 'int'104 static int test_int = MaxFloatRepresentableAsInt + 0x80;105 // CHECK-0: SUMMARY: {{.*}}Sanitizer: float-cast-overflow {{.*}}cast-overflow.cpp:[[@LINE-1]]106 return 0;107 }108 case '1': {109 // CHECK-1: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: -2.14748{{.*}} is outside the range of representable values of type 'int'110 static int test_int = MinFloatRepresentableAsInt - 0x100;111 return 0;112 }113 case '2': {114 // CHECK-2: {{.*}}cast-overflow.cpp:[[@LINE+2]]:37: runtime error: -1 is outside the range of representable values of type 'unsigned int'115 volatile float f = -1.0;116 volatile unsigned u = (unsigned)f;117 return 0;118 }119 case '3': {120 // CHECK-3: {{.*}}cast-overflow.cpp:[[@LINE+1]]:37: runtime error: 4.2949{{.*}} is outside the range of representable values of type 'unsigned int'121 static int test_int = (unsigned)(MaxFloatRepresentableAsUInt + 0x100);122 return 0;123 }124 125 case '4': {126 // CHECK-4: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: {{.*}} is outside the range of representable values of type 'int'127 static int test_int = Inf;128 return 0;129 }130 case '5': {131 // CHECK-5: {{.*}}cast-overflow.cpp:[[@LINE+1]]:27: runtime error: {{.*}} is outside the range of representable values of type 'int'132 static int test_int = NaN;133 return 0;134 }135 // Integer -> floating point overflow.136 case '6': {137 // CHECK-6: cast-overflow.cpp:[[@LINE+2]]:{{27: runtime error: 3.40282e\+38 is outside the range of representable values of type 'int'| __int128 not supported}}138#if defined(__SIZEOF_INT128__) && !defined(_WIN32)139 static int test_int = (float)(FloatMaxAsUInt128 + 1);140 return 0;141#else142 // Print the same line as the check above.143 // That way the test is robust to line changes around it144 printf("%s:%d: __int128 not supported", __FILE__, __LINE__ - 5);145 return 0;146#endif147 }148 case '7': {149 volatile long double ld = 300.0;150 // CHECK-7: {{.*}}cast-overflow.cpp:[[@LINE+1]]:14: runtime error: 300 is outside the range of representable values of type 'char'151 char c = ld;152 // `c` is allowed to contain UNDEF, thus we should not use153 // its value as an exit code.154 return 0;155 }156 }157}158