[gcc r17-2320] fortran: [PR126170] Fix LTO ICE in copy_function_or_variable

Jerry DeLisle via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:f935a7a9013d0748ba1f42dc532df3d278707bf6

commit r17-2320-gf935a7a9013d0748ba1f42dc532df3d278707bf6
Author: Jerry DeLisle <[email protected]>
Date:   Thu Jul 9 19:24:49 2026 -0700

    fortran: [PR126170] Fix LTO ICE in copy_function_or_variable
    
    A redundant USE of a module already visible via host association,
    written inside a contained procedure, caused gfortran's module
    reader to create a second copy of that module's derived
    type.
    
    PR fortran/126170
    
    gcc/fortran/ChangeLog:
    
            PR fortran/126170
            * class.cc (gfc_find_derived_vtab): Fix up a stale
            non-use-associated duplicate vtab symbol.
            (gfc_is_finalizable): Same fix-up, for the finalizer wrapper
            symbol.
            * module.cc (read_module): Skip re-importing a symbol already
            visible via host association from the same module.
    
    gcc/testsuite/ChangeLog:
    
            PR fortran/126170
            * gfortran.dg/lto/pr126170_0.f90: New test.
            * gfortran.dg/lto/pr126170_1.f90: New test.

Diff:
---
 gcc/fortran/class.cc                         | 22 ++++++++++++++++++++
 gcc/fortran/module.cc                        | 13 ++++++++++++
 gcc/testsuite/gfortran.dg/lto/pr126170_0.f90 | 31 ++++++++++++++++++++++++++++
 gcc/testsuite/gfortran.dg/lto/pr126170_1.f90 | 14 +++++++++++++
 4 files changed, 80 insertions(+)

diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc
index aa9bdb8f2795..18cff8f47a18 100644
--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -2523,6 +2523,15 @@ gfc_find_derived_vtab (gfc_symbol *derived)
       if (vtab == NULL && module_ns != ns)
 	gfc_find_symbol (name, module_ns, 0, &vtab);
 
+      /* Fix up a stale non-use-associated duplicate vtab.  */
+      if (vtab
+	  && (derived->attr.use_assoc || derived->attr.used_in_submodule)
+	  && !vtab->attr.use_assoc && !vtab->module)
+	{
+	  vtab->attr.use_assoc = 1;
+	  vtab->module = derived->module;
+	}
+
       if (vtab == NULL)
 	{
 	  gfc_get_symbol (name, ns, &vtab);
@@ -2860,6 +2869,19 @@ yes:
       gcc_assert (final->initializer
 		  && final->initializer->expr_type != EXPR_NULL);
       *final_expr = final->initializer;
+
+      /* Fix up a stale non-use-associated duplicate vtab.  */
+      if ((derived->attr.use_assoc || derived->attr.used_in_submodule)
+	  && (*final_expr)->expr_type == EXPR_VARIABLE
+	  && (*final_expr)->symtree)
+	{
+	  gfc_symbol *final_sym = (*final_expr)->symtree->n.sym;
+	  if (final_sym && !final_sym->attr.use_assoc && !final_sym->module)
+	    {
+	      final_sym->attr.use_assoc = 1;
+	      final_sym->module = derived->module;
+	    }
+	}
     }
   return true;
 }
diff --git a/gcc/fortran/module.cc b/gcc/fortran/module.cc
index 3bb81bab68a5..f7bf5854d745 100644
--- a/gcc/fortran/module.cc
+++ b/gcc/fortran/module.cc
@@ -6053,6 +6053,19 @@ read_module (void)
 				module_name, 0))
 	    continue;
 
+	  /* Skip re-importing a symbol already visible via host association
+	     from the same module.  */
+	  if (!only_flag && !info->u.rsym.renamed
+		&& strcmp (name, module_name) != 0
+		&& gfc_current_ns->parent)
+	    {
+	      gfc_symbol *host_sym;
+	      gfc_find_symbol (name, gfc_current_ns, 1, &host_sym);
+	      if (host_sym && host_sym->module
+		  && strcmp (host_sym->module, module_name) == 0)
+		continue;
+	    }
+
 	  st = gfc_find_symtree (gfc_current_ns->sym_root, p);
 
 	  if (st != NULL
diff --git a/gcc/testsuite/gfortran.dg/lto/pr126170_0.f90 b/gcc/testsuite/gfortran.dg/lto/pr126170_0.f90
new file mode 100644
index 000000000000..c862da5d5442
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/lto/pr126170_0.f90
@@ -0,0 +1,31 @@
+! { dg-lto-do link }
+!
+! PR fortran/126170
+! A redundant, already host-associated USE inside a contained function
+! caused gfortran to create duplicate of a derived type with
+! a FINAL binding.
+
+module vsm
+  type :: vs
+     integer :: c
+   contains
+     final :: vdst
+  end type vs
+contains
+  subroutine vdst(v)
+    type(vs), intent(inout) :: v
+  end subroutine vdst
+end module vsm
+
+module m_ds
+  use vsm
+  type :: mdcc
+  end type mdcc
+contains
+  function mdot(self)
+    use vsm
+    class(mdcc), intent(inout) :: self
+    type(vs) :: mdot
+    mdot%c = 1
+  end function mdot
+end module m_ds
diff --git a/gcc/testsuite/gfortran.dg/lto/pr126170_1.f90 b/gcc/testsuite/gfortran.dg/lto/pr126170_1.f90
new file mode 100644
index 000000000000..b13fd6c8edd9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/lto/pr126170_1.f90
@@ -0,0 +1,14 @@
+module caller
+  use m_ds
+contains
+  subroutine s()
+    type(mdcc) :: self
+    type(vs) :: vs_
+    vs_ = mdot(self)
+  end subroutine s
+end module caller
+
+program main
+  use caller
+  call s()
+end program main
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.