https://gcc.gnu.org/g:962723b046ae6406c0c457bfdb76318b3652673f
commit r17-4908-g962723b046ae6406c0c457bfdb76318b3652673f Author: Dominic P <[email protected]> Date: Fri Oct 2 19:10:50 2026 +0100 c: Do not keep excess precision for the result of ! [PR123370] build_unary_op strips an EXCESS_PRECISION_EXPR from its operand and wraps the result in one again, but the result of ! is int. So with _Float16 (or float with x87 excess precision), !(x - y) kept the type of x - y: sizeof and _Generic saw _Float16, ?: ICEd in build_conditional_expr, and !(x - y) / 2 ICEd at expand. Do not re-wrap the result of TRUTH_NOT_EXPR; the operand is still tested at its excess precision, as for (x - y) == 0. Bootstrapped and regression tested on x86_64-pc-linux-gnu. On aarch64-linux-gnu (qemu, SVE VL128), regression tested dg.exp, aarch64.exp and the SVE tests; the SVE tests also at VL2048. Tested together with the two PR121105 patches and an earlier version of the tests; the final gcc.dg/pr123370.c was compiled and run on aarch64-linux-gnu (qemu), gcc.target/i386/pr123370.c run on x86_64-pc-linux-gnu with -m32. Assisted-by: Claude Opus 5 (Anthropic) PR c/123370 gcc/c/ChangeLog: * c-typeck.cc (build_unary_op) <case TRUTH_NOT_EXPR>: Clear eptype. gcc/testsuite/ChangeLog: * gcc.dg/pr123370.c: New test. * gcc.target/i386/pr123370.c: New test. Signed-off-by: Dominic P <[email protected]> Diff: --- gcc/c/c-typeck.cc | 1 + gcc/testsuite/gcc.dg/pr123370.c | 36 ++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr123370.c | 25 ++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 9b01f3daec9b..974568691011 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -5986,6 +5986,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, else arg = c_objc_common_truthvalue_conversion (location, arg); ret = invert_truthvalue_loc (location, arg); + eptype = NULL_TREE; /* If the TRUTH_NOT_EXPR has been folded, reset the location. */ if (EXPR_P (ret) && EXPR_HAS_LOCATION (ret)) location = EXPR_LOCATION (ret); diff --git a/gcc/testsuite/gcc.dg/pr123370.c b/gcc/testsuite/gcc.dg/pr123370.c new file mode 100644 index 000000000000..bd205e8d9a48 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr123370.c @@ -0,0 +1,36 @@ +/* PR c/123370 */ +/* { dg-do run } */ +/* { dg-options "-O2 -fexcess-precision=standard" } */ +/* { dg-add-options float16 } */ +/* { dg-require-effective-target float16_runtime } */ + +volatile _Float16 x = 3, y = 1; + +_Static_assert (_Generic (!(x - y), int: 1, default: 0), ""); +_Static_assert (sizeof (!(x - y)) == sizeof (int), ""); + +__attribute__((noipa)) int +f1 (void) +{ + return (y == x) ? (y + 1) : !(x - y); +} + +__attribute__((noipa)) int +f2 (int c) +{ + return c ? !(x - y) : !!(x - y); +} + +__attribute__((noipa)) float +f3 (void) +{ + return !(x - x) / 2; +} + +int +main (void) +{ + if (f1 () != 0 || f2 (1) != 0 || f2 (0) != 1 || f3 () != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/pr123370.c b/gcc/testsuite/gcc.target/i386/pr123370.c new file mode 100644 index 000000000000..21410c8c9fbd --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr123370.c @@ -0,0 +1,25 @@ +/* PR c/123370 */ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -mfpmath=387 -fexcess-precision=standard" } */ + +float x, y; + +_Static_assert (_Generic (!(x - y), int: 1, default: 0), ""); + +int +f1 (int c) +{ + return c ? (y + 1) : !(x - y); +} + +int +f2 (int c) +{ + return c ? !(x - y) : !!(x - y); +} + +float +f3 (void) +{ + return !(x - y) / 2; +}
