fortran: Fix ICE in ALLOCATE of sub-objects with recursive types

The deep-copy wrapper generation for recursive allocatable array
components (PR121628) calls cgraph_node::add_new_function to register
the wrapper.  During PARSING state, add_new_function calls
finalize_function which triggers ggc_collect().  This garbage
collection frees locally-computed tree nodes (COMPONENT_REFs etc.)
in caller stack frames of structure_alloc_comps that are not yet
attached to any GC-rooted structure, causing a segfault when those
nodes are subsequently accessed.

Use finalize_function with no_collect=true to skip the collection.
The GC will run at a safe point later.

	PR fortran/124235

gcc/fortran/ChangeLog:

	* trans-array.cc (generate_element_copy_wrapper): Use
	cgraph_node::finalize_function with no_collect=true instead
	of cgraph_node::add_new_function to avoid garbage collection
	while caller frames hold unrooted tree nodes.

gcc/testsuite/ChangeLog:

	* gfortran.dg/pr124235.f90: New test.

Signed-off-by: Christopher Albert <albert@tugraz.at>
This commit is contained in:
Christopher Albert
2026-02-25 09:41:27 +01:00
committed by Jerry DeLisle
parent c6da5b9c32
commit e0b70284cf
2 changed files with 53 additions and 1 deletions

View File

@@ -10165,7 +10165,13 @@ generate_element_copy_wrapper (gfc_symbol *der_type, tree comp_type,
pop_cfun ();
cgraph_node::add_new_function (fndecl, false);
/* Use finalize_function with no_collect=true to skip the ggc_collect
call that add_new_function would trigger. This function is called
during tree lowering of structure_alloc_comps where caller stack
frames hold locally-computed tree nodes (COMPONENT_REFs etc.) that
are not yet attached to any GC root. A collection at this point
would free those nodes and cause segfaults. PR124235. */
cgraph_node::finalize_function (fndecl, true);
return build1 (ADDR_EXPR, get_copy_helper_pointer_type (), fndecl);
}

View File

@@ -0,0 +1,46 @@
! { dg-do compile }
! PR fortran/124235 - ICE in ALLOCATE of sub-objects with recursive types
!
! Mutually-referencing derived types with a mix of allocatable and
! fixed-size array components. Allocating a sub-object of an
! already-allocated component triggered a segfault during tree lowering
! because garbage collection during deep-copy wrapper generation
! invalidated locally-computed COMPONENT_REF tree nodes.
program pr124235
implicit none
type :: alpha_t
integer, allocatable :: vals(:)
type(alpha_t), allocatable :: a_kids(:)
type(gamma_t), allocatable :: g_ref(:)
integer :: tag
type(beta_t), allocatable :: b_ref(:)
end type
type :: beta_t
integer, allocatable :: vals(:)
type(alpha_t) :: a_fixed(4)
type(beta_t), allocatable :: b_kids(:)
integer :: tag
type(gamma_t), allocatable :: g_ref(:)
end type
type :: gamma_t
integer, allocatable :: vals(:)
type(beta_t) :: b_fixed(4)
integer :: tag
type(gamma_t), allocatable :: g_kids(:)
end type
type :: container_t
type(gamma_t), allocatable :: items(:)
type(gamma_t), allocatable :: spares(:)
end type
type(container_t) :: box
allocate(box%items(6))
allocate(box%items(2)%g_kids(3))
end program