This is a very interesting discussion! I tried a couple of different variations of the original code that do not seem to encounter the bug. One variation replaces the function with a subroutine, while the other one packs b and err into a derived type which allows one to declare the function pure.
Code
program main
use iso_fortran_env, only: dp => real64
implicit none
type :: t1
real(dp):: b(2)
character(:), allocatable :: err
endtype t1
call test_fun1()
contains
pure function fun1(a) result(t)
real(dp), intent(in) :: a
type(t1):: t
t%b = 1
if (a > 2) then
t%err = "a bigger than 2"
return
endif
end function
subroutine sub1(a,b,err)
real(dp), intent(in) :: a
real(dp), intent(out) :: b(2)
character(:), allocatable,intent(out) :: err
b = 1
if (a > 2) then
err = "a bigger than 2"
return
endif
end subroutine
subroutine test_fun1()
real(dp) :: a,b(2)
type(t1) :: t
character(:), allocatable :: err
a = 3
t = fun1(a)
if (allocated(t%err)) then
print*,'err is allocated'
print*,'next line tries to print err'
print*,t%err
else
print*,t%b
endif
a = 1
t = fun1(a)
if (allocated(t%err)) then
print*,'err is allocated'
print*,'next line tries to print err'
print*,t%err
else
print*,t%b
endif
a = 3
call sub1(a,b, err)
if (allocated(err)) then
print*,'err is allocated'
print*,'next line tries to print err'
print*,err
else
print*,b
endif
a = 1
call sub1(a,b, err)
if (allocated(err)) then
print*,'err is allocated'
print*,'next line tries to print err'
print*,err
else
print*,b
endif
end subroutine
end program