Bug 64290 - [F03] No finalization at deallocation of LHS
Summary: [F03] No finalization at deallocation of LHS
Status: ASSIGNED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 5.0
: P3 normal
Target Milestone: ---
Assignee: Paul Thomas
URL:
Keywords: wrong-code
Depends on:
Blocks: Finalization
  Show dependency treegraph
 
Reported: 2014-12-12 16:25 UTC by Bálint Aradi
Modified: 2021-05-04 12:31 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-12-15 00:00:00


Attachments
Self contained source demonstrating (253 bytes, text/x-fortran)
2014-12-12 16:25 UTC, Bálint Aradi
Details
Initial fix for the PR (697 bytes, patch)
2021-01-11 08:17 UTC, Paul Thomas
Details | Diff
Slightly better patch (912 bytes, patch)
2021-01-12 12:04 UTC, Paul Thomas
Details | Diff
realloc_class_8.f95 (681 bytes, text/plain)
2021-01-18 08:32 UTC, Ev Drikos
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Bálint Aradi 2014-12-12 16:25:53 UTC
Created attachment 34268 [details]
Self contained source demonstrating

During an assingment with an allocatable type on both, the LHS and the RHS, the destructor of the LHS-type is not called. IMHO, this is erroneous behaviour as the LHS gets (hopfully) deallocated on the assignment.
Comment 1 janus 2014-12-15 11:46:48 UTC
Confirmed. See also PR 37336 comment 27.
Comment 2 Paul Thomas 2021-01-11 08:17:11 UTC
Created attachment 49936 [details]
Initial fix for the PR

Triggered by a recent thread on clf, I have made a first stab at this PR. This patch is thus far perfect and has the following regressions:

FAIL: gfortran.dg/class_optional_1.f90   -O0  execution test
FAIL: gfortran.dg/dynamic_dispatch_6.f03   -O1  execution test
FAIL: gfortran.dg/finalize_15.f90   -O0  (internal compiler error)
FAIL: gfortran.dg/finalize_25.f90   -O0  execution test
FAIL: gfortran.dg/finalize_29.f08   -O0  execution test
plus
FAIL: gfortran.dg/prof/dynamic_dispatch_6.f03 execution,    -fprofile-generate -D_PROFILE_GENERATE

which is not too bad for a first attempt. Note that for arrays, finalization is occurring before reallocation of the lhs contrary to the requirements of the standard.

This test, based on the reporter's testcase, works as intended:
module testmode
  implicit none

  type :: simple
    integer :: ind
  contains
    final :: destruct1, destruct2
  end type simple

  integer :: check_scalar
  integer :: check_array(2)
  integer :: final_count = 0

contains

  subroutine destruct1(self)
    type(simple), intent(inout) :: self

!    print *, "DESTRUCTING SCALAR", self%ind
    check_scalar = self%ind
    check_array = 0
    final_count = final_count + 1

  end subroutine destruct1

  subroutine destruct2(self)
    type(simple), intent(inout) :: self(:)

!    print *, "DESTRUCTING ARRAY", self%ind
    check_scalar = 0
    check_array = self%ind
    final_count = final_count + 1

  end subroutine destruct2

  subroutine test (cnt, scalar, array, off)
    integer :: cnt
    integer :: scalar
    integer :: array(:)
    integer :: off
    if (final_count .ne. cnt) stop 1 + off
    if (check_scalar .ne. scalar) stop 2 + off
    if (any (check_array .ne. array)) stop 3 + off
  end subroutine test

end module testmode

program test_final
  use testmode
  implicit none

  type(simple), allocatable :: myres, myres2
  type(simple), allocatable :: myarray(:)
  type(simple) :: thyres = simple(21), thyres2 = simple(22)

  allocate(myres)
  allocate(myres2)
  myres%ind = 1
  myres2%ind = 2
  myres = myres2
  call test(1, 1, [0,0], 10)

  allocate(myarray(2))
  myarray%ind = [42, 43]
  myarray = [thyres, thyres2]
  call test(2, 0, [42,43], 20)

  thyres2 = simple(99)
  call test(3, 22, [0,0], 30)

  thyres = thyres2
  call test(4, 21, [0,0], 40)

  deallocate (myres, myres2)
  call test(6, 2, [0,0], 100)

  deallocate (myarray)
  call test(7, 0, [21,22], 200)

end program test_final

Paul
Comment 3 Paul Thomas 2021-01-12 12:04:46 UTC
Created attachment 49952 [details]
Slightly better patch

This gets rid of the regression in gfortran.dg/finalize_29.f08.

However, finalize_25.f90 exposes the real scale of the problem because it shows that finalization is partially implemented for variables with allocatable components and this causes collisions with the finalization in the patch.

Cheers

Paul
Comment 4 Ev Drikos 2021-01-12 13:03:38 UTC

Hello,

There are some open PRs related to elemental finalisers. Having seen
how you reallocate arrays, I'd the impression that the functionality
for polymorphic entities would had a similar design. As one may also
need ie to reset at least the '_len' field, ie class(*) x; x='a';

Which in turn may not cause regressions to "finalize_25.f90" and I see
that this test counts some finalisation calls. Of course I don't doubt
that finalization may be partially implemented as you say. Admittedly
the interpretation of 10.2.1.3 & 7.5.6.3 seems to be a herculean task.

To my understanding, an outcome of the discussion in c.l.f is that the
reallocation takes place if the LHS & RHS have different runtime types,
at least this seems to be a criterion for no rank polymorphic entities.


Hope this helps,
Ev. Drikos
Comment 5 Ev Drikos 2021-01-18 08:32:17 UTC
Created attachment 49990 [details]
realloc_class_8.f95

Hello,

Having seen a Note in F2018 draft, specifically
10.2.1.3 Interpretation of intrinsic assignments,
I wrote a test case that I thought should be ok,
but I face this: 

$ gfortran8 realloc_class_8.f95 && ./a.out

 DEFERRED LENGTH NAME

 NAME=NONE [LEN=           4 ]
 USER=NONE [LEN=           4 ]

 NAME=Mr. John Richard Doe [LEN=          20 ]
 USER=Mr. John RichardMr.  [LEN=          20 ]
STOP 6

Of course, there are no finalizers in this case,
yet I think that is closely related because they
have the same bug fix (class reallocations).  


Hope this helps,
Ev. Drikos