Re: [PATCH] Fortran: fix two minor front-end GMP memleaks

2024-12-09 Thread Harald Anlauf

Thanks, Jerry!

Pushed as r15-6053.

Am 08.12.24 um 23:57 schrieb Jerry Delisle:

Looks good, OK to push.

On Sun, Dec 8, 2024, 1:39 PM Harald Anlauf  wrote:


Dear all,

while looking at testcases with inquiry refs, I encountered two minor
GMP memleaks due to double-initialization of GMP variables.  Easily
plugged by the attached patch.

Regtested on x86_64-pc-linux-gnu.

I intend to commit as obvious within 24h unless there are objections.

Thanks,
Harald








[patch, libgfortran] Bug 117819 - Formatted READ with BZ in format fails

2024-12-09 Thread Jerry D

Hi all,

The attached patch fixes this bug by checking for the case of a short 
READ that should be padded with blanks and if the BZ mode is enabled, 
those blanks should be treated as trailing zero's.


New test case courtesy Malcom Cohen.

Regression tested on X86_64_linux_gnu.

OK for trunk and backport to 14 in a few days.

uthor: Jerry DeLisle 
Date:   Mon Dec 9 20:11:23 2024 -0800

Fortran: Fix READ with padding in BLANK ZERO mode.

PR fortran/117819

libgfortran/ChangeLog:

* io/read.c (read_decimal): If the read value is short of the
specified width and pad mode is PAD yes, check for BLANK ZERO
and adjust the value accordingly.
(read_decimal_unsigned): Likewise.
(read_radix): Likewise.

gcc/testsuite/ChangeLog:

* gfortran.dg/pr117819.f90: New test.
diff --git a/gcc/testsuite/gfortran.dg/pr117819.f90 b/gcc/testsuite/gfortran.dg/pr117819.f90
new file mode 100644
index 000..d9a9b7f6f9b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr117819.f90
@@ -0,0 +1,45 @@
+! { dg-do run }
+! PR117819 
+Program xe1
+  Implicit None
+  Character(6) string
+  Integer x
+  Logical :: ok = .True.
+  string = '11'
+  !print *, "String we read from is: ", string
+  Read(string,1) x
+1 Format(BZ,B8)
+  If (x/=Int(b'1100')) Then
+Print *,'FAIL B8 BZ wrong result'
+Print *,'Expected',Int(b'1100')
+Print *,'Received',x
+ok = .False.
+  End If
+  string = '123456'
+  !print *, "String we read from is: ", string
+  Read(string,2) x
+2 Format(BZ,I8)
+  If (x/=12345600) Then
+Print *,'FAIL I8 BZ wrong result'
+Print *,'Expected',12345600
+Print *,'Received',x
+ok = .False.
+  End If
+  Read(string,3) x
+3 Format(BZ,O8)
+  If (x/=Int(o'12345600')) Then
+Print *,'FAIL O8 BZ wrong result'
+Print *,'Expected',Int(o'12345600')
+Print *,'Received',x
+ok = .False.
+  End If
+  Read(string,4) x
+4 Format(BZ,Z8)
+  If (x/=Int(z'12345600')) Then
+Print *,'FAIL OZ BZ wrong result'
+Print *,'Expected',Int(z'12345600')
+Print *,'Received',x
+ok = .False.
+  End If
+  If (.not. ok) stop 1
+End Program
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c
index aa866bf31da..46413ade001 100644
--- a/libgfortran/io/read.c
+++ b/libgfortran/io/read.c
@@ -753,11 +753,11 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
 {
   GFC_UINTEGER_LARGEST value, maxv, maxv_10;
   GFC_INTEGER_LARGEST v;
-  size_t w;
+  size_t w, padding;
   int negative;
   char c, *p;
 
-  w = f->u.w;
+  w = padding = f->u.w;
 
   /* This is a legacy extension, and the frontend will only allow such cases
* through when -fdec-format-defaults is passed.
@@ -770,6 +770,10 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
   if (p == NULL)
 return;
 
+  /* If the read was not the full width we may need to pad with blanks or zeros
+   * depending on the PAD mode.  Save the number of pad characters needed.  */
+  padding -= w;
+
   p = eat_leading_spaces (&w, p);
   if (w == 0)
 {
@@ -807,7 +811,14 @@ read_decimal (st_parameter_dt *dtp, const fnode *f, char *dest, int length)
 {
   c = next_char (dtp, &p, &w);
   if (c == '\0')
-	break;
+	{
+	  if (dtp->u.p.blank_status == BLANK_ZERO)
+	{
+	  for (size_t n = 0; n < padding; n++)
+		value = 10 * value;
+	}
+	  break;
+	}
 
   if (c == ' ')
 {
@@ -864,11 +875,11 @@ read_decimal_unsigned (st_parameter_dt *dtp, const fnode *f, char *dest,
 		   int length)
 {
   GFC_UINTEGER_LARGEST value, old_value;
-  size_t w;
+  size_t w, padding;
   int negative;
   char c, *p;
 
-  w = f->u.w;
+  w = padding = f->u.w;
 
   /* This is a legacy extension, and the frontend will only allow such cases
* through when -fdec-format-defaults is passed.
@@ -881,6 +892,10 @@ read_decimal_unsigned (st_parameter_dt *dtp, const fnode *f, char *dest,
   if (p == NULL)
 return;
 
+  /* If the read was not the full width we may need to pad with blanks or zeros
+   * depending on the PAD mode.  Save the number of pad characters needed.  */
+  padding -= w;
+
   p = eat_leading_spaces (&w, p);
   if (w == 0)
 {
@@ -917,7 +932,14 @@ read_decimal_unsigned (st_parameter_dt *dtp, const fnode *f, char *dest,
 {
   c = next_char (dtp, &p, &w);
   if (c == '\0')
-	break;
+	{
+	  if (dtp->u.p.blank_status == BLANK_ZERO)
+	{
+	  for (size_t n = 0; n < padding; n++)
+		value = 10 * value;
+	}
+	  break;
+	}
 
   if (c == ' ')
 	{
@@ -981,17 +1003,21 @@ read_radix (st_parameter_dt *dtp, const fnode *f, char *dest, int length,
 {
   GFC_UINTEGER_LARGEST value, maxv, maxv_r;
   GFC_INTEGER_LARGEST v;
-  size_t w;
+  size_t w, padding;
   int negative;
   char c, *p;
 
-  w = f->u.w;
+  w = padding = f->u.w;
 
   p = read_block_form (dtp, &w);
 
   if (p == NULL)
 return;
 
+  /* If the read was not the full width we may need to pad with blanks or zeros
+   * depending on the PAD mode.  Save the 

insight needed on trans-* hacking

2024-12-09 Thread Steve Kargl
All,

I've an almost complete implementation of F_C_STRING,
but need a bit of insight on the inlining that I'm
trying to implement.  In pseudo-code, F_C_STRING is

case 1.  f_c_string(string)   = trim(string) // c_null_char
case 2.  f_c_string(string, asis=.false.) = trim(string) // c_null_char
case 3.  f_c_string(string, asis=.true.)  = string   // c_null_char

In trans-intrinsic.cc(conv_isocbinding_function), my current
implementation has

if (asis) /* asis is present. */
  {
case 3 
  }
else
  {
case 1
  }

Where I need a bit of a nudge is the actual evaluation of 'asis'
and how to write the gimple stuff, i.e., this part becomes

if (asis) /* asis is present. */
  {
   if (asis == .true.)
 case 2  
   else
 case 3
  }
else
  {
 case 1
  }

-- 
Steve