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)
{
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);
/* 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,
/* 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)
--- /dev/null
+!{ dg-do run }
+
+! Check freeing derived typed result's allocatable components is not done twice.
+! Contributed by Damian Rouson <damian@archaeologic.codes>
+
+program pr118747
+ implicit none
+
+ type string_t
+ character(len=:), allocatable :: string_
+ end type
+
+ call check_allocation([foo(), foo()])
+
+contains
+
+ type(string_t) function foo()
+ foo%string_ = "foo"
+ end function
+
+ elemental subroutine check_allocation(string)
+ type(string_t), intent(in) :: string
+ if (.not. allocated(string%string_)) error stop "unallocated"
+ end subroutine
+
+end program
+