I’ve got another standards question, this time related to the expected behavior when unformatted stream input encounters an end-of-file. I first encountered this problem >10 years ago with the Intel compiler (long since “fixed”), but it’s reappeared with the LLVM flang compiler that I’ve been testing.
The situation arises in the context of the unformatted stream input of a file in buffer-sized chunks. The last part of the file read will generally only partially fill the buffer and trigger an end-of-file condition. The following example illustrates this last case, reading a 4-character file into an 8-character buffer array.
use iso_fortran_env
character :: buffer(8) = '*'
integer :: lun, ios, last_pos, curr_pos, buflen
! Create a file to read
open(newunit=lun,file='input.txt',access='stream',action='write',status='replace',form='unformatted')
write(lun) 'abcd'
close(lun)
! Read the file into a character array buffer
open(newunit=lun,file='input.txt',access='stream',action='read',form='unformatted')
inquire(lun,pos=last_pos)
read(lun,iostat=ios) buffer
if (ios /= 0 .and. ios /= iostat_end) stop 1
inquire(lun,pos=curr_pos)
buflen = curr_pos - last_pos
print '(a,i0)', 'current position=', curr_pos
if (buflen > 0) then
print '(a,i0,9a)', 'buflen=', buflen, ', buffer=', buffer(:buflen)
else
print '(9a)', 'buflen=0, entire buffer=', buffer
end if
end
The desired/expected output is
current position=5
buflen=4, buffer=abcd
Gfortran, Intel, and NAG all give this. But flang gives
current position=1
buflen=0, entire buffer=********
It’s tempting to say that flang is wrong, but there’s a change in the wording between the 2008 standard and the 2023 standard that make this less clear to me.
The relevant bits from the (2008 / 2023) standard that I’ve found are:
- File position after data transfer (9.3.4.4 / 12.3.4.4). I’m not sure what the 2nd paragraph means, and it seems to contradict the 1st.
- An input list array is expanded to its individual elements as effective input list items (9.6.3 / 12.6.3)
- What happens when end-of-file is encountered (9.11.3 (3)) / 12.11.3 (3)). Here text is changed from “all input list items […] in the statement that initiated the transfer become undefined” to “all effective items resulting from the expansion of list items […] in the statement that initiated the transfer become undefined”.
The non-flang compilers appear to follow a 2008-interpretation in which the (effective) items from buffer are read until the EOF is reached and the remaining are undefined, while flang follows a 2023-interpretation that if an EOF is encountered all the effective items from buffer are undefined. The fact that it also doesn’t change the file position (I’m not convinced that’s correct) suggests that it’s just tossed the the entire read statement .
Thoughts?