if ((*func) (expr, sym, &f))
return true;
- if (expr->ts.type == BT_CHARACTER
- && expr->ts.u.cl
- && expr->ts.u.cl->length
- && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT
- && gfc_traverse_expr (expr->ts.u.cl->length, sym, func, f))
+ /* Descend into length type parameter of character expressions only for
+ non-negative f. */
+ if (f >= 0
+ && expr->ts.type == BT_CHARACTER
+ && expr->ts.u.cl
+ && expr->ts.u.cl->length
+ && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT
+ && gfc_traverse_expr (expr->ts.u.cl->length, sym, func, f))
return true;
switch (expr->expr_type)
break;
case REF_COMPONENT:
- if (ref->u.c.component->ts.type == BT_CHARACTER
- && ref->u.c.component->ts.u.cl
- && ref->u.c.component->ts.u.cl->length
- && ref->u.c.component->ts.u.cl->length->expr_type
- != EXPR_CONSTANT
- && gfc_traverse_expr (ref->u.c.component->ts.u.cl->length,
- sym, func, f))
+ if (f >= 0
+ && ref->u.c.component->ts.type == BT_CHARACTER
+ && ref->u.c.component->ts.u.cl
+ && ref->u.c.component->ts.u.cl->length
+ && ref->u.c.component->ts.u.cl->length->expr_type
+ != EXPR_CONSTANT
+ && gfc_traverse_expr (ref->u.c.component->ts.u.cl->length,
+ sym, func, f))
return true;
if (ref->u.c.component->as)
return gfc_traverse_expr (e, sym, sym_in_expr, 0);
}
+/* Same as gfc_find_sym_in_expr, but do not descend into length type parameter
+ of character expressions. */
+static bool
+gfc_find_var_in_expr (gfc_symbol *sym, gfc_expr *e)
+{
+ return gfc_traverse_expr (e, sym, sym_in_expr, -1);
+}
+
/* Given the expression node e for an allocatable/pointer of derived type to be
allocated, get the expression node to be initialized afterwards (needed for
continue;
if ((ar->start[i] != NULL
- && gfc_find_sym_in_expr (sym, ar->start[i]))
+ && gfc_find_var_in_expr (sym, ar->start[i]))
|| (ar->end[i] != NULL
- && gfc_find_sym_in_expr (sym, ar->end[i])))
+ && gfc_find_var_in_expr (sym, ar->end[i])))
{
gfc_error ("%qs must not appear in the array specification at "
"%L in the same ALLOCATE statement where it is "
--- /dev/null
+! { dg-do compile }
+! PR fortran/60560
+!
+! Original test case by Marco Restelli.
+
+module mstr
+ implicit none
+contains
+ subroutine sub(s)
+ character(len=*), allocatable, intent(out) :: s(:)
+ character(len=len(s)), allocatable :: s_tmp(:)
+ allocate(s_tmp(5))
+ allocate(s(size(s_tmp))) ! OK
+ allocate(s_tmp(5),s(size(s_tmp))) ! { dg-error "same ALLOCATE statement" }
+ allocate(s_tmp(5),s(len(s_tmp))) ! { dg-error "same ALLOCATE statement" }
+ end subroutine sub
+end module mstr