Bug 55117 - Programs fails to read namelist (contains derived types objects)
Summary: Programs fails to read namelist (contains derived types objects)
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.6.1
: P3 normal
Target Milestone: ---
Assignee: Jerry DeLisle
URL:
Keywords: wrong-code
Depends on:
Blocks: 56744
  Show dependency treegraph
 
Reported: 2012-10-29 14:31 UTC by pmarguinaud
Modified: 2014-06-07 17:43 UTC (History)
6 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-06-16 00:00:00


Attachments
Source code (314 bytes, text/x-fortran)
2012-10-29 14:31 UTC, pmarguinaud
Details
Namelist (109 bytes, text/plain)
2012-10-29 14:32 UTC, pmarguinaud
Details
Namelist patch (652 bytes, text/diff)
2013-02-25 01:00 UTC, Tilo Schwarz
Details
FE patch for namelist read with type extension (+ test case) (941 bytes, text/plain)
2013-04-25 12:42 UTC, Tobias Burnus
Details

Note You need to log in before you can comment on or make changes to this bug.
Description pmarguinaud 2012-10-29 14:31:25 UTC
Created attachment 28553 [details]
Source code
Comment 1 pmarguinaud 2012-10-29 14:32:32 UTC
Created attachment 28554 [details]
Namelist
Comment 2 pmarguinaud 2012-10-29 14:34:02 UTC
$ gfortran bat.F90
$ ./a.out
At line 33 of file bat.F90 (unit = 4, file = 'NAMELIST')
Fortran runtime error: Internal namelist read error

I tried 4.6.1, 4.6.2 and latest snapshot of 4.7. All the same.
Comment 3 janus 2012-10-29 16:03:22 UTC
I can confirm that I see the error with 4.3, 4.7 and trunk.

Slightly reduced test case:

***************************

IMPLICIT NONE

TYPE TC
  INTEGER :: E
END TYPE

TYPE TB
  TYPE(TC) :: C
  INTEGER :: D
END TYPE

INTEGER  :: A
TYPE(TB) :: B(1:10)

NAMELIST /N/ A, B

OPEN (4,FILE='NAMELIST')
READ (4,NML=N)

END 

***************************

&N
  A=12,
  B(1)%D=4
/

***************************

What's funny is that the error e.g. depends on the presence of the component 'C', although it is not referenced in the namelist at all. Furthermore the error only occurs if 'A' is also in the namelist.
Comment 4 Tobias Burnus 2012-10-31 19:53:22 UTC
Related to bugs: PR 49791 and PR 51825?
Comment 5 Walter Spector 2013-01-04 02:54:05 UTC
Adding myself to the CC list.

Walter Spector
Comment 6 Walter Spector 2013-01-04 14:33:15 UTC
Another manifestation of this problem is with type extension.  Here is another small example which fails.  (Tested on v4.6.3 and also a 1/4/2013 snapshot of the 4.8 trunk.):

program test_type_extension

  type t1_t
     real :: x
  end type t1_t

  type, extends(t1_t) :: t1e_t
     character(8) :: string
  end type t1e_t

  type(t1e_t) :: t1e

  integer :: answer
  namelist /test_NML/ t1e, answer

  open(unit=1,file='test1.inp')
  read(1,NML=test_NML)

  write(*,*) t1e%x, t1e%string, answer

end program test_type_extension

File test1.inp contains:

&test_NML
t1e%x = 2.,t1e%string='gfortran',answer=42
/

wws@w6ws-4:~/fortran/xxx$ gfortran --version
GNU Fortran (GCC) 4.8.0 20130104 (experimental)
Copyright (C) 2013 Free Software Foundation, Inc.

GNU Fortran comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of GNU Fortran
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING

wws@w6ws-4:~/fortran/xxx$ gfortran namelist.f90
wws@w6ws-4:~/fortran/xxx$ a.out
At line 17 of file namelist.f90 (unit = 1, file = 'test1.inp')
Fortran runtime error: Cannot match namelist object name %x

Backtrace for this error:
  + in the main program
    from file namelist.f90
  + /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed) [0x7ffe80c5376d]
wws@w6ws-4:~/fortran/xxx$

The NAG Fortran compiler has no problems with this test case.  (Intel and PGI are not so lucky.  :) )
Comment 7 kargls 2013-01-04 16:58:36 UTC
(In reply to comment #6)
> Another manifestation of this problem is with type extension.  Here is another
> small example which fails.  (Tested on v4.6.3 and also a 1/4/2013 snapshot of
> the 4.8 trunk.):
> 
> program test_type_extension
> 
>   type t1_t
>      real :: x
>   end type t1_t
> 
>   type, extends(t1_t) :: t1e_t
>      character(8) :: string
>   end type t1e_t
> 
>   type(t1e_t) :: t1e
> 
>   integer :: answer
>   namelist /test_NML/ t1e, answer
> 
>   open(unit=1,file='test1.inp')
>   read(1,NML=test_NML)
> 
>   write(*,*) t1e%x, t1e%string, answer
> 
> end program test_type_extension
> 
> File test1.inp contains:
> 
> &test_NML
> t1e%x = 2.,t1e%string='gfortran',answer=42
> /
> 
> wws@w6ws-4:~/fortran/xxx$ gfortran namelist.f90
> wws@w6ws-4:~/fortran/xxx$ a.out
> At line 17 of file namelist.f90 (unit = 1, file = 'test1.inp')
> Fortran runtime error: Cannot match namelist object name %x

If one modifies your code to have gfortran create the file 
with the namelist, it can then read it back.  Here's what I
have
program test_type_extension

  type t1_t
     real :: x
  end type t1_t

  type, extends(t1_t) :: t1e_t
     character(8) :: string
  end type t1e_t

  type(t1e_t) :: t1e

  integer :: answer
  namelist /test_NML/ t1e, answer

  t1e%x = 2.
  t1e%string='gfortran'
  answer=42

  open(unit=2,file='test2.inp')
  write(2,NML=test_NML)
  close(2)

  t1e%x = 0
  t1e%string=''
  answer=0

  open(unit=2,file='test2.inp')
  read(2,NML=test_NML)
  close(2)

  write(*,*) t1e%x, t1e%string, answer

  open(unit=1,file='test1.inp')
  read(1,NML=test_NML)

  write(*,*) t1e%x, t1e%string, answer

end program test_type_extension

% gfc4x -o z foo.f90 && ./z
   2.00000000     gfortran          42
At line 36 of file foo.f90 (unit = 1, file = 'test1.inp')
Fortran runtime error: Cannot match namelist object name %x

% cat test2.inp 
&TEST_NML
 T1E%T1_T%X=  2.00000000    ,
 T1E%STRING="gfortran",
 ANSWER=         42,
 /

It appears that gfortran's handling of an extended
derived type in its namelist code is incorrect.
Comment 8 Walter Spector 2013-01-04 17:22:31 UTC
Good point.  The key is:

>  T1E%T1_T%X=  2.00000000    ,

If the full expanded version is used, in other words %T1_T is specified, the example works.  (On Intel too.)
Comment 9 Jerry DeLisle 2013-01-05 19:15:33 UTC
I am actively working on these bugs right now so will assign to myself.  Our namelist code here is tricky to say the least and i am seeing odd behavior that looks like some pointers are not getting set or reset correctly.  If I get to a patch, I will post here.
Comment 10 Jerry DeLisle 2013-01-06 18:51:07 UTC
This bug appears to be unrelated to the other two namelist bugs.  It is related to not seeing the ending '/' marker.  I have more testing to go before submitting a patch.  The initial fix is to catch it in the do loop inside list_read.c at about line 2812.  I still need to confirm if the reads are actually correct.
Comment 11 Tilo Schwarz 2013-02-22 20:57:50 UTC
Hi,

I ran into this today and tried to produce a small test case from my big namelist problem.


program namelist

type d1
    integer :: j = 0
end type d1

type d2
    type(d1) k
end type d2

type d3
    type(d2) d(2)
end type d3

type(d3) der
namelist /nmlst/ der

read (*, nml = nmlst)
print nmlst

end program namelist


Running above program on all two line combinations of the namelist gives different errors using
4.7.2 and
gcc version 4.8.0 20130222 (experimental) (GCC)
(Details below).


Observations:

- If type d3 uses 'type(d1) d(2)' instead of 'type(d2) d(2)', the problem goes away.
- If the trailing %J is removed in the namelist, the problem goes away.
- If two separate members are used instead of the array 'type(d2) d(2)', the problem goes away.


Details of namelist variations:

% cat namelist.txt; echo -------; prg_namelist_bug < namelist.txt
&NMLST
 /
-------
&NMLST
 DER%D(1)%K%J=          0,
 DER%D(2)%K%J=          0,
 /


% cat namelist.txt; echo -------; prg_namelist_bug < namelist.txt
&NMLST
 DER%D(1)%K%J = 1,
 /
-------
&NMLST
 DER%D(1)%K%J=          1,
 DER%D(2)%K%J=          0,
 /


% cat namelist.txt; echo -------; prg_namelist_bug < namelist.txt
&NMLST
 DER%D(2)%K%J = 2,
 /
-------
&NMLST
 DER%D(1)%K%J=          2,
 DER%D(2)%K%J=          0,
 /


% cat namelist.txt; echo -------; prg_namelist_bug < namelist.txt
&NMLST
 DER%D(1)%K%J = 1,
 DER%D(2)%K%J = 2,
 /
-------
&NMLST
 DER%D(1)%K%J=          2,
 DER%D(2)%K%J=          0,
 /


% cat namelist.txt; echo -------; prg_namelist_bug < namelist.txt
&NMLST
 DER%D(2)%K%J = 2,
 DER%D(1)%K%J = 1,
 /
-------
&NMLST
 DER%D(1)%K%J=          1,
 DER%D(2)%K%J=          0,
 /


If the last component %J is removed in the namelist,
the problem goes away:

% cat namelist.txt; echo -------; prg_namelist_bug < namelist.txt
&NMLST
 DER%D(1)%K = 1,
 /
-------
&NMLST
 DER%D(1)%K%J=          1,
 DER%D(2)%K%J=          0,
 /


% cat namelist.txt; echo -------; prg_namelist_bug < namelist.txt
&NMLST
 DER%D(2)%K = 2,
 /
-------
&NMLST
 DER%D(1)%K%J=          0,
 DER%D(2)%K%J=          2,
 /


% cat namelist.txt; echo -------; prg_namelist_bug < namelist.txt
&NMLST
 DER%D(1)%K = 1,
 DER%D(2)%K = 2,
 /
-------
&NMLST
 DER%D(1)%K%J=          1,
 DER%D(2)%K%J=          2,
 /


% cat namelist.txt; echo -------; prg_namelist_bug < namelist.txt
&NMLST
 DER%D(2)%K = 2,
 DER%D(1)%K = 1,
 /
-------
&NMLST
 DER%D(1)%K%J=          1,
 DER%D(2)%K%J=          2,
 /


Regards,
Tilo
Comment 12 Tilo Schwarz 2013-02-22 22:40:11 UTC
(In reply to comment #11)

> Running above program on all two line combinations of the namelist gives
> different errors using
> 4.7.2 and
> gcc version 4.8.0 20130222 (experimental) (GCC)
> (Details below).

What I meant here was, that the namelist variations give different errors, not that 4.7.2 and 4.8.0 give different errors.

Tilo
Comment 13 Tilo Schwarz 2013-02-24 00:27:49 UTC
If in

gfortran.dg/namelist_64.f90

instead of 

    curve(1)%symbol%typee = 1234

any other array index > 1 is set and tested, e.g.

    curve(2)%symbol%typee = 1234

the testcase breaks.
Comment 14 Tilo Schwarz 2013-02-25 01:00:01 UTC
Created attachment 29532 [details]
Namelist patch
Comment 15 Tilo Schwarz 2013-02-25 01:02:45 UTC
This week I used the Fortran namelist feature for the first time and I was really impressed, that it does all the parsing for me.

But since I ran into this issue I was wondering and curious how the magic in libgfortran works.

I had a look at the code and could observe the following:

If I apply the attached patch (comment 14, namelist.diff) on gcc version 4.8.0 20130224

- my example from comment 11 works
- the example from comment 3 seems to work
- the changed namelist_64.f90 from comment 13 works
- the example from PR 51825 seems to work
- make check-fortran runs with no additional errors
- the example from comment 6 (type extension) does not work

The type extension problem might be related to the fact, that gfortran does not generate a namelist entry for the implicit component %x of t1e_t:

(no "t1e%x" below)
  
  _gfortran_st_set_nml_var (&dt_parm.1, &t1e, &"t1e"[1]{lb: 1 sz: 1}, 0, 0, 40);
  ... maybe "t1e%x" should be here? ...
  _gfortran_st_set_nml_var (&dt_parm.1, &t1e.t1_t, &"t1e%t1_t"[1]{lb: 1 sz: 1}, 0, 0, 40);
  _gfortran_st_set_nml_var (&dt_parm.1, &t1e.t1_t.x, &"t1e%t1_t%x"[1]{lb: 1 sz: 1}, 4, 0, 24);
  _gfortran_st_set_nml_var (&dt_parm.1, &t1e.string, &"t1e%string"[1]{lb: 1 sz: 1}, 1, 8, 48);
  _gfortran_st_set_nml_var (&dt_parm.1, &answer, &"answer"[1]{lb: 1 sz: 1}, 4, 0, 8);

So maybe this patch gives a hint to someone, who has a deeper understanding of the io-stuff than me (looked at it this weekend for the first time) ...

Tilo
Comment 16 Tilo Schwarz 2013-02-25 19:01:50 UTC
(In reply to comment #14)
> Created attachment 29532 [details]
> Namelist patch

Bummer, I had a typo in the comment:

The second hunk should read

"/* Don't move first_nl" instead of
"/* Don't move pprev_nl": 

@@ -2901,7 +2901,8 @@ get_name:
          goto nml_err_ret;
        }
 
-      if (*pprev_nl == NULL || !component_flag)
+      /* Don't move first_nl further in the list if a qualifier was found */
+      if ((*pprev_nl == NULL && !qualifier_flag) || !component_flag)
        first_nl = nl;


Sorry,
Tilo
Comment 17 Mikael Morin 2013-02-25 19:49:06 UTC
(In reply to comment #15)
> The type extension problem might be related to the fact, that gfortran does not
> generate a namelist entry for the implicit component %x of t1e_t:
> 
> (no "t1e%x" below)
> 
It is present...

>   _gfortran_st_set_nml_var (&dt_parm.1, &t1e.t1_t.x, &"t1e%t1_t%x"[1]{lb: 1 sz:
> 1}, 4, 0, 24);
>
... here.
Comment 18 Tilo Schwarz 2013-02-25 20:28:40 UTC
(In reply to comment #17)
> (In reply to comment #15)
> > The type extension problem might be related to the fact, that gfortran does not
> > generate a namelist entry for the implicit component %x of t1e_t:
> > 
> > (no "t1e%x" below)
> > 
> It is present...
> 
> >   _gfortran_st_set_nml_var (&dt_parm.1, &t1e.t1_t.x, &"t1e%t1_t%x"[1]{lb: 1 sz:
> > 1}, 4, 0, 24);
> >
> ... here.

Yes, somehow - but the code in list_read.c:find_nml_node() (as it is right now) searches for the exact string "t1e%x", not for "t1e%t1_t%x".

I have no idea what is simpler:

- modify the code in list_read.c to somehow also search "t1e%t1_t%x", not only "t1e%x". Maybe one could teach the code to conclude from the to namelist entries
  _gfortran_st_set_nml_var (&dt_parm.1, &t1e.t1_t, &"t1e%t1_t"... 
  _gfortran_st_set_nml_var (&dt_parm.1, &t1e.t1_t.x, &"t1e%t1_t%x"
that "t1e%x" is also valid a synonym of "t1e%t1_t%x".

or
- generate a line like
  _gfortran_st_set_nml_var (&dt_parm.1, &t1e.t1_t.x, &"t1e%x" ...
Comment 19 Tobias Burnus 2013-03-22 10:09:34 UTC
The issue of the original bug report in comment 0 - and the test cases comment 3 and comment 13 seem to be fixed by the patch for PR 51825 (see PR 51825
 comment 5).

Remaining seems to be the separate issue of type extension, where the parent's component is directly accessed without using the parent's name as in-between component name. See comment 6.
Comment 20 Jerry DeLisle 2013-03-30 03:54:27 UTC
Lets take namelist out of the picture here for the case of comment #6

program test_type_extension

  type t1_t
     real :: x
  end type t1_t

  type, extends(t1_t) :: t1e_t
     character(8) :: string
  end type t1e_t

  type(t1e_t) :: t1e

  tle%x = 5.678

end program test_type_extension

$ gfc pr55117.f90 
pr55117.f90:13.6:

  tle%x = 5.678
      1
Error: Symbol 'tle' at (1) has no IMPLICIT type

Ifort agrees with gfortran on this example

So, I think this PR (55117) can be closed and if the example in this comment and #6 is another bug, lets open a new PR for it.
Comment 21 Jerry DeLisle 2013-03-30 05:05:03 UTC
Oops! Disregard Comment #20. There is a not so subtle effect when one mixes up the letter 'l' and the digit '1' in names.
Comment 22 Tobias Burnus 2013-04-25 12:42:45 UTC
Created attachment 29938 [details]
FE patch for namelist read with type extension (+ test case)

Regarding the support of type extension: This patch uses in the front end a "+" instead of a "%" to denote a type extension, i.e.
  type%parent%var
becomes
  type+parent%var
in the call to st_set_nml_var. Then, libgfortran has the required information - the actual implementation is still pending.
Comment 23 Dominique d'Humieres 2013-06-16 18:04:45 UTC
> Created attachment 29938 [details]
> FE patch for namelist read with type extension (+ test case)

What happened to this patch?
Comment 24 Jerry DeLisle 2014-01-06 05:14:23 UTC
I am currently working with Tobias FE patch and modifying the library side now.
Comment 25 Jerry DeLisle 2014-03-23 23:20:02 UTC
Preliminary patch here:

http://gcc.gnu.org/ml/fortran/2014-03/msg00150.html
Comment 26 Jerry DeLisle 2014-05-26 15:20:08 UTC
Author: jvdelisle
Date: Mon May 26 15:19:36 2014
New Revision: 210934

URL: http://gcc.gnu.org/viewcvs?rev=210934&root=gcc&view=rev
Log:
2014-05-26  Tobias Burnus  <burnus@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-26  Jerry DeLisle  <jvdelisle@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.

Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/trans-io.c
    trunk/libgfortran/ChangeLog
    trunk/libgfortran/io/list_read.c
Comment 27 Jerry DeLisle 2014-05-26 15:33:05 UTC
Author: jvdelisle
Date: Mon May 26 15:32:33 2014
New Revision: 210935

URL: http://gcc.gnu.org/viewcvs?rev=210935&root=gcc&view=rev
Log:
2014-05-26  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/55117
	* gfortran.dg/namelist_85.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/namelist_85.f90
Modified:
    trunk/gcc/testsuite/ChangeLog
Comment 28 Jerry DeLisle 2014-06-07 17:42:36 UTC
Fixed on Trunk, closing
Comment 29 Jerry DeLisle 2014-06-07 17:43:35 UTC
Missed the button.