Hi All, This patch fixes a double ICE arising from confusion between the dummy symbol arising from a module function/subroutine interface and the module procedure itself. In both cases, use of the name is unambiguous, as explained in the ChangeLog. The testcase contains both the original and the variant in comment 1.
Regtests OK with FC41/x86_64 - OK for mainline and later backporting? Paul Fortran: Regression- fix ICE at fortran/trans-decl.c:1575 [PR96087] 2025-01-22 Paul Thomas <pa...@gcc.gnu.org> gcc/fortran PR fortran/96087 * trans-decl.cc (gfc_get_symbol_decl): If a dummy is missing a backend decl, it is likely that it has come from a module proc interface. Look for the formal symbol by name in the containing proc and use its backend decl. * trans-expr.cc (gfc_apply_interface_mapping_to_expr): For the same reason, match the name, rather than the symbol address to perform the mapping. gcc/testsuite/ PR fortran/96087 * gfortran.dg/pr96087.f90: New test.
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 4ae22a5584d..97bb0a41858 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -1722,6 +1722,21 @@ gfc_get_symbol_decl (gfc_symbol * sym) sym->backend_decl = DECL_CHAIN (sym->backend_decl); } + /* Automatic array indices in module procedures need the backend_decl + to be extracted from the procedure formal arglist. */ + if (sym->attr.dummy && !sym->backend_decl) + { + gfc_formal_arglist *f; + for (f = sym->ns->proc_name->formal; f; f = f->next) + { + gfc_symbol *fsym = f->sym; + if (strcmp (sym->name, fsym->name)) + continue; + sym->backend_decl = fsym->backend_decl; + break; + } + } + /* Dummy variables should already have been created. */ gcc_assert (sym->backend_decl); diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index bef49d32a58..1bf46c616bb 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -5099,7 +5099,7 @@ gfc_apply_interface_mapping_to_expr (gfc_interface_mapping * mapping, /* TODO Find out why the condition on expr->symtree had to be moved into the loop rather than being outside it, as originally. */ for (sym = mapping->syms; sym; sym = sym->next) - if (expr->symtree && sym->old == expr->symtree->n.sym) + if (expr->symtree && !strcmp (sym->old->name, expr->symtree->n.sym->name)) { if (sym->new_sym->n.sym->backend_decl) expr->symtree = sym->new_sym; diff --git a/gcc/testsuite/gfortran.dg/pr96087.f90 b/gcc/testsuite/gfortran.dg/pr96087.f90 new file mode 100644 index 00000000000..6c75d4f0cf2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr96087.f90 @@ -0,0 +1,46 @@ +! { dg-do run } + +module m + interface + module function f(a, n, b) result(z) + integer, intent(in) :: n + real :: z(n + 1) + real :: a, b + end + end interface +contains + module procedure f + integer :: i + do i = 1, size(z) + z(i) = real(i) + end do + end procedure +end + +! Comment 1 +module n + interface + module subroutine g(n, z) + integer, intent(in) :: n + real :: z(n) + end + end interface +contains + module procedure g + z = 1 + if (int (sum (z)) /= n) stop 1 + end procedure +end + + use m + use n + real, allocatable :: r(:) + integer :: i = 2 + r = f (1.0, i+1, 2.0) + if (any (r .ne. [(real(i), i = 1,4)])) stop 2 + if (any (f (3.0, 1, 4.0) .ne. [(real(i), i = 1,2)])) stop 3 + + r = [(real (i), i = 10,20)] + call g (5, r) + if (int (sum (r)) /= (sum ([(i, i = 15,20)]) + 5)) stop 4 +end