For Intel Fortran and gfortran, two cases where a FINAL subroutine of a derived type are called are when a local derived type goes out of scope in a procedure or when a local variable that is not allocatable or a pointer goes out of scope in a block (code below). I thought that the final subroutine would also be called when exiting blocks b2, b3, or b4. The Fortran standard in section “7.5.6.3 When finalization occurs” says
When a pointer is deallocated its target is finalized. When an allocatable entity is deallocated, it is finalized unless it is the variable in an intrinsic assignment statement or a subobject thereof. If an error condition occurs during deallocation, it is processor dependent whether finalization occurs.
module m
!
type :: vec
real, pointer :: x(:) => null()
contains
final :: destructor
end type vec
!
contains
!
subroutine destructor(v)
type(vec) :: v
print*,"entering destructor, associated(v%x) =",associated(v%x)
if (associated(v%x)) deallocate (v%x)
print*,"leaving destructor, associated(v%x) =",associated(v%x)
end subroutine destructor
!
subroutine sub_alloc()
type(vec) :: v
allocate (v%x(2))
v%x = [10.0,20.0]
print*,"in sub_alloc, v%x =",v%x
end subroutine sub_alloc
!
subroutine sub_automatic()
type(vec) :: v
allocate (v%x(2))
v%x = [10.0,20.0]
print*,"in sub_automatic, v%x =",v%x
end subroutine sub_automatic
!
end module m
!
program main
use m, only: vec, sub_alloc, sub_automatic
implicit none
b1: block
type(vec) :: v
allocate (v%x(3))
print*,"exiting b1"
end block b1
b2: block
type(vec), allocatable :: v(:)
allocate (v(3))
print*,"exiting b2"
end block b2
b3: block
type(vec), allocatable :: v(:)
allocate (v(3))
deallocate (v)
print*,"exiting b3"
end block b3
b4: block
type(vec), pointer :: v(:) => null()
allocate (v(3))
print*,"exiting b4"
end block b4
print*,"calling sub_alloc()"
call sub_alloc()
print*,"calling sub_automatic()"
call sub_automatic()
end program main
Output:
exiting b1
entering destructor, associated(v%x) = T
leaving destructor, associated(v%x) = F
exiting b2
exiting b3
exiting b4
calling sub_alloc()
in sub_alloc, v%x = 10.00000 20.00000
entering destructor, associated(v%x) = T
leaving destructor, associated(v%x) = F
calling sub_automatic()
in sub_automatic, v%x = 10.00000 20.00000
entering destructor, associated(v%x) = T
leaving destructor, associated(v%x) = F