https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121475

            Bug ID: 121475
           Summary: Missed finalization
           Product: gcc
           Version: 16.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: abensonca at gcc dot gnu.org
  Target Milestone: ---

The following appears to be a case where finalization of a function result is
missed by the latest gfortran:

module bugMod

  type :: r
   contains
     procedure :: rma
     generic   :: assignment(=) => rma
  end type r

  type, extends(r) :: rm
     integer :: i
   contains
     final :: rmd
   end type rm

  interface rm
     module procedure rmc
  end interface rm

contains

  subroutine rmd(self)
    implicit none
    type(rm), intent(inout) :: self

    write (0,*) "type(rm) destructor called"
    return
  end subroutine rmd

  function rmc() result(self)
    implicit none
    type(rm) :: self

    write (0,*) "type(rm) constructor called"
    self%i=0
    return
  end function rmc

  subroutine rma(to,from)
    implicit none
    class(r), intent(  out) :: to
    class(r), intent(in   ) :: from

    write (0,*) "class(r) assignment(=) called"
    select type (to)
    type is (rm)
       select type (from)
       type is (rm)
          to%i=from%i
       end select
    end select
    return
  end subroutine rma

end module bugMod

program bugDestructFuncResult
  use bugMod
  implicit none

  block
    type(rm) :: i
    write (0,*) "construct our instance"
    i=rm()
    write (0,*) "finished"
  end block

end program bugDestructFuncResult

In this case I have a defined assignment for the parent class r of type rm. 
When assignment is done (in the constructor call i=rm()) I expect two calls to
the finalizer for type rm (one to finalize the left hand side of the
assignment, and one to finalize the function result. But, with the current
gfortran this gives:

> gfortran -v
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/carnegie/nobackup/users/abenson/upstream/libexec/gcc/x86_64-pc-linux-gnu/16.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../configure
--prefix=/carnegie/nobackup/users/abenson/upstream --disable-multilib
--enable-checking=release --enable-host-shared --with-pic
--enable-languages=c,c++,fortran,jit,lto
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 16.0.0 20250804 (experimental) (GCC)

> gfortran -g bugDestructFuncResult.F90
> ./a.out
 construct our instance
 type(rm) constructor called
 type(rm) destructor called
 class(r) assignment(=) called
 finished
 type(rm) destructor called

so only one call to the finalizer between the construct of the instance and
finished outputs (there's a last finalizer call at the end block when i is
finalized).

With ifort, I get:
> ifort -g bugDestructFuncResult.F90
> ./a.out
 construct our instance
 type(rm) constructor called
 type(rm) destructor called
 class(r) assignment(=) called
 type(rm) destructor called
 finished
 type(rm) destructor called

so two calls to the finalizer as expected.

Reply via email to