https://gcc.gnu.org/g:b3f51ea894947e495baffc67407647a3b25acdd5

commit r15-7150-gb3f51ea894947e495baffc67407647a3b25acdd5
Author: Paul Thomas <pa...@gcc.gnu.org>
Date:   Thu Jan 23 08:27:04 2025 +0000

    Fortran: Regression- fix ICE at fortran/trans-decl.c:1575 [PR96087]
    
    2025-01-23  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:
---
 gcc/fortran/trans-decl.cc             | 15 ++++++++++++
 gcc/fortran/trans-expr.cc             |  2 +-
 gcc/testsuite/gfortran.dg/pr96087.f90 | 46 +++++++++++++++++++++++++++++++++++
 3 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 4ae22a5584d0..97bb0a418581 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 dcf42d531756..78caf1f8996c 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 000000000000..6c75d4f0cf27
--- /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