[J3] Finalization question(s)
Daniel Chen
cdchen at ca.ibm.com
Mon Jul 7 14:56:27 UTC 2025
Hi Jon,
Our implementation agrees with your interpretation of the standard. We also finalize “y” (y%f) and “ya” (ya%f) twice.
We output
“
non-allocatable
finalize 42
finalize -1
assign -1 7
x 7 y 8
allocatable
finalize 42
finalize 0
assign -1 7
x 7 y 8
“
Thanks,
Daniel
From: J3 <j3-bounces at mailman.j3-fortran.org> on behalf of Steidel, Jon L via J3 <j3 at mailman.j3-fortran.org>
Date: Thursday, July 3, 2025 at 4:13 PM
To: General J3 interest list <j3 at mailman.j3-fortran.org>
Cc: Steidel, Jon L <jon.l.steidel at intel.com>, Jahagirdar, Tanvi <tanvi.jahagirdar at intel.com>
Subject: [EXTERNAL] [J3] Finalization question(s)
Hello, I posted a version of this a while back and then withdrew my question. But upon closer inspection of the standard’s rule for finalization, I still have some questions about the correct behavior. Consider the following program: module
Hello,
I posted a version of this a while back and then withdrew my question. But upon closer inspection of the standard’s rule for finalization, I still have some questions about the correct behavior.
Consider the following program:
module TestTypesModule
type :: FooType
integer :: x
contains
generic :: assignment(=) => Assign
final :: Finalize
procedure :: Assign
end type
type :: BarType
type(FooType) :: f
end type
type :: BarAllocType
type(FooType), allocatable :: f
end type
contains
subroutine Assign(self, src)
class(FooType), intent(out) :: self
type(FooType), intent(in) :: src
write(*,*) "assign", self%x, src%x
self%x = src%x + 1
end subroutine
subroutine Finalize(self)
type(FooType), intent(inout) :: self
write(*,*) "finalize", self%x
self%x = -1
end subroutine
end module
program assigntest
use TestTypesModule
implicit none
type(BarType) :: x, y
type(BarAllocType) :: xa, ya
write(*,*) 'non-allocatable'
x%f%x = 7
y%f%x = 42
y = x ! y finalized twice?
write(*,*) 'x', x%f%x, 'y', y%f%x
write(*,*) 'allocatable'
allocate(xa%f)
allocate(ya%f)
xa%f%x = 7
ya%f%x = 42
ya = xa ! ya finalized twice?
write(*,*) 'x', xa%f%x, 'y', ya%f%x
end program
In section 7.5.6.1 Final subroutines, p2 states:
A derived type if finalizable if and only if it has a final subroutine or a nonpointer, nonallocatable component of finalizable type. A nonpointer data entity is finalizable if and only if it is of finalizable type. No other entity is finalizable.
TypeFoo type has a final subroutine, so it is finalizable. TypeBar type, while not having a final subroutine is still finalizable because it has a nonpointer, nonallocatable component of finalizable type. TypeAllocBar type is not finalizable as it has no final routine, and its only component is allocatable; the type does not have a nonpointer, nonallocatable component of finalizable type. Thus y is finalizable, ya is not.
In section 7.5.6.3 When finalization occurs p1
When an intrinsic assignment statement is executed, if the variable is not an unallocated allocatable variable, it is finalized after evaluation of expr and before the definition of the variable.
In this test the LHS of the assignment y = x is finalizable, so y is finalized after evaluation of x but before assignment to y. In assignment statement ya=xa, the LHS is not finalizable, so xa is evaluated and assigned to ya. More on ya=xa below.
In the same section, p7 states
When a procedure is invoked, a nonpointer, nonallocatable, INTENT (OUT) dummy argument of that procedure is finalized before it becomes defined.
When the assignment of x to y occurs, y%f=x%f is a defined assignment performed by the procedure Assign. The self dummy argument is an INTENT (OUT) dummy argument is not declared to be ALLOCATABLE, so it is finalized. This means that y%f is finalized a second time.
Now consider the assignment statement ya = xa. 10.2.1.3 Interpretation of intrinsic assignments p15 states:
. . . For a noncoarray allocatable component the following sequence of operations is applied.
1. If the component of the variable is allocated, it is deallocated.
2. If the component of the value of expr is allocated, the corresponding component of the variable is allocated with the same dynamic type and type parameters as the component of expr. … The value of the component of the value of expr is then assigned to the corresponding component of the variable using defined assignment if the declared type of the component has a type-bound defined assignment consistent with the component, and intrinsic assignment for the dynamic type of that component otherwise.
This says that ya%f, an allocated allocatable component of ya is deallocated. 7.5.6.3 When finalization occurs p2 states:
… When an allocatable entity is deallocated, it is finalized unless it is the variable in an intrinsic assignment statement.
So, when ya%f is deallocated, it is finalized. It is then allocated and assigned the value of xa%f by the defined assignment procedure ASSIGN. Since ya%f is associated with the INTENT (OUT) non-allocatable dummy argument of ASSIGN, it is finalized again a second time.
Different compilers produce different results with respect to what gets finalized and how many times each is finalized.
By my reading, both y%f and ya%f each get finalized twice. Is this behavior intended?
Thank you for any insights.
-jon
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.j3-fortran.org/pipermail/j3/attachments/20250707/e694b4a4/attachment.htm>
More information about the J3
mailing list