Hi folks,

This patch combines Tobias front-end patch with my libgfortran patch to resolve
this PR.

To denote extended derived types (classes) we use a '+' rather than '%' in
certain parts of the namelist name internally to identify that an extended type
is being dealt with.  The runtime is modified to look for this '+' and when it
is seen, scan ahead for the varname match.

For inherited types, a match could be found in two different ways.

parent%cousin%child

parent%child

This would be internally represented as:

parent+cousin%child

So the '+' sign is used to signal that we have to do a special matching check
for both possible cases depending on how the user chose to represent it, usually
as the shorter version of the name.

Admittedly, I do not have very many examples of code that use this feature yet.

Regression tested on x86-64.  Test case attached with patch.

OK for trunk?

Regards,

Jerry

2014-05-24  Tobias Burnus  <bur...@net-b.de>

        PR fortran/55117
        * trans-io.c (nml_full_name, transfer_namelist_element): Insert
        a '+' rather then '%' to differentiate namelist variable names
        that are based on extended derived types.
        
2014-05-24  Jerry DeLisle  <jvdeli...@gcc.gnu.org>

        PR libgfortran/55117
        * io/list_read.c (extended_look_ahead): New helper function to
        scan the namelist name and look for matches with the new '+'
        extended type parent indicator.  (str_comp_extended): New
        helper function to compare the namelist name with the varname
        namelist. (find_nml_name): Use the new helper functions to match
        the extended type varnames.

Index: gcc/fortran/trans-io.c
===================================================================
--- gcc/fortran/trans-io.c	(revision 210573)
+++ gcc/fortran/trans-io.c	(working copy)
@@ -1452,10 +1452,10 @@ gfc_trans_wait (gfc_code * code)
 
 
 /* nml_full_name builds up the fully qualified name of a
-   derived type component.  */
+   derived type component. '+' is used to denote a type extension.  */
 
 static char*
-nml_full_name (const char* var_name, const char* cmp_name)
+nml_full_name (const char* var_name, const char* cmp_name, bool parent)
 {
   int full_name_length;
   char * full_name;
@@ -1463,7 +1463,7 @@ static char*
   full_name_length = strlen (var_name) + strlen (cmp_name) + 1;
   full_name = XCNEWVEC (char, full_name_length + 1);
   strcpy (full_name, var_name);
-  full_name = strcat (full_name, "%");
+  full_name = strcat (full_name, parent ? "+" : "%");
   full_name = strcat (full_name, cmp_name);
   return full_name;
 }
@@ -1634,7 +1634,8 @@ transfer_namelist_element (stmtblock_t * block, co
 
       for (cmp = ts->u.derived->components; cmp; cmp = cmp->next)
 	{
-	  char *full_name = nml_full_name (var_name, cmp->name);
+	  char *full_name = nml_full_name (var_name, cmp->name,
+					   ts->u.derived->attr.extension);
 	  transfer_namelist_element (block,
 				     full_name,
 				     NULL, cmp, expr);
Index: libgfortran/io/list_read.c
===================================================================
--- libgfortran/io/list_read.c	(revision 210898)
+++ libgfortran/io/list_read.c	(working copy)
@@ -2557,6 +2557,38 @@ err_ret:
   return false;
 }
 
+
+static bool
+extended_look_ahead (char *p, char *q)
+{
+  char *r, *s;
+
+  /* Scan ahead to find a '%' in the p string.  */
+  for(r = p, s = q; *r && *s; s++)
+    if ((*s == '%' || *s == '+') && strcmp (r + 1, s + 1) == 0)
+      return true;
+  return false;
+}
+
+
+static bool
+strcmp_extended_type (char *p, char *q)
+{
+  char *r, *s;
+  
+  for (r = p, s = q; *r && *s; r++, s++)
+    {
+      if (*r != *s)
+	{
+	  if (*r == '%' && *s == '+' && extended_look_ahead (r, s))
+	    return true;
+	  break;
+	}
+    }
+  return false;
+}
+
+
 static namelist_info *
 find_nml_node (st_parameter_dt *dtp, char * var_name)
 {
@@ -2568,6 +2600,11 @@ find_nml_node (st_parameter_dt *dtp, char * var_na
 	  t->touched = 1;
 	  return t;
 	}
+      if (strcmp_extended_type (var_name, t->var_name))
+	{
+	  t->touched = 1;
+	  return t;
+	}
       t = t->next;
     }
   return NULL;
! { dg-do run }
! PR55117  Programs fails namelist read (contains derived types objects)
program test_type_extension

  type tk_t
     real :: x
  end type tk_t

  type, extends(tk_t) :: tke_t
     character(8) :: string
  end type tke_t

  type, extends(tke_t) :: deep
    integer :: int1
    real :: y
    character(10) :: the_name
  end type deep

  type other
    integer :: one_oh
    integer :: two_oh
  end type other

  type plain_type
    integer :: var1
    type(other) :: var2
    real :: var3
  end type plain_type

  type some_other
    complex :: varx
    type(tke_t) :: tke
    type (plain_type) :: varpy
    real  :: vary
  end type some_other

  type(deep) :: trouble
  type(some_other) :: somethinelse
  type(tke_t) :: tke
  integer :: answer
  
  namelist /test_NML/ trouble, somethinelse, tke, answer

  tke%x = 0.0
  tke%string = "xxxxxxxx"
  answer = 5
  trouble%x = 5.34
  trouble%y = 4.25
  trouble%string = "yyyy"
  trouble%the_name = "mischief"

  open(unit=10,file='good.inp')
  read(10,NML=test_NML)
  if (tke%x - 3.14000010 > .00001) call abort
  if (tke%string /= "kf7rcc") call abort
  if (answer /= 42) call abort ! hitchkikers guide to the galaxy
end program test_type_extension

Reply via email to