This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug fortran/80477] [OOP] Polymorphic function result generates memory leak


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?

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]