From patchwork Fri May 23 14:19:00 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Polacek X-Patchwork-Id: 351867 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id D548A140092 for ; Sat, 24 May 2014 00:19:29 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; q=dns; s=default; b=gonLBxFsUjSE7jWpsmtp5iVaXctYoYC+/3JsMVKGGG6bcHBkwJ Eb6xc6w1xqiEc99I1snG+z+0PsuJVx9YePncLhJZ7nVEF4hjkSGL/HHhtN3sTD0r fMImphNoulTwO/+uIlOhjXnDMrxVWptcG8+WDaR4jzcRMhMvw1CWVNoSc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:cc:subject:message-id:mime-version:content-type; s= default; bh=iOg5chWePH+Ljz3td6/59rUqrwM=; b=DR4INXzEw9ftTQOAFh3E oqlqOLtUe+1o7E0LSIqL3fCm/TW+iWHVoDA7acORQIyiwxyETNYQULyznMleXftB DRqr/pip+zczhGDLetgSBiuOpL7DvwaEpL2NY7w2JXCHKVdG9c8GUGUm8Txag7jn B91NMue9vpif/yJoEYDlFIg= Received: (qmail 28034 invoked by alias); 23 May 2014 14:19:19 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 28018 invoked by uid 89); 23 May 2014 14:19:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.1 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 23 May 2014 14:19:11 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s4NEJ6j8010012 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 23 May 2014 10:19:06 -0400 Received: from redhat.com (ovpn-116-22.ams2.redhat.com [10.36.116.22]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s4NEJ0S3028381 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NO); Fri, 23 May 2014 10:19:03 -0400 Date: Fri, 23 May 2014 16:19:00 +0200 From: Marek Polacek To: GCC Patches Cc: Jakub Jelinek , "Joseph S. Myers" Subject: [PATCH] Implement -fsanitize=float-cast-overflow (take 3) Message-ID: <20140523141900.GD17600@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) This is the latest patch for -fsanitize=float-cast-overflow. Since last version it: - adds tons of tests written by Jakub; - patches libubsan so it can handle 96-bit floating-point types (that is, long double and __float80 in -m32 mode); - includes a hack for printing __float{80,128}/_Decimal* types in libubsan. Since libubsan handles only float/double/long double floating-point types, we use TK_Unknown for other types, meaning that libubsan prints "" instead of the value. Regtested/bootstrapped on x86_64-linux. Couldn't test ppc64, as libsanitizer currently doesn't build on this architecture. Ok for trunk? 2014-05-23 Marek Polacek Jakub Jelinek * 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. Marek diff --git gcc/gcc/builtins.def gcc/gcc/builtins.def index d400ecb..cd823a3 100644 --- gcc/gcc/builtins.def +++ gcc/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 gcc/gcc/convert.c gcc/gcc/convert.c index 91c1da2..b8f3671 100644 --- gcc/gcc/convert.c +++ gcc/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 gcc/gcc/doc/invoke.texi gcc/gcc/doc/invoke.texi index dbb6af6..34ba721 100644 --- gcc/gcc/doc/invoke.texi +++ gcc/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 gcc/gcc/flag-types.h gcc/gcc/flag-types.h index caf4039..ed00046 100644 --- gcc/gcc/flag-types.h +++ gcc/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. */ diff --git gcc/gcc/gcc.c gcc/gcc/gcc.c index 7bea6d7..9ac18e6 100644 --- gcc/gcc/gcc.c +++ gcc/gcc/gcc.c @@ -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 diff --git gcc/gcc/opts.c gcc/gcc/opts.c index 5f4b2e3..2f4f913 100644 --- gcc/gcc/opts.c +++ gcc/gcc/opts.c @@ -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 gcc/gcc/sanitizer.def gcc/gcc/sanitizer.def index 6184b5a..a2f7ff0 100644 --- gcc/gcc/sanitizer.def +++ gcc/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 gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c index e69de29..249731d 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-1.c +++ gcc/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 +#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 gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c index e69de29..81ceb92 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-10.c +++ gcc/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 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 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 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value 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 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ diff --git gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-2.c gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-2.c index e69de29..15eacc9 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-2.c +++ gcc/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 gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-3.c gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-3.c index e69de29..2200e66 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-3.c +++ gcc/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 +#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 gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-4.c gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-4.c index e69de29..7704aa9 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-4.c +++ gcc/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 +#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 gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-5.c gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-5.c index e69de29..44910ee 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-5.c +++ gcc/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 +#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 gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-6.c gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-6.c index e69de29..f51a2c8 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-6.c +++ gcc/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 +#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 gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c index e69de29..3223d5e 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.c +++ gcc/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 gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.h gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.h index e69de29..b839a6c 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-7.h +++ gcc/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 gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c index e69de29..aa1c0da 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-8.c +++ gcc/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 gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c index e69de29..cadef31 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast-overflow-9.c +++ gcc/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 is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'signed char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned char'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'short unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type 'long long unsigned int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type '__int128'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ +/* { dg-output "\[^\n\r]*value is outside the range of representable values of type '__int128 unsigned'\[^\n\r]*(\n|\r\n|\r)" { target int128 } } */ diff --git gcc/gcc/testsuite/c-c++-common/ubsan/float-cast.h gcc/gcc/testsuite/c-c++-common/ubsan/float-cast.h index e69de29..166da8f 100644 --- gcc/gcc/testsuite/c-c++-common/ubsan/float-cast.h +++ gcc/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 gcc/gcc/testsuite/g++.dg/ubsan/float-cast-overflow-bf.C gcc/gcc/testsuite/g++.dg/ubsan/float-cast-overflow-bf.C index e69de29..d1df76d 100644 --- gcc/gcc/testsuite/g++.dg/ubsan/float-cast-overflow-bf.C +++ gcc/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 gcc/gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-bf.c gcc/gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-bf.c index e69de29..298d0d9 100644 --- gcc/gcc/testsuite/gcc.dg/ubsan/float-cast-overflow-bf.c +++ gcc/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 gcc/gcc/ubsan.c gcc/gcc/ubsan.c index 585569c..4de6d6e8 100644 --- gcc/gcc/ubsan.c +++ gcc/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 gcc/gcc/ubsan.h gcc/gcc/ubsan.h index 67cc6e9..b008419 100644 --- gcc/gcc/ubsan.h +++ gcc/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 */ diff --git gcc/libsanitizer/ubsan/ubsan_value.cc gcc/libsanitizer/ubsan/ubsan_value.cc index 141e8b5..e2f664d 100644 --- gcc/libsanitizer/ubsan/ubsan_value.cc +++ gcc/libsanitizer/ubsan/ubsan_value.cc @@ -92,6 +92,7 @@ FloatMax Value::getFloatValue() const { switch (getType().getFloatBitWidth()) { case 64: return *reinterpret_cast(Val); case 80: return *reinterpret_cast(Val); + case 96: return *reinterpret_cast(Val); case 128: return *reinterpret_cast(Val); } }