See attached patch. SELECT TYPE with an array section of a CLASS array
as the selector, e.g. select type (a => ptr(2:4)), ICEs in
tree_operand_check. When copying _len, trans_associate_var assumes
target_expr is a COMPONENT_REF to _data and strips it with
TREE_OPERAND, but a section gives a bare descriptor. The patch strips
only a COMPONENT_REF and otherwise gets the class container from the
selector expression with gfc_get_class_from_gfc_expr.

The fix is in trans_associate_var in trans-stmt.cc; the rest is the new
test. The bug was found with the Fujitsu compiler test suite; the test
is new.

Regression tested on x86_64.

OK for mainline?

Regards,

Jerry

---

fortran: [PR125760] Fix ICE in SELECT TYPE with array-section selector of a 
class array

In trans_associate_var, get the class container for the _len copy
from the selector expression when target_expr is not a _data
COMPONENT_REF.

Assisted-by: Claude Opus 5.5

        PR fortran/125760

gcc/fortran/ChangeLog:

        * trans-stmt.cc (trans_associate_var): Use
        gfc_get_class_from_gfc_expr when target_expr is not a
        COMPONENT_REF.

gcc/testsuite/ChangeLog:

        * gfortran.dg/select_type_52.f90: New test.
>From b6176379640fc865a3e3ace44307b065af417940 Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Thu, 11 Jun 2026 17:35:00 -0700
Subject: [PATCH] fortran: [PR125760] Fix ICE in SELECT TYPE with array-section
 selector of a class array

In trans_associate_var, get the class container for the _len copy
from the selector expression when target_expr is not a _data
COMPONENT_REF.

Assisted-by: Claude Opus 5.5

	PR fortran/125760

gcc/fortran/ChangeLog:

	* trans-stmt.cc (trans_associate_var): Use
	gfc_get_class_from_gfc_expr when target_expr is not a
	COMPONENT_REF.

gcc/testsuite/ChangeLog:

	* gfortran.dg/select_type_52.f90: New test.
---
 gcc/fortran/trans-stmt.cc                    |  6 ++-
 gcc/testsuite/gfortran.dg/select_type_52.f90 | 55 ++++++++++++++++++++
 2 files changed, 60 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.dg/select_type_52.f90

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 2a87176ffa9..b1bd044ff05 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -2273,9 +2273,13 @@ trans_associate_var (gfc_symbol *sym, gfc_wrapped_block *block)
 		   descriptor to get the target_expr.  */
 		target_expr =
 		    GFC_DECL_SAVED_DESCRIPTOR (e->symtree->n.sym->backend_decl);
-	      else
+	      else if (TREE_CODE (target_expr) == COMPONENT_REF)
 		/* Strip the _data component from the target_expr.  */
 		target_expr = TREE_OPERAND (target_expr, 0);
+	      else
+		/* An array section selector yields a bare descriptor; get the
+		   class container from the selector expression.  */
+		target_expr = gfc_get_class_from_gfc_expr (e);
 	      /* Add a reference to the _len comp to the target expr.  */
 	      tmp = gfc_class_len_get (target_expr);
 	      /* Get the component-ref for the temp structure's _len comp.  */
diff --git a/gcc/testsuite/gfortran.dg/select_type_52.f90 b/gcc/testsuite/gfortran.dg/select_type_52.f90
new file mode 100644
index 00000000000..b3eaa2b6152
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/select_type_52.f90
@@ -0,0 +1,55 @@
+! { dg-do run }
+!
+! PR 125760
+!
+! SELECT TYPE whose selector is an array section of an unlimited-polymorphic
+! array used to ICE in trans_associate_var (tree_operand_check at
+! trans-stmt.cc): the section yields a bare descriptor with no link back to the
+! class container, so stripping the _data component reference failed.
+
+program p
+  type t
+     integer :: i
+  end type t
+
+  ! Pointer to a class array.
+  class(*), pointer :: ptr(:)
+  integer, target :: arr(5) = [1, 2, 3, 4, 5]
+
+  ! Allocatable class array.
+  class(*), allocatable :: alo(:)
+
+  ! Class allocatable array component.
+  type cc
+     class(*), allocatable :: cmp(:)
+  end type cc
+  type(cc) :: obj
+
+  ptr => arr
+  select type (a => ptr(2:4))
+   type is (integer)
+     if (any (a /= [2, 3, 4])) stop 1
+  class default
+     stop 2
+  end select
+
+  ! Strided section.
+  select type (a => ptr(1:5:2))
+   type is (integer)
+     if (any (a /= [1, 3, 5])) stop 3
+  end select
+
+  allocate (alo, source = [t(10), t(20), t(30), t(40)])
+  select type (a => alo(2:3))
+   type is (t)
+     if (a(1)%i /= 20 .or. a(2)%i /= 30) stop 4
+  class default
+     stop 5
+  end select
+
+  allocate (obj%cmp, source = [11, 22, 33])
+  select type (a => obj%cmp(2:3))
+   type is (integer)
+     if (any (a /= [22, 33])) stop 6
+  end select
+end program p
-- 
2.56.0

Reply via email to