Quantcast
Channel: Intel® Fortran Composer XE
Viewing all articles
Browse latest Browse all 1424

What is the effect of indirect recursion on ELEMENTAL procedures, especially finalizers?

$
0
0

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,

     


Viewing all articles
Browse latest Browse all 1424

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>