Expected behavior of unformatted stream input and EOF

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?

1 Like

First of all, “undefined” means that you can’t depend on the value.

F2023 does say. “if the file specified in the input statement is an external record file, it is positioned after the endfile record;” (12.11..3p1(4)) This tells me that flang is wrong to set the position at 1 and that the other compilers are doing it correctly. However, the value of buffer is undefined.

1 Like

Do you happen to remember whether the change in wording from 2008 to 2023 (my last bullet) was meant to clarify that all of buffer was undefined rather than just some elements?

1 Like

This change from F2018 to F2023 was the result of these papers:

j3-fortran.org/doc/year/21/21-140.txt (See comment for 21-101r1)
j3-fortran.org/doc/year/21/21-161.txt
j3-fortran.org/doc/year/21/21-181.txt (probably not directly relevant, but including for completeness)

These are editorial changes, not interpretations.

1 Like