This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch, libgfortran] [4.9/4.10 Regression] Internal read of negative integer broken
- From: Jerry DeLisle <jvdelisle at charter dot net>
- To: gfortran <fortran at gcc dot gnu dot org>
- Cc: gcc patches <gcc-patches at gcc dot gnu dot org>
- Date: Wed, 25 Jun 2014 18:58:55 -0700
- Subject: [patch, libgfortran] [4.9/4.10 Regression] Internal read of negative integer broken
- Authentication-results: sourceware.org; auth=none
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