- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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,
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I sort-of followed the discussion in comp.lang.fortran but wasn't paying a lot of attention to it. In the example here, the compiler will likely use static allocation for the descriptor of foo, but the data will always be on the heap. I don't see what the problem with static allocation would be since the main program is never reentered. Am I missing something?
The finalizer would be called for each allocation of type node_t when it is deallocated.
That the finalizer could get recursively entered is a possible problem, but since there are no local variables in clean_node_t, the risk seems minimal. If however you had local variables in clean_node_t and it was recursively entered, that would be problematic as some of them could involve static allocation.
My take on this is that you're always taking a risk when you hide things from the compiler (or the standard). I don't see any feasible way to warn about this, especially if separate sources are involved.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Intel) wrote:
..
My take on this is that you're always taking a risk when you hide things from the compiler (or the standard). I don't see any feasible way to warn about this, especially if separate sources are involved.
Point well-taken.
By the way, draft Fortran 2015 says, "Procedures, including elemental procedures, can be invoked recursively by default; the RECURSIVE keyword is advisory only. The NON_RECURSIVE keyword specifies that a procedure is not recursive."
So is this change to recursive by default fully accepted in the next standard, or is it still up in the air in terms of votes?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The straw vote on recursion by default (paper 14-179, a UK proposal) was 12-1 with two undecided. I don't expect opposition to it.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page