Parent component finalization of child array

When compiled with recent releases of five production Fortran compilers, behavior on the following program differs. Two compilers call final1a to finalize an array of parent components (and only one of them prints the right values); three compilers call final1e on each of the parent component elements of the child array.

I think that a conforming compiler must call final2a, then final1a, and nothing else. Would you agree?

module m
  type :: parent
    integer :: j
   contains
    final :: final1e, final1a
  end type
  type, extends(parent) :: child
    integer :: k
   contains
    final :: final2e, final2a
  end type
 contains
  impure elemental subroutine final1e(x)
    type(parent), intent(in) :: x
    print *, 'parent final1e', x%j
  end subroutine
  subroutine final1a(x)
    type(parent) :: x(2,2)
    print *, 'parent final1a', x%j
  end subroutine
  impure elemental subroutine final2e(x)
    type(child), intent(in) :: x
    print *, 'child final2e', x%k
  end subroutine
  subroutine final2a(x)
    type(child) :: x(2,2)
    print *, 'child final2a', x%k
  end subroutine
end module

subroutine test
  use m
  type(child), allocatable :: x(:,:)
  allocate(x(2,2))
  x%j = reshape([11, 12, 13, 14], [2, 2])
  x%k = reshape([21, 22, 23, 24], [2, 2])
  print *, 'begin finalization'
  deallocate(x)
end subroutine

call test
end

I’m sure, but since you have defined the “final” procedures, you must call them. Therefore, you have to call “final1a” in the “final2a” subroutine and also call “final1e” in ““final2e””.

With the shown code in the original post, my hunch is output from all conforming programs will begin with the following lines:

begin finalization
child final2a 21 22 23 24

This is only as per the blurb in section 7.5.6.2 The finalization process of the standard which states:

2 1 Only finalizable entities are finalized. When an entity is finalized, the following steps are carried out in sequence.
3 (1) If the dynamic type of the entity has a final subroutine whose dummy argument has the same kind
4 type parameters and rank as the entity being finalized, it is called with the entity as an actual
5 argument.

However, I think the subsequent output will be processor-dependent because the Fortran standard does not get into implementation details. The standard does not quite stipulate how a processor might organize arrays of derived types, particularly with extended types. That is, other than to convey a parent type is effectively a component of an extended type.

Given how much leeway the standard extends (pun intended!) to the processor, particularly with arrays of derived types, I think one would be able to argue a program that outputs the following lines subsequently, like it does with a commercial compiler, is also standard-conforming:

parent final1e 11
parent final1e 12
parent final1e 13
parent final1e 14

In other words, similar to intrinsic assignment with arrays where the processing takes place element-by-element, I think a processor might be permitted to do finalization of components of an array instance of a finalizable child type an element-by-element fashion as well. At least, I couldn’t find anything in the standard that disallows this.

But I’ll be more than open-minded to be proven wrong with my understanding here!

The standard in paragraph (3) discusses finalization of the parent component, singular, even in the context of finalization of an “entity” that has rank (see paragraph (1)). In this case the parent component of the array is itself an array, and there’s a FINAL subroutine whose dummy argument has the matching rank. So paragraph (1) applies to the parent as well.

You must mean paragraph (2) in 18-007r1 document that has

9 (2) All finalizable components that appear in the type definition are finalized in a processor-dependent
10 order. If the entity being finalized is an array, each finalizable component of each element of that
11 entity is finalized separately.

The phrase, “each element of that (array) entity is finalized separately”, suggests to me, albeit with my decidedly limited understanding of Fortran standardese, the output I show upthread with a program created using a different processor is conformant.

“All finalizable components that appear in the type definition…” does not include the parent component, which is dealt with in the following paragraph (3).

I think that a conforming compiler must call final2a , then final1a , and nothing else. Would you agree?

Intuitively, I think "final2a() then final1a()" above seems most natural. This is partly because if we pass x % parent manually to some overloaded routines for finalization (say final1e() and final1a() above), the routine with an array dummy argument is selected (because x % parent is regarded as an array).


7.5.6.2 The finalization process

Only finalizable entities are finalized.

When an entity is finalized, the following steps are
carried out in sequence.

(1) If the dynamic type of the entity has a final
subroutine whose dummy argument has the same
kind type parameters and rank as the entity
being finalized, it is called with the entity as
an actual argument.

Otherwise, if there is an elemental final
subroutine whose dummy argument has the same
kind type parameters as the entity being finalized,
or (... about assumed-rank ...),
it is called with the entity as an actual argument.

Otherwise, no subroutine is called at this point.

(2) All finalizable components that appear in
the type definition are finalized in a processor-
dependent order.

If the entity being finalized is an array,
each finalizable component of each element
of that entity is finalized separately.

(3) If the entity is of extended type and
the parent type is finalizable, the parent
component is finalized.

I’ve read the above paragraphs 3 or 4 times, but still cannot understand
their meaning precisely… Anyway, if the rule (3) applies to
x % parent as an “entity” and Rule (1) is recursively used,
then I guess "final2a() then final1a()" will be the expected result.

By the way, I hope that more “code examples” will be included (in future) in the official docs (e.g., as in this site), so that it becomes easier to understand the syntax and semantics described by sentences…