On 5/24/26 12:38 AM, H.J. Lu wrote:
Note: The following floating-point exceptions are signalling:
IEEE_INVALID_FLAG IEEE_UNDERFLOW_FLAG IEEE_DENORMAL
STOP 3
FAIL: gfortran.dg/EXformat_1.F90   -O0  execution test

I fed the above and the CI report I received to Claude and it
arrived at the attached patch rather quickly. Can you try this and confirm whether it fixes it or not?

Regards,

Jerry

---------------

From 837ca2b4c3d1069ddb938a5a7c259d34a85479fc Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Sun, 24 May 2026 11:51:49 -0700
Subject: [PATCH] Fortran: [PR93727] Fix EX format kind=8 output on ILP32
 targets

On 32-bit targets such as ARM where unsigned long is 32 bits, the
kind=8 case in get_float_hex_string used unsigned long for frac_part.
The kind=8 mantissa requires 52 bits (13 hex digits), so the cast
silently truncated the upper bits, producing wrong hex output.  In
addition, converting a ~4.5e15 double value to a 32-bit unsigned long
is out of range, which raised IEEE_INVALID_FLAG on ARM hardware.

The kind=10 case already used unsigned long long for the same reason.
Fix kind=8 to match: change the type, the cast, and the two %lX
format specifiers to %llX.

        PR fortran/93727

libgfortran/ChangeLog:

        * io/write_float.def (get_float_hex_string): Change frac_part
        for kind=8 from unsigned long to unsigned long long and update
        format specifiers from %13.13lX to %13.13llX to fix truncated
        hex output and IEEE_INVALID_FLAG on ILP32 targets.

Assisted by: Claude Sonnet 4.6

From 837ca2b4c3d1069ddb938a5a7c259d34a85479fc Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Sun, 24 May 2026 11:51:49 -0700
Subject: [PATCH] Fortran: [PR93727] Fix EX format kind=8 output on ILP32
 targets

On 32-bit targets such as ARM where unsigned long is 32 bits, the
kind=8 case in get_float_hex_string used unsigned long for frac_part.
The kind=8 mantissa requires 52 bits (13 hex digits), so the cast
silently truncated the upper bits, producing wrong hex output.  In
addition, converting a ~4.5e15 double value to a 32-bit unsigned long
is out of range, which raised IEEE_INVALID_FLAG on ARM hardware.

The kind=10 case already used unsigned long long for the same reason.
Fix kind=8 to match: change the type, the cast, and the two %lX
format specifiers to %llX.

	PR fortran/93727

libgfortran/ChangeLog:

	* io/write_float.def (get_float_hex_string): Change frac_part
	for kind=8 from unsigned long to unsigned long long and update
	format specifiers from %13.13lX to %13.13llX to fix truncated
	hex output and IEEE_INVALID_FLAG on ILP32 targets.

Assisted by: Claude Sonnet 4.6
---
 libgfortran/io/write_float.def | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def
index 608106af7c7..66fd7cfe69a 100644
--- a/libgfortran/io/write_float.def
+++ b/libgfortran/io/write_float.def
@@ -128,7 +128,7 @@ get_float_hex_string (const void *source, int kind, char *buffer,
 	double mant;
 	int expon;
 	int int_part;
-	unsigned long frac_part;
+	unsigned long long frac_part;
 
 	val = *(const GFC_REAL_8 *) source;
 	is_negative = signbit (val);
@@ -172,11 +172,11 @@ get_float_hex_string (const void *source, int kind, char *buffer,
 	int_part = (int) mant;
 	/* 56 is the nearest integer divisible by 4 that is >= 53 (mantissa bits
 	   for kind=8).  (56-4)/4 = 13 hex digits for the fractional part.  */
-	frac_part = (unsigned long) scalbn (mant - (double) int_part, 56 - 4);
+	frac_part = (unsigned long long) scalbn (mant - (double) int_part, 56 - 4);
 	if (is_negative)
-	  result = snprintf (buffer, 25, "-0X%X.%13.13lXP%+d", int_part, frac_part, expon);
+	  result = snprintf (buffer, 25, "-0X%X.%13.13llXP%+d", int_part, frac_part, expon);
 	else
-	  result = snprintf (buffer, 25, "0X%X.%13.13lXP%+d", int_part, frac_part, expon);
+	  result = snprintf (buffer, 25, "0X%X.%13.13llXP%+d", int_part, frac_part, expon);
       }
       break;
 #ifdef HAVE_GFC_REAL_10
-- 
2.54.0

Reply via email to