diff options
author | Marek Polacek <polacek@redhat.com> | 2014-05-23 14:44:42 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2014-05-23 14:44:42 +0000 |
commit | 85a16bf8b55c7accb3b2f60568cd9119d9656494 (patch) | |
tree | 76c97d7e36a0b8b32edf3400c6c2d38538e33618 /gcc | |
parent | fee9ba422f9193fb5e560bd430d7b14c55c128d1 (diff) | |
download | gcc-85a16bf8b55c7accb3b2f60568cd9119d9656494.zip gcc-85a16bf8b55c7accb3b2f60568cd9119d9656494.tar.gz gcc-85a16bf8b55c7accb3b2f60568cd9119d9656494.tar.bz2 |
builtins.def: Change SANITIZE_FLOAT_DIVIDE to SANITIZE_NONDEFAULT.
* builtins.def: Change SANITIZE_FLOAT_DIVIDE to SANITIZE_NONDEFAULT.
* gcc.c (sanitize_spec_function): Likewise.
* convert.c (convert_to_integer): Include "ubsan.h". Add
floating-point to integer instrumentation.
* doc/invoke.texi: Document -fsanitize=float-cast-overflow.
* flag-types.h (enum sanitize_code): Add SANITIZE_FLOAT_CAST and
SANITIZE_NONDEFAULT.
* opts.c (common_handle_option): Handle -fsanitize=float-cast-overflow.
* sanitizer.def (BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW,
BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT): Add.
* ubsan.c: Include "realmpfr.h" and "dfp.h".
(get_ubsan_type_info_for_type): Handle REAL_TYPEs.
(ubsan_type_descriptor): Set tkind to 0xffff for types other than
float/double/long double.
(ubsan_instrument_float_cast): New function.
* ubsan.h (ubsan_instrument_float_cast): Declare.
testsuite/
* c-c++-common/ubsan/float-cast-overflow-1.c: New test.
* c-c++-common/ubsan/float-cast-overflow-10.c: New test.
* c-c++-common/ubsan/float-cast-overflow-2.c: New test.
* c-c++-common/ubsan/float-cast-overflow-3.c: New test.
* c-c++-common/ubsan/float-cast-overflow-4.c: New test.
* c-c++-common/ubsan/float-cast-overflow-5.c: New test.
* c-c++-common/ubsan/float-cast-overflow-6.c: New test.
* c-c++-common/ubsan/float-cast-overflow-7.c: New test.
* c-c++-common/ubsan/float-cast-overflow-7.h: New file.
* c-c++-common/ubsan/float-cast-overflow-8.c: New test.
* c-c++-common/ubsan/float-cast-overflow-9.c: New test.
* c-c++-common/ubsan/float-cast.h: New file.
* g++.dg/ubsan/float-cast-overflow-bf.C: New test.
* gcc.dg/ubsan/float-cast-overflow-bf.c: New test.
libsanitizer/
* ubsan/ubsan_value.cc (getFloatValue): Handle 96-bit
floating-point types.
Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
From-SVN: r210862
Diffstat (limited to 'gcc')
25 files changed, 1524 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ec102fe..9a3b0c9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2014-05-23 Marek Polacek <polacek@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + * builtins.def: Change SANITIZE_FLOAT_DIVIDE to SANITIZE_NONDEFAULT. + * gcc.c (sanitize_spec_function): Likewise. + * convert.c (convert_to_integer): Include "ubsan.h". Add + floating-point to integer instrumentation. + * doc/invoke.texi: Document -fsanitize=float-cast-overflow. + * flag-types.h (enum sanitize_code): Add SANITIZE_FLOAT_CAST and + SANITIZE_NONDEFAULT. + * opts.c (common_handle_option): Handle -fsanitize=float-cast-overflow. + * sanitizer.def (BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW, + BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT): Add. + * ubsan.c: Include "realmpfr.h" and "dfp.h". + (get_ubsan_type_info_for_type): Handle REAL_TYPEs. + (ubsan_type_descriptor): Set tkind to 0xffff for types other than + float/double/long double. + (ubsan_instrument_float_cast): New function. + * ubsan.h (ubsan_instrument_float_cast): Declare. + 2014-05-23 Jiong Wang <jiong.wang@arm.com> * config/aarch64/predicates.md (aarch64_call_insn_operand): New diff --git a/gcc/builtins.def b/gcc/builtins.def index d400ecb..cd823a3 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -176,7 +176,7 @@ along with GCC; see the file COPYING3. If not see DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \ true, true, true, ATTRS, true, \ (flag_sanitize & (SANITIZE_ADDRESS | SANITIZE_THREAD \ - | SANITIZE_UNDEFINED | SANITIZE_FLOAT_DIVIDE))) + | SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT))) #undef DEF_CILKPLUS_BUILTIN #define DEF_CILKPLUS_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ diff --git a/gcc/convert.c b/gcc/convert.c index 91c1da2..b8f3671 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "target.h" #include "langhooks.h" +#include "ubsan.h" /* Convert EXPR to some pointer or reference type TYPE. EXPR must be pointer, reference, integer, enumeral, or literal zero; @@ -394,6 +395,7 @@ convert_to_integer (tree type, tree expr) tree intype = TREE_TYPE (expr); unsigned int inprec = element_precision (intype); unsigned int outprec = element_precision (type); + location_t loc = EXPR_LOCATION (expr); /* An INTEGER_TYPE cannot be incomplete, but an ENUMERAL_TYPE can be. Consider `enum E = { a, b = (enum E) 3 };'. */ @@ -844,7 +846,17 @@ convert_to_integer (tree type, tree expr) return build1 (CONVERT_EXPR, type, expr); case REAL_TYPE: - return build1 (FIX_TRUNC_EXPR, type, expr); + if (flag_sanitize & SANITIZE_FLOAT_CAST) + { + expr = save_expr (expr); + tree check = ubsan_instrument_float_cast (loc, type, expr); + expr = build1 (FIX_TRUNC_EXPR, type, expr); + if (check == NULL) + return expr; + return fold_build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr); + } + else + return build1 (FIX_TRUNC_EXPR, type, expr); case FIXED_POINT_TYPE: return build1 (FIXED_CONVERT_EXPR, type, expr); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index dbb6af6..34ba721 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -5427,6 +5427,13 @@ Detect floating-point division by zero. Unlike other similar options, @option{-fsanitize=undefined}, since floating-point division by zero can be a legitimate way of obtaining infinities and NaNs. +@item -fsanitize=float-cast-overflow +@opindex fsanitize=float-cast-overflow + +This option enables floating-point type to integer conversion checking. +We check that the result of the conversion does not overflow. +This option does not work well with @code{FE_INVALID} exceptions enabled. + @item -fsanitize-recover @opindex fsanitize-recover By default @option{-fsanitize=undefined} sanitization (and its suboptions diff --git a/gcc/flag-types.h b/gcc/flag-types.h index caf4039..ed00046 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -229,9 +229,11 @@ enum sanitize_code { SANITIZE_BOOL = 1 << 10, SANITIZE_ENUM = 1 << 11, SANITIZE_FLOAT_DIVIDE = 1 << 12, + SANITIZE_FLOAT_CAST = 1 << 13, SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN - | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM + | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM, + SANITIZE_NONDEFAULT = SANITIZE_FLOAT_DIVIDE | SANITIZE_FLOAT_CAST }; /* flag_vtable_verify initialization levels. */ @@ -8170,7 +8170,7 @@ sanitize_spec_function (int argc, const char **argv) if (strcmp (argv[0], "thread") == 0) return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL; if (strcmp (argv[0], "undefined") == 0) - return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_FLOAT_DIVIDE)) + return ((flag_sanitize & (SANITIZE_UNDEFINED | SANITIZE_NONDEFAULT)) && !flag_sanitize_undefined_trap_on_error) ? "" : NULL; if (strcmp (argv[0], "leak") == 0) return ((flag_sanitize @@ -1463,6 +1463,8 @@ common_handle_option (struct gcc_options *opts, { "enum", SANITIZE_ENUM, sizeof "enum" - 1 }, { "float-divide-by-zero", SANITIZE_FLOAT_DIVIDE, sizeof "float-divide-by-zero" - 1 }, + { "float-cast-overflow", SANITIZE_FLOAT_CAST, + sizeof "float-cast-overflow" - 1 }, { NULL, 0, 0 } }; const char *comma; diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def index 6184b5a..a2f7ff0 100644 --- a/gcc/sanitizer.def +++ b/gcc/sanitizer.def @@ -371,3 +371,11 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_LOAD_INVALID_VALUE_ABORT, "__ubsan_handle_load_invalid_value_abort", BT_FN_VOID_PTR_PTR, ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW, + "__ubsan_handle_float_cast_overflow", + BT_FN_VOID_PTR_PTR, + ATTR_COLD_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT, + "__ubsan_handle_float_cast_overflow_abort", + BT_FN_VOID_PTR_PTR, + ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a765cb8..05fea9e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,21 @@ +2014-05-23 Marek Polacek <polacek@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + * c-c++-common/ubsan/float-cast-overflow-1.c: New test. + * c-c++-common/ubsan/float-cast-overflow-10.c: New test. + * c-c++-common/ubsan/float-cast-overflow-2.c: New test. + * c-c++-common/ubsan/float-cast-overflow-3.c: New test. + * c-c++-common/ubsan/float-cast-overflow-4.c: New test. + * c-c++-common/ubsan/float-cast-overflow-5.c: New test. + * c-c++-common/ubsan/float-cast-overflow-6.c: New test. + * c-c++-common/ubsan/float-cast-overflow-7.c: New test. + * c-c++-common/ubsan/float-cast-overflow-7.h: New file. + * c-c++-common/ubsan/float-cast-overflow-8.c: New test. + * c-c++-common/ubsan/float-cast-overflow-9.c: New test. + * c-c++-common/ubsan/float-cast.h: New file. + * g++.dg/ubsan/float-cast-overflow-bf.C: New test. + * gcc.dg/ubsan/float-cast-overflow-bf.c: New test. + 2014-05-23 Jiong Wang <jiong.wang@arm.com> * gcc.target/aarch64/tail_indirect_call_1.c: New. diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c new file mode 100644 index 0000000..249731d --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c @@ -0,0 +1,204 @@ +/* { dg-do run { target { lp64 || ilp32 } } } */ +/* { dg-options "-fsanitize=float-cast-overflow" } */ +/* { dg-additional-options "-msse2 -mfpmath=sse" { target { sse2_runtime && ia32 } } } */ + +#include <limits.h> +#include "float-cast.h" + +int +main (void) +{ + const double inf = __builtin_inf (); + const double nan = __builtin_nan (""); + volatile double d; + + volatile signed char sc; + d = SCHAR_MIN; + CHECK_BOUNDARY (sc, d); + d = 0.0; + CHECK_BOUNDARY (sc, d); + d = SCHAR_MAX; + CHECK_BOUNDARY (sc, d); + CHECK_NONNUMBERS (sc); + + volatile unsigned char uc; + d = UCHAR_MAX; + CHECK_BOUNDARY (uc, d); + d = 0.0; + CHECK_BOUNDARY (uc, d); + CHECK_NONNUMBERS (uc); + + volatile short int s; + d = SHRT_MIN; + CHECK_BOUNDARY (s, d); + d = 0.0; + CHECK_BOUNDARY (s, d); + d = SHRT_MAX; + CHECK_BOUNDARY (s, d); + CHECK_NONNUMBERS (s); + + volatile unsigned short int us; + d = USHRT_MAX; + CHECK_BOUNDARY (us, d); + d = 0.0; + CHECK_BOUNDARY (us, d); + CHECK_NONNUMBERS (us); + + volatile int i; + d = INT_MIN; + CHECK_BOUNDARY (i, d); + d = 0.0; + CHECK_BOUNDARY (i, d); + d = INT_MAX; + CHECK_BOUNDARY (i, d); + CHECK_NONNUMBERS (i); + + volatile unsigned int u; + d = UINT_MAX; + CHECK_BOUNDARY (u, d); + d = 0.0; + CHECK_BOUNDARY (u, d); + CHECK_NONNUMBERS (u); + + volatile long l; + /* 64-bit vs 32-bit longs matter causes too much of a headache. */ + d = 0.0; + CHECK_BOUNDARY (l, d); + CHECK_NONNUMBERS (l); + + volatile unsigned long ul; + d = 0.0; + CHECK_BOUNDARY (ul, d); + CHECK_NONNUMBERS (ul); + + volatile long long ll; + d = LLONG_MIN; + CHECK_BOUNDARY (ll, d); + d = 0.0; + CHECK_BOUNDARY (ll, d); + d = LLONG_MAX; + CHECK_BOUNDARY (ll, d); + CHECK_NONNUMBERS (ll); + + volatile unsigned long long ull; + d = ULLONG_MAX; + CHECK_BOUNDARY (ull, d); + d = 0.0; + CHECK_BOUNDARY (ull, d); + CHECK_NONNUMBERS (ull); + + return 0; +} + +/* { dg-output "value -133 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -129.5 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -129 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 128.5 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 132 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 256.5 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 260 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -32773 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -32769.5 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 32768.5 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 32772 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 65536.5 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 65540 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 9.22337e\\\+18 is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.84467e\\\+19 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c new file mode 100644 index 0000000..81ceb92 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c @@ -0,0 +1,79 @@ +/* { dg-do run { target dfp } } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */ +/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover" } */ +/* { dg-additional-options "-DUSE_INT128" { target int128 } } */ +/* FIXME: When _DecimalXX <-> {signed, unsigned} __int128 conversions are + supported, -DBROKEN_DECIMAL_INT128 can be removed. */ +/* { dg-additional-options "-DUSE_DFP -DBROKEN_DECIMAL_INT128" } */ + +#include "float-cast-overflow-8.c" + +/* _Decimal32 */ +/* { dg-output "value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* _Decimal64 */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* _Decimal128 */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-2.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-2.c new file mode 100644 index 0000000..15eacc9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-2.c @@ -0,0 +1,73 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int128 } */ +/* { dg-options "-fsanitize=float-cast-overflow" } */ + +#include "float-cast.h" + +int +main (void) +{ + const double inf = __builtin_inf (); + const double nan = __builtin_nan (""); + volatile double d; + + __int128 i; + d = INT128_MIN; + CHECK_BOUNDARY (i, d); + d = 0.0; + CHECK_BOUNDARY (i, d); + d = INT128_MAX; + CHECK_BOUNDARY (i, d); + CHECK_NONNUMBERS (i); + + unsigned __int128 u; + d = UINT128_MAX; + CHECK_BOUNDARY (u, d); + d = 0.0; + CHECK_BOUNDARY (u, d); + CHECK_NONNUMBERS (u); + + return 0; +} + +/* { dg-output "runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 1.70141e\\\+38 is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value nan is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value -nan is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value inf is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value -inf is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value 3.40282e\\\+38 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value -5 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value -1.5 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value -1 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value nan is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value -nan is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value inf is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*runtime error: value -inf is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-3.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-3.c new file mode 100644 index 0000000..2200e66 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-3.c @@ -0,0 +1,40 @@ +/* { dg-do run { target { lp64 || ilp32 } } } */ +/* { dg-options "-fsanitize=float-cast-overflow" } */ + +#include <limits.h> +#include "float-cast.h" + +int +main (void) +{ + volatile float f; + + volatile signed char s; + f = SCHAR_MIN; + CHECK_BOUNDARY (s, f); + f = 0.0; + CHECK_BOUNDARY (s, f); + f = SCHAR_MAX; + CHECK_BOUNDARY (s, f); + + volatile unsigned char u; + f = UCHAR_MAX; + CHECK_BOUNDARY (u, f); + f = 0.0; + CHECK_BOUNDARY (u, f); + + return 0; +} + +/* { dg-output "value -133* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -129.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -129 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 128.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 132 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 256.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 260 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-4.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-4.c new file mode 100644 index 0000000..7704aa9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-4.c @@ -0,0 +1,52 @@ +/* { dg-do run { target { lp64 } } } */ +/* { dg-options "-fsanitize=float-cast-overflow" } */ + +#include <limits.h> +#include "float-cast.h" + +int +main (void) +{ + const long double inf = __builtin_infl (); + const long double nan = __builtin_nanl (""); + volatile long double ld; + + volatile int i; + ld = INT_MIN; + CHECK_BOUNDARY (i, ld); + ld = 0.0l; + CHECK_BOUNDARY (i, ld); + ld = INT_MAX; + CHECK_BOUNDARY (i, ld); + CHECK_NONNUMBERS (i); + + volatile unsigned int u; + ld = UINT_MAX; + CHECK_BOUNDARY (u, ld); + ld = 0.0l; + CHECK_BOUNDARY (u, ld); + CHECK_NONNUMBERS (u); + + return 0; +} + +/* { dg-output "value -2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value nan is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -nan is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value inf is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -inf is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-5.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-5.c new file mode 100644 index 0000000..44910ee --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-5.c @@ -0,0 +1,40 @@ +/* { dg-do run { target i?86-*-* x86_64-*-* ia64-*-* } } */ +/* { dg-options "-fsanitize=float-cast-overflow" } */ + +#include <limits.h> +#include "float-cast.h" + +int +main (void) +{ + volatile __float128 f; + + volatile signed char s; + f = SCHAR_MIN; + CHECK_BOUNDARY (s, f); + f = 0.0q; + CHECK_BOUNDARY (s, f); + f = SCHAR_MAX; + CHECK_BOUNDARY (s, f); + + volatile unsigned char u; + f = UCHAR_MAX; + CHECK_BOUNDARY (u, f); + f = 0.0q; + CHECK_BOUNDARY (u, f); + + return 0; +} + +/* { dg-output "value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[^\n\r]* is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-6.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-6.c new file mode 100644 index 0000000..f51a2c8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-6.c @@ -0,0 +1,40 @@ +/* { dg-do run { target { { x86_64-*-* ia64-*-* } && { ! { ia32 } } } } } */ +/* { dg-options "-fsanitize=float-cast-overflow" } */ + +#include <limits.h> +#include "float-cast.h" + +int +main (void) +{ + volatile __float80 f; + + volatile signed char s; + f = SCHAR_MIN; + CHECK_BOUNDARY (s, f); + f = 0.0w; + CHECK_BOUNDARY (s, f); + f = SCHAR_MAX; + CHECK_BOUNDARY (s, f); + + volatile unsigned char u; + f = UCHAR_MAX; + CHECK_BOUNDARY (u, f); + f = 0.0w; + CHECK_BOUNDARY (u, f); + + return 0; +} + +/* { dg-output "value -133 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -129.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -129 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 128.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 132 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 256.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 260 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c new file mode 100644 index 0000000..3223d5e --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c @@ -0,0 +1,196 @@ +/* { dg-do run } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */ +/* { dg-options "-fsanitize=float-cast-overflow -fno-sanitize-recover" } */ +/* 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; +} diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.h b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.h new file mode 100644 index 0000000..b839a6c --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.h @@ -0,0 +1,156 @@ +#define CVTFN(type1, type2) \ +__attribute__((noinline)) type1 \ +cvt_##type1##_##type2 (type2 x) \ +{ \ + return x; \ +} + +typedef signed char sc; +#define sc_MIN (-__SCHAR_MAX__ - 1) +#define sc_MAX __SCHAR_MAX__ +typedef unsigned char uc; +#define uc_MIN 0 +#define uc_MAX (2U * __SCHAR_MAX__ + 1U) +typedef char c; +#define c_MIN ((((char) -1) > (char) 0) ? uc_MIN : sc_MIN) +#define c_MAX ((((char) -1) > (char) 0) ? uc_MAX : sc_MAX) +typedef signed short ss; +#define ss_MIN (-__SHRT_MAX__ - 1) +#define ss_MAX __SHRT_MAX__ +typedef unsigned short us; +#define us_MIN 0 +#define us_MAX (2U * __SHRT_MAX__ + 1U) +typedef signed int si; +#define si_MIN (-__INT_MAX__ - 1) +#define si_MAX __INT_MAX__ +typedef unsigned int ui; +#define ui_MIN 0 +#define ui_MAX (2U * __INT_MAX__ + 1U) +typedef signed long sl; +#define sl_MIN (-__LONG_MAX__ - 1L) +#define sl_MAX __LONG_MAX__ +typedef unsigned long ul; +#define ul_MIN 0L +#define ul_MAX (2UL * __LONG_MAX__ + 1UL) +typedef signed long long sll; +#define sll_MIN (-__LONG_LONG_MAX__ - 1LL) +#define sll_MAX __LONG_LONG_MAX__ +typedef unsigned long long ull; +#define ull_MIN 0LL +#define ull_MAX (2ULL * __LONG_LONG_MAX__ + 1ULL) +#ifdef USE_INT128 +typedef signed __int128 si128; +# define si128_MAX \ + ((signed __int128) ((((unsigned __int128) 1) \ + << (__CHAR_BIT__ * __SIZEOF_INT128__ - 1)) - 1)) +# define si128_MIN (-si128_MAX - 1) +typedef unsigned __int128 ui128; +#define ui128_MIN ((unsigned __int128) 0) +#define ui128_MAX (((unsigned __int128) 2) * si128_MAX + 1) +#endif + +#ifdef si128_MAX +# define CVTS128(type2) CVTFN (si128, type2) CVTFN (ui128, type2) +#else +# define CVTS128(type2) +#endif + +#define CVTS(type2) \ + CVTFN (sc, type2) CVTFN (c, type2) CVTFN (uc, type2) \ + CVTFN (ss, type2) CVTFN (us, type2) \ + CVTFN (si, type2) CVTFN (ui, type2) \ + CVTFN (sl, type2) CVTFN (ul, type2) \ + CVTFN (sll, type2) CVTFN (ull, type2) \ + CVTS128 (type2) + +#ifdef __SIZEOF_INT128__ +# define TWO ((unsigned __int128) 2) +# define M1U ((unsigned __int128) -1) +# define MAXS (__CHAR_BIT__ * __SIZEOF_INT128__) +# define MAXT unsigned __int128 +#else +# define TWO 2ULL +# define M1U -1ULL +# define MAXS (__CHAR_BIT__ * __SIZEOF_LONG_LONG__) +# define MAXT unsigned long long +#endif + +#ifdef USE_FLT_DBL_LDBL +typedef float f; +#define f_RADIX 2 +#define f_MANT_DIG __FLT_MANT_DIG__ +#define f_MAX ((TWO << (f_MANT_DIG - 1)) - 1) +typedef double d; +#define d_RADIX 2 +#define d_MANT_DIG __DBL_MANT_DIG__ +#define d_MAX ((TWO << (d_MANT_DIG - 1)) - 1) +typedef long double ld; +#define ld_RADIX 2 +#define ld_MANT_DIG __LDBL_MANT_DIG__ +#define ld_MAX \ + (ld_MANT_DIG > MAXS ? M1U : (TWO << (ld_MANT_DIG > MAXS \ + ? 0 : ld_MANT_DIG - 1)) - 1) +CVTS (f) +CVTS (d) +CVTS (ld) +#endif +#ifdef USE_FLOAT80 +typedef __float80 f80; +# define f80_RADIX 2 +# define f80_MANT_DIG 64 +# define f80_MAX ((TWO << (f80_MANT_DIG - 1)) - 1) +CVTS (f80) +#endif +#ifdef USE_FLOAT128 +typedef __float128 f128; +# define f128_RADIX 2 +# define f128_MANT_DIG 113 +# define f128_MAX \ + (f128_MANT_DIG > MAXS ? M1U : (TWO << (f128_MANT_DIG > MAXS \ + ? 0 : f128_MANT_DIG - 1)) - 1) +CVTS (f128) +#endif +#ifdef USE_DFP +# ifdef __cplusplus +typedef float _Decimal32 __attribute__((mode(SD))); +typedef float _Decimal64 __attribute__((mode(DD))); +typedef float _Decimal128 __attribute__((mode(TD))); +# endif +typedef _Decimal32 d32; +# define d32_RADIX 10 +# define d32_MANT_DIG __DEC32_MANT_DIG__ +# if d32_MANT_DIG == 7 +# define d32_MAX 9999999ULL +# endif +typedef _Decimal64 d64; +# define d64_RADIX 10 +# define d64_MANT_DIG __DEC64_MANT_DIG__ +# if d64_MANT_DIG == 16 +# define d64_MAX 9999999999999999ULL +# endif +typedef _Decimal128 d128; +# define d128_RADIX 10 +# define d128_MANT_DIG __DEC128_MANT_DIG__ +# if d128_MANT_DIG == 34 +# ifdef __SIZEOF_INT128__ +/* #define d128_MAX 0x1ed09bead87c0378d8e63ffffffff */ +# define d128_MAX \ + ((((unsigned __int128) 0x1ed09bead87c0) << 64) + 0x378d8e63ffffffffULL) +# else +# define d128_MAX M1U +# endif +# endif +# ifdef BROKEN_DECIMAL_INT128 +# undef CVTS128 +# define CVTS128(type2) +# endif +CVTS (d32) +CVTS (d64) +CVTS (d128) +#endif + +extern +#ifdef __cplusplus +"C" +#endif +void abort (); diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c new file mode 100644 index 0000000..aa1c0da --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c @@ -0,0 +1,205 @@ +/* { dg-do run } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */ +/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover -DUSE_FLT_DBL_LDBL" } */ +/* { dg-additional-options "-DUSE_INT128" { target int128 } } */ + +#include "float-cast-overflow-7.h" + +#define TEST(type1, type2) \ + if (type1##_MIN) \ + { \ + type2 min = type1##_MIN; \ + type2 add = -1.0; \ + while (1) \ + { \ + volatile type2 tem = min + add; \ + if (tem != min) \ + { \ + volatile type1 tem3 = cvt_##type1##_##type2 (tem);\ + break; \ + } \ + add = add * type2##_RADIX; \ + if (min == add) \ + break; \ + } \ + } \ + else \ + { \ + volatile type1 tem3 = cvt_##type1##_##type2 (-1.0f); \ + } \ + { \ + type2 max = type1##_MAX; \ + type2 add = 1.0; \ + while (1) \ + { \ + volatile type2 tem = max + add; \ + if (tem != max) \ + { \ + volatile type1 tem3 = cvt_##type1##_##type2 (tem); \ + break; \ + } \ + add = add * type2##_RADIX; \ + if (max == add) \ + break; \ + } \ + } + +#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 +# define TWO 2ULL +# define M1U -1ULL +# define MAXS (__CHAR_BIT__ * __SIZEOF_LONG_LONG__) +#endif +#ifdef d32_MAX + TESTS (d32) +#endif +#ifdef d64_MAX + TESTS (d64) +#endif +#ifdef d128_MAX + TESTS (d128) +#endif + return 0; +} + +/* float */ +/* { dg-output "value -129 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value (-129|-1) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value (128|256) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ +/* No error for float and __int128 unsigned max value, as ui128_MAX is +Inf in float. */ +/* double */ +/* { dg-output "\[^\n\r]*value -129 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value (-129|-1) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value (128|256) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ +/* long double */ +/* { dg-output "\[^\n\r]*value -129 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value (-129|-1) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value (128|256) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ilp32 || lp64 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" { target { ! { ilp32 || lp64 } } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target { int128 } } } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c new file mode 100644 index 0000000..cadef31 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c @@ -0,0 +1,61 @@ +/* { dg-do run { target { i?86-*-linux* x86_64-*-linux* } } } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O2" } } */ +/* { dg-options "-fsanitize=float-cast-overflow -fsanitize-recover -DUSE_FLOAT80 -DUSE_FLOAT128" } */ +/* { dg-additional-options "-DUSE_INT128" { target int128 } } */ + +#include "float-cast-overflow-8.c" + +/* __float80 */ +/* { dg-output "value -129 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 128 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value (-129|-1) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value (128|256) is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 256 is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -32769 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 32768 is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 65536 is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ +/* { dg-output "\[^\n\r]*value \[0-9.e+-]* is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ +/* __float128 */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ +/* { dg-output "\[^\n\r]*value <unknown> is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/float-cast.h b/gcc/testsuite/c-c++-common/ubsan/float-cast.h new file mode 100644 index 0000000..166da8f --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/float-cast.h @@ -0,0 +1,28 @@ +/* Various macros for -fsanitize=float-cast-overflow testing. */ + +#define INT128_MAX (__int128) (((unsigned __int128) 1 << ((__SIZEOF_INT128__ * __CHAR_BIT__) - 1)) - 1) +#define INT128_MIN (-INT128_MAX - 1) +#define UINT128_MAX ((2 * (unsigned __int128) INT128_MAX) + 1) + +#define CHECK_BOUNDARY(VAR, VAL) \ + (VAR) = (VAL) - 5.0; \ + (VAR) = (VAL) - 1.5; \ + (VAR) = (VAL) - 1.0; \ + (VAR) = (VAL) - 0.75; \ + (VAR) = (VAL) - 0.5; \ + (VAR) = (VAL) - 0.0000001; \ + (VAR) = (VAL) - 0.0; \ + (VAR) = (VAL); \ + (VAR) = (VAL) + 0.0; \ + (VAR) = (VAL) + 0.0000001; \ + (VAR) = (VAL) + 0.5; \ + (VAR) = (VAL) + 0.75; \ + (VAR) = (VAL) + 1.0; \ + (VAR) = (VAL) + 1.5; \ + (VAR) = (VAL) + 5.0; + +#define CHECK_NONNUMBERS(VAR) \ + (VAR) = nan; \ + (VAR) = -nan; \ + (VAR) = inf; \ + (VAR) = -inf; diff --git a/gcc/testsuite/g++.dg/ubsan/float-cast-overflow-bf.C b/gcc/testsuite/g++.dg/ubsan/float-cast-overflow-bf.C new file mode 100644 index 0000000..d1df76d --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/float-cast-overflow-bf.C @@ -0,0 +1,62 @@ +// { dg-do run { target { int32 } } } +// { dg-options "-fsanitize=float-cast-overflow" } + +#define INT_MAX __INT_MAX__ +#define INT_MIN (-__INT_MAX__ - 1) +#define UINT_MAX 2 * (unsigned) __INT_MAX__ + 1 + +struct S +{ + int i:1; +} s; + +struct T +{ + unsigned int i:1; +} t; + +int +main (void) +{ + volatile double d; + +#define CHECK_BOUNDARY(VAR, VAL) \ + (VAR) = (VAL) - 1.5; \ + (VAR) = (VAL) - 1.0; \ + (VAR) = (VAL) - 0.75; \ + (VAR) = (VAL) - 0.5; \ + (VAR) = (VAL) - 0.0000001; \ + (VAR) = (VAL) - 0.0; \ + (VAR) = (VAL); \ + (VAR) = (VAL) + 0.0; \ + (VAR) = (VAL) + 0.0000001; \ + (VAR) = (VAL) + 0.5; \ + (VAR) = (VAL) + 0.75; \ + (VAR) = (VAL) + 1.0; \ + (VAR) = (VAL) + 1.5; + + /* Signed bit-field. (INT_MIN, INT_MAX) is valid. */ + d = INT_MIN; + CHECK_BOUNDARY (s.i, d); + d = 0.0; + CHECK_BOUNDARY (s.i, d); + d = INT_MAX; + CHECK_BOUNDARY (s.i, d); + + /* Unsigned bit-field. (0, UINT_MAX) is valid. */ + d = UINT_MAX; + CHECK_BOUNDARY (t.i, d); + d = 0.0; + CHECK_BOUNDARY (t.i, d); + + return 0; +} + +/* { dg-output "value -2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2.14748e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 4.29497e\\\+09 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-bf.c b/gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-bf.c new file mode 100644 index 0000000..298d0d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-bf.c @@ -0,0 +1,72 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=float-cast-overflow" } */ + +struct +{ + int i:1; +} s; + +struct +{ + unsigned int i:1; +} t; + +int +main (void) +{ + volatile double d; + +#define CHECK_BOUNDARY(VAR, VAL) \ + (VAR) = (VAL) - 1.5; \ + (VAR) = (VAL) - 1.0; \ + (VAR) = (VAL) - 0.5; \ + (VAR) = (VAL) - 0.0000001; \ + (VAR) = (VAL) - 0.0; \ + (VAR) = (VAL); \ + (VAR) = (VAL) + 0.0; \ + (VAR) = (VAL) + 0.0000001; \ + (VAR) = (VAL) + 0.5; \ + (VAR) = (VAL) + 1.0; \ + (VAR) = (VAL) + 1.5; + + /* Signed bit-field. (-1, 0) is valid. */ + d = -1.0; + CHECK_BOUNDARY (s.i, d); + d = 0.0; + CHECK_BOUNDARY (s.i, d); + d = 1.0; + CHECK_BOUNDARY (s.i, d); + + /* Unsigned bit-field. (0, 1) is valid. */ + d = -1.0; + CHECK_BOUNDARY (t.i, d); + d = 0.0; + CHECK_BOUNDARY (t.i, d); + d = 1.0; + CHECK_BOUNDARY (t.i, d); + + return 0; +} + +/* { dg-output "value -2.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -2 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -2.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -2 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value -1 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 2.5 is outside the range of representable values of type\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/ubsan.c b/gcc/ubsan.c index 585569c..4de6d6e8 100644 --- a/gcc/ubsan.c +++ b/gcc/ubsan.c @@ -47,6 +47,8 @@ along with GCC; see the file COPYING3. If not see #include "asan.h" #include "gimplify-me.h" #include "intl.h" +#include "realmpfr.h" +#include "dfp.h" /* Map from a tree to a VAR_DECL tree. */ @@ -267,9 +269,14 @@ static unsigned short get_ubsan_type_info_for_type (tree type) { gcc_assert (TYPE_SIZE (type) && tree_fits_uhwi_p (TYPE_SIZE (type))); - int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type))); - gcc_assert (prec != -1); - return (prec << 1) | !TYPE_UNSIGNED (type); + if (TREE_CODE (type) == REAL_TYPE) + return tree_to_uhwi (TYPE_SIZE (type)); + else + { + int prec = exact_log2 (tree_to_uhwi (TYPE_SIZE (type))); + gcc_assert (prec != -1); + return (prec << 1) | !TYPE_UNSIGNED (type); + } } /* Helper routine that returns ADDR_EXPR of a VAR_DECL of a type @@ -359,7 +366,14 @@ ubsan_type_descriptor (tree type, bool want_pointer_type_p) tkind = 0x0000; break; case REAL_TYPE: - tkind = 0x0001; + /* FIXME: libubsan right now only supports float, double and + long double type formats. */ + if (TYPE_MODE (type) == TYPE_MODE (float_type_node) + || TYPE_MODE (type) == TYPE_MODE (double_type_node) + || TYPE_MODE (type) == TYPE_MODE (long_double_type_node)) + tkind = 0x0001; + else + tkind = 0xffff; break; default: tkind = 0xffff; @@ -891,6 +905,130 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi) gsi_insert_before (&gsi2, g, GSI_SAME_STMT); } +/* Instrument float point-to-integer conversion. TYPE is an integer type of + destination, EXPR is floating-point expression. */ + +tree +ubsan_instrument_float_cast (location_t loc, tree type, tree expr) +{ + tree expr_type = TREE_TYPE (expr); + tree t, tt, fn, min, max; + enum machine_mode mode = TYPE_MODE (expr_type); + int prec = TYPE_PRECISION (type); + bool uns_p = TYPE_UNSIGNED (type); + + /* Float to integer conversion first truncates toward zero, so + even signed char c = 127.875f; is not problematic. + Therefore, we should complain only if EXPR is unordered or smaller + or equal than TYPE_MIN_VALUE - 1.0 or greater or equal than + TYPE_MAX_VALUE + 1.0. */ + if (REAL_MODE_FORMAT (mode)->b == 2) + { + /* For maximum, TYPE_MAX_VALUE might not be representable + in EXPR_TYPE, e.g. if TYPE is 64-bit long long and + EXPR_TYPE is IEEE single float, but TYPE_MAX_VALUE + 1.0 is + either representable or infinity. */ + REAL_VALUE_TYPE maxval = dconst1; + SET_REAL_EXP (&maxval, REAL_EXP (&maxval) + prec - !uns_p); + real_convert (&maxval, mode, &maxval); + max = build_real (expr_type, maxval); + + /* For unsigned, assume -1.0 is always representable. */ + if (uns_p) + min = build_minus_one_cst (expr_type); + else + { + /* TYPE_MIN_VALUE is generally representable (or -inf), + but TYPE_MIN_VALUE - 1.0 might not be. */ + REAL_VALUE_TYPE minval = dconstm1, minval2; + SET_REAL_EXP (&minval, REAL_EXP (&minval) + prec - 1); + real_convert (&minval, mode, &minval); + real_arithmetic (&minval2, MINUS_EXPR, &minval, &dconst1); + real_convert (&minval2, mode, &minval2); + if (real_compare (EQ_EXPR, &minval, &minval2) + && !real_isinf (&minval)) + { + /* If TYPE_MIN_VALUE - 1.0 is not representable and + rounds to TYPE_MIN_VALUE, we need to subtract + more. As REAL_MODE_FORMAT (mode)->p is the number + of base digits, we want to subtract a number that + will be 1 << (REAL_MODE_FORMAT (mode)->p - 1) + times smaller than minval. */ + minval2 = dconst1; + gcc_assert (prec > REAL_MODE_FORMAT (mode)->p); + SET_REAL_EXP (&minval2, + REAL_EXP (&minval2) + prec - 1 + - REAL_MODE_FORMAT (mode)->p + 1); + real_arithmetic (&minval2, MINUS_EXPR, &minval, &minval2); + real_convert (&minval2, mode, &minval2); + } + min = build_real (expr_type, minval2); + } + } + else if (REAL_MODE_FORMAT (mode)->b == 10) + { + /* For _Decimal128 up to 34 decimal digits, - sign, + dot, e, exponent. */ + char buf[64]; + mpfr_t m; + int p = REAL_MODE_FORMAT (mode)->p; + REAL_VALUE_TYPE maxval, minval; + + /* Use mpfr_snprintf rounding to compute the smallest + representable decimal number greater or equal than + 1 << (prec - !uns_p). */ + mpfr_init2 (m, prec + 2); + mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN); + mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m); + decimal_real_from_string (&maxval, buf); + max = build_real (expr_type, maxval); + + /* For unsigned, assume -1.0 is always representable. */ + if (uns_p) + min = build_minus_one_cst (expr_type); + else + { + /* Use mpfr_snprintf rounding to compute the largest + representable decimal number less or equal than + (-1 << (prec - 1)) - 1. */ + mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN); + mpfr_sub_ui (m, m, 1, GMP_RNDN); + mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m); + decimal_real_from_string (&minval, buf); + min = build_real (expr_type, minval); + } + mpfr_clear (m); + } + else + return NULL_TREE; + + if (flag_sanitize_undefined_trap_on_error) + fn = build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TRAP), 0); + else + { + /* Create the __ubsan_handle_float_cast_overflow fn call. */ + tree data = ubsan_create_data ("__ubsan_float_cast_overflow_data", NULL, + NULL, + ubsan_type_descriptor (expr_type, false), + ubsan_type_descriptor (type, false), + NULL_TREE); + enum built_in_function bcode + = flag_sanitize_recover + ? BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW + : BUILT_IN_UBSAN_HANDLE_FLOAT_CAST_OVERFLOW_ABORT; + fn = builtin_decl_explicit (bcode); + fn = build_call_expr_loc (loc, fn, 2, + build_fold_addr_expr_loc (loc, data), + ubsan_encode_value (expr, false)); + } + + t = fold_build2 (UNLE_EXPR, boolean_type_node, expr, min); + tt = fold_build2 (UNGE_EXPR, boolean_type_node, expr, max); + return fold_build3 (COND_EXPR, void_type_node, + fold_build2 (TRUTH_OR_EXPR, boolean_type_node, t, tt), + fn, integer_zero_node); +} + namespace { const pass_data pass_data_ubsan = diff --git a/gcc/ubsan.h b/gcc/ubsan.h index 67cc6e9..b008419 100644 --- a/gcc/ubsan.h +++ b/gcc/ubsan.h @@ -44,6 +44,7 @@ extern tree ubsan_type_descriptor (tree, bool); extern tree ubsan_encode_value (tree, bool = false); extern bool is_ubsan_builtin_p (tree); extern tree ubsan_build_overflow_builtin (tree_code, location_t, tree, tree, tree); +extern tree ubsan_instrument_float_cast (location_t, tree, tree); #endif /* GCC_UBSAN_H */ |