Finalization with defined assignment

108 views
Skip to first unread message

Thomas Koenig

unread,
Aug 9, 2022, 10:53:00 AMAug 9
to
I have a question on finalization. The following program prints
different things with different compilers, and I wonder which
is correct. (The "assignment" is a bit strange to better see what
is going on). One output I get is (xlf and nagfor)

to_foo 3
assign 4
cleanup 3
cleanup 4

and the other one (gfortran)

to_foo 3
assign 4
cleanup 4

Now, if I look at where all the action is occuring,

a = to_foo(3)

this is not an intrinsic assignment, but rather a defined
assignment. Looking at "7.5.6.3 When finalization occurs", I do
not see defined assignment in the list. So, my conclusion would
be that cleanup should only be called once. (I am not sure that
this would be convenient, but it would be according to what I read
in the standard).

So, what is right? Or did I miss an erratum?

module y
implicit none
type foo
integer :: n
contains
final :: cleanup
end type foo
interface assignment (=)
module procedure assign
end interface assignment (=)
contains

subroutine assign (rop, op)
type(foo), intent(inout) :: rop
type(foo), intent(in) :: op
rop%n = op%n + 1
print '(A12,I3)',"assign", rop%n
end subroutine assign

function to_foo(n) result(res)
integer, intent(in) :: n
type (foo) :: res
res%n = n
print '(A12,I3)', "to_foo", res%n
end function to_foo

subroutine cleanup (self)
type (foo), intent(inout) :: self
print '(A12,I3)', "cleanup", self%n
end subroutine cleanup
end module y

program memain
use y
implicit none
call chk
contains
subroutine chk
type (foo) :: a
a = to_foo(3)
end subroutine chk
end program memain

FortranFan

unread,
Aug 9, 2022, 5:28:06 PMAug 9
to
On Tuesday, August 9, 2022 at 10:53:00 AM UTC-4, Thomas Koenig wrote:

> ..
> this is not an intrinsic assignment, but rather a defined
> assignment. Looking at "7.5.6.3 When finalization occurs", I do
> not see defined assignment in the list. So, my conclusion would
> be that cleanup should only be called once. (I am not sure that
> this would be convenient, but it would be according to what I read
> in the standard). ..

At first glance at the code (I did not copy and paste it to try it with Intel Fortran), the following in the standard appears applicable, "A nonpointer, nonallocatable object that is not a dummy argument or function result is finalized immediately before it would become undefined due to execution of a RETURN or END statement (19.6.6, item (3))."

From the output you show, it appears gfortran fails to finalize the function result i.e., the object created toward 'res' in the 'to_foo' function.

You might find outstanding bug reports toward finalization in gfortran Bugzilla that refer to the same or similar cases.

Thomas Koenig

unread,
Aug 10, 2022, 7:12:30 AMAug 10
to
FortranFan <pare...@gmail.com> schrieb:
> On Tuesday, August 9, 2022 at 10:53:00 AM UTC-4, Thomas Koenig wrote:
>
>> ..
>> this is not an intrinsic assignment, but rather a defined
>> assignment. Looking at "7.5.6.3 When finalization occurs", I do
>> not see defined assignment in the list. So, my conclusion would
>> be that cleanup should only be called once. (I am not sure that
>> this would be convenient, but it would be according to what I read
>> in the standard). ..
>
> At first glance at the code (I did not copy and paste it to try
> it with Intel Fortran), the following in the standard appears
> applicable, "A nonpointer, nonallocatable object that is not a
> dummy argument or function result is finalized immediately before it
> would become undefined due to execution of a RETURN or END statement
> (19.6.6, item (3))."

I saw that, but it did not seem to apply due to the definition of a
function result in 5.4.3.1: "A data entity that is the result of the
execution of a function reference is called the function result."

It is also strange because the object that is returned does
not become undefined due to RETURN or END. Rather it becomes
inaccessible (and could be defined to become undefined) once the
assignment is complete.

I am more than happy with nagfor's and xlf's behavior, because it
certainly is the right thing to do, but I have not yet to find
a justification for it in the standard.

Also, I do not see a change in 22-007r1.

(And taken note 1 to 7.5.6.3 into account, it would make no sense
_not_ to finalize).

JRR

unread,
Aug 10, 2022, 9:26:09 AMAug 10
to
Am 09.08.22 um 16:52 schrieb Thomas Koenig:
> I have a question on finalization. The following program prints
> different things with different compilers, and I wonder which
> is correct. (The "assignment" is a bit strange to better see what
> is going on). One output I get is (xlf and nagfor)
>
> to_foo 3
> assign 4
> cleanup 3
> cleanup 4
>
> and the other one (gfortran)
>
> to_foo 3
> assign 4
> cleanup 4
>
> Now, if I look at where all the action is occuring,
>
> a = to_foo(3)
>

Hi Thomas,
just as a quick check (then I will look in the standard myself),
Intel (v2021.5.0) supports the first version, while Nvidia (v22.3)
has yet another option:
$ nvfortran final.f90
reuter@t00pcx29380:~$ ./a.out
cleanup 0
to_foo 3
assign 4
cleanup 4
Cheers,
JRR


--
Juergen Reuter
Theoretical Particle Physics
Deutsches Elektronen-Synchrotron (DESY)
Hamburg, Germany


JRR

unread,
Aug 10, 2022, 12:50:09 PMAug 10
to
Am 10.08.22 um 13:12 schrieb Thomas Koenig:
> FortranFan <pare...@gmail.com> schrieb:
>> On Tuesday, August 9, 2022 at 10:53:00 AM UTC-4, Thomas Koenig wrote:
>>
..
>>
>> At first glance at the code (I did not copy and paste it to try
>> it with Intel Fortran), the following in the standard appears
>> applicable, "A nonpointer, nonallocatable object that is not a
>> dummy argument or function result is finalized immediately before it
>> would become undefined due to execution of a RETURN or END statement
>> (19.6.6, item (3))."
>
> I saw that, but it did not seem to apply due to the definition of a
> function result in 5.4.3.1: "A data entity that is the result of the
> execution of a function reference is called the function result."
>

I would say that 7.5.6.3.7 applies (a function result is an intent(out)
dummy argument of a procedure), 7.5.6.3.3 explicitly excludes function
results, or?:
"When a procedure is invoked, a nonpointer, nonallocatable, INTENT (OUT)
dummy argument of that procedure is finalized before it becomes undefined."
and then 19.6.6.15 c) applies:
"When a procedure is invoked an actual argument corresponding to a dummy
argument with INTENT (OUT) becomes undefined except for" [....any
nonpointer default-initialized subcomponents of the argument (doesn't
apply)],
An actual argument R1524 is one
entity (R1524) that appears in a procedure reference,
with
procedure reference
"appearance of a procedure designator, operator symbol, or assignment
symbol in a context requiring execution of the procedure at that point
during execution; or occurrence of defined input/output (13.7.6) or
derived-type finalization (7.5.6.2)"



> It is also strange because the object that is returned does
> not become undefined due to RETURN or END. Rather it becomes
> inaccessible (and could be defined to become undefined) once the
> assignment is complete.
>
> I am more than happy with nagfor's and xlf's behavior, because it
> certainly is the right thing to do, but I have not yet to find
> a justification for it in the standard.
>
> Also, I do not see a change in 22-007r1.
>
> (And taken note 1 to 7.5.6.3 into account, it would make no sense
> _not_ to finalize).

Thomas Koenig

unread,
Aug 10, 2022, 5:26:38 PMAug 10
to
JRR <juergen...@invalid.com> schrieb:
> Am 10.08.22 um 13:12 schrieb Thomas Koenig:
>> FortranFan <pare...@gmail.com> schrieb:
>>> On Tuesday, August 9, 2022 at 10:53:00 AM UTC-4, Thomas Koenig wrote:
>>>
> ..
>>>
>>> At first glance at the code (I did not copy and paste it to try
>>> it with Intel Fortran), the following in the standard appears
>>> applicable, "A nonpointer, nonallocatable object that is not a
>>> dummy argument or function result is finalized immediately before it
>>> would become undefined due to execution of a RETURN or END statement
>>> (19.6.6, item (3))."
>>
>> I saw that, but it did not seem to apply due to the definition of a
>> function result in 5.4.3.1: "A data entity that is the result of the
>> execution of a function reference is called the function result."
>>
>
> I would say that 7.5.6.3.7 applies (a function result is an intent(out)
> dummy argument of a procedure),

A function result is not an intent(out) dummy argument. They have
some similarities, but are defined to be different constructs.

It is not, for example, possible to pass an actual argument to
a function result, as you could with an intent(out) variable.

>7.5.6.3.3 explicitly excludes function
> results, or?:

Yes, it does. But I'm not quite clear what that entails.

[...]

Thomas Koenig

unread,
Aug 13, 2022, 3:45:13 AMAug 13
to
Thomas Koenig <tko...@netcologne.de> schrieb:
> FortranFan <pare...@gmail.com> schrieb:
>> On Tuesday, August 9, 2022 at 10:53:00 AM UTC-4, Thomas Koenig wrote:
>>
>>> ..
>>> this is not an intrinsic assignment, but rather a defined
>>> assignment. Looking at "7.5.6.3 When finalization occurs", I do
>>> not see defined assignment in the list. So, my conclusion would
>>> be that cleanup should only be called once. (I am not sure that
>>> this would be convenient, but it would be according to what I read
>>> in the standard). ..
>>
>> At first glance at the code (I did not copy and paste it to try
>> it with Intel Fortran), the following in the standard appears
>> applicable, "A nonpointer, nonallocatable object that is not a
>> dummy argument or function result is finalized immediately before it
>> would become undefined due to execution of a RETURN or END statement
>> (19.6.6, item (3))."
>
> I saw that, but it did not seem to apply due to the definition of a
> function result in 5.4.3.1: "A data entity that is the result of the
> execution of a function reference is called the function result."

Ah, I think I see the source of my misunderstanding.

In

function foo() result(res)
integer :: res
end function foo

res is the function result, but when invoking the function
in an expression, foo() is _not_ the function result.

Standardese...

FortranFan

unread,
Aug 13, 2022, 10:15:26 AMAug 13
to
On Saturday, August 13, 2022 at 3:45:13 AM UTC-4, Thomas Koenig wrote:

> ..
> > FortranFan schrieb:
> ..
> >> At first glance at the code (I did not copy and paste it to try
> >> it with Intel Fortran), the following in the standard appears
> >> applicable, "A nonpointer, nonallocatable object that is not a
> >> dummy argument or function result is finalized immediately before it
> >> would become undefined due to execution of a RETURN or END statement
> >> (19.6.6, item (3))."
> ..
> Ah, I think I see the source of my misunderstanding.
>
> In
>
> function foo() result(res)
> integer :: res
> end function foo
>
> res is the function result, but when invoking the function
> in an expression, foo() is _not_ the function result.
> ..

Glad you figured it out.

Please see the following link, perhaps you will touch base with Andrew (@abe...@carnegiescience.edu) and Paul Richard Thomas on enhancements to gfortran:
https://groups.google.com/g/comp.lang.fortran/c/n8Y4QX1_3tI/m/keJG5yFNAQAJ

Thomas Koenig

unread,
Aug 13, 2022, 11:31:14 AMAug 13
to
FortranFan <pare...@gmail.com> schrieb:
I've already started work on that myself, let's see how far I get
(or if I am even on the right track), but discussing with
Paul is definitely on the agenda :-)
Reply all
Reply to author
Forward
0 new messages