https://gcc.gnu.org/g:ca448bc5e435a2076cb3683a9be823c08a14e69e
commit r16-7200-gca448bc5e435a2076cb3683a9be823c08a14e69e Author: Jerry DeLisle <[email protected]> Date: Fri Jan 30 13:25:23 2026 -0800 Fortran: Fix PR123868 When copying derived types with allocatable array components where the array element type also has allocatable components, the condition at line 11071 was incorrectly triggering a call to gfc_duplicate_allocatable. However, for allocatable arrays with nested allocatables (where cmp_has_alloc_comps && c->as is true), the add_when_allocated code already includes a gfc_duplicate_allocatable call (generated by the recursive structure_alloc_comps call at lines 10290-10293). This caused the outer array to be allocated twice: first by the explicit gfc_duplicate_allocatable call at line 11099, and then again by the gfc_duplicate_allocatable embedded in add_when_allocated. The first allocation was leaked when the second allocation overwrote the data pointer. PR121628 added "add_when_allocated != NULL_TREE ||" to the condition, which was redundant for scalars (already handled by !c->as) and wrong for arrays (caused double allocation). Simply removing this clause restores the correct pre-PR121628 behavior. PR fortran/123868 gcc/fortran/ChangeLog: * trans-array.cc (structure_alloc_comps): For COPY_ALLOC_COMP, remove the add_when_allocated != NULL_TREE clause that PR121628 added. This clause was redundant for scalars and caused double allocation for arrays with nested allocatable components. gcc/testsuite/ChangeLog: * gfortran.dg/array_memcpy_2.f90: Update expected memcpy count from 4 to 3, as the double allocation bug is now fixed. * gfortran.dg/pr123868.f90: New test. Signed-off-by: Christopher Albert <[email protected]> Diff: --- gcc/fortran/trans-array.cc | 9 ++++++-- gcc/testsuite/gfortran.dg/array_memcpy_2.f90 | 5 ++-- gcc/testsuite/gfortran.dg/pr123868.f90 | 34 ++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index e207b0c06d35..ca2bff22ba31 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -11063,9 +11063,14 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl, tree dest, copy_wrapper); gfc_add_expr_to_block (&fnblock, call); } + /* For allocatable arrays with nested allocatable components, + add_when_allocated already includes gfc_duplicate_allocatable + (from the recursive structure_alloc_comps call at line 10290-10293), + so we must not call it again here. PR121628 added an + add_when_allocated != NULL clause that was redundant for scalars + (already handled by !c->as) and wrong for arrays (double alloc). */ else if (c->attr.allocatable && !c->attr.proc_pointer - && (add_when_allocated != NULL_TREE - || !cmp_has_alloc_comps + && (!cmp_has_alloc_comps || !c->as || c->attr.codimension || caf_in_coarray (caf_mode))) diff --git a/gcc/testsuite/gfortran.dg/array_memcpy_2.f90 b/gcc/testsuite/gfortran.dg/array_memcpy_2.f90 index a95908c2928b..8fcac0e63f1e 100644 --- a/gcc/testsuite/gfortran.dg/array_memcpy_2.f90 +++ b/gcc/testsuite/gfortran.dg/array_memcpy_2.f90 @@ -1,11 +1,12 @@ ! This checks that the "z = y" assignment is not considered copyable, as the ! array is of a derived type containing allocatable components. Hence, we -! we should expand the scalarized loop, which contains *two* memcpy calls +! should expand the scalarized loop, which contains *two* memcpy calls ! for the assignment itself, plus one for initialization. ! { dg-do compile } ! { dg-options "-O2 -fdump-tree-original" } ! ! PR 121628 +! PR 123868 - fixed double allocation that caused 4 memcpy instead of 3 ! type :: a integer, allocatable :: i(:) @@ -26,4 +27,4 @@ z = y end -! { dg-final { scan-tree-dump-times "__builtin_memcpy" 4 "original" } } +! { dg-final { scan-tree-dump-times "__builtin_memcpy" 3 "original" } } diff --git a/gcc/testsuite/gfortran.dg/pr123868.f90 b/gcc/testsuite/gfortran.dg/pr123868.f90 new file mode 100644 index 000000000000..e21501ddaccf --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr123868.f90 @@ -0,0 +1,34 @@ +! { dg-do run } +! PR fortran/123868 - Memory leak on assignment with nested allocatable +! components. Regression introduced by PR121628 commit which caused +! gfc_duplicate_allocatable to be called twice for allocatable array +! components with nested allocatable components. + +module bugMod + + type :: vs + character(len=1), allocatable :: s + end type vs + + type :: ih + type(vs), allocatable, dimension(:) :: hk + end type ih + +end module bugMod + +program bugProg + use bugMod + + block + type(ih) :: c, d + + allocate(d%hk(1)) + allocate(d%hk(1)%s) + d%hk(1)%s='z' + c=d + if (c%hk(1)%s /= 'z') stop 1 + if (d%hk(1)%s /= 'z') stop 2 + + end block + +end program bugProg
