c: Do not keep excess precision for the result of ! [PR123370]

Message ID 20261002194632.3051920-1-gcc@gcc.dp11.uk
State Committed
Commit 962723b046ae6406c0c457bfdb76318b3652673f
Headers
Series c: Do not keep excess precision for the result of ! [PR123370] |

Commit Message

DominicP Oct. 2, 2026, 7:46 p.m. UTC
  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 <gcc@gcc.dp11.uk>
---
The _Float16 ICE goes back to GCC 7 at least (per the PR); the float one
needs -m32 -mfpmath=387 -fexcess-precision=standard.

OK for trunk?

 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(+)
 create mode 100644 gcc/testsuite/gcc.dg/pr123370.c
 create mode 100644 gcc/testsuite/gcc.target/i386/pr123370.c
  

Comments

Joseph Myers Oct. 5, 2026, 5:07 p.m. UTC | #1
On Fri, 2 Oct 2026, Dominic P wrote:

> 	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.

OK.
  
DominicP Oct. 5, 2026, 9:03 p.m. UTC | #2
Thanks, pushed as 962723b046a.

Dominic
  

Patch

diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 9b01f3daec9..97456869101 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 00000000000..bd205e8d9a4
--- /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 00000000000..21410c8c9fb
--- /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;
+}