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)