Re: [patch, libgfortran] PR111022 ES0.0E0 format gave ES0.dE0 output with d too high.

2024-01-30 Thread Jerry D

On 1/30/24 12:36 PM, Harald Anlauf wrote:

Hi Jerry,

Am 30.01.24 um 19:15 schrieb Jerry D:

The attached patch attempts to fix the handling of the EN0.0E0 and
ES0.0E0 formatting by correctly calculating the number of digits needed
for the exponents and building those exponents into the float string.


while your patch addresses ENw.dE0 and ESw.dE0 formatting,
it does not fix Ew.dE0, which can be seen with the following test:

   write(buffer,"(E0.3E0)") .6660_4
   print *, buffer
   write(buffer,"(E0.3)") .6660_4
   print *, buffer

I get even with your patch:

  0.666
  0.666

but would have expected:

  0.666E+0   ! F2018 & F2023, table 13.1
  0.666E+0   ! F2023, table 13.1

The latter one is a bit ambiguous in F2018, but certainly gfortran's
current output in wrong.

Can you please check, and if you can fix that too, it would be great.
And if we do not want to be dependent on the standard version at
runtime, I'd rather go for F2023.



Certainly will look. This is why we need others checking. Corner cases 
abound.


Cheers,

Jerry



Re: [patch, libgfortran] PR111022 ES0.0E0 format gave ES0.dE0 output with d too high.

2024-01-30 Thread Harald Anlauf

Hi Jerry,

Am 30.01.24 um 19:15 schrieb Jerry D:

The attached patch attempts to fix the handling of the EN0.0E0 and
ES0.0E0 formatting by correctly calculating the number of digits needed
for the exponents and building those exponents into the float string.


while your patch addresses ENw.dE0 and ESw.dE0 formatting,
it does not fix Ew.dE0, which can be seen with the following test:

  write(buffer,"(E0.3E0)") .6660_4
  print *, buffer
  write(buffer,"(E0.3)") .6660_4
  print *, buffer

I get even with your patch:

 0.666
 0.666

but would have expected:

 0.666E+0   ! F2018 & F2023, table 13.1
 0.666E+0   ! F2023, table 13.1

The latter one is a bit ambiguous in F2018, but certainly gfortran's
current output in wrong.

Can you please check, and if you can fix that too, it would be great.
And if we do not want to be dependent on the standard version at
runtime, I'd rather go for F2023.


My editor judiciously deleted trailing blank spaces in a number of
places.  I apologize for the clutter, but we might as well get rid of it
now.

Two existing test cases needed to be adjusted and I am adding one new
test case to capture the changes in our testsuite.

Regression tested on X86_64.

OK for trunk?  Do we need to backport this?


If the above is fixed, I would not object a backport to the 13-branch,
but only if that change has sinked in for a while, and someone else
agrees on it.

Thanks so far!

Harald


Regards,

Jerry

Author: Jerry DeLisle 
Date:   Tue Jan 30 09:45:49 2024 -0800

     libgfortran: EN0.0E0 and ES0.0E0 format editing.

     PR libgfortran/111022

     F2018 and F2023 standards added zero width exponents. This required
     additional special handing in the process of building formatted
     floating point strings.

     libgfortran/ChangeLog:

     * io/write.c (select_buffer): Whitespace.
     (write_real): Whitespace.
     (write_real_w0): Adjust logic for d==0.
     * io/write_float.def (determine_precision): Whitespace.
     (build_float_string): Calculate the width of the E0 exponents.
     (build_infnan_string): Whitespace.
     (CALCULATE_EXP): Whitespace
     (quadmath_snprintf): Whitespace.
     (determine_en_precision): Whitespace.

     gcc/testsuite/ChangeLog:

     * gfortran.dg/pr96436_4.f90: Changed for ES0 and EN0.
     * gfortran.dg/pr96436_5.f90: Changed for ES0 and EN0.
     * gfortran.dg/pr111022.f90: New test.




[patch, libgfortran] PR111022 ES0.0E0 format gave ES0.dE0 output with d too high.

2024-01-30 Thread Jerry D
The attached patch attempts to fix the handling of the EN0.0E0 and 
ES0.0E0 formatting by correctly calculating the number of digits needed 
for the exponents and building those exponents into the float string.


My editor judiciously deleted trailing blank spaces in a number of 
places.  I apologize for the clutter, but we might as well get rid of it 
now.


Two existing test cases needed to be adjusted and I am adding one new 
test case to capture the changes in our testsuite.


Regression tested on X86_64.

OK for trunk?  Do we need to backport this?

Regards,

Jerry

Author: Jerry DeLisle 
Date:   Tue Jan 30 09:45:49 2024 -0800

libgfortran: EN0.0E0 and ES0.0E0 format editing.

PR libgfortran/111022

F2018 and F2023 standards added zero width exponents. This required
additional special handing in the process of building formatted
floating point strings.

libgfortran/ChangeLog:

* io/write.c (select_buffer): Whitespace.
(write_real): Whitespace.
(write_real_w0): Adjust logic for d==0.
* io/write_float.def (determine_precision): Whitespace.
(build_float_string): Calculate the width of the E0 exponents.
(build_infnan_string): Whitespace.
(CALCULATE_EXP): Whitespace
(quadmath_snprintf): Whitespace.
(determine_en_precision): Whitespace.

gcc/testsuite/ChangeLog:

* gfortran.dg/pr96436_4.f90: Changed for ES0 and EN0.
* gfortran.dg/pr96436_5.f90: Changed for ES0 and EN0.
* gfortran.dg/pr111022.f90: New test.
diff --git a/gcc/testsuite/gfortran.dg/pr111022.f90 b/gcc/testsuite/gfortran.dg/pr111022.f90
new file mode 100644
index 000..d7e8edf2d19
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr111022.f90
@@ -0,0 +1,60 @@
+! { dg-do run }
+program case2
+  character(20) :: buffer
+  write(buffer,"(EN0.3E0)") .6660_4
+  if (buffer.ne."666.000E-3") stop 1
+  write(buffer,"(EN0.3E0)") 6.660_4
+  if (buffer.ne."6.660E+0") stop 2
+  write(buffer,"(EN0.3E0)") 66.60_4
+  if (buffer.ne."66.600E+0") stop 3
+  write(buffer,"(EN0.3E0)") 666.0_4
+  if (buffer.ne."666.000E+0") stop 4
+  write(buffer,"(EN0.3E0)") 6660.0_4
+  if (buffer.ne."6.660E+3") stop 5
+  write(buffer,"(EN0.3E0)") 66600.0_4
+  if (buffer.ne."66.600E+3") stop 6
+  
+  write(buffer,"(EN0.0E0)") 666.0_4
+  if (buffer.ne."666.E+0") stop 7
+  write(buffer,"(EN0.0E1)") 666.0_4
+  if (buffer.ne."666.E+0") stop 8
+  write(buffer,"(EN0.0E2)") 666.0_4
+  if (buffer.ne."666.E+00") stop 9
+  write(buffer,"(EN0.0E3)") 666.0_4
+  if (buffer.ne."666.E+000") stop 10
+  write(buffer,"(EN0.0E4)") 666.0_4
+  if (buffer.ne."666.E+") stop 11
+  write(buffer,"(EN0.0E5)") 666.0_4
+  if (buffer.ne."666.E+0") stop 12
+  write(buffer,"(EN0.0E6)") 666.0_4
+  if (buffer.ne."666.E+00") stop 13
+  
+  write(buffer,"(ES0.3E0)") .6660_4
+  if (buffer.ne."6.660E-1") stop 14
+  write(buffer,"(ES0.3E0)") 6.660_4
+  if (buffer.ne."6.660E+0") stop 15
+  write(buffer,"(ES0.3E0)") 66.60_4
+  if (buffer.ne."6.660E+1") stop 16
+  write(buffer,"(ES0.3E0)") 666.0_4
+  if (buffer.ne."6.660E+2") stop 17
+  write(buffer,"(ES0.3E0)") 6660.0_4
+  if (buffer.ne."6.660E+3") stop 18
+  write(buffer,"(ES0.3E0)") 66600.0_4
+  if (buffer.ne."6.660E+4") stop 19
+  
+  write(buffer,"(ES0.0E0)") 666.0_4
+  if (buffer.ne."7.E+2") stop 20
+  write(buffer,"(ES0.0E1)") 666.0_4
+  if (buffer.ne."7.E+2") stop 21
+  write(buffer,"(ES0.0E2)") 666.0_4
+  if (buffer.ne."7.E+02") stop 22
+  write(buffer,"(ES0.0E3)") 666.0_4
+  if (buffer.ne."7.E+002") stop 23
+  write(buffer,"(ES0.0E4)") 666.0_4
+  if (buffer.ne."7.E+0002") stop 24
+  write(buffer,"(ES0.0E5)") 666.0_4
+  if (buffer.ne."7.E+2") stop 25
+  write(buffer,"(ES0.0E6)") 666.0_4
+  if (buffer.ne."7.E+02") stop 26
+
+end program case2
diff --git a/gcc/testsuite/gfortran.dg/pr96436_4.f90 b/gcc/testsuite/gfortran.dg/pr96436_4.f90
index 335ce5fb009..7d2cfef0ef8 100644
--- a/gcc/testsuite/gfortran.dg/pr96436_4.f90
+++ b/gcc/testsuite/gfortran.dg/pr96436_4.f90
@@ -17,9 +17,9 @@ write(buffer,fmt) ">", 3.0, "<"
 if (buffer.ne.">0.30E+1<") stop 4
 fmt = "(1a1,en0.2,1a1)"
 write(buffer,fmt) ">", 3.0, "<"
-if (buffer.ne.">3.00<") stop 5
+if (buffer.ne.">3.00E+0<") stop 5
 fmt = "(1a1,es0.2,1a1)"
 write(buffer,fmt) ">", 3.0, "<"
-if (buffer.ne.">3.00<") stop 6
+if (buffer.ne.">3.00E+0<") stop 6
 end
 
diff --git a/gcc/testsuite/gfortran.dg/pr96436_5.f90 b/gcc/testsuite/gfortran.dg/pr96436_5.f90
index a45df8963c8..3870d988f97 100644
--- a/gcc/testsuite/gfortran.dg/pr96436_5.f90
+++ b/gcc/testsuite/gfortran.dg/pr96436_5.f90
@@ -17,9 +17,9 @@ write(buffer,fmt) ">", 3.0, "<"
 if (buffer.ne.">0.30E+1<") stop 4
 fmt = "(1a1,en0.2,1a1)"
 write(buffer,fmt) ">", 3.0, "<"
-if (buffer.ne.">3.00<") stop 5
+if (buffer.ne.">3.00E+0<") stop 5
 fmt = "(1a1,es0.2,1a1)"
 write(buffer,fmt) ">", 3.0, "<"
-if (buffer.ne.">3.00<") stop 6
+if (buffer.ne.">3.00E+0<") stop 6
 end
 
diff --git 

Re: [PATCH] Fortran: use name of array component in runtime error message [PR30802]

2024-01-30 Thread Mikael Morin

Le 30/01/2024 à 11:38, Mikael Morin a écrit :


Another (easier) way to clarify the data reference would be rephrasing 
the message so that the array part is separate from the scalar part, 
like so (there are too many 'of', but I lack inspiration):

Index '0' of dimension 1 of component 'zz' of element from 'x1%vv'
below lower bound of 1


This has the same number of 'of' but sounds better maybe:
Out of bounds accessing component 'zz' of element from 'x1%yy': index 
'0' of dimension 1 below lower bound of 1


Re: [PATCH] Fortran: use name of array component in runtime error message [PR30802]

2024-01-30 Thread Mikael Morin

Le 29/01/2024 à 21:50, Harald Anlauf a écrit :

Am 29.01.24 um 18:25 schrieb Harald Anlauf:

I was talking about the generated format strings of runtime error
messages.

program p
   implicit none
   type t
  real :: zzz(10) = 42
   end type t
   class(t), allocatable :: xx(:)
   integer :: j
   j = 0
   allocate (t :: xx(1))
   print *, xx(1)% zzz(j)
end

This is generating the following error at runtime since at least gcc-7:

Fortran runtime error: Index '0' of dimension 1 of array 'xx%_data%zzz'
below lower bound of 1


Of course this is easily suppressed by:

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 1e0d698a949..fa0e00a28a6 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -4054,7 +4054,8 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref *
ar, gfc_expr *expr,
  {
    if (ref->type == REF_ARRAY && >u.ar == ar)
  break;
-  if (ref->type == REF_COMPONENT)
+  if (ref->type == REF_COMPONENT
+  && strcmp (ref->u.c.component->name, "_data") != 0)
  {
    strcat (var_name, "%%");
    strcat (var_name, ref->u.c.component->name);


I have been contemplating the generation the full chain of references as
suggested by Mikael and supported by NAG.



To be clear, my suggestion was to have the question marks (or dashes, 
dots, stars, whatever) literally in the array reference, without the 
actual values of the array indexes.


Another (easier) way to clarify the data reference would be rephrasing 
the message so that the array part is separate from the scalar part, 
like so (there are too many 'of', but I lack inspiration):

Index '0' of dimension 1 of component 'zz' of element from 'x1%vv'
below lower bound of 1



The main issue is: how do I easily generate that call?



gfc_trans_runtime_check is a vararg function, but what I would rather
have is a function that takes either a (chained?) list of trees or
an array of trees holding the (co-)indices of the reference.

Is there an example, or a recommendation which variant to prefer?


None that I know.
For a scalarized expression, the values are present (among others) in 
the gfc_loopinfo::ss linked list, maybe just use that?
In any case, I agree it would be nice to have, but it would probably be 
a non-negligible amount of new error-prone code; I would rather not 
attempt this during the stage4 stabilization phase as we are currently.