[gcc r16-9259] 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:86717c5808dacd36b85e5d4cd3499c6fe96d2733

commit r16-9259-g86717c5808dacd36b85e5d4cd3499c6fe96d2733
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.
    
    (cherry picked from commit f935a7a9013d0748ba1f42dc532df3d278707bf6)

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 956572f7de1a..d14f34ac4266 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 04ddf6b4476b..4600845f5f6d 100644
--- a/gcc/fortran/module.cc
+++ b/gcc/fortran/module.cc
@@ -5881,6 +5881,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.