The following simple code involving a linked list compiles with no errors or warnings with compiler 2015, update 2. It seems to execute without any run-time exceptions as well.
However, you will notice the code in module m invokes a finalizer for the derived type for linked list (node_t) that has indirect recursion via clear_node_t; this is to work around the restriction in the standard that both RECURSIVE and ELEMENTAL attributes cannot be applied with subroutines.
What are the risks associated with such a workaround?
Colud the compiler do a static allocation (non-automatic) for allocatable array foo in program p and could the indirect recursion then possibly lead to a failure of some sort under some circumstances? Note, however, I have not noticed any such issues - no memory leaks are detected nor any other run-time exceptions; I tried /heaparrays0 also.
module m implicit none private type, public :: node_t private type(node_t), pointer :: m_child => null() character(len=:), allocatable :: m_key contains private procedure, pass(this) :: clear => clear_node_t final :: clean_node_t procedure, pass(this), public :: put => put_node_t end type node_t contains recursive pure subroutine put_node_t(this, key) class(node_t), intent(inout) :: this character(len=*), intent(in) :: key if (allocated(this%m_key)) then if (this%m_key /= key) then if (.not. associated(this%m_child)) then allocate(this%m_Child) end if call put_node_t(this%m_Child, key) end if else this%m_key = key end if return end subroutine put_node_t pure recursive subroutine clear_node_t(this) class(node_t), intent(inout) :: this if (allocated(this%m_key)) then deallocate(this%m_key) end if if (associated(this%m_child)) then deallocate(this%m_child) this%m_child => null() end if return end subroutine clear_node_t pure elemental subroutine clean_node_t(this) type(node_t), intent(inout) :: this call clear_node_t(this) end subroutine clean_node_t end module m
program p use m, only : node_t implicit none type(node_t), allocatable :: foo(:) integer :: istat allocate( node_t :: foo(2), stat=istat) if (istat /= 0) then print *, " istat = ", istat stop end if call foo(1)%put("red") call foo(1)%put("green") call foo(2)%put("circle") call foo(2)%put("triangle") deallocate(foo, stat=istat) print *, " deallocate(foo): istat = ", istat stop end program p
I understand Fortran 2015 lifts the restriction on RECURSIVE and ELEMENTAL but that is for the long-term. With the current standard, is such an indirect recursion a concern? If yes, is there any way to make the coder aware of it?
Thanks,