[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