Clang rejects the casts on asm output operands in longlong.h
(-Winvalid-gnu-asm-cast is an error by default), so several of its
blocks do not build with clang.  v1 dropped the casts.  Richard pointed
out that they do check something, because GCC accepts a cast on an asm
output only when it is a no-op, so an output of the wrong size fails to
build.  This version keeps that check.

Patches 1 and 2 are the fix.  Patches 3 and 4 are an optional
simplification of patch 2.  Patch 3 only exists to enable patch 4, and
it is fine to take 1-2 and stop there.

 1. Remove the Z8000 block.  GCC has no Z8000 port, so drop it instead
    of editing code nobody can build, as Richard suggested.

 2. Replace each output cast with a __ll_check_output (type, x)
    statement before the asm.  It is a sizeof check that fails the build
    when the output's size differs from the type's.  Macros whose body
    was a bare asm statement are wrapped in do { } while (0) to make
    room for it, so the diff is large (~350 lines).

 3. Drop "register" from a few libquadmath locals that are passed as
    macro outputs, so that patch 4 can take their address.

 4. Replace __ll_check_output with __ll_out (type, x), which does the
    same check inside the operand and yields it as an lvalue:

        : "=r" (__ll_out (USItype, sh)),

    That is a one-for-one replacement for the old casts.  The macros no
    longer need the do { } while (0) wrappers, and the total change to
    longlong.h drops to ~100 lines.  __ll_out takes the address of the
    output, so the output can no longer be a register variable or a
    bit-field.  Patch 3 fixes the only such callers in the tree, but
    out-of-tree copies of longlong.h may have others.

An exact type check with _Generic or __builtin_types_compatible_p does
not work: g++ supports neither, and it would reject callers the casts
accept today.  Patch 2 has the details.

Testing: a test unit that instantiates every macro, compiled as C and C++
at -O2 for W_TYPE_SIZE 32 and 64 with every cross compiler I have (the
list is in patch 2).  After each of patches 2 and 4:

 - the generated assembly is byte-identical to master;
 - outputs of the wrong size are rejected in every configuration where
   they were rejected before;
 - same-size outputs of a different type are still accepted.

With clang, x86_64, x32, i386, armv5, armv7 and sparcv9 fail to build
before the series and build after it, and wrong-size outputs are now
rejected there too.

Changes in v2:
- Keep the output size check instead of dropping it (patch 2).
- Remove the Z8000 block instead of editing it (patch 1).
- New, optional: patches 3 and 4.
- v1 patch 2/2 (sdiv_qrnnd parentheses) is already committed.
- Link to v1: 
https://inbox.sourceware.org/gcc-patches/[email protected]/

---
Matt Turner (4):
      include: Remove Z8000 support from longlong.h
      include: Replace casts on asm output operands in longlong.h
      libquadmath: Drop register from longlong.h macro outputs
      include: Check longlong.h asm output sizes inside the operand

 include/longlong.h            | 227 +++++++++++++++++++-----------------------
 libquadmath/printf/addmul_1.c |   8 +-
 libquadmath/printf/mul_1.c    |   6 +-
 libquadmath/printf/submul_1.c |   8 +-
 libquadmath/strtod/strtod_l.c |   2 +-
 5 files changed, 112 insertions(+), 139 deletions(-)
---
base-commit: e47eccbe6d118023e4fe83bde14075729c40e030
change-id: 20260921-longlong-fixes-v2-d8f7bb2376cc

Best regards,
-- 
Matt Turner <[email protected]>

Reply via email to