Here's an update to the previous patch. Upon reflection, I think it is better for performance to have two versions of the loop so the test is only performed when it is needed.
So, OK for trunk? Regards Thomas Fix EOF handling for arrays. 2019-11-23 Thomas Koenig <tkoe...@gcc.gnu.org> Harald Anlauf <anl...@gmx.de> PR fortran/92569 * io/transfer.c (transfer_array_inner): If position is at AFTER_ENDFILE in current unit, return from data loop. 2019-11-23 Thomas Koenig <tkoe...@gcc.gnu.org> Harald Anlauf <anl...@gmx.de> PR fortran/92569 * gfortran.dg/eof_4.f90: New test.
Index: io/transfer.c =================================================================== --- io/transfer.c (Revision 278025) +++ io/transfer.c (Arbeitskopie) @@ -2542,26 +2542,62 @@ transfer_array_inner (st_parameter_dt *dtp, gfc_ar data = GFC_DESCRIPTOR_DATA (desc); - while (data) + /* When reading, we need to check endfile conditions so we do not miss + an END=label. Make this separate so we do not have an extra test + in a tight loop when it is not needed. */ + + if (dtp->u.p.current_unit && dtp->u.p.mode == READING) { - dtp->u.p.transfer (dtp, iotype, data, kind, size, tsize); - data += stride0 * tsize; - count[0] += tsize; - n = 0; - while (count[n] == extent[n]) + while (data) { - count[n] = 0; - data -= stride[n] * extent[n]; - n++; - if (n == rank) + if (unlikely (dtp->u.p.current_unit->endfile == AFTER_ENDFILE)) + return; + + dtp->u.p.transfer (dtp, iotype, data, kind, size, tsize); + data += stride0 * tsize; + count[0] += tsize; + n = 0; + while (count[n] == extent[n]) { - data = NULL; - break; + count[n] = 0; + data -= stride[n] * extent[n]; + n++; + if (n == rank) + { + data = NULL; + break; + } + else + { + count[n]++; + data += stride[n]; + } } - else + } + } + else + { + while (data) + { + dtp->u.p.transfer (dtp, iotype, data, kind, size, tsize); + data += stride0 * tsize; + count[0] += tsize; + n = 0; + while (count[n] == extent[n]) { - count[n]++; - data += stride[n]; + count[n] = 0; + data -= stride[n] * extent[n]; + n++; + if (n == rank) + { + data = NULL; + break; + } + else + { + count[n]++; + data += stride[n]; + } } } }
! { dg-do run } ! { dg-options "-ffrontend-optimize" } ! PR 92569 - the EOF condition was not recognized with ! -ffrontend-optimize. Originjal test case by Bill Lipa. program main implicit none real(kind=8) :: tdat(1000,10) real(kind=8) :: res (10, 3) integer :: i, j, k, np open (unit=20, status="scratch") res = reshape([(real(i),i=1,30)], shape(res)) write (20,'(10G12.5)') res rewind 20 do j = 1,1000 read (20,*,end=1)(tdat(j,k),k=1,10) end do 1 continue np = j-1 if (np /= 3) stop 1 if (any(transpose(res) /= tdat(1:np,:))) stop 2 end program main