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;