Hi all, attached patch fixes a 15-regression where an element of an actual temporary array, i.e., elemental([ e1, e2...]) passed to the formal polymorphic dummy leads to a double free of the derived types components. This patch prevents this by preventing the deallocation of the array constructors temporary, when the formal is polymorphic. ...
Folks its so hard to explain this in prose. I rewrote above paragraph the third time now. And I still don't understand on re-reading. So here is some pseudo code: struct derived { char *c; // This is the component suffering from double-free }; derived[2] atmp = [ derived(""), derived("")] forall a in atmp derived t_a = a; // <- Copy of a, but no deep copy, i.e. t_a.c == a.c class_temp = class_derived(a); // set _vtype left out for brevity call elemental_function(class_temp); if (class_temp._data.c != NULL) free(class_temp._data.c); // and set it to NULL if (t_a.c != NULL) free(t_a.c); // BOOM, this is freeing the same c end Generating the last if-block and the free is what this patch prevents for polymorphic dummys that stem from an array construction. And only for those. Sorry, I am having a hard time explaining things today. So I hope the code above will do. Regtested ok on x86_64-pc-linux-gnu / F41. Ok for mainline? Regards, Andre -- Andre Vehreschild * Email: vehre ad gmx dot de
From 8f9c24fe01a1e34bea2e1c95102329562abdb9e1 Mon Sep 17 00:00:00 2001 From: Andre Vehreschild <ve...@gcc.gnu.org> Date: Thu, 20 Mar 2025 13:37:21 +0100 Subject: [PATCH] Fortran: Fix double free on polymorphic array dummy argument [PR119349] Calling elemental routines with polymorphic formals leads to generation of a temporary polymorphic variable and code for its deallocation. Sourcing this element from an array constructor the latter now is prevented from generating a second deallocation. PR fortran/119349 gcc/fortran/ChangeLog: * trans-expr.cc (gfc_conv_procedure_call): Prevent deallocation of array temporary for polymorphic temporary argument. gcc/testsuite/ChangeLog: * gfortran.dg/class_79.f90: New test. --- gcc/fortran/trans-expr.cc | 6 +++++- gcc/testsuite/gfortran.dg/class_79.f90 | 25 +++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gfortran.dg/class_79.f90 diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index d965539f11e..923d46cb47c 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -7994,7 +7994,11 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, gfc_add_expr_to_block (&se->post, local_tmp); } - if (!finalized && !e->must_finalize) + /* Items of array expressions passed to a polymorphic formal arguments + create their own clean up, so prevent double free. */ + if (!finalized && !e->must_finalize + && !(e->expr_type == EXPR_ARRAY && fsym + && fsym->ts.type == BT_CLASS)) { bool scalar_res_outside_loop; scalar_res_outside_loop = e->expr_type == EXPR_FUNCTION diff --git a/gcc/testsuite/gfortran.dg/class_79.f90 b/gcc/testsuite/gfortran.dg/class_79.f90 new file mode 100644 index 00000000000..a2226e47aff --- /dev/null +++ b/gcc/testsuite/gfortran.dg/class_79.f90 @@ -0,0 +1,25 @@ +!{ dg-do run } + +! Check double free on array constructor in argument list is fixed. +! Contributed by Damian Rouson <damian@archaeologic.codes> +program pr119349 + implicit none + + type string_t + character(len=:), allocatable :: string_ + end type + + print *, true([string()]) + +contains + + type(string_t) function string() + string%string_ = "" + end function + + logical elemental function true(rhs) + class(string_t), intent(in) :: rhs + true = .true. + end function + +end program -- 2.48.1