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