Dear all,
I have realized a draft patch for the PR 46321, currently it works
only with the explicit DEALLOCATE.
Running the regression tests it doesn't pass the following:
- gfortran.dg/class_19.f03 (too much "__builtin_free")
- gfortran.dg/auto_dealloc_2.f90 (too much "__builtin_free")
- gfortran.dg/dynamic_dispatch_4.f03 (free on invalid pointer)
- gfortran.dg/typebound_operator_9.f03 (fails during the execution test)
The first two tests fail due to the introduction of "__builtin_free"
in the freeing functions, so it is not a problem.
The gfortran.dg/dynamic_dispatch_4.f03 had this problem in the past
(http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43986); currently it
calls the __free_s_bar_mod_S_bar function instead of the proper
doit().
Regarding typebound_operator_9.f03, I don't know how to fix the patch...
The patch is written in a "raw" way due to my newbieness, so any
suggestion is well accepted.
Regards.
Alessandro
Index: gcc/fortran/class.c
===================================================================
--- gcc/fortran/class.c (revisione 188002)
+++ gcc/fortran/class.c (copia locale)
@@ -717,6 +717,7 @@
gfc_namespace *ns;
gfc_symbol *vtab = NULL, *vtype = NULL, *found_sym = NULL, *def_init = NULL;
gfc_symbol *copy = NULL, *src = NULL, *dst = NULL;
+ gfc_symbol *free = NULL, *tofree = NULL;
/* Find the top-level namespace (MODULE or PROGRAM). */
for (ns = gfc_current_ns; ns; ns = ns->parent)
@@ -907,6 +908,119 @@
c->ts.interface = copy;
}
+ /* Add component _free. */
+ gfc_component *temp = NULL;
+ bool der_comp_alloc = false, comp_alloc = false;
+ bool class_comp_alloc = false;
+ for (temp = derived->components; temp; temp = temp->next)
+ {
+ if (temp == derived->components && derived->attr.extension)
+ continue;
+
+ if (temp->ts.type == BT_DERIVED
+ && !temp->attr.pointer
+ && (temp->attr.alloc_comp || temp->attr.allocatable))
+ der_comp_alloc = true;
+ else if (temp->ts.type != BT_DERIVED
+ && !temp->attr.pointer
+ && (temp->attr.alloc_comp
+ || temp->attr.allocatable))
+ comp_alloc = true;
+ else if (temp->ts.u.derived
+ && temp->ts.type == BT_CLASS
+ && CLASS_DATA (temp)
+ //&& (CLASS_DATA (temp)->attr.class_pointer
+ // || CLASS_DATA (temp)->attr.allocatable))
+ && CLASS_DATA (temp)->attr.allocatable)
+ class_comp_alloc = true;
+ }
+ if (derived->attr.extension
+ && (!der_comp_alloc && !comp_alloc && !class_comp_alloc))
+ {
+ gfc_component *parent = derived->components;
+ gfc_component *free_proc = NULL;
+ gfc_symbol *vtab2 = NULL;
+ gfc_expr *tmp1 = NULL, *tmp2 = NULL;
+ vtab2 = gfc_find_derived_vtab (parent->ts.u.derived);
+
+ for (free_proc = vtab2->ts.u.derived->components;
+ free_proc; free_proc = free_proc->next)
+ if (free_proc->name[0] == '_'
+ && free_proc->name[1] == 'f')
+ break;
+
+ if (!free_proc)
+ goto end_vtab;
+
+ if (gfc_add_component (vtype, "_free", &c) == FAILURE)
+ goto cleanup;
+ c->attr.proc_pointer = 1;
+ c->attr.access = ACCESS_PRIVATE;
+ c->tb = XCNEW (gfc_typebound_proc);
+ c->tb->ppc = 1;
+ /* Not sure about this part */
+ tmp1 = gfc_lval_expr_from_sym (free_proc->ts.interface);
+ tmp2 = gfc_copy_expr (tmp1);
+ c->initializer = tmp2;
+ c->ts.interface = tmp2->symtree->n.sym;
+ goto end_vtab;
+
+ }
+
+ if (derived->attr.alloc_comp || der_comp_alloc
+ || class_comp_alloc)
+ {
+ gfc_alloc *head = NULL;
+ if (gfc_add_component (vtype, "_free", &c) == FAILURE)
+ goto cleanup;
+ c->attr.proc_pointer = 1;
+ c->attr.access = ACCESS_PRIVATE;
+ c->tb = XCNEW (gfc_typebound_proc);
+ c->tb->ppc = 1;
+ if (derived->attr.abstract)
+ c->initializer = gfc_get_null_expr (NULL);
+ else
+ {
+ /* Set up namespace. */
+ gfc_namespace *sub_ns2 = gfc_get_namespace (ns, 0);
+ sub_ns2->sibling = ns->contained;
+ ns->contained = sub_ns2;
+ sub_ns2->resolved = 1;
+ /* Set up procedure symbol. */
+ sprintf (name, "__free_%s", tname);
+ gfc_get_symbol (name, sub_ns2, &free);
+ sub_ns2->proc_name = free;
+ free->attr.flavor = FL_PROCEDURE;
+ free->attr.subroutine = 1;
+ free->attr.if_source = IFSRC_DECL;
+ /* This is elemental so that arrays are automatically
+ treated correctly by the scalarizer. */
+ free->attr.elemental = 1;
+ if (ns->proc_name->attr.flavor == FL_MODULE)
+ free->module = ns->proc_name->name;
+ gfc_set_sym_referenced (free);
+ /* Set up formal arguments. */
+ gfc_get_symbol ("tofree", sub_ns2, &tofree);
+ tofree->ts.type = BT_DERIVED;
+ tofree->ts.u.derived = derived;
+ tofree->attr.flavor = FL_VARIABLE;
+ tofree->attr.dummy = 1;
+ tofree->attr.intent = INTENT_OUT;
+ gfc_set_sym_referenced (tofree);
+ free->formal = gfc_get_formal_arglist ();
+ free->formal->sym = tofree;
+ /* Set up code. */
+ sub_ns2->code = gfc_get_code ();
+ sub_ns2->code->op = EXEC_NOP;
+ head = gfc_get_alloc ();
+ head->expr = gfc_lval_expr_from_sym (tofree);
+ sub_ns2->code->ext.alloc.list = head;
+ /* Set initializer. */
+ c->initializer = gfc_lval_expr_from_sym (free);
+ c->ts.interface = free;
+ }
+ }
+end_vtab:
/* Add procedure pointers for type-bound procedures. */
add_procs_to_declared_vtab (derived, vtype);
}
@@ -935,6 +1049,10 @@
gfc_commit_symbol (src);
if (dst)
gfc_commit_symbol (dst);
+ if (free)
+ gfc_commit_symbol (free);
+ if (tofree)
+ gfc_commit_symbol (tofree);
}
else
gfc_undo_symbols ();
Index: gcc/fortran/trans-stmt.c
===================================================================
--- gcc/fortran/trans-stmt.c (revisione 188002)
+++ gcc/fortran/trans-stmt.c (copia locale)
@@ -5343,6 +5343,11 @@
{
gfc_expr *expr = gfc_copy_expr (al->expr);
gcc_assert (expr->expr_type == EXPR_VARIABLE);
+ gfc_expr *ppc;
+ gfc_code *ppc_code;
+ gfc_actual_arglist *actual;
+ gfc_component *free_proc = NULL;
+ gfc_symbol *vtab2 = NULL, *tmp_sym = NULL;
if (expr->ts.type == BT_CLASS)
gfc_add_data_component (expr);
@@ -5354,6 +5359,43 @@
se.descriptor_only = 1;
gfc_conv_expr (&se, expr);
+ actual = gfc_get_actual_arglist ();
+ actual->expr = gfc_copy_expr (expr);
+ if (expr->symtree->n.sym->ts.type == BT_CLASS
+ && expr->symtree->n.sym->tlink
+ && expr->symtree->n.sym->tlink->ts.u.derived)
+ {
+ if (expr->ref && expr->ref->u.c.component->ts.type == BT_CLASS)
+ {
+ tmp_sym = expr->ref->u.c.component->ts.u.derived;
+ tmp_sym = tmp_sym->components->ts.u.derived;
+ }
+ else
+ {
+ tmp_sym = expr->symtree->n.sym->tlink->ts.u.derived;
+ }
+ vtab2 = gfc_find_derived_vtab (tmp_sym);
+ vtab2 = vtab2->ts.u.derived;
+ for (free_proc = vtab2->components;
+ free_proc; free_proc = free_proc->next)
+ if (free_proc->name[0] == '_'
+ && free_proc->name[1] == 'f')
+ break;
+ if (free_proc)
+ {
+ ppc = gfc_copy_expr(free_proc->initializer);
+ ppc_code = gfc_get_code ();
+ ppc_code->resolved_sym = ppc->symtree->n.sym;
+ ppc_code->resolved_sym->attr.elemental = 1;
+ ppc_code->ext.actual = actual;
+ ppc_code->expr1 = ppc;
+ ppc_code->op = EXEC_CALL;
+ tmp = gfc_trans_call (ppc_code, true, NULL, NULL, false);
+ gfc_free_statements (ppc_code);
+ gfc_add_expr_to_block (&block, tmp);
+ }
+ }
+
if (expr->rank || gfc_is_coarray (expr))
{
if (expr->ts.type == BT_DERIVED &&
expr->ts.u.derived->attr.alloc_comp)