blob: 69d46284b5ecb82d77bef6ca5ad7f020c34385d1 [file] [log] [blame]
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */
/* { dg-options "-fsanitize=float-cast-overflow -fno-sanitize-recover=float-cast-overflow" } */
/* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are
supported, -DBROKEN_DECIMAL_INT128 can be removed. */
/* { dg-additional-options "-DUSE_DFP -DBROKEN_DECIMAL_INT128" { target dfp } } */
#define USE_FLT_DBL_LDBL
#ifdef __SIZEOF_INT128__
#define USE_INT128
#endif
#ifdef __SIZEOF_FLOAT80__
#define USE_FLOAT80
#endif
#ifdef __SIZEOF_FLOAT128__
#define USE_FLOAT128
#endif
#include "float-cast-overflow-7.h"
#define TEST(type1, type2) \
if (cvt_##type1##_##type2 (-0.5f) != 0) abort (); \
if (cvt_##type1##_##type2 (0.5f) != 0) abort (); \
if (cvt_##type1##_##type2 (-0.75f) != 0) abort (); \
if (cvt_##type1##_##type2 (0.75f) != 0) abort (); \
if (type1##_MIN) \
{ \
/* For RADIX 2 type1##_MIN should be always */ \
/* exactly representable in type2. */ \
if (type2##_RADIX == 2 \
|| type1##_MAX <= type2##_MAX) \
{ \
if (cvt_##type1##_##type2 (type1##_MIN) \
!= type1##_MIN) abort (); \
volatile type2 tem = ((type2) -0.75f) + type1##_MIN; \
volatile type2 tem2 = ((type2) -1.0f) + type1##_MIN; \
if (tem != tem2 \
&& cvt_##type1##_##type2 ((type2) -0.75f \
+ type1##_MIN) \
!= type1##_MIN) abort (); \
} \
else \
{ \
type2 min = type1##_MIN; \
/* tem could be below minimum here due to */ \
/* rounding. */ \
MAXT add = 1; \
while (add) \
{ \
volatile type2 tem = type1##_MIN + (type1) add; \
if (tem != min) \
break; \
MAXT newadd = add * type2##_RADIX; \
if (newadd < add || newadd > type1##_MAX) \
add = 0; \
else \
add = newadd; \
} \
if (add) \
{ \
MAXT newadd \
= (-(type1##_MIN + (type1) add)) % add; \
volatile type2 tem = type1##_MIN + (type1) newadd;\
volatile type2 tem2 = type1##_MIN + (type1) add; \
if (tem == tem2) \
add = newadd; \
else \
{ \
newadd += add; \
if (newadd < add || newadd > type1##_MAX) \
add = 0; \
else \
{ \
tem = type1##_MIN + (type1) newadd; \
if (tem == tem2) \
add = newadd; \
else \
add = 0; \
} \
} \
} \
if (add \
&& cvt_##type1##_##type2 (type1##_MIN \
+ (type1) add) \
!= type1##_MIN + (type1) add) abort (); \
} \
} \
if (type1##_MAX <= type2##_MAX) \
{ \
if (cvt_##type1##_##type2 (type1##_MAX) != type1##_MAX) \
abort (); \
volatile type2 tem = ((type2) 0.75f) + type1##_MAX; \
volatile type2 tem2 = ((type2) 1.0f) + type1##_MAX; \
if (tem < tem2 \
&& cvt_##type1##_##type2 ((type2) 0.75f + type1##_MAX)\
!= type1##_MAX) abort (); \
} \
else \
{ \
type2 max = type1##_MAX; \
/* tem could be above maximum here due to rounding. */ \
MAXT sub = 1; \
while (sub) \
{ \
volatile type2 tem = type1##_MAX - sub; \
if (tem != max) \
break; \
MAXT newsub = sub * type2##_RADIX; \
if (newsub < sub || newsub > type1##_MAX) \
sub = 0; \
else \
sub = newsub; \
} \
if (sub) \
{ \
MAXT newsub = ((type1##_MAX - sub) % sub); \
volatile type2 tem = type1##_MAX - newsub; \
volatile type2 tem2 = type1##_MAX - sub; \
if (tem == tem2) \
sub = newsub; \
else \
{ \
newsub += sub; \
if (newsub < sub || newsub > type1##_MAX) \
sub = 0; \
else \
{ \
tem = type1##_MAX - newsub; \
if (tem == tem2) \
sub = newsub; \
else \
sub = 0; \
} \
} \
} \
if (sub \
&& cvt_##type1##_##type2 (type1##_MAX - sub) \
!= type1##_MAX - sub) abort (); \
}
#ifdef si128_MAX
# define TESTS128(type2) TEST (si128, type2) TEST (ui128, type2)
#else
# define TESTS128(type2)
#endif
#define TESTS(type2) \
TEST (sc, type2) TEST (c, type2) TEST (uc, type2) \
TEST (ss, type2) TEST (us, type2) \
TEST (si, type2) TEST (ui, type2) \
TEST (sl, type2) TEST (ul, type2) \
TEST (sll, type2) TEST (ull, type2) \
TESTS128 (type2)
int
main ()
{
#ifdef f_MAX
TESTS (f)
#endif
#ifdef d_MAX
TESTS (d)
#endif
#ifdef ld_MAX
TESTS (ld)
#endif
#ifdef f80_MAX
TESTS (f80)
#endif
#ifdef f128_MAX
TESTS (f128)
#endif
#ifdef BROKEN_DECIMAL_INT128
# undef TESTS128
# define TESTS128(type2)
# undef TWO
# undef M1U
# undef MAXS
# undef MAXT
# define TWO 2ULL
# define M1U -1ULL
# define MAXS (__CHAR_BIT__ * __SIZEOF_LONG_LONG__)
# define MAXT unsigned long long
#endif
#ifdef d32_MAX
TESTS (d32)
#endif
#ifdef d64_MAX
TESTS (d64)
#endif
#ifdef d128_MAX
TESTS (d128)
#endif
return 0;
}