aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/class.c
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2020-06-14 13:01:24 +0200
committerThomas Koenig <tkoenig@gcc.gnu.org>2020-06-14 13:01:24 +0200
commit1af22e455584ef5fcad2b4474c1efc3fd26f6cb3 (patch)
tree769ed6b4561d0635ea175b5a1b496690efc39c75 /gcc/fortran/class.c
parent275bef5fbae9d1e22885c581cfbe6fc5248ca8ad (diff)
downloadgcc-1af22e455584ef5fcad2b4474c1efc3fd26f6cb3.zip
gcc-1af22e455584ef5fcad2b4474c1efc3fd26f6cb3.tar.gz
gcc-1af22e455584ef5fcad2b4474c1efc3fd26f6cb3.tar.bz2
When avoiding double deallocation, look at namespace, expression and component.
Our finalization handling is a mess. Really, we should get to try and get this fixed for gcc 11. In the meantime, here is a patch which fixes a regression I introduced when fixing a regression with a memory leak. The important thing here is to realize that we do not need to finalize (and deallocate) multiple times for the same expression and the same component in the same namespace. It might cause code size regressions, but better big code than wrong code... gcc/fortran/ChangeLog: PR fortran/94109 * class.c (finalize_component): Return early if finalization has already happened for expression and component within namespace. * gfortran.h (gfc_was_finalized): New type. (gfc_namespace): Add member was_finalzed. (gfc_expr): Remove finalized. * symbol.c (gfc_free_namespace): Free was_finalized. gcc/testsuite/ChangeLog: PR fortran/94109 * gfortran.dg/finalize_34.f90: Adjust free counts. * gfortran.dg/finalize_36.f90: New test.
Diffstat (limited to 'gcc/fortran/class.c')
-rw-r--r--gcc/fortran/class.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index 2b55859..cfc4502 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -920,12 +920,18 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
{
gfc_expr *e;
gfc_ref *ref;
+ gfc_was_finalized *f;
if (!comp_is_finalizable (comp))
return;
- if (expr->finalized)
- return;
+ /* If this expression with this component has been finalized
+ already in this namespace, there is nothing to do. */
+ for (f = sub_ns->was_finalized; f; f = f->next)
+ {
+ if (f->e == expr && f->c == comp)
+ return;
+ }
e = gfc_copy_expr (expr);
if (!e->ref)
@@ -1055,7 +1061,13 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
sub_ns);
gfc_free_expr (e);
}
- expr->finalized = 1;
+
+ /* Record that this was finalized already in this namespace. */
+ f = sub_ns->was_finalized;
+ sub_ns->was_finalized = XCNEW (gfc_was_finalized);
+ sub_ns->was_finalized->e = expr;
+ sub_ns->was_finalized->c = comp;
+ sub_ns->was_finalized->next = f;
}