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;
+}

Reply via email to