Finalization depends on the expression, not on the component.

This patch fixes a 8/9/10/11 regression, where finalized types
were not finalized (and deallocated), which led to memory
leaks.

gcc/fortran/ChangeLog:

2020-05-24  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/94361
	* class.c (finalize_component): Use expr->finalized instead of
	comp->finalized.
	* gfortran.h (gfc_component): Remove finalized member.
	(gfc_expr): Add it here instead.

gcc/testsuite/ChangeLog:

2020-05-24  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/94361
	* gfortran.dg/finalize_28.f90: Adjusted free counts.
	* gfortran.dg/finalize_33.f90: Likewise.
	* gfortran.dg/finalize_34.f90: Likewise.
	* gfortran.dg/finalize_35.f90: New test.
This commit is contained in:
Thomas Koenig 2020-05-31 10:26:40 +02:00
parent dc8c02ca1c
commit 811f902b76
6 changed files with 57 additions and 6 deletions

View File

@ -921,7 +921,7 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
if (!comp_is_finalizable (comp))
return;
if (comp->finalized)
if (expr->finalized)
return;
e = gfc_copy_expr (expr);
@ -1012,6 +1012,7 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
}
else
(*code) = cond;
}
else if (comp->ts.type == BT_DERIVED
&& comp->ts.u.derived->f2k_derived
@ -1051,7 +1052,7 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
sub_ns);
gfc_free_expr (e);
}
comp->finalized = true;
expr->finalized = 1;
}

View File

@ -1107,7 +1107,6 @@ typedef struct gfc_component
struct gfc_typebound_proc *tb;
/* When allocatable/pointer and in a coarray the associated token. */
tree caf_token;
bool finalized;
}
gfc_component;
@ -2218,6 +2217,9 @@ typedef struct gfc_expr
/* Set this if the expression came from expanding an array constructor. */
unsigned int from_constructor : 1;
/* Set this if the expression has already been finalized. */
unsigned int finalized : 1;
/* If an expression comes from a Hollerith constant or compile-time
evaluation of a transfer statement, it may have a prescribed target-
memory representation, and these cannot always be backformed from

View File

@ -21,4 +21,4 @@ contains
integer, intent(out) :: edges(:,:)
end subroutine coo_dump_edges
end module coo_graphs
! { dg-final { scan-tree-dump-times "__builtin_free" 5 "original" } }
! { dg-final { scan-tree-dump-times "__builtin_free" 6 "original" } }

View File

@ -116,4 +116,4 @@ contains
! (iii) mci_template
end program main_ut
! { dg-final { scan-tree-dump-times "__builtin_malloc" 17 "original" } }
! { dg-final { scan-tree-dump-times "__builtin_free" 19 "original" } }
! { dg-final { scan-tree-dump-times "__builtin_free" 20 "original" } }

View File

@ -22,4 +22,4 @@ program main
use testmodule
type(evtlist_type), dimension(10) :: a
end program main
! { dg-final { scan-tree-dump-times "__builtin_free" 8 "original" } }
! { dg-final { scan-tree-dump-times "__builtin_free" 12 "original" } }

View File

@ -0,0 +1,48 @@
! { dg-do compile }
! { dg-additional-options "-fdump-tree-original" }
! PR 94361 - this left open some memory leaks. Original test case by
! Antony Lewis.
module debug
private
Type TypeWithFinal
contains
FINAL :: finalizer !No leak if this line is commented
end type TypeWithFinal
Type Tester
real, dimension(:), allocatable :: Dat
Type(TypeWithFinal) :: X
end Type Tester
Type :: TestType2
Type(Tester) :: T
end type TestType2
public Leaker
contains
subroutine Leaker
type(TestType2) :: Test
allocate(Test%T%Dat(1000))
end subroutine Leaker
subroutine finalizer(this)
Type(TypeWithFinal) :: this
end subroutine finalizer
end module debug
program run
use debug
implicit none
integer i
do i=1, 1000
call Leaker()
end do
end program run
! { dg-final { scan-tree-dump-times "__builtin_free\\ \\(ptr2" 2 "original" } }