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, libgfortran] [4.9/4.10 Regression] Internal read of negative integer broken


Hi,

This bug has nothing to do with negative numbers as in the description.
However, the problem is due to seeking when there are no spaces to skip.  I
restructured the loop so that the skipping is not done if there are no spaces.

Regression tested on x86-64.  New test case from the PR.

OK for trunk and 4.9?

Regards,

Jerry

2014-06-25  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR libgfortran/61499
	* io/list_read.c (eat_spaces): Use a 'for' loop instead of
	'while' loop to skip the loop if there are no bytes left in the
	string. Only seek if actual spaces can be skipped.
Index: io/list_read.c
===================================================================
--- io/list_read.c	(revision 211765)
+++ io/list_read.c	(working copy)
@@ -387,50 +387,39 @@ eat_spaces (st_parameter_dt *dtp)
   int c;
 
   /* If internal character array IO, peak ahead and seek past spaces.
-     This is an optimazation to eliminate numerous calls to
-     next character unique to character arrays with large character
-     lengths (PR38199). */
-  if (is_array_io (dtp))
+     This is an optimization unique to character arrays with large
+     character lengths (PR38199).  This code eliminates numerous calls
+     to next_character.  */
+  if (is_array_io (dtp) && (dtp->u.p.last_char == EOF - 1))
     {
       gfc_offset offset = stell (dtp->u.p.current_unit->s);
-      gfc_offset limit = offset + dtp->u.p.current_unit->bytes_left;
+      gfc_offset i;
 
       if (dtp->common.unit) /* kind=4 */
 	{
-	  gfc_char4_t cc;
-	  limit *= (sizeof (gfc_char4_t));
-	  do
+	  for (i = 0; i < dtp->u.p.current_unit->bytes_left; i++)
 	    {
-	      cc = dtp->internal_unit[offset];
-	      offset += (sizeof (gfc_char4_t));
-	      dtp->u.p.current_unit->bytes_left--;
+	      if (dtp->internal_unit[offset + i * sizeof (gfc_char4_t)]
+		  != (gfc_char4_t)' ')
+	        break;
 	    }
-	  while (offset < limit && cc == (gfc_char4_t)' ');
-	  /* Back up, seek ahead, and fall through to complete the
-	     process so that END conditions are handled correctly.  */
-	  dtp->u.p.current_unit->bytes_left++;
-
-	  cc = dtp->internal_unit[offset];
-	  if (cc != (gfc_char4_t)' ')
-	    sseek (dtp->u.p.current_unit->s,
-		   offset-(sizeof (gfc_char4_t)), SEEK_SET);
 	}
       else
 	{
-	  do
+	  for (i = 0; i < dtp->u.p.current_unit->bytes_left; i++)
 	    {
-	      c = dtp->internal_unit[offset++];
-	      dtp->u.p.current_unit->bytes_left--;
+	      if (dtp->internal_unit[offset + i] != ' ')
+	        break;
 	    }
-	  while (offset < limit && c == ' ');
-	  /* Back up, seek ahead, and fall through to complete the
-	     process so that END conditions are handled correctly.  */
-	  dtp->u.p.current_unit->bytes_left++;
+	}
 
-	  if (dtp->internal_unit[offset] != ' ')
-	    sseek (dtp->u.p.current_unit->s, offset - 1, SEEK_SET);
+      if (i != 0)
+	{
+	  sseek (dtp->u.p.current_unit->s, offset + i, SEEK_SET);
+	  dtp->u.p.current_unit->bytes_left -= i;
 	}
     }
+
   /* Now skip spaces, EOF and EOL are handled in next_char.  */
   do
     c = next_char (dtp);
! { dg-do run }
! PR61499
program read_internal

  integer :: x(9),i,iostat
  character(len=512) :: iomsg
  character(kind=1,len=30), dimension(:), allocatable, save :: source
  allocate(source(3))
  source=["  1   1  -1","  1  -1   1"," -1   1   1"]      !This fails
  read(source,*) (x(i), i=1,6)
end program read_internal

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