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,