• Finalization with defined assignment

    From Thomas Koenig@21:1/5 to All on Tue Aug 9 14:52:57 2022
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to Thomas Koenig on Tue Aug 9 14:28:04 2022
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to FortranFan on Wed Aug 10 11:12:26 2022
    FortranFan <parekhvs@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).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From JRR@21:1/5 to All on Wed Aug 10 15:26:01 2022
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From JRR@21:1/5 to All on Wed Aug 10 18:50:03 2022
    Am 10.08.22 um 13:12 schrieb Thomas Koenig:
    FortranFan <parekhvs@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).

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to JRR on Wed Aug 10 21:26:35 2022
    JRR <juergen.reuter@invalid.com> schrieb:
    Am 10.08.22 um 13:12 schrieb Thomas Koenig:
    FortranFan <parekhvs@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.

    [...]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to Thomas Koenig on Sat Aug 13 07:45:07 2022
    Thomas Koenig <tkoenig@netcologne.de> schrieb:
    FortranFan <parekhvs@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...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From FortranFan@21:1/5 to Thomas Koenig on Sat Aug 13 07:15:23 2022
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Thomas Koenig@21:1/5 to FortranFan on Sat Aug 13 15:31:11 2022
    FortranFan <parekhvs@gmail.com> schrieb:
    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

    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 :-)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)