See attached patch. When the type of an associate name is guessed at
parse time, its component references are built in the guessed type,
and resolution corrected only the first of them, and only its u.c.sym.
A wrong guess, or a CLASS associate name whose first component is
_data, then reaches gfc_conv_component_ref with a component that does
not belong to the type it is referenced from. The fix looks every
component reference up again by name in the corrected type, which
relies on the component names being the same in the guessed and the
real type, as they are by construction of the guess.

The fix is in gfc_fixup_inferred_type_refs in resolve.cc; the other
hunk only declares a variable. The rest is the new test.

This also fixes the CLASS IS case of PR128017 (SELECT TYPE on an
associate name for a polymorphic function), whose patches will follow
and rely on this one.

Regression tested on x86_64.

OK for mainline?

Regards,

Jerry

---

fortran: [PR126968] ICE for wrongly guessed inferred ASSOCIATE type

When an ASSOCIATE selector is a function that has not been parsed yet,
primary.cc types the associate name by guessing: it takes the first
accessible derived type that has a component of the name being
referenced.  resolve_assoc_var later corrects the associate name's type
from the resolved selector, and gfc_fixup_inferred_type_refs repaired
the reference chain.

That repair only reset ref->u.c.sym and left ref->u.c.component pointing
into the guessed type.  When the guess was wrong, the component and the
type it is referenced from no longer belonged together, which reached
the backend and gave

  internal compiler error: in gfc_conv_component_ref, at
  fortran/trans-expr.cc:3010

Bind each component reference to the corrected type by looking it up
again by name, walking the whole chain so that nested references are
corrected too.

Assisted-by: Claude Opus 5.5

        PR fortran/126968

gcc/fortran/ChangeLog:

        * resolve.cc (gfc_fixup_inferred_type_refs): Look each component
        reference up again by name in the corrected derived type and
        update both u.c.sym and u.c.component.  Walk the whole reference
        chain instead of stopping at the first component.

gcc/testsuite/ChangeLog:

        * gfortran.dg/associate_89.f90: New test.
>From e9ee9141a8329ae8e5b7608e987cf4060639e58e Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Thu, 20 Aug 2026 12:18:35 -0700
Subject: [PATCH] fortran: [PR126968] ICE for wrongly guessed inferred
 ASSOCIATE type

When an ASSOCIATE selector is a function that has not been parsed yet,
primary.cc types the associate name by guessing: it takes the first
accessible derived type that has a component of the name being
referenced.  resolve_assoc_var later corrects the associate name's type
from the resolved selector, and gfc_fixup_inferred_type_refs repaired
the reference chain.

That repair only reset ref->u.c.sym and left ref->u.c.component pointing
into the guessed type.  When the guess was wrong, the component and the
type it is referenced from no longer belonged together, which reached
the backend and gave

  internal compiler error: in gfc_conv_component_ref, at
  fortran/trans-expr.cc:3010

Bind each component reference to the corrected type by looking it up
again by name, walking the whole chain so that nested references are
corrected too.

Assisted-by: Claude Opus 5.5

	PR fortran/126968

gcc/fortran/ChangeLog:

	* resolve.cc (gfc_fixup_inferred_type_refs): Look each component
	reference up again by name in the corrected derived type and
	update both u.c.sym and u.c.component.  Walk the whole reference
	chain instead of stopping at the first component.

gcc/testsuite/ChangeLog:

	* gfortran.dg/associate_89.f90: New test.
---
 gcc/fortran/resolve.cc                     | 48 +++++++++++++++----
 gcc/testsuite/gfortran.dg/associate_89.f90 | 56 ++++++++++++++++++++++
 2 files changed, 95 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/associate_89.f90

diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index a37a5024ecc..401431252d1 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -7007,7 +7007,7 @@ void
 gfc_fixup_inferred_type_refs (gfc_expr *e)
 {
   gfc_ref *ref, *new_ref;
-  gfc_symbol *sym, *derived;
+  gfc_symbol *sym, *derived, *dt;
   gfc_expr *target;
   sym = e->symtree->n.sym;
 
@@ -7108,17 +7108,47 @@ gfc_fixup_inferred_type_refs (gfc_expr *e)
 	}
     }
 
-  /* Proceed as far as the first component reference and ensure that the
-     correct derived type is being used.  */
+  /* The type used to build the component references at parse time was only
+     a guess, so they can point into a different derived type that happens
+     to have a component of the same name.  Bind each one by name to the
+     corrected type.  */
+  dt = derived;
   for (ref = e->ref; ref; ref = ref->next)
-    if (ref->type == REF_COMPONENT)
-      {
-	if (ref->u.c.component->name[0] != '_')
-	  ref->u.c.sym = derived;
-	else
+    {
+      gfc_component *c;
+
+      if (ref->type != REF_COMPONENT)
+	continue;
+
+      /* The '_data', '_vptr' and '_len' fields belong to the class
+	 container, and 'derived' already is the type that follows '_data'.  */
+      if (ref->u.c.component->name[0] == '_')
+	{
 	  ref->u.c.sym = sym->ts.u.derived;
+	  continue;
+	}
+
+      if (!dt)
 	break;
-      }
+
+      c = gfc_find_component (dt, ref->u.c.component->name, true, true, NULL);
+      if (!c)
+	{
+	  gfc_error ("%qs at %L is not a member of the %qs structure",
+		     ref->u.c.component->name, &e->where, dt->name);
+	  return;
+	}
+
+      ref->u.c.sym = dt;
+      ref->u.c.component = c;
+
+      if (c->ts.type == BT_DERIVED)
+	dt = c->ts.u.derived;
+      else if (c->ts.type == BT_CLASS && CLASS_DATA (c))
+	dt = CLASS_DATA (c)->ts.u.derived;
+      else
+	dt = NULL;
+    }
 
   /* Verify that the type inference mechanism has not introduced a spurious
      array reference.  This can happen with an associate name, whose selector
diff --git a/gcc/testsuite/gfortran.dg/associate_89.f90 b/gcc/testsuite/gfortran.dg/associate_89.f90
new file mode 100644
index 00000000000..75a48b63e30
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associate_89.f90
@@ -0,0 +1,56 @@
+! { dg-do run }
+! PR fortran/126968
+! ICE in gfc_conv_component_ref when the type of an associate name, whose
+! selector is a function that has not yet been parsed, is guessed wrongly.
+! The guess is the first accessible type with a component of the right name,
+! so 'wrong_t' is picked and has to be corrected during resolution.
+!
+module m
+  type :: wrong_t
+     integer :: x = 1
+     integer :: pad = 0
+  end type
+  type :: right_t
+     real :: junk = 0.0
+     real :: x = 2.5
+  end type
+  type :: outer_t
+     type(right_t) :: c
+  end type
+end module
+
+program p
+  use m
+  implicit none
+  real :: r, ra(3)
+
+  associate (q => scalar_fcn ())
+    r = q%x
+  end associate
+  if (abs (r - 2.5) > 1.0e-6) stop 1
+
+  associate (q => array_fcn ())
+    ra = q(:)%x
+  end associate
+  if (any (abs (ra - 2.5) > 1.0e-6)) stop 2
+
+  associate (q => nested_fcn ())
+    r = q%c%x
+  end associate
+  if (abs (r - 2.5) > 1.0e-6) stop 3
+
+contains
+
+  function scalar_fcn () result (y)
+    type(right_t) :: y
+  end function
+
+  function array_fcn () result (y)
+    type(right_t) :: y(3)
+  end function
+
+  function nested_fcn () result (y)
+    type(outer_t) :: y
+  end function
+
+end program
-- 
2.56.0

Reply via email to