* FINAL subroutines
@ 2022-01-24 13:50 Salvatore Filippone
2022-01-24 14:49 ` Salvatore Filippone
0 siblings, 1 reply; 10+ messages in thread
From: Salvatore Filippone @ 2022-01-24 13:50 UTC (permalink / raw)
To: Fortran List
[-- Attachment #1: Type: text/plain, Size: 2162 bytes --]
Hi all
The attached code compiles and runs fine under both GNU and Intel, but it
produces different results, in particular the FINAL subroutine is invoked
just once with GNU, three times with Intel.
It seems to me that they cannot both be right; I am not sure what the
standard is mandating in this case.
Any ideas?
Salvatore
--------------- Intel
[pr1eio03@login1: newstuff]$ ifort -v
ifort version 19.1.1.217
[pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90
[pr1eio03@login1: newstuff]$ ./testfinal
Allocating wrapper
Calling new_outer_type
Assigning outer%test_item
Called delete_test_type
Called delete_test_type
End of new_outer_type
DeAllocating wrapper
Called delete_test_type
----------------------------- GNU
sfilippo@lagrange newstuff]$ gfortran -v
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap
--enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr
--mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=
http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix
--enable-checking=release --enable-multilib --with-system-zlib
--enable-__cxa_atexit --disable-libunwind-exceptions
--enable-gnu-unique-object --enable-linker-build-id
--with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin
--enable-initfini-array
--with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-linux/isl-install
--enable-offload-targets=nvptx-none --without-cuda-driver
--enable-gnu-indirect-function --enable-cet --with-tune=generic
--with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
[sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90
[sfilippo@lagrange newstuff]$ ./testfinal
Allocating wrapper
Calling new_outer_type
Assigning outer%test_item
End of new_outer_type
DeAllocating wrapper
Called delete_test_type
---------------------
[-- Attachment #2: testfinal.f90 --]
[-- Type: text/x-fortran, Size: 1460 bytes --]
module test_type_mod
type :: my_test_type
integer, allocatable :: i
contains
final :: delete_test_type
end type my_test_type
interface my_test_type
module procedure new_test_type_object
end interface my_test_type
contains
subroutine delete_test_type(this)
type(my_test_type) :: this
write(*,*) 'Called delete_test_type'
if (allocated(this%i)) deallocate(this%i)
end subroutine delete_test_type
function new_test_type_object(item) result(res)
type(my_test_type) :: res
integer, intent(in) :: item
!Allocation on assignment
res%i=item
end function new_test_type_object
end module test_type_mod
module target_mod
use test_type_mod
type :: outer_type
type(my_test_type), allocatable :: test_item
end type outer_type
contains
subroutine new_outer_type(outer,item)
type(outer_type), intent(out) :: outer
integer :: item
allocate(outer%test_item)
write(*,*) 'Assigning outer%test_item'
outer%test_item = my_test_type(itemi)
write(*,*) 'End of new_outer_type'
end subroutine new_outer_type
end module target_mod
program testfinal
use target_mod
implicit none
integer :: i=10
type(outer_type), allocatable :: wrapper
write(*,*) 'Allocating wrapper '
allocate(wrapper)
write(*,*) 'Calling new_outer_type '
call new_outer_type(wrapper,i)
write(*,*) 'DeAllocating wrapper '
deallocate(wrapper)
end program testfinal
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines
2022-01-24 13:50 FINAL subroutines Salvatore Filippone
@ 2022-01-24 14:49 ` Salvatore Filippone
2022-01-24 15:45 ` Andrew Benson
0 siblings, 1 reply; 10+ messages in thread
From: Salvatore Filippone @ 2022-01-24 14:49 UTC (permalink / raw)
To: Fortran List
And here is the code embedded as text............ sorry about sending an
attachment that was purged
------------------------- testfinal.f90 ---------------------
module test_type_mod
type :: my_test_type
integer, allocatable :: i
contains
final :: delete_test_type
end type my_test_type
interface my_test_type
module procedure new_test_type_object
end interface my_test_type
contains
subroutine delete_test_type(this)
type(my_test_type) :: this
write(*,*) 'Called delete_test_type'
if (allocated(this%i)) deallocate(this%i)
end subroutine delete_test_type
function new_test_type_object(item) result(res)
type(my_test_type) :: res
integer, intent(in) :: item
!Allocation on assignment
res%i=item
end function new_test_type_object
end module test_type_mod
module target_mod
use test_type_mod
type :: outer_type
type(my_test_type), allocatable :: test_item
end type outer_type
contains
subroutine new_outer_type(outer,item)
type(outer_type), intent(out) :: outer
integer :: item
allocate(outer%test_item)
write(*,*) 'Assigning outer%test_item'
outer%test_item = my_test_type(itemi)
write(*,*) 'End of new_outer_type'
end subroutine new_outer_type
end module target_mod
program testfinal
use target_mod
implicit none
integer :: i=10
type(outer_type), allocatable :: wrapper
write(*,*) 'Allocating wrapper '
allocate(wrapper)
write(*,*) 'Calling new_outer_type '
call new_outer_type(wrapper,i)
write(*,*) 'DeAllocating wrapper '
deallocate(wrapper)
end program testfinal
On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone <
filippone.salvatore@gmail.com> wrote:
> Hi all
> The attached code compiles and runs fine under both GNU and Intel, but it
> produces different results, in particular the FINAL subroutine is invoked
> just once with GNU, three times with Intel.
>
> It seems to me that they cannot both be right; I am not sure what the
> standard is mandating in this case.
> Any ideas?
> Salvatore
> --------------- Intel
> [pr1eio03@login1: newstuff]$ ifort -v
> ifort version 19.1.1.217
> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90
> [pr1eio03@login1: newstuff]$ ./testfinal
> Allocating wrapper
> Calling new_outer_type
> Assigning outer%test_item
> Called delete_test_type
> Called delete_test_type
> End of new_outer_type
> DeAllocating wrapper
> Called delete_test_type
> ----------------------------- GNU
> sfilippo@lagrange newstuff]$ gfortran -v
> Using built-in specs.
> COLLECT_GCC=gfortran
> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
> OFFLOAD_TARGET_NAMES=nvptx-none
> OFFLOAD_TARGET_DEFAULT=1
> Target: x86_64-redhat-linux
> Configured with: ../configure --enable-bootstrap
> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr
> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=
> http://bugzilla.redhat.com/bugzilla --enable-shared
> --enable-threads=posix --enable-checking=release --enable-multilib
> --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions
> --enable-gnu-unique-object --enable-linker-build-id
> --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin
> --enable-initfini-array
> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-linux/isl-install
> --enable-offload-targets=nvptx-none --without-cuda-driver
> --enable-gnu-indirect-function --enable-cet --with-tune=generic
> --with-arch_32=i686 --build=x86_64-redhat-linux
> Thread model: posix
> Supported LTO compression algorithms: zlib zstd
> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90
> [sfilippo@lagrange newstuff]$ ./testfinal
> Allocating wrapper
> Calling new_outer_type
> Assigning outer%test_item
> End of new_outer_type
> DeAllocating wrapper
> Called delete_test_type
> ---------------------
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines
2022-01-24 14:49 ` Salvatore Filippone
@ 2022-01-24 15:45 ` Andrew Benson
2022-01-24 16:11 ` Salvatore Filippone
0 siblings, 1 reply; 10+ messages in thread
From: Andrew Benson @ 2022-01-24 15:45 UTC (permalink / raw)
To: Salvatore Filippone; +Cc: Fortran List
Hi Salvatore,
This looks like it's related to some of the missing finalization functionality
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some patches
(e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html) which
implement most of the missing functionality. With those patches incorporated
your code gives the following output with gfortran:
$ ./testfinal
Allocating wrapper
Calling new_outer_type
Assigning outer%test_item
Called delete_test_type
End of new_outer_type
DeAllocating wrapper
Called delete_test_type
So there is one more call to the finalizer than you found - I haven't checked
carefully but I would guess this is a deallocation of LHS on assignment.
In testing these patches using the Intel compiler we found that it seems to
call the finalization wrapper more than it should, sometimes on objects that
have already been deallocated. Your code, compiled with the Intel compiler and
then run under valgrind shows the following:
$ valgrind ./testfinal
==7340== Memcheck, a memory error detector
==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==7340== Command: ./testfinal
==7340==
==7340== Conditional jump or move depends on uninitialised value(s)
==7340== at 0x493A51: __intel_sse2_strcpy (in /home/abensonca/Scratch/
ifortTests/testfinal)
==7340== by 0x45D70E: for__add_to_lf_table (in /home/abensonca/Scratch/
ifortTests/testfinal)
==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/
ifortTests/testfinal)
==7340== by 0x423A64: for__open_default (in /home/abensonca/Scratch/
ifortTests/testfinal)
==7340== by 0x4305A9: for_write_seq_lis (in /home/abensonca/Scratch/
ifortTests/testfinal)
==7340== by 0x4047E1: MAIN__ (testfinal.f90:62)
==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
testfinal)
==7340==
Allocating wrapper
Calling new_outer_type
Assigning outer%test_item
Called delete_test_type
==7340== Conditional jump or move depends on uninitialised value(s)
==7340== at 0x40572A: do_alloc_copy (in /home/abensonca/Scratch/ifortTests/
testfinal)
==7340== by 0x406B9A: do_alloc_copy (in /home/abensonca/Scratch/ifortTests/
testfinal)
==7340== by 0x4084ED: for_alloc_assign_v2 (in /home/abensonca/Scratch/
ifortTests/testfinal)
==7340== by 0x404474: target_mod_mp_new_outer_type_ (testfinal.f90:48)
==7340== by 0x40485E: MAIN__ (testfinal.f90:65)
==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
testfinal)
==7340==
Called delete_test_type
End of new_outer_type
DeAllocating wrapper
Called delete_test_type
==7340==
==7340== HEAP SUMMARY:
==7340== in use at exit: 48 bytes in 1 blocks
==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes allocated
==7340==
==7340== LEAK SUMMARY:
==7340== definitely lost: 48 bytes in 1 blocks
==7340== indirectly lost: 0 bytes in 0 blocks
==7340== possibly lost: 0 bytes in 0 blocks
==7340== still reachable: 0 bytes in 0 blocks
==7340== suppressed: 0 bytes in 0 blocks
==7340== Rerun with --leak-check=full to see details of leaked memory
==7340==
==7340== For counts of detected and suppressed errors, rerun with: -v
==7340== Use --track-origins=yes to see where uninitialised values come from
==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
so there are some cases of what look like incorrect accesses (and some leaked
memory).
Your code compiled with gfortran (with Paul's patches in place) shows no
errors or leaks from valgrind.
So, in summary, in this case I think the current gfortran is missing some
finalizations (which are fixed by Paul's patches), and ifort is likely doing
something wrong and probably calling the finalizer more times than it should.
-Andrew
On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via Fortran
wrote:
> And here is the code embedded as text............ sorry about sending an
> attachment that was purged
> ------------------------- testfinal.f90 ---------------------
> module test_type_mod
>
> type :: my_test_type
> integer, allocatable :: i
> contains
> final :: delete_test_type
> end type my_test_type
>
> interface my_test_type
> module procedure new_test_type_object
> end interface my_test_type
>
> contains
>
> subroutine delete_test_type(this)
> type(my_test_type) :: this
>
> write(*,*) 'Called delete_test_type'
> if (allocated(this%i)) deallocate(this%i)
>
> end subroutine delete_test_type
>
>
> function new_test_type_object(item) result(res)
> type(my_test_type) :: res
> integer, intent(in) :: item
> !Allocation on assignment
> res%i=item
> end function new_test_type_object
>
>
> end module test_type_mod
>
> module target_mod
> use test_type_mod
> type :: outer_type
> type(my_test_type), allocatable :: test_item
> end type outer_type
>
> contains
>
> subroutine new_outer_type(outer,item)
> type(outer_type), intent(out) :: outer
> integer :: item
>
> allocate(outer%test_item)
> write(*,*) 'Assigning outer%test_item'
> outer%test_item = my_test_type(itemi)
> write(*,*) 'End of new_outer_type'
> end subroutine new_outer_type
>
> end module target_mod
>
> program testfinal
> use target_mod
>
> implicit none
>
> integer :: i=10
> type(outer_type), allocatable :: wrapper
>
> write(*,*) 'Allocating wrapper '
> allocate(wrapper)
> write(*,*) 'Calling new_outer_type '
> call new_outer_type(wrapper,i)
> write(*,*) 'DeAllocating wrapper '
> deallocate(wrapper)
>
> end program testfinal
>
> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone <
>
> filippone.salvatore@gmail.com> wrote:
> > Hi all
> > The attached code compiles and runs fine under both GNU and Intel, but it
> > produces different results, in particular the FINAL subroutine is invoked
> > just once with GNU, three times with Intel.
> >
> > It seems to me that they cannot both be right; I am not sure what the
> > standard is mandating in this case.
> > Any ideas?
> > Salvatore
> > --------------- Intel
> > [pr1eio03@login1: newstuff]$ ifort -v
> > ifort version 19.1.1.217
> > [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90
> > [pr1eio03@login1: newstuff]$ ./testfinal
> >
> > Allocating wrapper
> > Calling new_outer_type
> > Assigning outer%test_item
> > Called delete_test_type
> > Called delete_test_type
> > End of new_outer_type
> > DeAllocating wrapper
> > Called delete_test_type
> >
> > ----------------------------- GNU
> > sfilippo@lagrange newstuff]$ gfortran -v
> > Using built-in specs.
> > COLLECT_GCC=gfortran
> > COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
> > OFFLOAD_TARGET_NAMES=nvptx-none
> > OFFLOAD_TARGET_DEFAULT=1
> > Target: x86_64-redhat-linux
> > Configured with: ../configure --enable-bootstrap
> > --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr
> > --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=
> > http://bugzilla.redhat.com/bugzilla --enable-shared
> > --enable-threads=posix --enable-checking=release --enable-multilib
> > --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions
> > --enable-gnu-unique-object --enable-linker-build-id
> > --with-gcc-major-version-only --with-linker-hash-style=gnu --enable-plugin
> > --enable-initfini-array
> > --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin
> > ux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver
> > --enable-gnu-indirect-function --enable-cet --with-tune=generic
> > --with-arch_32=i686 --build=x86_64-redhat-linux
> > Thread model: posix
> > Supported LTO compression algorithms: zlib zstd
> > gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
> > [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90
> > [sfilippo@lagrange newstuff]$ ./testfinal
> >
> > Allocating wrapper
> > Calling new_outer_type
> > Assigning outer%test_item
> > End of new_outer_type
> > DeAllocating wrapper
> > Called delete_test_type
> >
> > ---------------------
--
* Andrew Benson: https://abensonca.github.io
* Galacticus: https://github.com/galacticusorg/galacticus
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines
2022-01-24 15:45 ` Andrew Benson
@ 2022-01-24 16:11 ` Salvatore Filippone
2022-01-26 21:29 ` Jerry D
0 siblings, 1 reply; 10+ messages in thread
From: Salvatore Filippone @ 2022-01-24 16:11 UTC (permalink / raw)
To: Andrew Benson; +Cc: Fortran List, Damian Rouson
Thanks a lot
(yes, I suspected both gfortran and intel were wrong, precisely because I
could see why you'd need two FINAL calls, but not three).
Salvatore
On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson <abenson@carnegiescience.edu>
wrote:
> Hi Salvatore,
>
> This looks like it's related to some of the missing finalization
> functionality
> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some
> patches
> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html)
> which
> implement most of the missing functionality. With those patches
> incorporated
> your code gives the following output with gfortran:
>
> $ ./testfinal
> Allocating wrapper
> Calling new_outer_type
> Assigning outer%test_item
> Called delete_test_type
> End of new_outer_type
> DeAllocating wrapper
> Called delete_test_type
>
> So there is one more call to the finalizer than you found - I haven't
> checked
> carefully but I would guess this is a deallocation of LHS on assignment.
>
> In testing these patches using the Intel compiler we found that it seems
> to
> call the finalization wrapper more than it should, sometimes on objects
> that
> have already been deallocated. Your code, compiled with the Intel compiler
> and
> then run under valgrind shows the following:
>
> $ valgrind ./testfinal
> ==7340== Memcheck, a memory error detector
> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
> ==7340== Command: ./testfinal
> ==7340==
> ==7340== Conditional jump or move depends on uninitialised value(s)
> ==7340== at 0x493A51: __intel_sse2_strcpy (in /home/abensonca/Scratch/
> ifortTests/testfinal)
> ==7340== by 0x45D70E: for__add_to_lf_table (in /home/abensonca/Scratch/
> ifortTests/testfinal)
> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/
> ifortTests/testfinal)
> ==7340== by 0x423A64: for__open_default (in /home/abensonca/Scratch/
> ifortTests/testfinal)
> ==7340== by 0x4305A9: for_write_seq_lis (in /home/abensonca/Scratch/
> ifortTests/testfinal)
> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62)
> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
> testfinal)
> ==7340==
> Allocating wrapper
> Calling new_outer_type
> Assigning outer%test_item
> Called delete_test_type
> ==7340== Conditional jump or move depends on uninitialised value(s)
> ==7340== at 0x40572A: do_alloc_copy (in
> /home/abensonca/Scratch/ifortTests/
> testfinal)
> ==7340== by 0x406B9A: do_alloc_copy (in
> /home/abensonca/Scratch/ifortTests/
> testfinal)
> ==7340== by 0x4084ED: for_alloc_assign_v2 (in /home/abensonca/Scratch/
> ifortTests/testfinal)
> ==7340== by 0x404474: target_mod_mp_new_outer_type_ (testfinal.f90:48)
> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65)
> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
> testfinal)
> ==7340==
> Called delete_test_type
> End of new_outer_type
> DeAllocating wrapper
> Called delete_test_type
> ==7340==
> ==7340== HEAP SUMMARY:
> ==7340== in use at exit: 48 bytes in 1 blocks
> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes allocated
> ==7340==
> ==7340== LEAK SUMMARY:
> ==7340== definitely lost: 48 bytes in 1 blocks
> ==7340== indirectly lost: 0 bytes in 0 blocks
> ==7340== possibly lost: 0 bytes in 0 blocks
> ==7340== still reachable: 0 bytes in 0 blocks
> ==7340== suppressed: 0 bytes in 0 blocks
> ==7340== Rerun with --leak-check=full to see details of leaked memory
> ==7340==
> ==7340== For counts of detected and suppressed errors, rerun with: -v
> ==7340== Use --track-origins=yes to see where uninitialised values come
> from
> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
>
> so there are some cases of what look like incorrect accesses (and some
> leaked
> memory).
>
> Your code compiled with gfortran (with Paul's patches in place) shows no
> errors or leaks from valgrind.
>
> So, in summary, in this case I think the current gfortran is missing some
> finalizations (which are fixed by Paul's patches), and ifort is likely
> doing
> something wrong and probably calling the finalizer more times than it
> should.
>
> -Andrew
>
> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via Fortran
> wrote:
> > And here is the code embedded as text............ sorry about sending an
> > attachment that was purged
> > ------------------------- testfinal.f90 ---------------------
> > module test_type_mod
> >
> > type :: my_test_type
> > integer, allocatable :: i
> > contains
> > final :: delete_test_type
> > end type my_test_type
> >
> > interface my_test_type
> > module procedure new_test_type_object
> > end interface my_test_type
> >
> > contains
> >
> > subroutine delete_test_type(this)
> > type(my_test_type) :: this
> >
> > write(*,*) 'Called delete_test_type'
> > if (allocated(this%i)) deallocate(this%i)
> >
> > end subroutine delete_test_type
> >
> >
> > function new_test_type_object(item) result(res)
> > type(my_test_type) :: res
> > integer, intent(in) :: item
> > !Allocation on assignment
> > res%i=item
> > end function new_test_type_object
> >
> >
> > end module test_type_mod
> >
> > module target_mod
> > use test_type_mod
> > type :: outer_type
> > type(my_test_type), allocatable :: test_item
> > end type outer_type
> >
> > contains
> >
> > subroutine new_outer_type(outer,item)
> > type(outer_type), intent(out) :: outer
> > integer :: item
> >
> > allocate(outer%test_item)
> > write(*,*) 'Assigning outer%test_item'
> > outer%test_item = my_test_type(itemi)
> > write(*,*) 'End of new_outer_type'
> > end subroutine new_outer_type
> >
> > end module target_mod
> >
> > program testfinal
> > use target_mod
> >
> > implicit none
> >
> > integer :: i=10
> > type(outer_type), allocatable :: wrapper
> >
> > write(*,*) 'Allocating wrapper '
> > allocate(wrapper)
> > write(*,*) 'Calling new_outer_type '
> > call new_outer_type(wrapper,i)
> > write(*,*) 'DeAllocating wrapper '
> > deallocate(wrapper)
> >
> > end program testfinal
> >
> > On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone <
> >
> > filippone.salvatore@gmail.com> wrote:
> > > Hi all
> > > The attached code compiles and runs fine under both GNU and Intel, but
> it
> > > produces different results, in particular the FINAL subroutine is
> invoked
> > > just once with GNU, three times with Intel.
> > >
> > > It seems to me that they cannot both be right; I am not sure what the
> > > standard is mandating in this case.
> > > Any ideas?
> > > Salvatore
> > > --------------- Intel
> > > [pr1eio03@login1: newstuff]$ ifort -v
> > > ifort version 19.1.1.217
> > > [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90
> > > [pr1eio03@login1: newstuff]$ ./testfinal
> > >
> > > Allocating wrapper
> > > Calling new_outer_type
> > > Assigning outer%test_item
> > > Called delete_test_type
> > > Called delete_test_type
> > > End of new_outer_type
> > > DeAllocating wrapper
> > > Called delete_test_type
> > >
> > > ----------------------------- GNU
> > > sfilippo@lagrange newstuff]$ gfortran -v
> > > Using built-in specs.
> > > COLLECT_GCC=gfortran
> > > COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
> > > OFFLOAD_TARGET_NAMES=nvptx-none
> > > OFFLOAD_TARGET_DEFAULT=1
> > > Target: x86_64-redhat-linux
> > > Configured with: ../configure --enable-bootstrap
> > > --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto
> --prefix=/usr
> > > --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=
> > > http://bugzilla.redhat.com/bugzilla --enable-shared
> > > --enable-threads=posix --enable-checking=release --enable-multilib
> > > --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions
> > > --enable-gnu-unique-object --enable-linker-build-id
> > > --with-gcc-major-version-only --with-linker-hash-style=gnu
> --enable-plugin
> > > --enable-initfini-array
> > >
> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin
> > > ux/isl-install --enable-offload-targets=nvptx-none
> --without-cuda-driver
> > > --enable-gnu-indirect-function --enable-cet --with-tune=generic
> > > --with-arch_32=i686 --build=x86_64-redhat-linux
> > > Thread model: posix
> > > Supported LTO compression algorithms: zlib zstd
> > > gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
> > > [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90
> > > [sfilippo@lagrange newstuff]$ ./testfinal
> > >
> > > Allocating wrapper
> > > Calling new_outer_type
> > > Assigning outer%test_item
> > > End of new_outer_type
> > > DeAllocating wrapper
> > > Called delete_test_type
> > >
> > > ---------------------
>
>
> --
>
> * Andrew Benson: https://abensonca.github.io
>
> * Galacticus: https://github.com/galacticusorg/galacticus
>
>
>
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines
2022-01-24 16:11 ` Salvatore Filippone
@ 2022-01-26 21:29 ` Jerry D
2022-01-26 22:59 ` Paul Richard Thomas
0 siblings, 1 reply; 10+ messages in thread
From: Jerry D @ 2022-01-26 21:29 UTC (permalink / raw)
To: Salvatore Filippone, Andrew Benson; +Cc: Damian Rouson, Fortran List
Is there any reason these patches can not be applied and use this test
as a test case?
Regards,
Jerry
On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote:
> Thanks a lot
> (yes, I suspected both gfortran and intel were wrong, precisely because I
> could see why you'd need two FINAL calls, but not three).
>
> Salvatore
>
> On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson <abenson@carnegiescience.edu>
> wrote:
>
>> Hi Salvatore,
>>
>> This looks like it's related to some of the missing finalization
>> functionality
>> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some
>> patches
>> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html)
>> which
>> implement most of the missing functionality. With those patches
>> incorporated
>> your code gives the following output with gfortran:
>>
>> $ ./testfinal
>> Allocating wrapper
>> Calling new_outer_type
>> Assigning outer%test_item
>> Called delete_test_type
>> End of new_outer_type
>> DeAllocating wrapper
>> Called delete_test_type
>>
>> So there is one more call to the finalizer than you found - I haven't
>> checked
>> carefully but I would guess this is a deallocation of LHS on assignment.
>>
>> In testing these patches using the Intel compiler we found that it seems
>> to
>> call the finalization wrapper more than it should, sometimes on objects
>> that
>> have already been deallocated. Your code, compiled with the Intel compiler
>> and
>> then run under valgrind shows the following:
>>
>> $ valgrind ./testfinal
>> ==7340== Memcheck, a memory error detector
>> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
>> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
>> ==7340== Command: ./testfinal
>> ==7340==
>> ==7340== Conditional jump or move depends on uninitialised value(s)
>> ==7340== at 0x493A51: __intel_sse2_strcpy (in /home/abensonca/Scratch/
>> ifortTests/testfinal)
>> ==7340== by 0x45D70E: for__add_to_lf_table (in /home/abensonca/Scratch/
>> ifortTests/testfinal)
>> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/
>> ifortTests/testfinal)
>> ==7340== by 0x423A64: for__open_default (in /home/abensonca/Scratch/
>> ifortTests/testfinal)
>> ==7340== by 0x4305A9: for_write_seq_lis (in /home/abensonca/Scratch/
>> ifortTests/testfinal)
>> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62)
>> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
>> testfinal)
>> ==7340==
>> Allocating wrapper
>> Calling new_outer_type
>> Assigning outer%test_item
>> Called delete_test_type
>> ==7340== Conditional jump or move depends on uninitialised value(s)
>> ==7340== at 0x40572A: do_alloc_copy (in
>> /home/abensonca/Scratch/ifortTests/
>> testfinal)
>> ==7340== by 0x406B9A: do_alloc_copy (in
>> /home/abensonca/Scratch/ifortTests/
>> testfinal)
>> ==7340== by 0x4084ED: for_alloc_assign_v2 (in /home/abensonca/Scratch/
>> ifortTests/testfinal)
>> ==7340== by 0x404474: target_mod_mp_new_outer_type_ (testfinal.f90:48)
>> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65)
>> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
>> testfinal)
>> ==7340==
>> Called delete_test_type
>> End of new_outer_type
>> DeAllocating wrapper
>> Called delete_test_type
>> ==7340==
>> ==7340== HEAP SUMMARY:
>> ==7340== in use at exit: 48 bytes in 1 blocks
>> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes allocated
>> ==7340==
>> ==7340== LEAK SUMMARY:
>> ==7340== definitely lost: 48 bytes in 1 blocks
>> ==7340== indirectly lost: 0 bytes in 0 blocks
>> ==7340== possibly lost: 0 bytes in 0 blocks
>> ==7340== still reachable: 0 bytes in 0 blocks
>> ==7340== suppressed: 0 bytes in 0 blocks
>> ==7340== Rerun with --leak-check=full to see details of leaked memory
>> ==7340==
>> ==7340== For counts of detected and suppressed errors, rerun with: -v
>> ==7340== Use --track-origins=yes to see where uninitialised values come
>> from
>> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
>>
>> so there are some cases of what look like incorrect accesses (and some
>> leaked
>> memory).
>>
>> Your code compiled with gfortran (with Paul's patches in place) shows no
>> errors or leaks from valgrind.
>>
>> So, in summary, in this case I think the current gfortran is missing some
>> finalizations (which are fixed by Paul's patches), and ifort is likely
>> doing
>> something wrong and probably calling the finalizer more times than it
>> should.
>>
>> -Andrew
>>
>> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via Fortran
>> wrote:
>>> And here is the code embedded as text............ sorry about sending an
>>> attachment that was purged
>>> ------------------------- testfinal.f90 ---------------------
>>> module test_type_mod
>>>
>>> type :: my_test_type
>>> integer, allocatable :: i
>>> contains
>>> final :: delete_test_type
>>> end type my_test_type
>>>
>>> interface my_test_type
>>> module procedure new_test_type_object
>>> end interface my_test_type
>>>
>>> contains
>>>
>>> subroutine delete_test_type(this)
>>> type(my_test_type) :: this
>>>
>>> write(*,*) 'Called delete_test_type'
>>> if (allocated(this%i)) deallocate(this%i)
>>>
>>> end subroutine delete_test_type
>>>
>>>
>>> function new_test_type_object(item) result(res)
>>> type(my_test_type) :: res
>>> integer, intent(in) :: item
>>> !Allocation on assignment
>>> res%i=item
>>> end function new_test_type_object
>>>
>>>
>>> end module test_type_mod
>>>
>>> module target_mod
>>> use test_type_mod
>>> type :: outer_type
>>> type(my_test_type), allocatable :: test_item
>>> end type outer_type
>>>
>>> contains
>>>
>>> subroutine new_outer_type(outer,item)
>>> type(outer_type), intent(out) :: outer
>>> integer :: item
>>>
>>> allocate(outer%test_item)
>>> write(*,*) 'Assigning outer%test_item'
>>> outer%test_item = my_test_type(itemi)
>>> write(*,*) 'End of new_outer_type'
>>> end subroutine new_outer_type
>>>
>>> end module target_mod
>>>
>>> program testfinal
>>> use target_mod
>>>
>>> implicit none
>>>
>>> integer :: i=10
>>> type(outer_type), allocatable :: wrapper
>>>
>>> write(*,*) 'Allocating wrapper '
>>> allocate(wrapper)
>>> write(*,*) 'Calling new_outer_type '
>>> call new_outer_type(wrapper,i)
>>> write(*,*) 'DeAllocating wrapper '
>>> deallocate(wrapper)
>>>
>>> end program testfinal
>>>
>>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone <
>>>
>>> filippone.salvatore@gmail.com> wrote:
>>>> Hi all
>>>> The attached code compiles and runs fine under both GNU and Intel, but
>> it
>>>> produces different results, in particular the FINAL subroutine is
>> invoked
>>>> just once with GNU, three times with Intel.
>>>>
>>>> It seems to me that they cannot both be right; I am not sure what the
>>>> standard is mandating in this case.
>>>> Any ideas?
>>>> Salvatore
>>>> --------------- Intel
>>>> [pr1eio03@login1: newstuff]$ ifort -v
>>>> ifort version 19.1.1.217
>>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90
>>>> [pr1eio03@login1: newstuff]$ ./testfinal
>>>>
>>>> Allocating wrapper
>>>> Calling new_outer_type
>>>> Assigning outer%test_item
>>>> Called delete_test_type
>>>> Called delete_test_type
>>>> End of new_outer_type
>>>> DeAllocating wrapper
>>>> Called delete_test_type
>>>>
>>>> ----------------------------- GNU
>>>> sfilippo@lagrange newstuff]$ gfortran -v
>>>> Using built-in specs.
>>>> COLLECT_GCC=gfortran
>>>> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
>>>> OFFLOAD_TARGET_NAMES=nvptx-none
>>>> OFFLOAD_TARGET_DEFAULT=1
>>>> Target: x86_64-redhat-linux
>>>> Configured with: ../configure --enable-bootstrap
>>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto
>> --prefix=/usr
>>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=
>>>> http://bugzilla.redhat.com/bugzilla --enable-shared
>>>> --enable-threads=posix --enable-checking=release --enable-multilib
>>>> --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions
>>>> --enable-gnu-unique-object --enable-linker-build-id
>>>> --with-gcc-major-version-only --with-linker-hash-style=gnu
>> --enable-plugin
>>>> --enable-initfini-array
>>>>
>> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin
>>>> ux/isl-install --enable-offload-targets=nvptx-none
>> --without-cuda-driver
>>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic
>>>> --with-arch_32=i686 --build=x86_64-redhat-linux
>>>> Thread model: posix
>>>> Supported LTO compression algorithms: zlib zstd
>>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
>>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90
>>>> [sfilippo@lagrange newstuff]$ ./testfinal
>>>>
>>>> Allocating wrapper
>>>> Calling new_outer_type
>>>> Assigning outer%test_item
>>>> End of new_outer_type
>>>> DeAllocating wrapper
>>>> Called delete_test_type
>>>>
>>>> ---------------------
>>
>> --
>>
>> * Andrew Benson: https://abensonca.github.io
>>
>> * Galacticus: https://github.com/galacticusorg/galacticus
>>
>>
>>
>>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines
2022-01-26 21:29 ` Jerry D
@ 2022-01-26 22:59 ` Paul Richard Thomas
2022-01-27 7:17 ` Salvatore Filippone
0 siblings, 1 reply; 10+ messages in thread
From: Paul Richard Thomas @ 2022-01-26 22:59 UTC (permalink / raw)
To: Jerry D; +Cc: Salvatore Filippone, Andrew Benson, Damian Rouson, Fortran List
Hi Jerry,
I am trying to fix the failure of my latest patch with this very test case.
Otherwise it fixes most of the remaining dependencies in PR37336.
At a pinch, I could submit the earlier patch that Andrew mentions and work
from there. However, you will note that it does miss one of the
finalizations. This is critical because function results, which should be
finalized, are not.
I'll keep an eye on the state of the branch. By and large, release occurs
3-4 months after the start of stage 4. I will leave 2 months maximum.
Best regards
Paul
On Wed, 26 Jan 2022 at 21:29, Jerry D via Fortran <fortran@gcc.gnu.org>
wrote:
> Is there any reason these patches can not be applied and use this test
> as a test case?
>
> Regards,
>
> Jerry
>
> On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote:
> > Thanks a lot
> > (yes, I suspected both gfortran and intel were wrong, precisely because I
> > could see why you'd need two FINAL calls, but not three).
> >
> > Salvatore
> >
> > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson <
> abenson@carnegiescience.edu>
> > wrote:
> >
> >> Hi Salvatore,
> >>
> >> This looks like it's related to some of the missing finalization
> >> functionality
> >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some
> >> patches
> >> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html)
> >> which
> >> implement most of the missing functionality. With those patches
> >> incorporated
> >> your code gives the following output with gfortran:
> >>
> >> $ ./testfinal
> >> Allocating wrapper
> >> Calling new_outer_type
> >> Assigning outer%test_item
> >> Called delete_test_type
> >> End of new_outer_type
> >> DeAllocating wrapper
> >> Called delete_test_type
> >>
> >> So there is one more call to the finalizer than you found - I haven't
> >> checked
> >> carefully but I would guess this is a deallocation of LHS on assignment.
> >>
> >> In testing these patches using the Intel compiler we found that it seems
> >> to
> >> call the finalization wrapper more than it should, sometimes on objects
> >> that
> >> have already been deallocated. Your code, compiled with the Intel
> compiler
> >> and
> >> then run under valgrind shows the following:
> >>
> >> $ valgrind ./testfinal
> >> ==7340== Memcheck, a memory error detector
> >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
> >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright
> info
> >> ==7340== Command: ./testfinal
> >> ==7340==
> >> ==7340== Conditional jump or move depends on uninitialised value(s)
> >> ==7340== at 0x493A51: __intel_sse2_strcpy (in
> /home/abensonca/Scratch/
> >> ifortTests/testfinal)
> >> ==7340== by 0x45D70E: for__add_to_lf_table (in
> /home/abensonca/Scratch/
> >> ifortTests/testfinal)
> >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/
> >> ifortTests/testfinal)
> >> ==7340== by 0x423A64: for__open_default (in /home/abensonca/Scratch/
> >> ifortTests/testfinal)
> >> ==7340== by 0x4305A9: for_write_seq_lis (in /home/abensonca/Scratch/
> >> ifortTests/testfinal)
> >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62)
> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
> >> testfinal)
> >> ==7340==
> >> Allocating wrapper
> >> Calling new_outer_type
> >> Assigning outer%test_item
> >> Called delete_test_type
> >> ==7340== Conditional jump or move depends on uninitialised value(s)
> >> ==7340== at 0x40572A: do_alloc_copy (in
> >> /home/abensonca/Scratch/ifortTests/
> >> testfinal)
> >> ==7340== by 0x406B9A: do_alloc_copy (in
> >> /home/abensonca/Scratch/ifortTests/
> >> testfinal)
> >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in
> /home/abensonca/Scratch/
> >> ifortTests/testfinal)
> >> ==7340== by 0x404474: target_mod_mp_new_outer_type_
> (testfinal.f90:48)
> >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65)
> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
> >> testfinal)
> >> ==7340==
> >> Called delete_test_type
> >> End of new_outer_type
> >> DeAllocating wrapper
> >> Called delete_test_type
> >> ==7340==
> >> ==7340== HEAP SUMMARY:
> >> ==7340== in use at exit: 48 bytes in 1 blocks
> >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes allocated
> >> ==7340==
> >> ==7340== LEAK SUMMARY:
> >> ==7340== definitely lost: 48 bytes in 1 blocks
> >> ==7340== indirectly lost: 0 bytes in 0 blocks
> >> ==7340== possibly lost: 0 bytes in 0 blocks
> >> ==7340== still reachable: 0 bytes in 0 blocks
> >> ==7340== suppressed: 0 bytes in 0 blocks
> >> ==7340== Rerun with --leak-check=full to see details of leaked memory
> >> ==7340==
> >> ==7340== For counts of detected and suppressed errors, rerun with: -v
> >> ==7340== Use --track-origins=yes to see where uninitialised values come
> >> from
> >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
> >>
> >> so there are some cases of what look like incorrect accesses (and some
> >> leaked
> >> memory).
> >>
> >> Your code compiled with gfortran (with Paul's patches in place) shows
> no
> >> errors or leaks from valgrind.
> >>
> >> So, in summary, in this case I think the current gfortran is missing
> some
> >> finalizations (which are fixed by Paul's patches), and ifort is likely
> >> doing
> >> something wrong and probably calling the finalizer more times than it
> >> should.
> >>
> >> -Andrew
> >>
> >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via
> Fortran
> >> wrote:
> >>> And here is the code embedded as text............ sorry about sending
> an
> >>> attachment that was purged
> >>> ------------------------- testfinal.f90 ---------------------
> >>> module test_type_mod
> >>>
> >>> type :: my_test_type
> >>> integer, allocatable :: i
> >>> contains
> >>> final :: delete_test_type
> >>> end type my_test_type
> >>>
> >>> interface my_test_type
> >>> module procedure new_test_type_object
> >>> end interface my_test_type
> >>>
> >>> contains
> >>>
> >>> subroutine delete_test_type(this)
> >>> type(my_test_type) :: this
> >>>
> >>> write(*,*) 'Called delete_test_type'
> >>> if (allocated(this%i)) deallocate(this%i)
> >>>
> >>> end subroutine delete_test_type
> >>>
> >>>
> >>> function new_test_type_object(item) result(res)
> >>> type(my_test_type) :: res
> >>> integer, intent(in) :: item
> >>> !Allocation on assignment
> >>> res%i=item
> >>> end function new_test_type_object
> >>>
> >>>
> >>> end module test_type_mod
> >>>
> >>> module target_mod
> >>> use test_type_mod
> >>> type :: outer_type
> >>> type(my_test_type), allocatable :: test_item
> >>> end type outer_type
> >>>
> >>> contains
> >>>
> >>> subroutine new_outer_type(outer,item)
> >>> type(outer_type), intent(out) :: outer
> >>> integer :: item
> >>>
> >>> allocate(outer%test_item)
> >>> write(*,*) 'Assigning outer%test_item'
> >>> outer%test_item = my_test_type(itemi)
> >>> write(*,*) 'End of new_outer_type'
> >>> end subroutine new_outer_type
> >>>
> >>> end module target_mod
> >>>
> >>> program testfinal
> >>> use target_mod
> >>>
> >>> implicit none
> >>>
> >>> integer :: i=10
> >>> type(outer_type), allocatable :: wrapper
> >>>
> >>> write(*,*) 'Allocating wrapper '
> >>> allocate(wrapper)
> >>> write(*,*) 'Calling new_outer_type '
> >>> call new_outer_type(wrapper,i)
> >>> write(*,*) 'DeAllocating wrapper '
> >>> deallocate(wrapper)
> >>>
> >>> end program testfinal
> >>>
> >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone <
> >>>
> >>> filippone.salvatore@gmail.com> wrote:
> >>>> Hi all
> >>>> The attached code compiles and runs fine under both GNU and Intel, but
> >> it
> >>>> produces different results, in particular the FINAL subroutine is
> >> invoked
> >>>> just once with GNU, three times with Intel.
> >>>>
> >>>> It seems to me that they cannot both be right; I am not sure what the
> >>>> standard is mandating in this case.
> >>>> Any ideas?
> >>>> Salvatore
> >>>> --------------- Intel
> >>>> [pr1eio03@login1: newstuff]$ ifort -v
> >>>> ifort version 19.1.1.217
> >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90
> >>>> [pr1eio03@login1: newstuff]$ ./testfinal
> >>>>
> >>>> Allocating wrapper
> >>>> Calling new_outer_type
> >>>> Assigning outer%test_item
> >>>> Called delete_test_type
> >>>> Called delete_test_type
> >>>> End of new_outer_type
> >>>> DeAllocating wrapper
> >>>> Called delete_test_type
> >>>>
> >>>> ----------------------------- GNU
> >>>> sfilippo@lagrange newstuff]$ gfortran -v
> >>>> Using built-in specs.
> >>>> COLLECT_GCC=gfortran
> >>>>
> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
> >>>> OFFLOAD_TARGET_NAMES=nvptx-none
> >>>> OFFLOAD_TARGET_DEFAULT=1
> >>>> Target: x86_64-redhat-linux
> >>>> Configured with: ../configure --enable-bootstrap
> >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto
> >> --prefix=/usr
> >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=
> >>>> http://bugzilla.redhat.com/bugzilla --enable-shared
> >>>> --enable-threads=posix --enable-checking=release --enable-multilib
> >>>> --with-system-zlib --enable-__cxa_atexit
> --disable-libunwind-exceptions
> >>>> --enable-gnu-unique-object --enable-linker-build-id
> >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu
> >> --enable-plugin
> >>>> --enable-initfini-array
> >>>>
> >>
> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin
> >>>> ux/isl-install --enable-offload-targets=nvptx-none
> >> --without-cuda-driver
> >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic
> >>>> --with-arch_32=i686 --build=x86_64-redhat-linux
> >>>> Thread model: posix
> >>>> Supported LTO compression algorithms: zlib zstd
> >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
> >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90
> >>>> [sfilippo@lagrange newstuff]$ ./testfinal
> >>>>
> >>>> Allocating wrapper
> >>>> Calling new_outer_type
> >>>> Assigning outer%test_item
> >>>> End of new_outer_type
> >>>> DeAllocating wrapper
> >>>> Called delete_test_type
> >>>>
> >>>> ---------------------
> >>
> >> --
> >>
> >> * Andrew Benson: https://abensonca.github.io
> >>
> >> * Galacticus: https://github.com/galacticusorg/galacticus
> >>
> >>
> >>
> >>
>
>
--
"If you can't explain it simply, you don't understand it well enough" -
Albert Einstein
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines
2022-01-26 22:59 ` Paul Richard Thomas
@ 2022-01-27 7:17 ` Salvatore Filippone
2022-01-27 22:10 ` Paul Richard Thomas
0 siblings, 1 reply; 10+ messages in thread
From: Salvatore Filippone @ 2022-01-27 7:17 UTC (permalink / raw)
To: Paul Richard Thomas; +Cc: Jerry D, Andrew Benson, Damian Rouson, Fortran List
One more data point: Cray FTN issues TWO calls to the FINAL.
Which begs the question: what is the correct number of calls one, two or
three?
Salvatore
fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
ftn --version
Cray Fortran : Version 11.0.0
fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
ftn -o testfinal testfinal.f90
fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
./testfinal
Allocating wrapper
Calling new_outer_type
Assigning outer%test_item
Called delete_test_type
End of new_outer_type
DeAllocating wrapper
Called delete_test_type
On Wed, Jan 26, 2022 at 11:59 PM Paul Richard Thomas <
paul.richard.thomas@gmail.com> wrote:
> Hi Jerry,
>
> I am trying to fix the failure of my latest patch with this very test
> case. Otherwise it fixes most of the remaining dependencies in PR37336.
>
> At a pinch, I could submit the earlier patch that Andrew mentions and work
> from there. However, you will note that it does miss one of the
> finalizations. This is critical because function results, which should be
> finalized, are not.
>
> I'll keep an eye on the state of the branch. By and large, release occurs
> 3-4 months after the start of stage 4. I will leave 2 months maximum.
>
> Best regards
>
> Paul
>
>
> On Wed, 26 Jan 2022 at 21:29, Jerry D via Fortran <fortran@gcc.gnu.org>
> wrote:
>
>> Is there any reason these patches can not be applied and use this test
>> as a test case?
>>
>> Regards,
>>
>> Jerry
>>
>> On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote:
>> > Thanks a lot
>> > (yes, I suspected both gfortran and intel were wrong, precisely because
>> I
>> > could see why you'd need two FINAL calls, but not three).
>> >
>> > Salvatore
>> >
>> > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson <
>> abenson@carnegiescience.edu>
>> > wrote:
>> >
>> >> Hi Salvatore,
>> >>
>> >> This looks like it's related to some of the missing finalization
>> >> functionality
>> >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some
>> >> patches
>> >> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html)
>> >> which
>> >> implement most of the missing functionality. With those patches
>> >> incorporated
>> >> your code gives the following output with gfortran:
>> >>
>> >> $ ./testfinal
>> >> Allocating wrapper
>> >> Calling new_outer_type
>> >> Assigning outer%test_item
>> >> Called delete_test_type
>> >> End of new_outer_type
>> >> DeAllocating wrapper
>> >> Called delete_test_type
>> >>
>> >> So there is one more call to the finalizer than you found - I haven't
>> >> checked
>> >> carefully but I would guess this is a deallocation of LHS on
>> assignment.
>> >>
>> >> In testing these patches using the Intel compiler we found that it
>> seems
>> >> to
>> >> call the finalization wrapper more than it should, sometimes on objects
>> >> that
>> >> have already been deallocated. Your code, compiled with the Intel
>> compiler
>> >> and
>> >> then run under valgrind shows the following:
>> >>
>> >> $ valgrind ./testfinal
>> >> ==7340== Memcheck, a memory error detector
>> >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et
>> al.
>> >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright
>> info
>> >> ==7340== Command: ./testfinal
>> >> ==7340==
>> >> ==7340== Conditional jump or move depends on uninitialised value(s)
>> >> ==7340== at 0x493A51: __intel_sse2_strcpy (in
>> /home/abensonca/Scratch/
>> >> ifortTests/testfinal)
>> >> ==7340== by 0x45D70E: for__add_to_lf_table (in
>> /home/abensonca/Scratch/
>> >> ifortTests/testfinal)
>> >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/
>> >> ifortTests/testfinal)
>> >> ==7340== by 0x423A64: for__open_default (in /home/abensonca/Scratch/
>> >> ifortTests/testfinal)
>> >> ==7340== by 0x4305A9: for_write_seq_lis (in /home/abensonca/Scratch/
>> >> ifortTests/testfinal)
>> >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62)
>> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
>> >> testfinal)
>> >> ==7340==
>> >> Allocating wrapper
>> >> Calling new_outer_type
>> >> Assigning outer%test_item
>> >> Called delete_test_type
>> >> ==7340== Conditional jump or move depends on uninitialised value(s)
>> >> ==7340== at 0x40572A: do_alloc_copy (in
>> >> /home/abensonca/Scratch/ifortTests/
>> >> testfinal)
>> >> ==7340== by 0x406B9A: do_alloc_copy (in
>> >> /home/abensonca/Scratch/ifortTests/
>> >> testfinal)
>> >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in
>> /home/abensonca/Scratch/
>> >> ifortTests/testfinal)
>> >> ==7340== by 0x404474: target_mod_mp_new_outer_type_
>> (testfinal.f90:48)
>> >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65)
>> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
>> >> testfinal)
>> >> ==7340==
>> >> Called delete_test_type
>> >> End of new_outer_type
>> >> DeAllocating wrapper
>> >> Called delete_test_type
>> >> ==7340==
>> >> ==7340== HEAP SUMMARY:
>> >> ==7340== in use at exit: 48 bytes in 1 blocks
>> >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes
>> allocated
>> >> ==7340==
>> >> ==7340== LEAK SUMMARY:
>> >> ==7340== definitely lost: 48 bytes in 1 blocks
>> >> ==7340== indirectly lost: 0 bytes in 0 blocks
>> >> ==7340== possibly lost: 0 bytes in 0 blocks
>> >> ==7340== still reachable: 0 bytes in 0 blocks
>> >> ==7340== suppressed: 0 bytes in 0 blocks
>> >> ==7340== Rerun with --leak-check=full to see details of leaked memory
>> >> ==7340==
>> >> ==7340== For counts of detected and suppressed errors, rerun with: -v
>> >> ==7340== Use --track-origins=yes to see where uninitialised values come
>> >> from
>> >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
>> >>
>> >> so there are some cases of what look like incorrect accesses (and some
>> >> leaked
>> >> memory).
>> >>
>> >> Your code compiled with gfortran (with Paul's patches in place) shows
>> no
>> >> errors or leaks from valgrind.
>> >>
>> >> So, in summary, in this case I think the current gfortran is missing
>> some
>> >> finalizations (which are fixed by Paul's patches), and ifort is likely
>> >> doing
>> >> something wrong and probably calling the finalizer more times than it
>> >> should.
>> >>
>> >> -Andrew
>> >>
>> >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via
>> Fortran
>> >> wrote:
>> >>> And here is the code embedded as text............ sorry about
>> sending an
>> >>> attachment that was purged
>> >>> ------------------------- testfinal.f90 ---------------------
>> >>> module test_type_mod
>> >>>
>> >>> type :: my_test_type
>> >>> integer, allocatable :: i
>> >>> contains
>> >>> final :: delete_test_type
>> >>> end type my_test_type
>> >>>
>> >>> interface my_test_type
>> >>> module procedure new_test_type_object
>> >>> end interface my_test_type
>> >>>
>> >>> contains
>> >>>
>> >>> subroutine delete_test_type(this)
>> >>> type(my_test_type) :: this
>> >>>
>> >>> write(*,*) 'Called delete_test_type'
>> >>> if (allocated(this%i)) deallocate(this%i)
>> >>>
>> >>> end subroutine delete_test_type
>> >>>
>> >>>
>> >>> function new_test_type_object(item) result(res)
>> >>> type(my_test_type) :: res
>> >>> integer, intent(in) :: item
>> >>> !Allocation on assignment
>> >>> res%i=item
>> >>> end function new_test_type_object
>> >>>
>> >>>
>> >>> end module test_type_mod
>> >>>
>> >>> module target_mod
>> >>> use test_type_mod
>> >>> type :: outer_type
>> >>> type(my_test_type), allocatable :: test_item
>> >>> end type outer_type
>> >>>
>> >>> contains
>> >>>
>> >>> subroutine new_outer_type(outer,item)
>> >>> type(outer_type), intent(out) :: outer
>> >>> integer :: item
>> >>>
>> >>> allocate(outer%test_item)
>> >>> write(*,*) 'Assigning outer%test_item'
>> >>> outer%test_item = my_test_type(itemi)
>> >>> write(*,*) 'End of new_outer_type'
>> >>> end subroutine new_outer_type
>> >>>
>> >>> end module target_mod
>> >>>
>> >>> program testfinal
>> >>> use target_mod
>> >>>
>> >>> implicit none
>> >>>
>> >>> integer :: i=10
>> >>> type(outer_type), allocatable :: wrapper
>> >>>
>> >>> write(*,*) 'Allocating wrapper '
>> >>> allocate(wrapper)
>> >>> write(*,*) 'Calling new_outer_type '
>> >>> call new_outer_type(wrapper,i)
>> >>> write(*,*) 'DeAllocating wrapper '
>> >>> deallocate(wrapper)
>> >>>
>> >>> end program testfinal
>> >>>
>> >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone <
>> >>>
>> >>> filippone.salvatore@gmail.com> wrote:
>> >>>> Hi all
>> >>>> The attached code compiles and runs fine under both GNU and Intel,
>> but
>> >> it
>> >>>> produces different results, in particular the FINAL subroutine is
>> >> invoked
>> >>>> just once with GNU, three times with Intel.
>> >>>>
>> >>>> It seems to me that they cannot both be right; I am not sure what the
>> >>>> standard is mandating in this case.
>> >>>> Any ideas?
>> >>>> Salvatore
>> >>>> --------------- Intel
>> >>>> [pr1eio03@login1: newstuff]$ ifort -v
>> >>>> ifort version 19.1.1.217
>> >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90
>> >>>> [pr1eio03@login1: newstuff]$ ./testfinal
>> >>>>
>> >>>> Allocating wrapper
>> >>>> Calling new_outer_type
>> >>>> Assigning outer%test_item
>> >>>> Called delete_test_type
>> >>>> Called delete_test_type
>> >>>> End of new_outer_type
>> >>>> DeAllocating wrapper
>> >>>> Called delete_test_type
>> >>>>
>> >>>> ----------------------------- GNU
>> >>>> sfilippo@lagrange newstuff]$ gfortran -v
>> >>>> Using built-in specs.
>> >>>> COLLECT_GCC=gfortran
>> >>>>
>> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
>> >>>> OFFLOAD_TARGET_NAMES=nvptx-none
>> >>>> OFFLOAD_TARGET_DEFAULT=1
>> >>>> Target: x86_64-redhat-linux
>> >>>> Configured with: ../configure --enable-bootstrap
>> >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto
>> >> --prefix=/usr
>> >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=
>> >>>> http://bugzilla.redhat.com/bugzilla --enable-shared
>> >>>> --enable-threads=posix --enable-checking=release --enable-multilib
>> >>>> --with-system-zlib --enable-__cxa_atexit
>> --disable-libunwind-exceptions
>> >>>> --enable-gnu-unique-object --enable-linker-build-id
>> >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu
>> >> --enable-plugin
>> >>>> --enable-initfini-array
>> >>>>
>> >>
>> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin
>> >>>> ux/isl-install --enable-offload-targets=nvptx-none
>> >> --without-cuda-driver
>> >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic
>> >>>> --with-arch_32=i686 --build=x86_64-redhat-linux
>> >>>> Thread model: posix
>> >>>> Supported LTO compression algorithms: zlib zstd
>> >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
>> >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90
>> >>>> [sfilippo@lagrange newstuff]$ ./testfinal
>> >>>>
>> >>>> Allocating wrapper
>> >>>> Calling new_outer_type
>> >>>> Assigning outer%test_item
>> >>>> End of new_outer_type
>> >>>> DeAllocating wrapper
>> >>>> Called delete_test_type
>> >>>>
>> >>>> ---------------------
>> >>
>> >> --
>> >>
>> >> * Andrew Benson: https://abensonca.github.io
>> >>
>> >> * Galacticus: https://github.com/galacticusorg/galacticus
>> >>
>> >>
>> >>
>> >>
>>
>>
>
> --
> "If you can't explain it simply, you don't understand it well enough" -
> Albert Einstein
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines
2022-01-27 7:17 ` Salvatore Filippone
@ 2022-01-27 22:10 ` Paul Richard Thomas
2022-01-28 8:05 ` Salvatore Filippone
0 siblings, 1 reply; 10+ messages in thread
From: Paul Richard Thomas @ 2022-01-27 22:10 UTC (permalink / raw)
To: Salvatore Filippone; +Cc: Jerry D, Andrew Benson, Damian Rouson, Fortran List
[-- Attachment #1: Type: text/plain, Size: 13270 bytes --]
Hi Salvatore,
My reading of F2018: 7.5.6.3 "When finalization occurs" is that three calls
is correct. (i) Paragraph 1 stipulates that the 'var' expression be
evaluated before the reallocation and intrinsic assignment; (ii)stipulates
that the function result be finalised "the result is finalized after
execution of the innermost
executable construct containing the reference." ; and (iii) Finalisation
occurs on going out of scope.
That is what is implemented in the attached. I am working my way through
the testcase dependencies of PR37336 making sure that finalizat
ion occurs as required by 7.5.6.3 and in the order defined in the previous
section. It will all be done in the next few days.
What will remain is finalization of function results within array
constructors and one or two other corner cases. Following that, the
existing finalization calls will be brought into the framework as the new
calls.
Best regards
Paul
On Thu, 27 Jan 2022 at 07:17, Salvatore Filippone <
filippone.salvatore@gmail.com> wrote:
> One more data point: Cray FTN issues TWO calls to the FINAL.
> Which begs the question: what is the correct number of calls one, two or
> three?
> Salvatore
>
> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
> ftn --version
> Cray Fortran : Version 11.0.0
> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
> ftn -o testfinal testfinal.f90
> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
> ./testfinal
> Allocating wrapper
> Calling new_outer_type
> Assigning outer%test_item
> Called delete_test_type
> End of new_outer_type
> DeAllocating wrapper
> Called delete_test_type
>
> On Wed, Jan 26, 2022 at 11:59 PM Paul Richard Thomas <
> paul.richard.thomas@gmail.com> wrote:
>
>> Hi Jerry,
>>
>> I am trying to fix the failure of my latest patch with this very test
>> case. Otherwise it fixes most of the remaining dependencies in PR37336.
>>
>> At a pinch, I could submit the earlier patch that Andrew mentions and
>> work from there. However, you will note that it does miss one of the
>> finalizations. This is critical because function results, which should be
>> finalized, are not.
>>
>> I'll keep an eye on the state of the branch. By and large, release occurs
>> 3-4 months after the start of stage 4. I will leave 2 months maximum.
>>
>> Best regards
>>
>> Paul
>>
>>
>> On Wed, 26 Jan 2022 at 21:29, Jerry D via Fortran <fortran@gcc.gnu.org>
>> wrote:
>>
>>> Is there any reason these patches can not be applied and use this test
>>> as a test case?
>>>
>>> Regards,
>>>
>>> Jerry
>>>
>>> On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote:
>>> > Thanks a lot
>>> > (yes, I suspected both gfortran and intel were wrong, precisely
>>> because I
>>> > could see why you'd need two FINAL calls, but not three).
>>> >
>>> > Salvatore
>>> >
>>> > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson <
>>> abenson@carnegiescience.edu>
>>> > wrote:
>>> >
>>> >> Hi Salvatore,
>>> >>
>>> >> This looks like it's related to some of the missing finalization
>>> >> functionality
>>> >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some
>>> >> patches
>>> >> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html)
>>> >> which
>>> >> implement most of the missing functionality. With those patches
>>> >> incorporated
>>> >> your code gives the following output with gfortran:
>>> >>
>>> >> $ ./testfinal
>>> >> Allocating wrapper
>>> >> Calling new_outer_type
>>> >> Assigning outer%test_item
>>> >> Called delete_test_type
>>> >> End of new_outer_type
>>> >> DeAllocating wrapper
>>> >> Called delete_test_type
>>> >>
>>> >> So there is one more call to the finalizer than you found - I haven't
>>> >> checked
>>> >> carefully but I would guess this is a deallocation of LHS on
>>> assignment.
>>> >>
>>> >> In testing these patches using the Intel compiler we found that it
>>> seems
>>> >> to
>>> >> call the finalization wrapper more than it should, sometimes on
>>> objects
>>> >> that
>>> >> have already been deallocated. Your code, compiled with the Intel
>>> compiler
>>> >> and
>>> >> then run under valgrind shows the following:
>>> >>
>>> >> $ valgrind ./testfinal
>>> >> ==7340== Memcheck, a memory error detector
>>> >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et
>>> al.
>>> >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for
>>> copyright info
>>> >> ==7340== Command: ./testfinal
>>> >> ==7340==
>>> >> ==7340== Conditional jump or move depends on uninitialised value(s)
>>> >> ==7340== at 0x493A51: __intel_sse2_strcpy (in
>>> /home/abensonca/Scratch/
>>> >> ifortTests/testfinal)
>>> >> ==7340== by 0x45D70E: for__add_to_lf_table (in
>>> /home/abensonca/Scratch/
>>> >> ifortTests/testfinal)
>>> >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/
>>> >> ifortTests/testfinal)
>>> >> ==7340== by 0x423A64: for__open_default (in
>>> /home/abensonca/Scratch/
>>> >> ifortTests/testfinal)
>>> >> ==7340== by 0x4305A9: for_write_seq_lis (in
>>> /home/abensonca/Scratch/
>>> >> ifortTests/testfinal)
>>> >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62)
>>> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
>>> >> testfinal)
>>> >> ==7340==
>>> >> Allocating wrapper
>>> >> Calling new_outer_type
>>> >> Assigning outer%test_item
>>> >> Called delete_test_type
>>> >> ==7340== Conditional jump or move depends on uninitialised value(s)
>>> >> ==7340== at 0x40572A: do_alloc_copy (in
>>> >> /home/abensonca/Scratch/ifortTests/
>>> >> testfinal)
>>> >> ==7340== by 0x406B9A: do_alloc_copy (in
>>> >> /home/abensonca/Scratch/ifortTests/
>>> >> testfinal)
>>> >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in
>>> /home/abensonca/Scratch/
>>> >> ifortTests/testfinal)
>>> >> ==7340== by 0x404474: target_mod_mp_new_outer_type_
>>> (testfinal.f90:48)
>>> >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65)
>>> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
>>> >> testfinal)
>>> >> ==7340==
>>> >> Called delete_test_type
>>> >> End of new_outer_type
>>> >> DeAllocating wrapper
>>> >> Called delete_test_type
>>> >> ==7340==
>>> >> ==7340== HEAP SUMMARY:
>>> >> ==7340== in use at exit: 48 bytes in 1 blocks
>>> >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes
>>> allocated
>>> >> ==7340==
>>> >> ==7340== LEAK SUMMARY:
>>> >> ==7340== definitely lost: 48 bytes in 1 blocks
>>> >> ==7340== indirectly lost: 0 bytes in 0 blocks
>>> >> ==7340== possibly lost: 0 bytes in 0 blocks
>>> >> ==7340== still reachable: 0 bytes in 0 blocks
>>> >> ==7340== suppressed: 0 bytes in 0 blocks
>>> >> ==7340== Rerun with --leak-check=full to see details of leaked memory
>>> >> ==7340==
>>> >> ==7340== For counts of detected and suppressed errors, rerun with: -v
>>> >> ==7340== Use --track-origins=yes to see where uninitialised values
>>> come
>>> >> from
>>> >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from
>>> 0)
>>> >>
>>> >> so there are some cases of what look like incorrect accesses (and some
>>> >> leaked
>>> >> memory).
>>> >>
>>> >> Your code compiled with gfortran (with Paul's patches in place)
>>> shows no
>>> >> errors or leaks from valgrind.
>>> >>
>>> >> So, in summary, in this case I think the current gfortran is missing
>>> some
>>> >> finalizations (which are fixed by Paul's patches), and ifort is likely
>>> >> doing
>>> >> something wrong and probably calling the finalizer more times than it
>>> >> should.
>>> >>
>>> >> -Andrew
>>> >>
>>> >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via
>>> Fortran
>>> >> wrote:
>>> >>> And here is the code embedded as text............ sorry about
>>> sending an
>>> >>> attachment that was purged
>>> >>> ------------------------- testfinal.f90 ---------------------
>>> >>> module test_type_mod
>>> >>>
>>> >>> type :: my_test_type
>>> >>> integer, allocatable :: i
>>> >>> contains
>>> >>> final :: delete_test_type
>>> >>> end type my_test_type
>>> >>>
>>> >>> interface my_test_type
>>> >>> module procedure new_test_type_object
>>> >>> end interface my_test_type
>>> >>>
>>> >>> contains
>>> >>>
>>> >>> subroutine delete_test_type(this)
>>> >>> type(my_test_type) :: this
>>> >>>
>>> >>> write(*,*) 'Called delete_test_type'
>>> >>> if (allocated(this%i)) deallocate(this%i)
>>> >>>
>>> >>> end subroutine delete_test_type
>>> >>>
>>> >>>
>>> >>> function new_test_type_object(item) result(res)
>>> >>> type(my_test_type) :: res
>>> >>> integer, intent(in) :: item
>>> >>> !Allocation on assignment
>>> >>> res%i=item
>>> >>> end function new_test_type_object
>>> >>>
>>> >>>
>>> >>> end module test_type_mod
>>> >>>
>>> >>> module target_mod
>>> >>> use test_type_mod
>>> >>> type :: outer_type
>>> >>> type(my_test_type), allocatable :: test_item
>>> >>> end type outer_type
>>> >>>
>>> >>> contains
>>> >>>
>>> >>> subroutine new_outer_type(outer,item)
>>> >>> type(outer_type), intent(out) :: outer
>>> >>> integer :: item
>>> >>>
>>> >>> allocate(outer%test_item)
>>> >>> write(*,*) 'Assigning outer%test_item'
>>> >>> outer%test_item = my_test_type(itemi)
>>> >>> write(*,*) 'End of new_outer_type'
>>> >>> end subroutine new_outer_type
>>> >>>
>>> >>> end module target_mod
>>> >>>
>>> >>> program testfinal
>>> >>> use target_mod
>>> >>>
>>> >>> implicit none
>>> >>>
>>> >>> integer :: i=10
>>> >>> type(outer_type), allocatable :: wrapper
>>> >>>
>>> >>> write(*,*) 'Allocating wrapper '
>>> >>> allocate(wrapper)
>>> >>> write(*,*) 'Calling new_outer_type '
>>> >>> call new_outer_type(wrapper,i)
>>> >>> write(*,*) 'DeAllocating wrapper '
>>> >>> deallocate(wrapper)
>>> >>>
>>> >>> end program testfinal
>>> >>>
>>> >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone <
>>> >>>
>>> >>> filippone.salvatore@gmail.com> wrote:
>>> >>>> Hi all
>>> >>>> The attached code compiles and runs fine under both GNU and Intel,
>>> but
>>> >> it
>>> >>>> produces different results, in particular the FINAL subroutine is
>>> >> invoked
>>> >>>> just once with GNU, three times with Intel.
>>> >>>>
>>> >>>> It seems to me that they cannot both be right; I am not sure what
>>> the
>>> >>>> standard is mandating in this case.
>>> >>>> Any ideas?
>>> >>>> Salvatore
>>> >>>> --------------- Intel
>>> >>>> [pr1eio03@login1: newstuff]$ ifort -v
>>> >>>> ifort version 19.1.1.217
>>> >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90
>>> >>>> [pr1eio03@login1: newstuff]$ ./testfinal
>>> >>>>
>>> >>>> Allocating wrapper
>>> >>>> Calling new_outer_type
>>> >>>> Assigning outer%test_item
>>> >>>> Called delete_test_type
>>> >>>> Called delete_test_type
>>> >>>> End of new_outer_type
>>> >>>> DeAllocating wrapper
>>> >>>> Called delete_test_type
>>> >>>>
>>> >>>> ----------------------------- GNU
>>> >>>> sfilippo@lagrange newstuff]$ gfortran -v
>>> >>>> Using built-in specs.
>>> >>>> COLLECT_GCC=gfortran
>>> >>>>
>>> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
>>> >>>> OFFLOAD_TARGET_NAMES=nvptx-none
>>> >>>> OFFLOAD_TARGET_DEFAULT=1
>>> >>>> Target: x86_64-redhat-linux
>>> >>>> Configured with: ../configure --enable-bootstrap
>>> >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto
>>> >> --prefix=/usr
>>> >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=
>>> >>>> http://bugzilla.redhat.com/bugzilla --enable-shared
>>> >>>> --enable-threads=posix --enable-checking=release --enable-multilib
>>> >>>> --with-system-zlib --enable-__cxa_atexit
>>> --disable-libunwind-exceptions
>>> >>>> --enable-gnu-unique-object --enable-linker-build-id
>>> >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu
>>> >> --enable-plugin
>>> >>>> --enable-initfini-array
>>> >>>>
>>> >>
>>> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin
>>> >>>> ux/isl-install --enable-offload-targets=nvptx-none
>>> >> --without-cuda-driver
>>> >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic
>>> >>>> --with-arch_32=i686 --build=x86_64-redhat-linux
>>> >>>> Thread model: posix
>>> >>>> Supported LTO compression algorithms: zlib zstd
>>> >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
>>> >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90
>>> >>>> [sfilippo@lagrange newstuff]$ ./testfinal
>>> >>>>
>>> >>>> Allocating wrapper
>>> >>>> Calling new_outer_type
>>> >>>> Assigning outer%test_item
>>> >>>> End of new_outer_type
>>> >>>> DeAllocating wrapper
>>> >>>> Called delete_test_type
>>> >>>>
>>> >>>> ---------------------
>>> >>
>>> >> --
>>> >>
>>> >> * Andrew Benson: https://abensonca.github.io
>>> >>
>>> >> * Galacticus: https://github.com/galacticusorg/galacticus
>>> >>
>>> >>
>>> >>
>>> >>
>>>
>>>
>>
>> --
>> "If you can't explain it simply, you don't understand it well enough" -
>> Albert Einstein
>>
>
--
"If you can't explain it simply, you don't understand it well enough" -
Albert Einstein
[-- Attachment #2: Check270222.diff --]
[-- Type: text/x-patch, Size: 34670 bytes --]
diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc
index 731e9b0fe6a..a249eea4a30 100644
--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -896,7 +896,8 @@ has_finalizer_component (gfc_symbol *derived)
gfc_component *c;
for (c = derived->components; c; c = c->next)
- if (c->ts.type == BT_DERIVED && !c->attr.pointer && !c->attr.allocatable)
+ if (c->ts.type == BT_DERIVED && !c->attr.pointer && !c->attr.allocatable
+ && c->attr.flavor != FL_PROCEDURE)
{
if (c->ts.u.derived->f2k_derived
&& c->ts.u.derived->f2k_derived->finalizers)
@@ -1059,7 +1060,8 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
{
/* Call FINAL_WRAPPER (comp); */
gfc_code *final_wrap;
- gfc_symbol *vtab;
+ gfc_symbol *vtab, *byte_stride;
+ gfc_expr *scalar, *size_expr, *fini_coarray_expr;
gfc_component *c;
vtab = gfc_find_derived_vtab (comp->ts.u.derived);
@@ -1068,12 +1070,54 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
break;
gcc_assert (c);
+
+ /* Set scalar argument for storage_size. */
+ gfc_get_symbol ("comp_byte_stride", sub_ns, &byte_stride);
+ byte_stride->ts = e->ts;
+ byte_stride->attr.flavor = FL_VARIABLE;
+ byte_stride->attr.value = 1;
+ byte_stride->attr.artificial = 1;
+ gfc_set_sym_referenced (byte_stride);
+ gfc_commit_symbol (byte_stride);
+ scalar = gfc_lval_expr_from_sym (byte_stride);
+
final_wrap = gfc_get_code (EXEC_CALL);
final_wrap->symtree = c->initializer->symtree;
final_wrap->resolved_sym = c->initializer->symtree->n.sym;
final_wrap->ext.actual = gfc_get_actual_arglist ();
final_wrap->ext.actual->expr = e;
+ /* size_expr = STORAGE_SIZE (...) / NUMERIC_STORAGE_SIZE. */
+ size_expr = gfc_get_expr ();
+ size_expr->where = gfc_current_locus;
+ size_expr->expr_type = EXPR_OP;
+ size_expr->value.op.op = INTRINSIC_DIVIDE;
+
+ /* STORAGE_SIZE (array,kind=c_intptr_t). */
+ size_expr->value.op.op1
+ = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_STORAGE_SIZE,
+ "storage_size", gfc_current_locus, 2,
+ scalar,
+ gfc_get_int_expr (gfc_index_integer_kind,
+ NULL, 0));
+
+ /* NUMERIC_STORAGE_SIZE. */
+ size_expr->value.op.op2 = gfc_get_int_expr (gfc_index_integer_kind, NULL,
+ gfc_character_storage_size);
+ size_expr->value.op.op1->ts = size_expr->value.op.op2->ts;
+ size_expr->ts = size_expr->value.op.op1->ts;
+
+ /* Which provides the argument 'byte_stride'..... */
+ final_wrap->ext.actual->next = gfc_get_actual_arglist ();
+ final_wrap->ext.actual->next->expr = size_expr;
+
+ /* ...and last of all the 'fini_coarray' argument. */
+ fini_coarray_expr = gfc_lval_expr_from_sym (fini_coarray);
+ final_wrap->ext.actual->next->next = gfc_get_actual_arglist ();
+ final_wrap->ext.actual->next->next->expr = fini_coarray_expr;
+
+
+
if (*code)
{
(*code)->next = final_wrap;
@@ -1430,8 +1474,6 @@ finalizer_insert_packed_call (gfc_code *block, gfc_finalizer *fini,
block->next->resolved_sym = fini->proc_tree->n.sym;
block->next->ext.actual = gfc_get_actual_arglist ();
block->next->ext.actual->expr = gfc_lval_expr_from_sym (array);
- block->next->ext.actual->next = gfc_get_actual_arglist ();
- block->next->ext.actual->next->expr = gfc_copy_expr (size_expr);
/* ELSE. */
diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 835a4783718..5558af4e2ba 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -10512,6 +10512,10 @@ resolve_where (gfc_code *code, gfc_expr *mask)
if (e && !resolve_where_shape (cnext->expr1, e))
gfc_error ("WHERE assignment target at %L has "
"inconsistent shape", &cnext->expr1->where);
+
+ if (cnext->op == EXEC_ASSIGN)
+ cnext->expr1->must_finalize = 1;
+
break;
@@ -10599,6 +10603,10 @@ gfc_resolve_where_code_in_forall (gfc_code *code, int nvar,
/* WHERE assignment statement */
case EXEC_ASSIGN:
gfc_resolve_assign_in_forall (cnext, nvar, var_expr);
+
+ if (cnext->op == EXEC_ASSIGN)
+ cnext->expr1->must_finalize = 1;
+
break;
/* WHERE operator assignment statement */
@@ -10645,6 +10653,10 @@ gfc_resolve_forall_body (gfc_code *code, int nvar, gfc_expr **var_expr)
case EXEC_ASSIGN:
case EXEC_POINTER_ASSIGN:
gfc_resolve_assign_in_forall (c, nvar, var_expr);
+
+ if (c->op == EXEC_ASSIGN)
+ c->expr1->must_finalize = 1;
+
break;
case EXEC_ASSIGN_CALL:
@@ -12069,6 +12081,9 @@ start:
&& code->expr1->ts.u.derived->attr.defined_assign_comp)
generate_component_assignments (&code, ns);
+ if (code->op == EXEC_ASSIGN)
+ code->expr1->must_finalize = 1;
+
break;
case EXEC_LABEL_ASSIGN:
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 2f0c8a4d412..b03e74960ce 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -994,9 +994,9 @@ gfc_get_array_span (tree desc, gfc_expr *expr)
if (tmp && TREE_CODE (tmp) == ARRAY_TYPE && TYPE_STRING_FLAG (tmp))
{
gcc_assert (expr->ts.type == BT_CHARACTER);
-
+
tmp = gfc_get_character_len_in_bytes (tmp);
-
+
if (tmp == NULL_TREE || integer_zerop (tmp))
{
tree bs;
@@ -1007,7 +1007,7 @@ gfc_get_array_span (tree desc, gfc_expr *expr)
tmp = fold_build2_loc (input_location, MULT_EXPR,
gfc_array_index_type, tmp, bs);
}
-
+
tmp = (tmp && !integer_zerop (tmp))
? (fold_convert (gfc_array_index_type, tmp)) : (NULL_TREE);
}
@@ -5657,7 +5657,12 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
gfc_se se;
int n;
- type = TREE_TYPE (descriptor);
+ if (expr->ts.type == BT_CLASS
+ && expr3_desc != NULL_TREE
+ && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (expr3_desc)))
+ type = TREE_TYPE (expr3_desc);
+ else
+ type = TREE_TYPE (descriptor);
stride = gfc_index_one_node;
offset = gfc_index_zero_node;
@@ -7478,7 +7483,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
if (!se->direct_byref)
se->unlimited_polymorphic = UNLIMITED_POLY (expr);
-
+
/* Special case things we know we can pass easily. */
switch (expr->expr_type)
{
@@ -8922,7 +8927,7 @@ static gfc_actual_arglist *pdt_param_list;
static tree
structure_alloc_comps (gfc_symbol * der_type, tree decl,
tree dest, int rank, int purpose, int caf_mode,
- gfc_co_subroutines_args *args)
+ gfc_co_subroutines_args *args, bool no_finalization)
{
gfc_component *c;
gfc_loopinfo loop;
@@ -9010,11 +9015,12 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
gfc_conv_array_data (dest));
dref = gfc_build_array_ref (tmp, index, NULL);
tmp = structure_alloc_comps (der_type, vref, dref, rank,
- COPY_ALLOC_COMP, caf_mode, args);
+ COPY_ALLOC_COMP, caf_mode, args,
+ no_finalization);
}
else
tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose,
- caf_mode, args);
+ caf_mode, args, no_finalization);
gfc_add_expr_to_block (&loopbody, tmp);
@@ -9048,13 +9054,15 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
if (purpose == DEALLOCATE_ALLOC_COMP && der_type->attr.pdt_type)
{
tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
- DEALLOCATE_PDT_COMP, 0, args);
+ DEALLOCATE_PDT_COMP, 0, args,
+ no_finalization);
gfc_add_expr_to_block (&fnblock, tmp);
}
else if (purpose == ALLOCATE_PDT_COMP && der_type->attr.alloc_comp)
{
tmp = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
- NULLIFY_ALLOC_COMP, 0, args);
+ NULLIFY_ALLOC_COMP, 0, args,
+ no_finalization);
gfc_add_expr_to_block (&fnblock, tmp);
}
@@ -9112,7 +9120,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
add_when_allocated
= structure_alloc_comps (CLASS_DATA (c)->ts.u.derived,
comp, NULL_TREE, rank, purpose,
- caf_mode, args);
+ caf_mode, args, no_finalization);
}
else
{
@@ -9120,7 +9128,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
add_when_allocated = structure_alloc_comps (c->ts.u.derived,
comp, NULL_TREE,
rank, purpose,
- caf_mode, args);
+ caf_mode, args,
+ no_finalization);
}
}
@@ -9216,8 +9225,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
continue;
}
- if ((c->ts.type == BT_DERIVED && !c->attr.pointer)
- || (c->ts.type == BT_CLASS && !CLASS_DATA (c)->attr.class_pointer))
+ if (!no_finalization && ((c->ts.type == BT_DERIVED && !c->attr.pointer)
+ || (c->ts.type == BT_CLASS && !CLASS_DATA (c)->attr.class_pointer)))
/* Call the finalizer, which will free the memory and nullify the
pointer of an array. */
deallocate_called = gfc_add_comp_finalizer_call (&tmpblock, comp, c,
@@ -9245,7 +9254,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
add_when_allocated
= structure_alloc_comps (CLASS_DATA (c)->ts.u.derived,
comp, NULL_TREE, rank, purpose,
- caf_mode, args);
+ caf_mode, args, no_finalization);
}
else
{
@@ -9253,7 +9262,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
add_when_allocated = structure_alloc_comps (c->ts.u.derived,
comp, NULL_TREE,
rank, purpose,
- caf_mode, args);
+ caf_mode, args,
+ no_finalization);
}
}
@@ -9551,7 +9561,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
decl, cdecl, NULL_TREE);
rank = c->as ? c->as->rank : 0;
tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
- rank, purpose, caf_mode, args);
+ rank, purpose, caf_mode, args,
+ no_finalization);
gfc_add_expr_to_block (&fnblock, tmp);
}
break;
@@ -9587,7 +9598,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
rank, purpose, caf_mode
| GFC_STRUCTURE_CAF_MODE_IN_COARRAY,
- args);
+ args, no_finalization);
gfc_add_expr_to_block (&fnblock, tmp);
}
}
@@ -9695,7 +9706,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
add_when_allocated = structure_alloc_comps (c->ts.u.derived,
comp, dcmp,
rank, purpose,
- caf_mode, args);
+ caf_mode, args,
+ no_finalization);
}
else
add_when_allocated = NULL_TREE;
@@ -10068,7 +10080,8 @@ gfc_nullify_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
{
return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
NULLIFY_ALLOC_COMP,
- GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode, NULL);
+ GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode,
+ NULL, false);
}
@@ -10081,7 +10094,8 @@ gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank,
{
return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
DEALLOCATE_ALLOC_COMP,
- GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode, NULL);
+ GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY | caf_mode,
+ NULL, false);
}
tree
@@ -10119,7 +10133,8 @@ gfc_bcast_alloc_comp (gfc_symbol *derived, gfc_expr *expr, int rank,
tmp = structure_alloc_comps (derived, array, NULL_TREE, rank,
BCAST_ALLOC_COMP,
- GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY, &args);
+ GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY,
+ &args, false);
return tmp;
}
@@ -10129,10 +10144,12 @@ gfc_bcast_alloc_comp (gfc_symbol *derived, gfc_expr *expr, int rank,
status of coarrays. */
tree
-gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank)
+gfc_deallocate_alloc_comp_no_caf (gfc_symbol * der_type, tree decl, int rank,
+ bool no_finalization)
{
return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
- DEALLOCATE_ALLOC_COMP, 0, NULL);
+ DEALLOCATE_ALLOC_COMP, 0, NULL,
+ no_finalization);
}
@@ -10140,7 +10157,8 @@ tree
gfc_reassign_alloc_comp_caf (gfc_symbol *der_type, tree decl, tree dest)
{
return structure_alloc_comps (der_type, decl, dest, 0, REASSIGN_CAF_COMP,
- GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY, NULL);
+ GFC_STRUCTURE_CAF_MODE_ENABLE_COARRAY,
+ NULL, false);
}
@@ -10152,7 +10170,7 @@ gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank,
int caf_mode)
{
return structure_alloc_comps (der_type, decl, dest, rank, COPY_ALLOC_COMP,
- caf_mode, NULL);
+ caf_mode, NULL, false);
}
@@ -10163,7 +10181,7 @@ tree
gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
{
return structure_alloc_comps (der_type, decl, dest, rank,
- COPY_ONLY_ALLOC_COMP, 0, NULL);
+ COPY_ONLY_ALLOC_COMP, 0, NULL, false);
}
@@ -10178,7 +10196,7 @@ gfc_allocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank,
gfc_actual_arglist *old_param_list = pdt_param_list;
pdt_param_list = param_list;
res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
- ALLOCATE_PDT_COMP, 0, NULL);
+ ALLOCATE_PDT_COMP, 0, NULL, false);
pdt_param_list = old_param_list;
return res;
}
@@ -10190,7 +10208,7 @@ tree
gfc_deallocate_pdt_comp (gfc_symbol * der_type, tree decl, int rank)
{
return structure_alloc_comps (der_type, decl, NULL_TREE, rank,
- DEALLOCATE_PDT_COMP, 0, NULL);
+ DEALLOCATE_PDT_COMP, 0, NULL, false);
}
@@ -10205,7 +10223,7 @@ gfc_check_pdt_dummy (gfc_symbol * der_type, tree decl, int rank,
gfc_actual_arglist *old_param_list = pdt_param_list;
pdt_param_list = param_list;
res = structure_alloc_comps (der_type, decl, NULL_TREE, rank,
- CHECK_PDT_DUMMY, 0, NULL);
+ CHECK_PDT_DUMMY, 0, NULL, false);
pdt_param_list = old_param_list;
return res;
}
@@ -10926,7 +10944,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
&& expr1->ts.u.derived->attr.alloc_comp)
{
tmp = gfc_deallocate_alloc_comp_no_caf (expr1->ts.u.derived, old_desc,
- expr1->rank);
+ expr1->rank, true);
gfc_add_expr_to_block (&realloc_block, tmp);
}
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index 04fee617590..3aae4d2c4eb 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -56,7 +56,8 @@ tree gfc_nullify_alloc_comp (gfc_symbol *, tree, int, int cm = 0);
tree gfc_deallocate_alloc_comp (gfc_symbol *, tree, int, int cm = 0);
tree gfc_bcast_alloc_comp (gfc_symbol *, gfc_expr *, int, tree,
tree, tree, tree);
-tree gfc_deallocate_alloc_comp_no_caf (gfc_symbol *, tree, int);
+tree gfc_deallocate_alloc_comp_no_caf (gfc_symbol *, tree, int,
+ bool no_finalization = false);
tree gfc_reassign_alloc_comp_caf (gfc_symbol *, tree, tree);
tree gfc_copy_alloc_comp (gfc_symbol *, tree, tree, int, int);
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index eb6a78c3a62..6ffe317afbf 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -1904,6 +1904,7 @@ gfc_init_se (gfc_se * se, gfc_se * parent)
{
memset (se, 0, sizeof (gfc_se));
gfc_init_block (&se->pre);
+ gfc_init_block (&se->finalblock);
gfc_init_block (&se->post);
se->parent = parent;
@@ -5975,6 +5976,116 @@ post_call:
}
+/* Finalize a function result using the finalizer wrapper. The result is fixed
+ in order to prevent repeated calls. */
+
+static void
+finalize_function_result (gfc_se *se, gfc_symbol *derived,
+ symbol_attribute attr)
+{
+ tree vptr, final_fndecl, desc, tmp, size, is_final, data_ptr;
+ gfc_symbol *vtab;
+ gfc_se post_se;
+ bool is_class = GFC_CLASS_TYPE_P (TREE_TYPE (se->expr));
+
+ if (attr.pointer)
+ return;
+
+ if (is_class)
+ {
+ if (!VAR_P (se->expr))
+ {
+ desc = gfc_evaluate_now (se->expr, &se->pre);
+ se->expr = desc;
+ }
+ desc = gfc_class_data_get (se->expr);
+ vptr = gfc_class_vptr_get (se->expr);
+ }
+ else
+ {
+ desc = gfc_evaluate_now (se->expr, &se->pre);
+ se->expr = gfc_evaluate_now (desc, &se->pre);
+ gfc_add_expr_to_block (&se->pre,
+ gfc_copy_alloc_comp (derived, se->expr,
+ desc, 0, 0));
+ vtab = gfc_find_derived_vtab (derived);
+ if (vtab->backend_decl == NULL_TREE)
+ vptr = gfc_get_symbol_decl (vtab);
+ else
+ vptr = vtab->backend_decl;
+ vptr = gfc_build_addr_expr (NULL, vptr);
+ }
+
+ size = gfc_vptr_size_get (vptr);
+ final_fndecl = gfc_vptr_final_get (vptr);
+ is_final = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node,
+ final_fndecl,
+ fold_convert (TREE_TYPE (final_fndecl),
+ null_pointer_node));
+
+ final_fndecl = build_fold_indirect_ref_loc (input_location,
+ final_fndecl);
+ if (!GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
+ {
+ if (is_class)
+ desc = gfc_conv_scalar_to_descriptor (se, desc, attr);
+ else
+ {
+ gfc_init_se (&post_se, NULL);
+ desc = gfc_conv_scalar_to_descriptor (&post_se, desc, attr);
+ gfc_add_expr_to_block (&se->pre, gfc_finish_block (&post_se.pre));
+ }
+ }
+
+ tmp = gfc_create_var (TREE_TYPE (desc), "res");
+ gfc_add_modify (&se->pre, tmp, desc);
+ desc = tmp;
+
+ tmp = build_call_expr_loc (input_location, final_fndecl, 3,
+ gfc_build_addr_expr (NULL, desc),
+ size, boolean_false_node);
+
+ tmp = fold_build3_loc (input_location, COND_EXPR,
+ void_type_node, is_final, tmp,
+ build_empty_stmt (input_location));
+
+ if (is_class && se->ss && se->ss->loop)
+ {
+ data_ptr = gfc_conv_descriptor_data_get (desc);
+
+ gfc_add_expr_to_block (&se->loop->post, tmp);
+ tmp = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node,
+ data_ptr,
+ fold_convert (TREE_TYPE (data_ptr),
+ null_pointer_node));
+ tmp = fold_build3_loc (input_location, COND_EXPR,
+ void_type_node, tmp,
+ gfc_call_free (data_ptr),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&se->loop->post, tmp);
+ }
+ else
+ {
+ gfc_add_expr_to_block (&se->finalblock, tmp);
+ if (is_class)
+ {
+ data_ptr = gfc_conv_descriptor_data_get (desc);
+ tmp = fold_build2_loc (input_location, NE_EXPR,
+ logical_type_node,
+ data_ptr,
+ fold_convert (TREE_TYPE (data_ptr),
+ null_pointer_node));
+ tmp = fold_build3_loc (input_location, COND_EXPR,
+ void_type_node, tmp,
+ gfc_call_free (data_ptr),
+ build_empty_stmt (input_location));
+ gfc_add_expr_to_block (&se->finalblock, tmp);
+ }
+ }
+}
+
/* Generate code for a procedure call. Note can return se->post != NULL.
If se->direct_byref is set then se->expr contains the return parameter.
Return nonzero, if the call has alternate specifiers.
@@ -7011,6 +7122,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_add_block_to_block (&se->pre, &parmse.pre);
gfc_add_block_to_block (&post, &parmse.post);
+ gfc_add_block_to_block (&se->finalblock, &parmse.finalblock);
/* Allocated allocatable components of derived types must be
deallocated for non-variable scalars, array arguments to elemental
@@ -7675,9 +7787,17 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
/* Allocatable scalar function results must be freed and nullified
after use. This necessitates the creation of a temporary to
hold the result to prevent duplicate calls. */
+ symbol_attribute attr = comp ? comp->attr : sym->attr;
+ bool allocatable = attr.allocatable && !attr.dimension;
+ gfc_symbol *der = comp && comp->ts.type == BT_DERIVED ? comp->ts.u.derived
+ : (sym->ts.type == BT_DERIVED ? sym->ts.u.derived : NULL);
+ bool finalizable = der != NULL && gfc_is_finalizable (der, NULL);
+
+ if (!byref && finalizable)
+ finalize_function_result (se, der, attr);
+
if (!byref && sym->ts.type != BT_CHARACTER
- && ((sym->attr.allocatable && !sym->attr.dimension && !comp)
- || (comp && comp->attr.allocatable && !comp->attr.dimension)))
+ && allocatable && !finalizable)
{
tmp = gfc_create_var (TREE_TYPE (se->expr), NULL);
gfc_add_modify (&se->pre, tmp, se->expr);
@@ -7737,6 +7857,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
se->expr = info->descriptor;
/* Bundle in the string length. */
se->string_length = len;
+
+ if (finalizable)
+ finalize_function_result (se, der, attr);
}
else if (ts.type == BT_CHARACTER)
{
@@ -7829,8 +7952,6 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
&& se->expr && GFC_CLASS_TYPE_P (TREE_TYPE (se->expr))
&& expr->must_finalize)
{
- tree final_fndecl;
- tree is_final;
int n;
if (se->ss && se->ss->loop)
{
@@ -7852,66 +7973,15 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
/* TODO Eliminate the doubling of temporaries. This
one is necessary to ensure no memory leakage. */
se->expr = gfc_evaluate_now (se->expr, &se->pre);
- tmp = gfc_class_data_get (se->expr);
- tmp = gfc_conv_scalar_to_descriptor (se, tmp,
- CLASS_DATA (expr->value.function.esym->result)->attr);
}
- if ((gfc_is_class_array_function (expr)
- || gfc_is_alloc_class_scalar_function (expr))
- && CLASS_DATA (expr->value.function.esym->result)->attr.pointer)
- goto no_finalization;
-
- final_fndecl = gfc_class_vtab_final_get (se->expr);
- is_final = fold_build2_loc (input_location, NE_EXPR,
- logical_type_node,
- final_fndecl,
- fold_convert (TREE_TYPE (final_fndecl),
- null_pointer_node));
- final_fndecl = build_fold_indirect_ref_loc (input_location,
- final_fndecl);
- tmp = build_call_expr_loc (input_location,
- final_fndecl, 3,
- gfc_build_addr_expr (NULL, tmp),
- gfc_class_vtab_size_get (se->expr),
- boolean_false_node);
- tmp = fold_build3_loc (input_location, COND_EXPR,
- void_type_node, is_final, tmp,
- build_empty_stmt (input_location));
-
- if (se->ss && se->ss->loop)
- {
- gfc_prepend_expr_to_block (&se->ss->loop->post, tmp);
- tmp = fold_build2_loc (input_location, NE_EXPR,
- logical_type_node,
- info->data,
- fold_convert (TREE_TYPE (info->data),
- null_pointer_node));
- tmp = fold_build3_loc (input_location, COND_EXPR,
- void_type_node, tmp,
- gfc_call_free (info->data),
- build_empty_stmt (input_location));
- gfc_add_expr_to_block (&se->ss->loop->post, tmp);
- }
- else
- {
- tree classdata;
- gfc_prepend_expr_to_block (&se->post, tmp);
- classdata = gfc_class_data_get (se->expr);
- tmp = fold_build2_loc (input_location, NE_EXPR,
- logical_type_node,
- classdata,
- fold_convert (TREE_TYPE (classdata),
- null_pointer_node));
- tmp = fold_build3_loc (input_location, COND_EXPR,
- void_type_node, tmp,
- gfc_call_free (classdata),
- build_empty_stmt (input_location));
- gfc_add_expr_to_block (&se->post, tmp);
- }
+ /* Finalize the result, if necessary. */
+ attr = CLASS_DATA (expr->value.function.esym->result)->attr;
+ if (!((gfc_is_class_array_function (expr)
+ || gfc_is_alloc_class_scalar_function (expr))
+ && attr.pointer))
+ finalize_function_result (se, NULL, attr);
}
-
-no_finalization:
gfc_add_block_to_block (&se->post, &post);
}
@@ -10430,7 +10500,8 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, gfc_typespec ts,
if (dealloc)
{
tmp_var = gfc_evaluate_now (lse->expr, &lse->pre);
- tmp = gfc_deallocate_alloc_comp_no_caf (ts.u.derived, tmp_var, 0);
+ tmp = gfc_deallocate_alloc_comp_no_caf (ts.u.derived, tmp_var,
+ 0, true);
if (deep_copy)
tmp = build3_v (COND_EXPR, cond, build_empty_stmt (input_location),
tmp);
@@ -10872,6 +10943,7 @@ gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
gfc_conv_function_expr (&se, expr2);
gfc_add_block_to_block (&se.pre, &se.post);
+ gfc_add_block_to_block (&se.pre, &se.finalblock);
if (ss)
gfc_cleanup_loop (&loop);
@@ -11387,6 +11459,89 @@ is_runtime_conformable (gfc_expr *expr1, gfc_expr *expr2)
}
+ /* F2018 (7.5.6.3): "When an intrinsic assignment statement is executed
+ (10.2.1.3), if the variable is not an unallocated allocatable variable,
+ it is finalized after evaluation of expr and before the definition of
+ the variable. If the variable is an allocated allocatable variable, or
+ has an allocated allocatable subobject, that would be deallocated by
+ intrinsic assignment, the finalization occurs before the deallocation */
+
+static tree
+gfc_assignment_finalizer_call (gfc_expr *expr1, bool init_flag)
+{
+ stmtblock_t final_block;
+ gfc_init_block (&final_block);
+ symbol_attribute lhs_attr;
+ tree final_expr;
+ tree ptr;
+ tree cond;
+ gfc_se se;
+
+ /* We have to exclude vtable procedures (_copy and _final especially), uses
+ of gfc_trans_assignment_1 in initialization and allocation before trying
+ to build a final call. */
+ if (!expr1->must_finalize
+ || expr1->symtree->n.sym->attr.artificial
+ || expr1->symtree->n.sym->ns->proc_name->attr.artificial
+ || init_flag)
+ return NULL_TREE;
+
+ if (!(expr1->ts.type == BT_CLASS
+ || (expr1->ts.type == BT_DERIVED
+ && gfc_is_finalizable (expr1->ts.u.derived, NULL)))
+ || !gfc_add_finalizer_call (&final_block, expr1))
+ return NULL_TREE;
+
+ lhs_attr = gfc_expr_attr (expr1);
+
+ /* Check allocatable/pointer is allocated/associated. */
+ if (lhs_attr.allocatable || lhs_attr.pointer)
+ {
+ if (expr1->ts.type == BT_CLASS)
+ {
+ ptr = gfc_get_class_from_gfc_expr (expr1);
+ gcc_assert (ptr != NULL_TREE);
+ ptr = gfc_class_data_get (ptr);
+ if (lhs_attr.dimension)
+ ptr = gfc_conv_descriptor_data_get (ptr);
+ }
+ else
+ {
+ gfc_init_se (&se, NULL);
+ if (expr1->rank)
+ {
+ gfc_conv_expr_descriptor (&se, expr1);
+ ptr = gfc_conv_descriptor_data_get (se.expr);
+ }
+ else
+ {
+ gfc_conv_expr (&se, expr1);
+ ptr = gfc_build_addr_expr (NULL_TREE, se.expr);
+ }
+ }
+
+ cond = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ ptr, build_zero_cst (TREE_TYPE (ptr)));
+ final_expr = build3_loc (input_location, COND_EXPR, void_type_node,
+ cond, gfc_finish_block (&final_block),
+ build_empty_stmt (input_location));
+ }
+ else
+ final_expr = gfc_finish_block (&final_block);
+
+ /* Check optional present. */
+ if (expr1->symtree->n.sym->attr.optional)
+ {
+ cond = gfc_conv_expr_present (expr1->symtree->n.sym);
+ final_expr = build3_loc (input_location, COND_EXPR, void_type_node,
+ cond, final_expr,
+ build_empty_stmt (input_location));
+ }
+
+ return final_expr;
+}
+
+
static tree
trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs,
gfc_se *lse, gfc_se *rse, bool use_vptr_copy,
@@ -11394,6 +11549,16 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs,
{
tree tmp, fcn, stdcopy, to_len, from_len, vptr, old_vptr;
vec<tree, va_gc> *args = NULL;
+ tree final_expr;
+
+ final_expr = gfc_assignment_finalizer_call (lhs, false);
+ if (final_expr != NULL_TREE)
+ {
+ if (rse->loop)
+ gfc_prepend_expr_to_block (&rse->loop->pre, final_expr);
+ else
+ gfc_add_expr_to_block (block, final_expr);
+ }
/* Store the old vptr so that dynamic types can be compared for
reallocation to occur or not. */
@@ -11419,8 +11584,12 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs,
old_vptr = build_int_cst (TREE_TYPE (vptr), 0);
size = gfc_vptr_size_get (vptr);
- class_han = GFC_CLASS_TYPE_P (TREE_TYPE (lse->expr))
- ? gfc_class_data_get (lse->expr) : lse->expr;
+ if (TREE_CODE (lse->expr) == INDIRECT_REF)
+ tmp = TREE_OPERAND (lse->expr, 0);
+ else
+ tmp = lse->expr;
+ class_han = GFC_CLASS_TYPE_P (TREE_TYPE (tmp))
+ ? gfc_class_data_get (tmp) : tmp;
/* Allocate block. */
gfc_init_block (&alloc);
@@ -11519,6 +11688,7 @@ trans_class_assignment (stmtblock_t *block, gfc_expr *lhs, gfc_expr *rhs,
}
}
+
/* Subroutine of gfc_trans_assignment that actually scalarizes the
assignment. EXPR1 is the destination/LHS and EXPR2 is the source/RHS.
init_flag indicates initialization expressions and dealloc that no
@@ -11542,6 +11712,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
tree tmp;
stmtblock_t block;
stmtblock_t body;
+ tree final_expr;
bool l_is_temp;
bool scalar_to_array;
tree string_length;
@@ -11582,6 +11753,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
needed at two locations, so do it once only before the information is
needed. */
lhs_attr = gfc_expr_attr (expr1);
+
is_poly_assign = (use_vptr_copy || lhs_attr.pointer
|| (lhs_attr.allocatable && !lhs_attr.dimension))
&& (expr1->ts.type == BT_CLASS
@@ -11855,6 +12027,8 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
else
gfc_add_expr_to_block (&loop.post, tmp2);
}
+
+ expr1->must_finalize = 0;
}
else if (flag_coarray == GFC_FCOARRAY_LIB
&& lhs_caf_attr.codimension && rhs_caf_attr.codimension
@@ -11909,12 +12083,36 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
!(l_is_temp || init_flag) && dealloc,
expr1->symtree->n.sym->attr.codimension);
- /* Add the pre blocks to the body. */
- gfc_add_block_to_block (&body, &rse.pre);
+ /* Comply with F2018 (7.5.6.3). Make sure that any finalization code is added
+ after evaluation of the rhs and before reallocation. */
+ final_expr = gfc_assignment_finalizer_call (expr1, init_flag);
+ if (final_expr)
+ {
+ if (lss == gfc_ss_terminator)
+ {
+ gfc_add_block_to_block (&block, &rse.pre);
+ gfc_add_expr_to_block (&block, final_expr);
+ }
+ else
+ {
+ gfc_add_block_to_block (&body, &rse.pre);
+ gfc_add_expr_to_block (&loop.code[expr1->rank - 1], final_expr);
+ }
+ }
+ else
+ gfc_add_block_to_block (&body, &rse.pre);
+
+ /* Add the lse pre block to the body */
gfc_add_block_to_block (&body, &lse.pre);
gfc_add_expr_to_block (&body, tmp);
/* Add the post blocks to the body. */
- gfc_add_block_to_block (&body, &rse.post);
+ if (lss == gfc_ss_terminator)
+ {
+ gfc_add_block_to_block (&rse.finalblock, &rse.post);
+ gfc_add_block_to_block (&body, &rse.finalblock);
+ }
+ else
+ gfc_add_block_to_block (&body, &rse.post);
gfc_add_block_to_block (&body, &lse.post);
if (lss == gfc_ss_terminator)
@@ -11979,6 +12177,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
/* Wrap the whole thing up. */
gfc_add_block_to_block (&block, &loop.pre);
gfc_add_block_to_block (&block, &loop.post);
+ gfc_add_block_to_block (&block, &rse.finalblock);
gfc_cleanup_loop (&loop);
}
diff --git a/gcc/fortran/trans-io.cc b/gcc/fortran/trans-io.cc
index 732221f848b..bf4f0671585 100644
--- a/gcc/fortran/trans-io.cc
+++ b/gcc/fortran/trans-io.cc
@@ -2664,6 +2664,7 @@ scalarize:
gfc_add_block_to_block (&body, &se.pre);
gfc_add_block_to_block (&body, &se.post);
+ gfc_add_block_to_block (&body, &se.finalblock);
if (se.ss == NULL)
tmp = gfc_finish_block (&body);
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 04f8147d23b..e0f513f8941 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -443,7 +443,8 @@ gfc_trans_call (gfc_code * code, bool dependency_check,
else
gfc_add_expr_to_block (&se.pre, se.expr);
- gfc_add_block_to_block (&se.pre, &se.post);
+ gfc_add_block_to_block (&se.finalblock, &se.post);
+ gfc_add_block_to_block (&se.pre, &se.finalblock);
}
else
@@ -542,6 +543,7 @@ gfc_trans_call (gfc_code * code, bool dependency_check,
gfc_trans_scalarizing_loops (&loop, &body);
gfc_add_block_to_block (&se.pre, &loop.pre);
gfc_add_block_to_block (&se.pre, &loop.post);
+ gfc_add_block_to_block (&se.pre, &loopse.finalblock);
gfc_add_block_to_block (&se.pre, &se.post);
gfc_cleanup_loop (&loop);
}
@@ -6337,7 +6339,10 @@ gfc_trans_allocate (gfc_code * code)
}
gfc_add_block_to_block (&block, &se.pre);
if (code->expr3->must_finalize)
- gfc_add_block_to_block (&final_block, &se.post);
+ {
+ gfc_add_block_to_block (&final_block, &se.finalblock);
+ gfc_add_block_to_block (&final_block, &se.post);
+ }
else
gfc_add_block_to_block (&post, &se.post);
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 738c7487a56..72af54c4d29 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -43,6 +43,10 @@ typedef struct gfc_se
stmtblock_t pre;
stmtblock_t post;
+ /* Carries finalization code that is required to be executed execution of the
+ innermost executable construct. */
+ stmtblock_t finalblock;
+
/* the result of the expression */
tree expr;
@@ -55,7 +59,7 @@ typedef struct gfc_se
/* Whether expr is a reference to an unlimited polymorphic object. */
unsigned unlimited_polymorphic:1;
-
+
/* If set gfc_conv_variable will return an expression for the array
descriptor. When set, want_pointer should also be set.
If not set scalarizing variables will be substituted. */
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90 b/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90
index 92dc50756d4..de20a147842 100644
--- a/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_25.f90
@@ -68,4 +68,4 @@ contains
end function func_foo_a
end program simple_leak
-! { dg-final { scan-tree-dump-times "\>_final" 6 "original" } }
+! { dg-final { scan-tree-dump-times "\>_final" 4 "original" } }
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines
2022-01-27 22:10 ` Paul Richard Thomas
@ 2022-01-28 8:05 ` Salvatore Filippone
2022-01-28 9:01 ` Paul Richard Thomas
0 siblings, 1 reply; 10+ messages in thread
From: Salvatore Filippone @ 2022-01-28 8:05 UTC (permalink / raw)
To: Paul Richard Thomas; +Cc: Jerry D, Andrew Benson, Damian Rouson, Fortran List
So, you are saying that three calls is the correct number, one for the LHS,
one for the RHS, and one for the deallocation in the main program.
I have (re)-read the standard, I would concur with your interpretation.
On Thu, Jan 27, 2022 at 11:10 PM Paul Richard Thomas <
paul.richard.thomas@gmail.com> wrote:
> Hi Salvatore,
>
>
> My reading of F2018: 7.5.6.3 "When finalization occurs" is that three
> calls is correct. (i) Paragraph 1 stipulates that the 'var' expression be
> evaluated before the reallocation and intrinsic assignment; (ii)stipulates
> that the function result be finalised "the result is finalized after
> execution of the innermost
> executable construct containing the reference." ; and (iii) Finalisation
> occurs on going out of scope.
>
> That is what is implemented in the attached. I am working my way through
> the testcase dependencies of PR37336 making sure that finalizat
> ion occurs as required by 7.5.6.3 and in the order defined in the previous
> section. It will all be done in the next few days.
>
> What will remain is finalization of function results within array
> constructors and one or two other corner cases. Following that, the
> existing finalization calls will be brought into the framework as the new
> calls.
>
> Best regards
>
> Paul
>
>
> On Thu, 27 Jan 2022 at 07:17, Salvatore Filippone <
> filippone.salvatore@gmail.com> wrote:
>
>> One more data point: Cray FTN issues TWO calls to the FINAL.
>> Which begs the question: what is the correct number of calls one, two or
>> three?
>> Salvatore
>>
>> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
>> ftn --version
>> Cray Fortran : Version 11.0.0
>> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
>> ftn -o testfinal testfinal.f90
>> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
>> ./testfinal
>> Allocating wrapper
>> Calling new_outer_type
>> Assigning outer%test_item
>> Called delete_test_type
>> End of new_outer_type
>> DeAllocating wrapper
>> Called delete_test_type
>>
>> On Wed, Jan 26, 2022 at 11:59 PM Paul Richard Thomas <
>> paul.richard.thomas@gmail.com> wrote:
>>
>>> Hi Jerry,
>>>
>>> I am trying to fix the failure of my latest patch with this very test
>>> case. Otherwise it fixes most of the remaining dependencies in PR37336.
>>>
>>> At a pinch, I could submit the earlier patch that Andrew mentions and
>>> work from there. However, you will note that it does miss one of the
>>> finalizations. This is critical because function results, which should be
>>> finalized, are not.
>>>
>>> I'll keep an eye on the state of the branch. By and large, release
>>> occurs 3-4 months after the start of stage 4. I will leave 2 months maximum.
>>>
>>> Best regards
>>>
>>> Paul
>>>
>>>
>>> On Wed, 26 Jan 2022 at 21:29, Jerry D via Fortran <fortran@gcc.gnu.org>
>>> wrote:
>>>
>>>> Is there any reason these patches can not be applied and use this test
>>>> as a test case?
>>>>
>>>> Regards,
>>>>
>>>> Jerry
>>>>
>>>> On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote:
>>>> > Thanks a lot
>>>> > (yes, I suspected both gfortran and intel were wrong, precisely
>>>> because I
>>>> > could see why you'd need two FINAL calls, but not three).
>>>> >
>>>> > Salvatore
>>>> >
>>>> > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson <
>>>> abenson@carnegiescience.edu>
>>>> > wrote:
>>>> >
>>>> >> Hi Salvatore,
>>>> >>
>>>> >> This looks like it's related to some of the missing finalization
>>>> >> functionality
>>>> >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some
>>>> >> patches
>>>> >> (e.g. https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html
>>>> )
>>>> >> which
>>>> >> implement most of the missing functionality. With those patches
>>>> >> incorporated
>>>> >> your code gives the following output with gfortran:
>>>> >>
>>>> >> $ ./testfinal
>>>> >> Allocating wrapper
>>>> >> Calling new_outer_type
>>>> >> Assigning outer%test_item
>>>> >> Called delete_test_type
>>>> >> End of new_outer_type
>>>> >> DeAllocating wrapper
>>>> >> Called delete_test_type
>>>> >>
>>>> >> So there is one more call to the finalizer than you found - I haven't
>>>> >> checked
>>>> >> carefully but I would guess this is a deallocation of LHS on
>>>> assignment.
>>>> >>
>>>> >> In testing these patches using the Intel compiler we found that it
>>>> seems
>>>> >> to
>>>> >> call the finalization wrapper more than it should, sometimes on
>>>> objects
>>>> >> that
>>>> >> have already been deallocated. Your code, compiled with the Intel
>>>> compiler
>>>> >> and
>>>> >> then run under valgrind shows the following:
>>>> >>
>>>> >> $ valgrind ./testfinal
>>>> >> ==7340== Memcheck, a memory error detector
>>>> >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et
>>>> al.
>>>> >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for
>>>> copyright info
>>>> >> ==7340== Command: ./testfinal
>>>> >> ==7340==
>>>> >> ==7340== Conditional jump or move depends on uninitialised value(s)
>>>> >> ==7340== at 0x493A51: __intel_sse2_strcpy (in
>>>> /home/abensonca/Scratch/
>>>> >> ifortTests/testfinal)
>>>> >> ==7340== by 0x45D70E: for__add_to_lf_table (in
>>>> /home/abensonca/Scratch/
>>>> >> ifortTests/testfinal)
>>>> >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/
>>>> >> ifortTests/testfinal)
>>>> >> ==7340== by 0x423A64: for__open_default (in
>>>> /home/abensonca/Scratch/
>>>> >> ifortTests/testfinal)
>>>> >> ==7340== by 0x4305A9: for_write_seq_lis (in
>>>> /home/abensonca/Scratch/
>>>> >> ifortTests/testfinal)
>>>> >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62)
>>>> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
>>>> >> testfinal)
>>>> >> ==7340==
>>>> >> Allocating wrapper
>>>> >> Calling new_outer_type
>>>> >> Assigning outer%test_item
>>>> >> Called delete_test_type
>>>> >> ==7340== Conditional jump or move depends on uninitialised value(s)
>>>> >> ==7340== at 0x40572A: do_alloc_copy (in
>>>> >> /home/abensonca/Scratch/ifortTests/
>>>> >> testfinal)
>>>> >> ==7340== by 0x406B9A: do_alloc_copy (in
>>>> >> /home/abensonca/Scratch/ifortTests/
>>>> >> testfinal)
>>>> >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in
>>>> /home/abensonca/Scratch/
>>>> >> ifortTests/testfinal)
>>>> >> ==7340== by 0x404474: target_mod_mp_new_outer_type_
>>>> (testfinal.f90:48)
>>>> >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65)
>>>> >> ==7340== by 0x403CE1: main (in /home/abensonca/Scratch/ifortTests/
>>>> >> testfinal)
>>>> >> ==7340==
>>>> >> Called delete_test_type
>>>> >> End of new_outer_type
>>>> >> DeAllocating wrapper
>>>> >> Called delete_test_type
>>>> >> ==7340==
>>>> >> ==7340== HEAP SUMMARY:
>>>> >> ==7340== in use at exit: 48 bytes in 1 blocks
>>>> >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes
>>>> allocated
>>>> >> ==7340==
>>>> >> ==7340== LEAK SUMMARY:
>>>> >> ==7340== definitely lost: 48 bytes in 1 blocks
>>>> >> ==7340== indirectly lost: 0 bytes in 0 blocks
>>>> >> ==7340== possibly lost: 0 bytes in 0 blocks
>>>> >> ==7340== still reachable: 0 bytes in 0 blocks
>>>> >> ==7340== suppressed: 0 bytes in 0 blocks
>>>> >> ==7340== Rerun with --leak-check=full to see details of leaked memory
>>>> >> ==7340==
>>>> >> ==7340== For counts of detected and suppressed errors, rerun with: -v
>>>> >> ==7340== Use --track-origins=yes to see where uninitialised values
>>>> come
>>>> >> from
>>>> >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from
>>>> 0)
>>>> >>
>>>> >> so there are some cases of what look like incorrect accesses (and
>>>> some
>>>> >> leaked
>>>> >> memory).
>>>> >>
>>>> >> Your code compiled with gfortran (with Paul's patches in place)
>>>> shows no
>>>> >> errors or leaks from valgrind.
>>>> >>
>>>> >> So, in summary, in this case I think the current gfortran is missing
>>>> some
>>>> >> finalizations (which are fixed by Paul's patches), and ifort is
>>>> likely
>>>> >> doing
>>>> >> something wrong and probably calling the finalizer more times than it
>>>> >> should.
>>>> >>
>>>> >> -Andrew
>>>> >>
>>>> >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via
>>>> Fortran
>>>> >> wrote:
>>>> >>> And here is the code embedded as text............ sorry about
>>>> sending an
>>>> >>> attachment that was purged
>>>> >>> ------------------------- testfinal.f90 ---------------------
>>>> >>> module test_type_mod
>>>> >>>
>>>> >>> type :: my_test_type
>>>> >>> integer, allocatable :: i
>>>> >>> contains
>>>> >>> final :: delete_test_type
>>>> >>> end type my_test_type
>>>> >>>
>>>> >>> interface my_test_type
>>>> >>> module procedure new_test_type_object
>>>> >>> end interface my_test_type
>>>> >>>
>>>> >>> contains
>>>> >>>
>>>> >>> subroutine delete_test_type(this)
>>>> >>> type(my_test_type) :: this
>>>> >>>
>>>> >>> write(*,*) 'Called delete_test_type'
>>>> >>> if (allocated(this%i)) deallocate(this%i)
>>>> >>>
>>>> >>> end subroutine delete_test_type
>>>> >>>
>>>> >>>
>>>> >>> function new_test_type_object(item) result(res)
>>>> >>> type(my_test_type) :: res
>>>> >>> integer, intent(in) :: item
>>>> >>> !Allocation on assignment
>>>> >>> res%i=item
>>>> >>> end function new_test_type_object
>>>> >>>
>>>> >>>
>>>> >>> end module test_type_mod
>>>> >>>
>>>> >>> module target_mod
>>>> >>> use test_type_mod
>>>> >>> type :: outer_type
>>>> >>> type(my_test_type), allocatable :: test_item
>>>> >>> end type outer_type
>>>> >>>
>>>> >>> contains
>>>> >>>
>>>> >>> subroutine new_outer_type(outer,item)
>>>> >>> type(outer_type), intent(out) :: outer
>>>> >>> integer :: item
>>>> >>>
>>>> >>> allocate(outer%test_item)
>>>> >>> write(*,*) 'Assigning outer%test_item'
>>>> >>> outer%test_item = my_test_type(itemi)
>>>> >>> write(*,*) 'End of new_outer_type'
>>>> >>> end subroutine new_outer_type
>>>> >>>
>>>> >>> end module target_mod
>>>> >>>
>>>> >>> program testfinal
>>>> >>> use target_mod
>>>> >>>
>>>> >>> implicit none
>>>> >>>
>>>> >>> integer :: i=10
>>>> >>> type(outer_type), allocatable :: wrapper
>>>> >>>
>>>> >>> write(*,*) 'Allocating wrapper '
>>>> >>> allocate(wrapper)
>>>> >>> write(*,*) 'Calling new_outer_type '
>>>> >>> call new_outer_type(wrapper,i)
>>>> >>> write(*,*) 'DeAllocating wrapper '
>>>> >>> deallocate(wrapper)
>>>> >>>
>>>> >>> end program testfinal
>>>> >>>
>>>> >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone <
>>>> >>>
>>>> >>> filippone.salvatore@gmail.com> wrote:
>>>> >>>> Hi all
>>>> >>>> The attached code compiles and runs fine under both GNU and Intel,
>>>> but
>>>> >> it
>>>> >>>> produces different results, in particular the FINAL subroutine is
>>>> >> invoked
>>>> >>>> just once with GNU, three times with Intel.
>>>> >>>>
>>>> >>>> It seems to me that they cannot both be right; I am not sure what
>>>> the
>>>> >>>> standard is mandating in this case.
>>>> >>>> Any ideas?
>>>> >>>> Salvatore
>>>> >>>> --------------- Intel
>>>> >>>> [pr1eio03@login1: newstuff]$ ifort -v
>>>> >>>> ifort version 19.1.1.217
>>>> >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90
>>>> >>>> [pr1eio03@login1: newstuff]$ ./testfinal
>>>> >>>>
>>>> >>>> Allocating wrapper
>>>> >>>> Calling new_outer_type
>>>> >>>> Assigning outer%test_item
>>>> >>>> Called delete_test_type
>>>> >>>> Called delete_test_type
>>>> >>>> End of new_outer_type
>>>> >>>> DeAllocating wrapper
>>>> >>>> Called delete_test_type
>>>> >>>>
>>>> >>>> ----------------------------- GNU
>>>> >>>> sfilippo@lagrange newstuff]$ gfortran -v
>>>> >>>> Using built-in specs.
>>>> >>>> COLLECT_GCC=gfortran
>>>> >>>>
>>>> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
>>>> >>>> OFFLOAD_TARGET_NAMES=nvptx-none
>>>> >>>> OFFLOAD_TARGET_DEFAULT=1
>>>> >>>> Target: x86_64-redhat-linux
>>>> >>>> Configured with: ../configure --enable-bootstrap
>>>> >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto
>>>> >> --prefix=/usr
>>>> >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=
>>>> >>>> http://bugzilla.redhat.com/bugzilla --enable-shared
>>>> >>>> --enable-threads=posix --enable-checking=release --enable-multilib
>>>> >>>> --with-system-zlib --enable-__cxa_atexit
>>>> --disable-libunwind-exceptions
>>>> >>>> --enable-gnu-unique-object --enable-linker-build-id
>>>> >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu
>>>> >> --enable-plugin
>>>> >>>> --enable-initfini-array
>>>> >>>>
>>>> >>
>>>> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin
>>>> >>>> ux/isl-install --enable-offload-targets=nvptx-none
>>>> >> --without-cuda-driver
>>>> >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic
>>>> >>>> --with-arch_32=i686 --build=x86_64-redhat-linux
>>>> >>>> Thread model: posix
>>>> >>>> Supported LTO compression algorithms: zlib zstd
>>>> >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
>>>> >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90
>>>> >>>> [sfilippo@lagrange newstuff]$ ./testfinal
>>>> >>>>
>>>> >>>> Allocating wrapper
>>>> >>>> Calling new_outer_type
>>>> >>>> Assigning outer%test_item
>>>> >>>> End of new_outer_type
>>>> >>>> DeAllocating wrapper
>>>> >>>> Called delete_test_type
>>>> >>>>
>>>> >>>> ---------------------
>>>> >>
>>>> >> --
>>>> >>
>>>> >> * Andrew Benson: https://abensonca.github.io
>>>> >>
>>>> >> * Galacticus: https://github.com/galacticusorg/galacticus
>>>> >>
>>>> >>
>>>> >>
>>>> >>
>>>>
>>>>
>>>
>>> --
>>> "If you can't explain it simply, you don't understand it well enough" -
>>> Albert Einstein
>>>
>>
>
> --
> "If you can't explain it simply, you don't understand it well enough" -
> Albert Einstein
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: FINAL subroutines
2022-01-28 8:05 ` Salvatore Filippone
@ 2022-01-28 9:01 ` Paul Richard Thomas
0 siblings, 0 replies; 10+ messages in thread
From: Paul Richard Thomas @ 2022-01-28 9:01 UTC (permalink / raw)
To: Salvatore Filippone; +Cc: Jerry D, Andrew Benson, Damian Rouson, Fortran List
Hi Salvatore,
That's correct. It's what ifort does too. Thus far I have found only one or
two minor niggles with the Intel implementation of finalization. Since, as
often or not, the two compilers are frequently used by the same users, I
will attempt to make them compliant with one another. I will have a
conversation with the Intel developers sometime next week.
BTW I noticed a small error in the patch that I attached last night. I
introduced a kludge to fix your testcase in the call to gfc_copy_alloc_comp
in finalize_function_result. The the expression rank is needed and has been
introduced as a new argument to gfc_copy_alloc_comp.
Ciao
Paul
On Fri, 28 Jan 2022 at 08:05, Salvatore Filippone <
filippone.salvatore@gmail.com> wrote:
> So, you are saying that three calls is the correct number, one for the
> LHS, one for the RHS, and one for the deallocation in the main program.
> I have (re)-read the standard, I would concur with your interpretation.
>
> On Thu, Jan 27, 2022 at 11:10 PM Paul Richard Thomas <
> paul.richard.thomas@gmail.com> wrote:
>
>> Hi Salvatore,
>>
>>
>> My reading of F2018: 7.5.6.3 "When finalization occurs" is that three
>> calls is correct. (i) Paragraph 1 stipulates that the 'var' expression be
>> evaluated before the reallocation and intrinsic assignment; (ii)stipulates
>> that the function result be finalised "the result is finalized after
>> execution of the innermost
>> executable construct containing the reference." ; and (iii) Finalisation
>> occurs on going out of scope.
>>
>> That is what is implemented in the attached. I am working my way through
>> the testcase dependencies of PR37336 making sure that finalizat
>> ion occurs as required by 7.5.6.3 and in the order defined in the
>> previous section. It will all be done in the next few days.
>>
>> What will remain is finalization of function results within array
>> constructors and one or two other corner cases. Following that, the
>> existing finalization calls will be brought into the framework as the new
>> calls.
>>
>> Best regards
>>
>> Paul
>>
>>
>> On Thu, 27 Jan 2022 at 07:17, Salvatore Filippone <
>> filippone.salvatore@gmail.com> wrote:
>>
>>> One more data point: Cray FTN issues TWO calls to the FINAL.
>>> Which begs the question: what is the correct number of calls one, two or
>>> three?
>>> Salvatore
>>>
>>> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
>>> ftn --version
>>> Cray Fortran : Version 11.0.0
>>> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
>>> ftn -o testfinal testfinal.f90
>>> fsalvato@daint102:/project/prce01/fsalvato/NUMERICAL/PSBLAS/V4/psblas4/test/newstuff>
>>> ./testfinal
>>> Allocating wrapper
>>> Calling new_outer_type
>>> Assigning outer%test_item
>>> Called delete_test_type
>>> End of new_outer_type
>>> DeAllocating wrapper
>>> Called delete_test_type
>>>
>>> On Wed, Jan 26, 2022 at 11:59 PM Paul Richard Thomas <
>>> paul.richard.thomas@gmail.com> wrote:
>>>
>>>> Hi Jerry,
>>>>
>>>> I am trying to fix the failure of my latest patch with this very test
>>>> case. Otherwise it fixes most of the remaining dependencies in PR37336.
>>>>
>>>> At a pinch, I could submit the earlier patch that Andrew mentions and
>>>> work from there. However, you will note that it does miss one of the
>>>> finalizations. This is critical because function results, which should be
>>>> finalized, are not.
>>>>
>>>> I'll keep an eye on the state of the branch. By and large, release
>>>> occurs 3-4 months after the start of stage 4. I will leave 2 months maximum.
>>>>
>>>> Best regards
>>>>
>>>> Paul
>>>>
>>>>
>>>> On Wed, 26 Jan 2022 at 21:29, Jerry D via Fortran <fortran@gcc.gnu.org>
>>>> wrote:
>>>>
>>>>> Is there any reason these patches can not be applied and use this test
>>>>> as a test case?
>>>>>
>>>>> Regards,
>>>>>
>>>>> Jerry
>>>>>
>>>>> On 1/24/22 8:11 AM, Salvatore Filippone via Fortran wrote:
>>>>> > Thanks a lot
>>>>> > (yes, I suspected both gfortran and intel were wrong, precisely
>>>>> because I
>>>>> > could see why you'd need two FINAL calls, but not three).
>>>>> >
>>>>> > Salvatore
>>>>> >
>>>>> > On Mon, Jan 24, 2022 at 4:45 PM Andrew Benson <
>>>>> abenson@carnegiescience.edu>
>>>>> > wrote:
>>>>> >
>>>>> >> Hi Salvatore,
>>>>> >>
>>>>> >> This looks like it's related to some of the missing finalization
>>>>> >> functionality
>>>>> >> (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=37336). Paul has some
>>>>> >> patches
>>>>> >> (e.g.
>>>>> https://gcc.gnu.org/pipermail/fortran/2022-January/057415.html)
>>>>> >> which
>>>>> >> implement most of the missing functionality. With those patches
>>>>> >> incorporated
>>>>> >> your code gives the following output with gfortran:
>>>>> >>
>>>>> >> $ ./testfinal
>>>>> >> Allocating wrapper
>>>>> >> Calling new_outer_type
>>>>> >> Assigning outer%test_item
>>>>> >> Called delete_test_type
>>>>> >> End of new_outer_type
>>>>> >> DeAllocating wrapper
>>>>> >> Called delete_test_type
>>>>> >>
>>>>> >> So there is one more call to the finalizer than you found - I
>>>>> haven't
>>>>> >> checked
>>>>> >> carefully but I would guess this is a deallocation of LHS on
>>>>> assignment.
>>>>> >>
>>>>> >> In testing these patches using the Intel compiler we found that it
>>>>> seems
>>>>> >> to
>>>>> >> call the finalization wrapper more than it should, sometimes on
>>>>> objects
>>>>> >> that
>>>>> >> have already been deallocated. Your code, compiled with the Intel
>>>>> compiler
>>>>> >> and
>>>>> >> then run under valgrind shows the following:
>>>>> >>
>>>>> >> $ valgrind ./testfinal
>>>>> >> ==7340== Memcheck, a memory error detector
>>>>> >> ==7340== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward
>>>>> et al.
>>>>> >> ==7340== Using Valgrind-3.13.0 and LibVEX; rerun with -h for
>>>>> copyright info
>>>>> >> ==7340== Command: ./testfinal
>>>>> >> ==7340==
>>>>> >> ==7340== Conditional jump or move depends on uninitialised value(s)
>>>>> >> ==7340== at 0x493A51: __intel_sse2_strcpy (in
>>>>> /home/abensonca/Scratch/
>>>>> >> ifortTests/testfinal)
>>>>> >> ==7340== by 0x45D70E: for__add_to_lf_table (in
>>>>> /home/abensonca/Scratch/
>>>>> >> ifortTests/testfinal)
>>>>> >> ==7340== by 0x4410CB: for__open_proc (in /home/abensonca/Scratch/
>>>>> >> ifortTests/testfinal)
>>>>> >> ==7340== by 0x423A64: for__open_default (in
>>>>> /home/abensonca/Scratch/
>>>>> >> ifortTests/testfinal)
>>>>> >> ==7340== by 0x4305A9: for_write_seq_lis (in
>>>>> /home/abensonca/Scratch/
>>>>> >> ifortTests/testfinal)
>>>>> >> ==7340== by 0x4047E1: MAIN__ (testfinal.f90:62)
>>>>> >> ==7340== by 0x403CE1: main (in
>>>>> /home/abensonca/Scratch/ifortTests/
>>>>> >> testfinal)
>>>>> >> ==7340==
>>>>> >> Allocating wrapper
>>>>> >> Calling new_outer_type
>>>>> >> Assigning outer%test_item
>>>>> >> Called delete_test_type
>>>>> >> ==7340== Conditional jump or move depends on uninitialised value(s)
>>>>> >> ==7340== at 0x40572A: do_alloc_copy (in
>>>>> >> /home/abensonca/Scratch/ifortTests/
>>>>> >> testfinal)
>>>>> >> ==7340== by 0x406B9A: do_alloc_copy (in
>>>>> >> /home/abensonca/Scratch/ifortTests/
>>>>> >> testfinal)
>>>>> >> ==7340== by 0x4084ED: for_alloc_assign_v2 (in
>>>>> /home/abensonca/Scratch/
>>>>> >> ifortTests/testfinal)
>>>>> >> ==7340== by 0x404474: target_mod_mp_new_outer_type_
>>>>> (testfinal.f90:48)
>>>>> >> ==7340== by 0x40485E: MAIN__ (testfinal.f90:65)
>>>>> >> ==7340== by 0x403CE1: main (in
>>>>> /home/abensonca/Scratch/ifortTests/
>>>>> >> testfinal)
>>>>> >> ==7340==
>>>>> >> Called delete_test_type
>>>>> >> End of new_outer_type
>>>>> >> DeAllocating wrapper
>>>>> >> Called delete_test_type
>>>>> >> ==7340==
>>>>> >> ==7340== HEAP SUMMARY:
>>>>> >> ==7340== in use at exit: 48 bytes in 1 blocks
>>>>> >> ==7340== total heap usage: 14 allocs, 13 frees, 12,879 bytes
>>>>> allocated
>>>>> >> ==7340==
>>>>> >> ==7340== LEAK SUMMARY:
>>>>> >> ==7340== definitely lost: 48 bytes in 1 blocks
>>>>> >> ==7340== indirectly lost: 0 bytes in 0 blocks
>>>>> >> ==7340== possibly lost: 0 bytes in 0 blocks
>>>>> >> ==7340== still reachable: 0 bytes in 0 blocks
>>>>> >> ==7340== suppressed: 0 bytes in 0 blocks
>>>>> >> ==7340== Rerun with --leak-check=full to see details of leaked
>>>>> memory
>>>>> >> ==7340==
>>>>> >> ==7340== For counts of detected and suppressed errors, rerun with:
>>>>> -v
>>>>> >> ==7340== Use --track-origins=yes to see where uninitialised values
>>>>> come
>>>>> >> from
>>>>> >> ==7340== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0
>>>>> from 0)
>>>>> >>
>>>>> >> so there are some cases of what look like incorrect accesses (and
>>>>> some
>>>>> >> leaked
>>>>> >> memory).
>>>>> >>
>>>>> >> Your code compiled with gfortran (with Paul's patches in place)
>>>>> shows no
>>>>> >> errors or leaks from valgrind.
>>>>> >>
>>>>> >> So, in summary, in this case I think the current gfortran is
>>>>> missing some
>>>>> >> finalizations (which are fixed by Paul's patches), and ifort is
>>>>> likely
>>>>> >> doing
>>>>> >> something wrong and probably calling the finalizer more times than
>>>>> it
>>>>> >> should.
>>>>> >>
>>>>> >> -Andrew
>>>>> >>
>>>>> >> On Monday, January 24, 2022 6:49:23 AM PST Salvatore Filippone via
>>>>> Fortran
>>>>> >> wrote:
>>>>> >>> And here is the code embedded as text............ sorry about
>>>>> sending an
>>>>> >>> attachment that was purged
>>>>> >>> ------------------------- testfinal.f90 ---------------------
>>>>> >>> module test_type_mod
>>>>> >>>
>>>>> >>> type :: my_test_type
>>>>> >>> integer, allocatable :: i
>>>>> >>> contains
>>>>> >>> final :: delete_test_type
>>>>> >>> end type my_test_type
>>>>> >>>
>>>>> >>> interface my_test_type
>>>>> >>> module procedure new_test_type_object
>>>>> >>> end interface my_test_type
>>>>> >>>
>>>>> >>> contains
>>>>> >>>
>>>>> >>> subroutine delete_test_type(this)
>>>>> >>> type(my_test_type) :: this
>>>>> >>>
>>>>> >>> write(*,*) 'Called delete_test_type'
>>>>> >>> if (allocated(this%i)) deallocate(this%i)
>>>>> >>>
>>>>> >>> end subroutine delete_test_type
>>>>> >>>
>>>>> >>>
>>>>> >>> function new_test_type_object(item) result(res)
>>>>> >>> type(my_test_type) :: res
>>>>> >>> integer, intent(in) :: item
>>>>> >>> !Allocation on assignment
>>>>> >>> res%i=item
>>>>> >>> end function new_test_type_object
>>>>> >>>
>>>>> >>>
>>>>> >>> end module test_type_mod
>>>>> >>>
>>>>> >>> module target_mod
>>>>> >>> use test_type_mod
>>>>> >>> type :: outer_type
>>>>> >>> type(my_test_type), allocatable :: test_item
>>>>> >>> end type outer_type
>>>>> >>>
>>>>> >>> contains
>>>>> >>>
>>>>> >>> subroutine new_outer_type(outer,item)
>>>>> >>> type(outer_type), intent(out) :: outer
>>>>> >>> integer :: item
>>>>> >>>
>>>>> >>> allocate(outer%test_item)
>>>>> >>> write(*,*) 'Assigning outer%test_item'
>>>>> >>> outer%test_item = my_test_type(itemi)
>>>>> >>> write(*,*) 'End of new_outer_type'
>>>>> >>> end subroutine new_outer_type
>>>>> >>>
>>>>> >>> end module target_mod
>>>>> >>>
>>>>> >>> program testfinal
>>>>> >>> use target_mod
>>>>> >>>
>>>>> >>> implicit none
>>>>> >>>
>>>>> >>> integer :: i=10
>>>>> >>> type(outer_type), allocatable :: wrapper
>>>>> >>>
>>>>> >>> write(*,*) 'Allocating wrapper '
>>>>> >>> allocate(wrapper)
>>>>> >>> write(*,*) 'Calling new_outer_type '
>>>>> >>> call new_outer_type(wrapper,i)
>>>>> >>> write(*,*) 'DeAllocating wrapper '
>>>>> >>> deallocate(wrapper)
>>>>> >>>
>>>>> >>> end program testfinal
>>>>> >>>
>>>>> >>> On Mon, Jan 24, 2022 at 2:50 PM Salvatore Filippone <
>>>>> >>>
>>>>> >>> filippone.salvatore@gmail.com> wrote:
>>>>> >>>> Hi all
>>>>> >>>> The attached code compiles and runs fine under both GNU and
>>>>> Intel, but
>>>>> >> it
>>>>> >>>> produces different results, in particular the FINAL subroutine is
>>>>> >> invoked
>>>>> >>>> just once with GNU, three times with Intel.
>>>>> >>>>
>>>>> >>>> It seems to me that they cannot both be right; I am not sure what
>>>>> the
>>>>> >>>> standard is mandating in this case.
>>>>> >>>> Any ideas?
>>>>> >>>> Salvatore
>>>>> >>>> --------------- Intel
>>>>> >>>> [pr1eio03@login1: newstuff]$ ifort -v
>>>>> >>>> ifort version 19.1.1.217
>>>>> >>>> [pr1eio03@login1: newstuff]$ ifort -o testfinal testfinal.f90
>>>>> >>>> [pr1eio03@login1: newstuff]$ ./testfinal
>>>>> >>>>
>>>>> >>>> Allocating wrapper
>>>>> >>>> Calling new_outer_type
>>>>> >>>> Assigning outer%test_item
>>>>> >>>> Called delete_test_type
>>>>> >>>> Called delete_test_type
>>>>> >>>> End of new_outer_type
>>>>> >>>> DeAllocating wrapper
>>>>> >>>> Called delete_test_type
>>>>> >>>>
>>>>> >>>> ----------------------------- GNU
>>>>> >>>> sfilippo@lagrange newstuff]$ gfortran -v
>>>>> >>>> Using built-in specs.
>>>>> >>>> COLLECT_GCC=gfortran
>>>>> >>>>
>>>>> COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/11/lto-wrapper
>>>>> >>>> OFFLOAD_TARGET_NAMES=nvptx-none
>>>>> >>>> OFFLOAD_TARGET_DEFAULT=1
>>>>> >>>> Target: x86_64-redhat-linux
>>>>> >>>> Configured with: ../configure --enable-bootstrap
>>>>> >>>> --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto
>>>>> >> --prefix=/usr
>>>>> >>>> --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=
>>>>> >>>> http://bugzilla.redhat.com/bugzilla --enable-shared
>>>>> >>>> --enable-threads=posix --enable-checking=release --enable-multilib
>>>>> >>>> --with-system-zlib --enable-__cxa_atexit
>>>>> --disable-libunwind-exceptions
>>>>> >>>> --enable-gnu-unique-object --enable-linker-build-id
>>>>> >>>> --with-gcc-major-version-only --with-linker-hash-style=gnu
>>>>> >> --enable-plugin
>>>>> >>>> --enable-initfini-array
>>>>> >>>>
>>>>> >>
>>>>> --with-isl=/builddir/build/BUILD/gcc-11.2.1-20210728/obj-x86_64-redhat-lin
>>>>> >>>> ux/isl-install --enable-offload-targets=nvptx-none
>>>>> >> --without-cuda-driver
>>>>> >>>> --enable-gnu-indirect-function --enable-cet --with-tune=generic
>>>>> >>>> --with-arch_32=i686 --build=x86_64-redhat-linux
>>>>> >>>> Thread model: posix
>>>>> >>>> Supported LTO compression algorithms: zlib zstd
>>>>> >>>> gcc version 11.2.1 20210728 (Red Hat 11.2.1-1) (GCC)
>>>>> >>>> [sfilippo@lagrange newstuff]$ gfortran -o testfinal testfinal.f90
>>>>> >>>> [sfilippo@lagrange newstuff]$ ./testfinal
>>>>> >>>>
>>>>> >>>> Allocating wrapper
>>>>> >>>> Calling new_outer_type
>>>>> >>>> Assigning outer%test_item
>>>>> >>>> End of new_outer_type
>>>>> >>>> DeAllocating wrapper
>>>>> >>>> Called delete_test_type
>>>>> >>>>
>>>>> >>>> ---------------------
>>>>> >>
>>>>> >> --
>>>>> >>
>>>>> >> * Andrew Benson: https://abensonca.github.io
>>>>> >>
>>>>> >> * Galacticus: https://github.com/galacticusorg/galacticus
>>>>> >>
>>>>> >>
>>>>> >>
>>>>> >>
>>>>>
>>>>>
>>>>
>>>> --
>>>> "If you can't explain it simply, you don't understand it well enough" -
>>>> Albert Einstein
>>>>
>>>
>>
>> --
>> "If you can't explain it simply, you don't understand it well enough" -
>> Albert Einstein
>>
>
--
"If you can't explain it simply, you don't understand it well enough" -
Albert Einstein
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2022-01-28 9:01 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-24 13:50 FINAL subroutines Salvatore Filippone
2022-01-24 14:49 ` Salvatore Filippone
2022-01-24 15:45 ` Andrew Benson
2022-01-24 16:11 ` Salvatore Filippone
2022-01-26 21:29 ` Jerry D
2022-01-26 22:59 ` Paul Richard Thomas
2022-01-27 7:17 ` Salvatore Filippone
2022-01-27 22:10 ` Paul Richard Thomas
2022-01-28 8:05 ` Salvatore Filippone
2022-01-28 9:01 ` Paul Richard Thomas
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).