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

Reply via email to