Gfortran bug on a simple program?

I am really confused by a weird behavior of gfortran-compiled, really simple program:

program rc
  implicit none
  character(:), allocatable :: str
  str = '1234567890123'
  print *, getx(str)
  str = '12.34567890123'
  print *, getx(str)
contains
  real function getx(s)
    character(*), intent(in) :: s
    real :: x
    print *, len(s), s(2:6)
    read(s(2:6),'(f5.0)') x
    getx = x
  end function getx
end program rc

ifx, as well as gfortran ver. 8 and 9 create executables which give, as expected:

          13 23456
   23456.0000    
          14 2.345
   2.34500003    

Now when compiled with gfortran ver. 11.4.0 (Ubuntu), 12.2.0 (Debian) and 13.2.0 (Homebrew GCC on Debian), just hangs w/o any output until one types Ctrl-C.
Can anybody confirm this weirdness?

Yeah, with GNU Fortran (Ubuntu 11.2.0-19ubuntu1) 11.2.0, the program “just hangs”.
Using
real :: x
x = getx(str)
print*, x
the program works.
Maybe it’s some issue with the print command

Same here gfortran 13.2 also on homebrew (m2 Mac if that matters). Tried lfortran but it wouldn’t compile. Updating lfortran and if it still fails I’ll report an issue there.

This has me worried about gfortran 13.2. I spent the past few days chasing my tail with some pointer related code that had similar “just hang” behavior. Literally removing just a call to associated(pointer variable that was most definitely associated) cleared up the hang.

The code shown uses recursive I/O, which is prohibited. Quoting @sblionel from an Intel Forum thread about the same question,

An input/output statement that is executed while another input/output statement is being executed is a recursive input/output statement. A recursive input/output statement shall not identify an external unit that is identified by another input/output statement being executed except that a child data transfer statement may identify its parent data transfer statement external unit. (F2018 12.12p2)

3 Likes

But it works if you use different output units:

use iso_fortran_env, only: error_unit
...
! Standard unit:
print *, getx(str)
...
! stderr unit:
write(error_unit, *) len(s), s(2:6)

Or if you use an intermediate variable, or associate block:

program rc
  implicit none
  character(:), allocatable :: str
  real :: x
  str = '1234567890123'
  x = getx(str)
  print *, x
  str = '12.34567890123'
  x = getx(str)
  print *, x
contains
  real function getx(s)
    character(*), intent(in) :: s
    real :: x
    print *, len(s), s(2:6)
    read(s(2:6),'(f5.0)') x
    getx = x
  end function getx
end program rc
program rc
  implicit none
  character(:), allocatable :: str
  str = '1234567890123'
  associate(x => getx(str))
    print *, x
  end associate
  str = '12.34567890123'
  associate(x => getx(str))
    print *, x
  end associate
contains
  real function getx(s)
    character(*), intent(in) :: s
    real :: x
    print *, len(s), s(2:6)
    read(s(2:6),'(f5.0)') x
    getx = x
  end function getx
end program rc

Thanks to all. That happens if one does not follow practices that one teaches others. Do not use I/O in functions! I thought that reading from internal file should be safe but forgot about debugging output to stdout.

2 Likes