This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch,libfortran] PR56660 Fails to read NAMELIST with certain form array syntax


Hi all,

When doing namelist reads, nml_read_obj calls itself recursively to read through
arrays.  Short lists are allowed so we have to have a way to detect if we have a
short read or a real error.

We do this by flagging errors and then backing out of the read and checking to
see if what we error-ed on was a valid object name rather than data. This is
problematic for reading strings or logicals, since the data can look like names.
 To resolve the problem, we use a line_buffer to hold reads as we look ahead and
if we find an error we rewind, bail out of the read, and proceed to the next
read cycle which looks for an object name followed by an "=" sign.

With this particular bug, nml_read_obj was clearing the error flag itself with
the read so that rather then bailing out, it tried to continue reading data
until it was done, then the subsequent read failed looking for a valid name,
which had been passed by.

The problem is resolved by moving the error flag reset outside nml_read_obj just
before the call to nml_read_obj.  Also, we test the flag on entering
nml_read_obj, and if it is set, we bail out right away, a do nothing, until the
parent nml_read_obj finishes its loops.

Regression tested on x86-64.  Test case attached.

OK for trunk?

Jerry

2013-04-01  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libfortran/56660
	* io/list_read.c (nml_read_obj): Do not reset the read error flag
	inside nml_read_obj. If the read error flag is found set just exit.
	Fix some whitespace on comments.
	(nml_read_obj_data): Reset the read error flag before the first call
	to nml_read_object.

Index: list_read.c
===================================================================
--- list_read.c	(revision 197290)
+++ list_read.c	(working copy)
@@ -2490,9 +2490,9 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info
   size_t obj_name_len;
   void * pdata;
 
-  /* This object not touched in name parsing.  */
-
-  if (!nl->touched)
+  /* If we have encountered a previous read error or this object has not been
+     touched in name parsing, just return.  */
+  if (dtp->u.p.nml_read_error || !nl->touched)
     return true;
 
   dtp->u.p.repeat_count = 0;
@@ -2532,10 +2532,8 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info
 				 - GFC_DESCRIPTOR_LBOUND(nl,dim))
 			* GFC_DESCRIPTOR_STRIDE(nl,dim) * nl->size);
 
-      /* Reset the error flag and try to read next value, if
-	 dtp->u.p.repeat_count=0  */
+      /* If we are finished with the repeat count, try to read next value.  */
 
-      dtp->u.p.nml_read_error = 0;
       nml_carry = 0;
       if (--dtp->u.p.repeat_count <= 0)
 	{
@@ -2564,8 +2562,8 @@ nml_read_obj (st_parameter_dt *dtp, namelist_info
 	    break;
 
 	  case BT_REAL:
-	    /* Need to copy data back from the real location to the temp in order
-	       to handle nml reads into arrays.  */
+	    /* Need to copy data back from the real location to the temp in
+	       order to handle nml reads into arrays.  */
 	    read_real (dtp, pdata, len);
 	    memcpy (dtp->u.p.value, pdata, dlen);
 	    break;
@@ -3022,6 +3020,7 @@ get_name:
 	nl = first_nl;
     }
 
+  dtp->u.p.nml_read_error = 0;
   if (!nml_read_obj (dtp, nl, 0, pprev_nl, nml_err_msg, nml_err_msg_size,
 		    clow, chigh))
     goto nml_err_ret;
! { dg-do run }
! PR56660  Fails to read NAMELIST with certain form array syntax
type ptracer
   character(len = 2)  :: sname
   logical             :: lini
end type ptracer

type(ptracer) , dimension(3) :: tracer
namelist/naml1/  tracer

tracer(:) = ptracer('XXX', .false.)

open (99, file='nml.dat', status="replace")
write(99,*) "&naml1"
!write(99,*) "   tracer(2)   = 'bb' , .true."
write(99,*) "   tracer(:)   = 'aa' , .true."
write(99,*) "   tracer(2)   = 'bb' , .true."
write(99,*) "/"
rewind(99)

read (99, nml=naml1)
close (99, status="delete")

if (tracer(1)%sname.ne.'aa') call abort()
if (.not.tracer(1)%lini) call abort()
if (tracer(2)%sname.ne.'bb') call abort()
if (.not.tracer(2)%lini) call abort()
if (tracer(3)%sname.ne.'XX') call abort()
if (tracer(3)%lini) call abort()

!write (*, nml=naml1)

end

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]