Re: [PATCH, fortran] PR93727 Implement new EX format specifier

Jerry D <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.fortran
Message-ID <[email protected]>
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
0001-Fortran-PR93727-Fix-EX-format-kind-8-output-on-ILP32.patch (text/x-patch, 2.5 KB)
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.