Ping [hmz. it's been a while, I'll rebase and retest this one. Ok if it passes?]
On Mon, 15 Oct 2018 10:23:06 +0200 Bernhard Reutner-Fischer <rep.dot....@gmail.com> wrote: > If a finalization is not required we created a namespace containing > formal arguments for an internal interface definition but never used > any of these. So the whole sub_ns namespace was not wired up to the > program and consequently was never freed. The fix is to simply not > generate any finalization wrappers if we know that it will be unused. > Note that this reverts back to the original r190869 > (8a96d64282ac534cb597f446f02ac5d0b13249cc) handling for this case > by reverting this specific part of r194075 > (f1ee56b4be7cc3892e6ccc75d73033c129098e87) for PR fortran/37336. > > Regtests cleanly, installed to the fortran-fe-stringpool branch, sent > here for reference and later inclusion. > I might plug a few more leaks in preparation of switching to hash-maps. > I fear that the leaks around interfaces are another candidate ;) > > Should probably add a tag for the compile-time leak PR68800 shouldn't i. > > valgrind summary for e.g. > gfortran.dg/abstract_type_3.f03 and gfortran.dg/abstract_type_4.f03 > where ".orig" is pristine trunk and ".mine" contains this fix: > > at3.orig.vg:LEAK SUMMARY: > at3.orig.vg- definitely lost: 8,460 bytes in 11 blocks > at3.orig.vg- indirectly lost: 13,288 bytes in 55 blocks > at3.orig.vg- possibly lost: 0 bytes in 0 blocks > at3.orig.vg- still reachable: 572,278 bytes in 2,142 blocks > at3.orig.vg- suppressed: 0 bytes in 0 blocks > at3.orig.vg- > at3.orig.vg-Use --track-origins=yes to see where uninitialised values come > from > at3.orig.vg-ERROR SUMMARY: 38 errors from 33 contexts (suppressed: 0 from 0) > -- > at3.mine.vg:LEAK SUMMARY: > at3.mine.vg- definitely lost: 344 bytes in 1 blocks > at3.mine.vg- indirectly lost: 7,192 bytes in 18 blocks > at3.mine.vg- possibly lost: 0 bytes in 0 blocks > at3.mine.vg- still reachable: 572,278 bytes in 2,142 blocks > at3.mine.vg- suppressed: 0 bytes in 0 blocks > at3.mine.vg- > at3.mine.vg-ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) > at3.mine.vg-ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) > at4.orig.vg:LEAK SUMMARY: > at4.orig.vg- definitely lost: 13,751 bytes in 12 blocks > at4.orig.vg- indirectly lost: 11,976 bytes in 60 blocks > at4.orig.vg- possibly lost: 0 bytes in 0 blocks > at4.orig.vg- still reachable: 572,278 bytes in 2,142 blocks > at4.orig.vg- suppressed: 0 bytes in 0 blocks > at4.orig.vg- > at4.orig.vg-Use --track-origins=yes to see where uninitialised values come > from > at4.orig.vg-ERROR SUMMARY: 18 errors from 16 contexts (suppressed: 0 from 0) > -- > at4.mine.vg:LEAK SUMMARY: > at4.mine.vg- definitely lost: 3,008 bytes in 3 blocks > at4.mine.vg- indirectly lost: 4,056 bytes in 11 blocks > at4.mine.vg- possibly lost: 0 bytes in 0 blocks > at4.mine.vg- still reachable: 572,278 bytes in 2,142 blocks > at4.mine.vg- suppressed: 0 bytes in 0 blocks > at4.mine.vg- > at4.mine.vg-ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0) > at4.mine.vg-ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0) > > gcc/fortran/ChangeLog: > > 2018-10-12 Bernhard Reutner-Fischer <al...@gcc.gnu.org> > > * class.c (generate_finalization_wrapper): Do leak finalization > wrappers if they will not be used. > * expr.c (gfc_free_actual_arglist): Formatting fix. > * gfortran.h (gfc_free_symbol): Pass argument by reference. > (gfc_release_symbol): Likewise. > (gfc_free_namespace): Likewise. > * symbol.c (gfc_release_symbol): Adjust acordingly. > (free_components): Set procedure pointer components > of derived types to NULL after freeing. > (free_tb_tree): Likewise. > (gfc_free_symbol): Set sym to NULL after freeing. > (gfc_free_namespace): Set namespace to NULL after freeing. > --- > gcc/fortran/class.c | 25 +++++++++---------------- > gcc/fortran/expr.c | 2 +- > gcc/fortran/gfortran.h | 6 +++--- > gcc/fortran/symbol.c | 19 ++++++++++--------- > 4 files changed, 23 insertions(+), 29 deletions(-) > > diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c > index 69c95fc5dfa..e0bb381a55f 100644 > --- a/gcc/fortran/class.c > +++ b/gcc/fortran/class.c > @@ -1533,7 +1533,6 @@ generate_finalization_wrapper (gfc_symbol *derived, > gfc_namespace *ns, > gfc_code *last_code, *block; > const char *name; > bool finalizable_comp = false; > - bool expr_null_wrapper = false; > gfc_expr *ancestor_wrapper = NULL, *rank; > gfc_iterator *iter; > > @@ -1561,13 +1560,17 @@ generate_finalization_wrapper (gfc_symbol *derived, > gfc_namespace *ns, > } > > /* No wrapper of the ancestor and no own FINAL subroutines and allocatable > - components: Return a NULL() expression; we defer this a bit to have have > + components: Return a NULL() expression; we defer this a bit to have > an interface declaration. */ > if ((!ancestor_wrapper || ancestor_wrapper->expr_type == EXPR_NULL) > && !derived->attr.alloc_comp > && (!derived->f2k_derived || !derived->f2k_derived->finalizers) > && !has_finalizer_component (derived)) > - expr_null_wrapper = true; > + { > + vtab_final->initializer = gfc_get_null_expr (NULL); > + gcc_assert (vtab_final->ts.interface == NULL); > + return; > + } > else > /* Check whether there are new allocatable components. */ > for (comp = derived->components; comp; comp = comp->next) > @@ -1581,7 +1584,7 @@ generate_finalization_wrapper (gfc_symbol *derived, > gfc_namespace *ns, > > /* If there is no new finalizer and no new allocatable, return with > an expr to the ancestor's one. */ > - if (!expr_null_wrapper && !finalizable_comp > + if (!finalizable_comp > && (!derived->f2k_derived || !derived->f2k_derived->finalizers)) > { > gcc_assert (ancestor_wrapper && ancestor_wrapper->ref == NULL > @@ -1605,8 +1608,7 @@ generate_finalization_wrapper (gfc_symbol *derived, > gfc_namespace *ns, > /* Set up the namespace. */ > sub_ns = gfc_get_namespace (ns, 0); > sub_ns->sibling = ns->contained; > - if (!expr_null_wrapper) > - ns->contained = sub_ns; > + ns->contained = sub_ns; > sub_ns->resolved = 1; > > /* Set up the procedure symbol. */ > @@ -1622,7 +1624,7 @@ generate_finalization_wrapper (gfc_symbol *derived, > gfc_namespace *ns, > final->ts.kind = 4; > final->attr.artificial = 1; > final->attr.always_explicit = 1; > - final->attr.if_source = expr_null_wrapper ? IFSRC_IFBODY : IFSRC_DECL; > + final->attr.if_source = IFSRC_DECL; > if (ns->proc_name->attr.flavor == FL_MODULE) > final->module = ns->proc_name->name; > gfc_set_sym_referenced (final); > @@ -1672,15 +1674,6 @@ generate_finalization_wrapper (gfc_symbol *derived, > gfc_namespace *ns, > final->formal->next->next->sym = fini_coarray; > gfc_commit_symbol (fini_coarray); > > - /* Return with a NULL() expression but with an interface which has > - the formal arguments. */ > - if (expr_null_wrapper) > - { > - vtab_final->initializer = gfc_get_null_expr (NULL); > - vtab_final->ts.interface = final; > - return; > - } > - > /* Local variables. */ > > gfc_get_symbol (gfc_get_string ("%s", "idx"), sub_ns, &idx); > diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c > index cc12e0a8402..3d744ec9641 100644 > --- a/gcc/fortran/expr.c > +++ b/gcc/fortran/expr.c > @@ -533,7 +533,7 @@ gfc_free_actual_arglist (gfc_actual_arglist *a1) > { > a2 = a1->next; > if (a1->expr) > - gfc_free_expr (a1->expr); > + gfc_free_expr (a1->expr); > free (a1); > a1 = a2; > } > diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h > index 4612835706b..3466c42132f 100644 > --- a/gcc/fortran/gfortran.h > +++ b/gcc/fortran/gfortran.h > @@ -3032,8 +3032,8 @@ gfc_user_op *gfc_get_uop (const char *); > gfc_user_op *gfc_find_uop (const char *, gfc_namespace *); > const char *gfc_get_uop_from_name (const char*); > const char *gfc_get_name_from_uop (const char*); > -void gfc_free_symbol (gfc_symbol *); > -void gfc_release_symbol (gfc_symbol *); > +void gfc_free_symbol (gfc_symbol *&); > +void gfc_release_symbol (gfc_symbol *&); > gfc_symbol *gfc_new_symbol (const char *, gfc_namespace *); > gfc_symtree* gfc_find_symtree_in_proc (const char *, gfc_namespace *); > int gfc_find_symbol (const char *, gfc_namespace *, int, gfc_symbol **); > @@ -3058,7 +3058,7 @@ void gfc_commit_symbols (void); > void gfc_commit_symbol (gfc_symbol *); > gfc_charlen *gfc_new_charlen (gfc_namespace *, gfc_charlen *); > void gfc_free_charlen (gfc_charlen *, gfc_charlen *); > -void gfc_free_namespace (gfc_namespace *); > +void gfc_free_namespace (gfc_namespace *&); > > void gfc_symbol_init_2 (void); > void gfc_symbol_done_2 (void); > diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c > index 09ad2bbf0cd..c99c106a0c0 100644 > --- a/gcc/fortran/symbol.c > +++ b/gcc/fortran/symbol.c > @@ -2590,8 +2590,9 @@ free_components (gfc_component *p) > gfc_free_expr (p->kind_expr); > if (p->param_list) > gfc_free_actual_arglist (p->param_list); > - free (p->tb); > > + free (p->tb); > + p->tb = NULL; > free (p); > } > } > @@ -3070,7 +3071,7 @@ set_symbol_common_block (gfc_symbol *sym, > gfc_common_head *common_block) > /* Remove a gfc_symbol structure and everything it points to. */ > > void > -gfc_free_symbol (gfc_symbol *sym) > +gfc_free_symbol (gfc_symbol *&sym) > { > > if (sym == NULL) > @@ -3078,8 +3079,6 @@ gfc_free_symbol (gfc_symbol *sym) > > gfc_free_array_spec (sym->as); > > - free_components (sym->components); > - > gfc_free_expr (sym->value); > > gfc_free_namelist (sym->namelist); > @@ -3094,19 +3093,22 @@ gfc_free_symbol (gfc_symbol *sym) > > gfc_free_namespace (sym->f2k_derived); > > + free_components (sym->components); > + > set_symbol_common_block (sym, NULL); > > if (sym->param_list) > gfc_free_actual_arglist (sym->param_list); > > free (sym); > + sym = NULL; > } > > > /* Decrease the reference counter and free memory when we reach zero. */ > > void > -gfc_release_symbol (gfc_symbol *sym) > +gfc_release_symbol (gfc_symbol *&sym) > { > if (sym == NULL) > return; > @@ -3826,10 +3828,8 @@ free_tb_tree (gfc_symtree *t) > > free_tb_tree (t->left); > free_tb_tree (t->right); > - > - /* TODO: Free type-bound procedure structs themselves; probably needs some > - sort of ref-counting mechanism. */ > free (t->n.tb); > + t->n.tb = NULL; > free (t); > } > > @@ -4019,7 +4019,7 @@ free_entry_list (gfc_entry_list *el) > taken care of when a specific name is freed. */ > > void > -gfc_free_namespace (gfc_namespace *ns) > +gfc_free_namespace (gfc_namespace *&ns) > { > gfc_namespace *p, *q; > int i; > @@ -4057,6 +4057,7 @@ gfc_free_namespace (gfc_namespace *ns) > gfc_free_data (ns->data); > p = ns->contained; > free (ns); > + ns = NULL; > > /* Recursively free any contained namespaces. */ > while (p != NULL)