PR123012 Namelist input of variable accessed by use association with renaming fails

Message ID 4b17feb3-0f45-46ec-b9b6-c83b8be7202d@gmail.com
State New
Headers
Series PR123012 Namelist input of variable accessed by use association with renaming fails |

Commit Message

Jerry D Jan. 7, 2026, 11:52 p.m. UTC
  Planning to commit this soon.

Patch developed by Steve. I did one fix-up after reading that
giving strlen a NULL pointer can be undefined on some systems.

Regression tested on x86_64-linux-gnu.

Thanks Steve.

Regards all,

Jerry

$ git show
commit 2df097c4934ac47eadbd8b9b5d23e7bec8bb1049 (HEAD -> master)
Author: Steve Kargl <kargl@gcc.gnu.org>
Date:   Wed Jan 7 15:14:23 2026 -0800

     Fortran: Fix namelist with use association and renaming

             PR fortran/123012

     gcc/fortran/ChangeLog:

             * trans-io.cc (transfer_namelist_element): Adjust the
             conditions determining when to use the local name or
             the var name to build the object name.

     gcc/testsuite/ChangeLog:

             * gfortran.dg/namelist_99.f90: New test.
  

Comments

Jerry D Jan. 8, 2026, 1:48 a.m. UTC | #1
I put the wrong PR on it, it should have been 123321,

Sorry about that.

On 1/7/26 3:52 PM, Jerry D wrote:
> Planning to commit this soon.
> 
> Patch developed by Steve. I did one fix-up after reading that
> giving strlen a NULL pointer can be undefined on some systems.
> 
> Regression tested on x86_64-linux-gnu.
> 
> Thanks Steve.
> 
> Regards all,
> 
> Jerry
> 
> $ git show
> commit 2df097c4934ac47eadbd8b9b5d23e7bec8bb1049 (HEAD -> master)
> Author: Steve Kargl <kargl@gcc.gnu.org>
> Date:   Wed Jan 7 15:14:23 2026 -0800
> 
>      Fortran: Fix namelist with use association and renaming
> 
>              PR fortran/123012
> 
>      gcc/fortran/ChangeLog:
> 
>              * trans-io.cc (transfer_namelist_element): Adjust the
>              conditions determining when to use the local name or
>              the var name to build the object name.
> 
>      gcc/testsuite/ChangeLog:
> 
>              * gfortran.dg/namelist_99.f90: New test.
>
  
Steve Kargl Jan. 8, 2026, 3:10 a.m. UTC | #2
On Wed, Jan 07, 2026 at 03:52:33PM -0800, Jerry D wrote:
>    /* Build the namelist object name.  */
> -  if (sym && !sym->attr.use_only && sym->attr.use_rename
> -      && sym->ns->use_stmts->rename)
> +  if (sym && sym->attr.use_rename && sym->ns->use_stmts->rename
> +      && sym->ns->use_stmts->rename->local_name
> +      && sym->ns->use_stmts->rename->local_name[0]
> +      && strcmp(sym->ns->use_stmts->rename->use_name, var_name) == 0)
>      string = gfc_build_cstring_const (sym->ns->use_stmts->rename->local_name);

This breaks on FreeBSD.  sym->ns->use_stmts->rename->local_name
is not a pointer.  local_name is a component of a gfc_use_rename
struct with a fixed size.  The strlen() I had in the code was
correct.


typedef struct gfc_use_rename
{
  char local_name[GFC_MAX_SYMBOL_LEN + 1], use_name[GFC_MAX_SYMBOL_LEN + 1];
  struct gfc_use_rename *next;
  int found;
  gfc_intrinsic_op op;
  locus where;
}
gfc_use_rename;


This combination

gfortran.h:#define gfc_get_use_rename() XCNEW (gfc_use_rename);
./include/libiberty.h:#define XCNEW(T)          ((T *) xcalloc (1, sizeof (T)))

should give a NULL terminated string when sym->...->rename is
alocated, and that string will have a zero length of 0 if it
is not set.
  
Jerry D Jan. 8, 2026, 4:45 a.m. UTC | #3
On 1/7/26 7:10 PM, Steve Kargl wrote:
> On Wed, Jan 07, 2026 at 03:52:33PM -0800, Jerry D wrote:
>>     /* Build the namelist object name.  */
>> -  if (sym && !sym->attr.use_only && sym->attr.use_rename
>> -      && sym->ns->use_stmts->rename)
>> +  if (sym && sym->attr.use_rename && sym->ns->use_stmts->rename
>> +      && sym->ns->use_stmts->rename->local_name
>> +      && sym->ns->use_stmts->rename->local_name[0]
>> +      && strcmp(sym->ns->use_stmts->rename->use_name, var_name) == 0)
>>       string = gfc_build_cstring_const (sym->ns->use_stmts->rename->local_name);
> 
> This breaks on FreeBSD.  sym->ns->use_stmts->rename->local_name
> is not a pointer.  local_name is a component of a gfc_use_rename
> struct with a fixed size.  The strlen() I had in the code was
> correct.
> 
OK Steve, my apologies, I did not understand. These little nuances between 
systems are getting us in several ways.

I will adjust it back to what you had and push it.

Regards,

Jerry
  

Patch

commit 2df097c4934ac47eadbd8b9b5d23e7bec8bb1049
Author: Steve Kargl <kargl@gcc.gnu.org>
Date:   Wed Jan 7 15:14:23 2026 -0800

    Fortran: Fix namelist with use association and renaming
    
            PR fortran/123012
    
    gcc/fortran/ChangeLog:
    
            * trans-io.cc (transfer_namelist_element): Adjust the
            conditions determining when to use the local name or
            the var name to build the object name.
    
    gcc/testsuite/ChangeLog:
    
            * gfortran.dg/namelist_99.f90: New test.

diff --git a/gcc/fortran/trans-io.cc b/gcc/fortran/trans-io.cc
index 2ed256ef30b..2d799b12972 100644
--- a/gcc/fortran/trans-io.cc
+++ b/gcc/fortran/trans-io.cc
@@ -1698,8 +1698,10 @@  transfer_namelist_element (stmtblock_t * block, const char * var_name,
   gcc_assert (sym || c);
 
   /* Build the namelist object name.  */
-  if (sym && !sym->attr.use_only && sym->attr.use_rename
-      && sym->ns->use_stmts->rename)
+  if (sym && sym->attr.use_rename && sym->ns->use_stmts->rename
+      && sym->ns->use_stmts->rename->local_name
+      && sym->ns->use_stmts->rename->local_name[0]
+      && strcmp(sym->ns->use_stmts->rename->use_name, var_name) == 0)
     string = gfc_build_cstring_const (sym->ns->use_stmts->rename->local_name);
   else
     string = gfc_build_cstring_const (var_name);
diff --git a/gcc/testsuite/gfortran.dg/namelist_99.f90 b/gcc/testsuite/gfortran.dg/namelist_99.f90
new file mode 100644
index 00000000000..9be12732a8a
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/namelist_99.f90
@@ -0,0 +1,46 @@ 
+! { dg-do run }
+module m
+   implicit none
+   private
+   public tol, z
+   integer :: tol = 42
+   integer :: z = 42
+end module m
+
+subroutine no_only_clause
+   use m
+   implicit none
+   character(len=20) :: str = "&v z=1 tol=1/"
+   namelist /v/ tol, z
+   read(str, nml=v)
+   if (z /= 1) stop 3
+   if (tol /= 1) stop 4
+end subroutine no_only_clause
+
+subroutine only_clause_without_renaming
+   use m, only : tol, z
+   implicit none
+   character(len=20) :: str = "&v z=1 tol=1/"
+   namelist /v/ z, tol
+   read(str, nml=v)
+   if (z /= 1) stop 3
+   if (tol /= 1) stop 4
+end subroutine only_clause_without_renaming
+
+subroutine only_clause_with_renaming
+   use m, only: y => tol, z
+   implicit none
+   character(len=20) :: str = "&v z=1 y=1/"
+   real :: tol = 0
+   namelist /v/ y, z
+   read(str, nml=v)
+   if (z /= 1) stop 3
+   if (y /= 1) stop 4
+   if (tol /= 0) stop 5
+end subroutine only_clause_with_renaming
+
+program p
+   call no_only_clause
+   call only_clause_without_renaming
+   call only_clause_with_renaming
+end program p