This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug fortran/80477] [OOP] Polymorphic function result generates memory leak
- From: "janus at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Sun, 23 Apr 2017 11:02:09 +0000
- Subject: [Bug fortran/80477] [OOP] Polymorphic function result generates memory leak
- Auto-submitted: auto-generated
- References: <bug-80477-4@http.gcc.gnu.org/bugzilla/>
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?