aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorAndre Vehreschild <vehre@gcc.gnu.org>2025-02-26 14:30:13 +0100
committerAndre Vehreschild <vehre@gcc.gnu.org>2025-03-03 08:55:59 +0100
commit43c11931acc50f3a44efb485b03e6a8d44df97e0 (patch)
treeb27a3a3329718d5eb2a5f476bbd298c14abcef46 /gcc/fortran
parent0163d5052dcb5e517da95a9b518f98a5ba3138dd (diff)
downloadgcc-43c11931acc50f3a44efb485b03e6a8d44df97e0.zip
gcc-43c11931acc50f3a44efb485b03e6a8d44df97e0.tar.gz
gcc-43c11931acc50f3a44efb485b03e6a8d44df97e0.tar.bz2
Fortran: Fix regression on double free on elemental function [PR118747]
Fix a regression were adding a temporary variable inserted a copy of the argument to the elemental function. That copy was then later used to free allocated memory, but the freeing was not tracked in the source array correctly. PR fortran/118747 gcc/fortran/ChangeLog: * trans-array.cc (gfc_trans_array_ctor_element): Remove copy to temporary variable. * trans-expr.cc (gfc_conv_procedure_call): Use references to array members instead of copies when freeing after use. Formatting fix. gcc/testsuite/ChangeLog: * gfortran.dg/alloc_comp_auto_array_4.f90: New test.
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/trans-array.cc11
-rw-r--r--gcc/fortran/trans-expr.cc13
2 files changed, 14 insertions, 10 deletions
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 8f76870..6a00d26 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -2002,13 +2002,10 @@ gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
if (expr->expr_type == EXPR_FUNCTION && expr->ts.type == BT_DERIVED
&& expr->ts.u.derived->attr.alloc_comp)
- {
- if (!VAR_P (se->expr))
- se->expr = gfc_evaluate_now (se->expr, &se->pre);
- gfc_add_expr_to_block (&se->finalblock,
- gfc_deallocate_alloc_comp_no_caf (
- expr->ts.u.derived, se->expr, expr->rank, true));
- }
+ gfc_add_expr_to_block (&se->finalblock,
+ gfc_deallocate_alloc_comp_no_caf (expr->ts.u.derived,
+ tmp, expr->rank,
+ true));
if (expr->ts.type == BT_CHARACTER)
{
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index ab55940..e619013 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -6999,6 +6999,12 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
if ((fsym && fsym->attr.value)
|| (ulim_copy && (argc == 2 || argc == 3)))
gfc_conv_expr (&parmse, e);
+ else if (e->expr_type == EXPR_ARRAY)
+ {
+ gfc_conv_expr (&parmse, e);
+ if (e->ts.type != BT_CHARACTER)
+ parmse.expr = gfc_build_addr_expr (NULL_TREE, parmse.expr);
+ }
else
gfc_conv_expr_reference (&parmse, e);
@@ -7930,11 +7936,11 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
/* It is known the e returns a structure type with at least one
allocatable component. When e is a function, ensure that the
function is called once only by using a temporary variable. */
- if (!DECL_P (parmse.expr))
+ if (!DECL_P (parmse.expr) && e->expr_type == EXPR_FUNCTION)
parmse.expr = gfc_evaluate_now_loc (input_location,
parmse.expr, &se->pre);
- if (fsym && fsym->attr.value)
+ if ((fsym && fsym->attr.value) || e->expr_type == EXPR_ARRAY)
tmp = parmse.expr;
else
tmp = build_fold_indirect_ref_loc (input_location,
@@ -7993,7 +7999,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
/* Scalars passed to an assumed rank argument are converted to
a descriptor. Obtain the data field before deallocating any
allocatable components. */
- if (parm_rank == 0 && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
+ if (parm_rank == 0 && e->expr_type != EXPR_ARRAY
+ && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (tmp)))
tmp = gfc_conv_descriptor_data_get (tmp);
if (scalar_res_outside_loop)