From 811f902b764c5a13178cbd7588e96c16b3fab504 Mon Sep 17 00:00:00 2001 From: Thomas Koenig Date: Sun, 31 May 2020 10:26:40 +0200 Subject: [PATCH] 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 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 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. --- gcc/fortran/class.c | 5 ++- gcc/fortran/gfortran.h | 4 +- gcc/testsuite/gfortran.dg/finalize_28.f90 | 2 +- gcc/testsuite/gfortran.dg/finalize_33.f90 | 2 +- gcc/testsuite/gfortran.dg/finalize_34.f90 | 2 +- gcc/testsuite/gfortran.dg/finalize_35.f90 | 48 +++++++++++++++++++++++ 6 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/finalize_35.f90 diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c index afd8885a1ea..b1764073ab4 100644 --- a/gcc/fortran/class.c +++ b/gcc/fortran/class.c @@ -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; } diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 7094791e871..5af44847f9b 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -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 diff --git a/gcc/testsuite/gfortran.dg/finalize_28.f90 b/gcc/testsuite/gfortran.dg/finalize_28.f90 index 597413b2dd3..f0c9665252f 100644 --- a/gcc/testsuite/gfortran.dg/finalize_28.f90 +++ b/gcc/testsuite/gfortran.dg/finalize_28.f90 @@ -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" } } diff --git a/gcc/testsuite/gfortran.dg/finalize_33.f90 b/gcc/testsuite/gfortran.dg/finalize_33.f90 index 2205f9eed7f..3857e4485ee 100644 --- a/gcc/testsuite/gfortran.dg/finalize_33.f90 +++ b/gcc/testsuite/gfortran.dg/finalize_33.f90 @@ -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" } } diff --git a/gcc/testsuite/gfortran.dg/finalize_34.f90 b/gcc/testsuite/gfortran.dg/finalize_34.f90 index e2f02a5c51c..fef7dac6d89 100644 --- a/gcc/testsuite/gfortran.dg/finalize_34.f90 +++ b/gcc/testsuite/gfortran.dg/finalize_34.f90 @@ -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" } } diff --git a/gcc/testsuite/gfortran.dg/finalize_35.f90 b/gcc/testsuite/gfortran.dg/finalize_35.f90 new file mode 100644 index 00000000000..66435c43ecc --- /dev/null +++ b/gcc/testsuite/gfortran.dg/finalize_35.f90 @@ -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" } } -- 2.30.2