subroutine a()
implicit none
real :: u(3)
print*, 'a'
goto 1
entry b()
print*, 'b'
data u/ 0.1, 0.2, 0.3 /
1 print*, u ! what is u here ?
end subroutine a
program main
call a()
end program main
The result (using latest gfortran) is:
a
0.100000001 0.200000003 0.300000012
Which I guess sort of suprised me. I would have thought that since the b() entry was never called, that data statement was not executed, but I guess it is? Is that normal for a data statement?
Placing the DATA statements anywhere in the body of the subroutine should be flagged as non-standard if you add the flags to enforce standard conformance. DATA statements are not executables, but are used to initialize the routine at start-up not on each call, so the refactoring is equivalent. In cases where the values will not be changed it is preferable to use PARAMETER instead of SAVE, but the fact they are not changed is not the general case and this is just a small example. In new code using ENTRY is generally deprecated in favor of other methods such as using CONTAINS and a conditional:
subroutine a(flag)
! shared declarations and code
if(flag) then
call b()
else
call c()
endif
contains
subroutine (b)
end
subroutine (c)
end
You can even pass in the routine name and eliminate the conditional and so on.
https://fortran-lang.discourse.group/t/should-the-entry-statement-be-used-in-new-code/2636
https://fortranwiki.org/fortran/show/Modernizing+Old+Fortran
It is just considered obsolescent. I used to do it a lot, but I always place them after the declarations and before the executable statements if I use them now. I guess I phrased that a little too strongly. Probably no compiler enforces not allowing it(?)
gfortran --std=f2018 nodata.f90
nodata.f90:3:11:
3 | data a/100/
| 1
Warning: Obsolescent feature: DATA statement at (1) after the first executable statement
urbanjs@mercury:~$ cat nodata.f90
program nodata
write(*,*)a
data a/100/
end program nodata
urbanjs@mercury:~$ ./a.out
100.000000
There is one case where a small module is an easy replacement for a procedure with multiple entries.
When no executable statements are shared, just data:
module M_
! when what is shared between entries is declarations and data
! a module is an easy replacement. Gets more complicated if
! there is shared text as well.
! shared stuff
implicit none
private
public case1, case2
integer, parameter :: ivals(3) = [100, 200, 300]
contains
subroutine case1()
write (*, *) 'case1', ivals
end subroutine case1
subroutine case2()
write (*, *) 'case2', ivals
end subroutine case2
end module M_
program noentry
use M_, only: case1, case2
implicit none
call case1()
call case2()
end program noentry
It can be confusing to apply a current or recent version of the Fortran standard to a program in which old/obsolescent features are combined with features that were not present in Fortran 77. The table that @sblionel showed appears to rule out DATA statements in internal procedures, but they are allowed.
subroutine a()
implicit none
real :: u(3)
character ep
data u/ 0.1, 0.2, 0.3 /, ep/'a'/
goto 1
entry b()
ep = 'b'
data u/ 0.3, 0.2, 0.1 / ! u is already initialized; error or no effect?
1 print *, ep, u ! what is u here ?
end subroutine a
program main
call a()
call b()
call c()
CONTAINS
subroutine c()
character ep
real u(2)
data u/0.5,0.6/, ep/'c'/
print *,ep,u
end subroutine c
end program main
Try Gfortran on this version with and without -fstd=f2008. Try other compilers.