c: Do not keep excess precision for the result of ! [PR123370]
Commit Message
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
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.
Thanks, pushed as 962723b046a.
Dominic
@@ -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);
new file mode 100644
@@ -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;
+}
new file mode 100644
@@ -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;
+}