https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90744
--- Comment #3 from Tomáš Trnka <trnka at scm dot com> ---
I think the issue stems from this code in gfc_conv_procedure_call():
/* Deferred length dummies pass the character length by reference
so that the value can be returned. */
if (parmse.string_length && fsym && fsym->ts.deferred)
{
if (INDIRECT_REF_P (parmse.string_length))
/* In chains of functions/procedure calls the string_length already
is a pointer to the variable holding the length. Therefore
remove the deref on call. */
parmse.string_length = TREE_OPERAND (parmse.string_length, 0);
else
{
tmp = parmse.string_length;
if (!VAR_P (tmp) && TREE_CODE (tmp) != COMPONENT_REF)
tmp = gfc_evaluate_now (parmse.string_length, &se->pre);
parmse.string_length = gfc_build_addr_expr (NULL_TREE, tmp);
}
}
On the first call to an external procedure, fsym is NULL here, so the
string_length is passed as is. Then, after the argument processing loop
finishes, conv_function_val() is called, which in turn calls
get_formal_from_actual_arglist() and populates fsym. On subsequent calls to the
same external procedure, fsym is no longer NULL and in the case of this
character(:), allocatable temporary it also has ts.deferred==true. The snippet
above then runs and converts the string length to a reference (even though the
procedure doesn't expect one).
I'm not sure how to fix this properly, but the following one-liner seems to
work for me:
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3006,6 +3006,7 @@ get_formal_from_actual_arglist (gfc_symbol *sym,
gfc_actual_arglist *actual_args
{
s->ts = a->expr->ts;
s->attr.flavor = FL_VARIABLE;
+ s->ts.deferred = false;
if (a->expr->rank > 0)
{
s->attr.dimension = 1;