[J3] Procedure pointers to internal procedures contained in subprogram
Malcolm Cohen
malcolm at nag-j.co.jp
Fri Sep 27 02:50:43 UTC 2024
Hi Thomas,
Yes it is intentional.
There is no problem as compilers can see that there is a procedure pointer assignment for the internal procedure, and thus it could be invoked from any place that can see the pointer. The pointer will go undefined on return from the host instance of the internal procedure - that we spell this out shows that we meant it!
15.6.2.4 describes instances.
19.5.2.5 item (8) specifies the "undefined on return from the host instance" semantics. The NAG compiler can produce sensible runtime error messages if the pointer is subsequently referenced.
Cheers,
--
..............Malcolm Cohen, NAG Oxford/Tokyo.
-----Original Message-----
From: J3 <j3-bounces at mailman.j3-fortran.org> On Behalf Of Thomas Konig via J3
Sent: Friday, September 27, 2024 4:36 AM
To: General J3 interest list <j3 at mailman.j3-fortran.org>
Cc: Thomas König <tk at tkoenig.net>
Subject: [J3] Procedure pointers to internal procedures contained in subprogram
Hello,
I have a question regarding procedure pointers.
In the following little program, the subroutine extsub saves procedure pointers to the internal subroutine intsub from different instances of callit. That saves them into the array cache, and later calls them from yet another instance, in reverse order, via calling do_things.
This appears to work with gfortran, but I can easily see case where this could be problematic. Assume the invocation is far away from the point where the pointer is saved; the memory location containing local_var could long since have been overwritten with something else by an optimizing compiler.
Is this allowed by the standard? I didn't find anything that said it's not, but I may have overlooked something.
If it is actually allowed by the standard, is this an intentional feature?
Best regards
Thomas König
module stash_things
implicit none
abstract interface
subroutine sub()
end subroutine sub
end interface
type cache_proc_pointer
procedure(sub), pointer, nopass :: p
integer :: n
end type cache_proc_pointer
type (cache_proc_pointer), dimension(100) :: cache
integer :: n_sub = 0
contains
recursive subroutine extsub (subname, n)
procedure(sub), pointer :: subname
integer, intent(in) :: n
n_sub = n_sub + 1
cache(n_sub)%p => subname
cache(n_sub)%n = n
end subroutine extsub
subroutine do_things()
integer :: i
do i=n_sub,1,-1
call cache(i)%p()
end do
end subroutine do_things
end module stash_things
recursive subroutine callit(n)
use stash_things
integer, intent(in) :: n
integer :: localvar
procedure(sub), pointer :: p
if (n <= 0) then
call do_things
return
end if
localvar = 1+10*n
p => intsub
call extsub(p,n)
call callit(n-1)
contains
recursive subroutine intsub
print *, localvar
end subroutine intsub
end subroutine callit
program thunk
use stash_things
implicit none
call callit(5)
end program thunk
More information about the J3
mailing list