https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80477
janus at gcc dot gnu.org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |pault at gcc dot gnu.org --- Comment #9 from janus at gcc dot gnu.org --- Anyway, getting back to the discussion of the actual bug ... (In reply to janus from comment #4) > When changing the function result from CLASS to TYPE, this deallocation > seems to be done properly (valgrind shows no leak), and the dump looks like > this: > > [...] Based on this observation, I cooked up a draft patch that tries to modify the code which does the freeing for TYPEs and make it work for CLASSes: Index: gcc/fortran/trans-expr.c =================================================================== --- gcc/fortran/trans-expr.c (revision 247083) +++ gcc/fortran/trans-expr.c (working copy) @@ -6131,15 +6131,26 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * /* Allocatable scalar function results must be freed and nullified after use. This necessitates the creation of a temporary to hold the result to prevent duplicate calls. */ - if (!byref && sym->ts.type != BT_CHARACTER - && sym->attr.allocatable && !sym->attr.dimension) + if (!byref && sym->ts.type != BT_CHARACTER) { - tmp = gfc_create_var (TREE_TYPE (se->expr), NULL); - gfc_add_modify (&se->pre, tmp, se->expr); - se->expr = tmp; - tmp = gfc_call_free (tmp); - gfc_add_expr_to_block (&post, tmp); - gfc_add_modify (&post, se->expr, build_int_cst (TREE_TYPE (se->expr), 0)); + if (sym->attr.allocatable && !sym->attr.dimension) + { + tmp = gfc_create_var (TREE_TYPE (se->expr), NULL); + gfc_add_modify (&se->pre, tmp, se->expr); + se->expr = tmp; + gfc_add_expr_to_block (&post, gfc_call_free (tmp)); + gfc_add_modify (&post, tmp, build_int_cst (TREE_TYPE (tmp), 0)); + } + else if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->attr.allocatable + && !CLASS_DATA (sym)->attr.dimension) + { + tmp = gfc_create_var (TREE_TYPE (se->expr), NULL); + gfc_add_modify (&se->pre, tmp, se->expr); + se->expr = tmp; + tmp = gfc_class_data_get (tmp); + gfc_add_expr_to_block (&post, gfc_call_free (tmp)); + gfc_add_modify (&post, tmp, build_int_cst (TREE_TYPE (tmp), 0)); + } } /* If we have a pointer function, but we don't want a pointer, e.g. Unfortunately it does not work, because it only creates a copy of the class container, but frees up the class data too early: polymorphic_operators_memory_leaks () { static struct a_type_t a = {.x=1.0e+0}; static struct a_type_t b = {.x=2.0e+0}; { struct __class_a_type_m_A_type_t_a D.3528; struct __class_a_type_m_A_type_t_a D.3529; D.3528 = add_a_type (&a, &b); D.3529 = D.3528; __builtin_free ((void *) D.3528._data); D.3528._data = 0B; assign_a_type (&a, D.3529._data); } } I guess I could use some help here (I always tend to get a bit lost in the trans-stage). Paul, do you by chance have any idea how to handle this properly?