Dear all, this patch appears to fix an almost 10-year old puzzle, where an attempt was made to prevent some optimizations by declaring instances of derived types with DTIO as static. This has the side-effect that automatic deallocation did not work.
The root cause was a wrong fnspec attribute for the argument relating to the variable being read. Regtested on x86_64-pc-linux-gnu. OK for mainline? And OK for backport to 16-branch? Thanks, Harald
From 6a01f0cc3f37be4d64e4bf5a2b611fa89b6e79ad Mon Sep 17 00:00:00 2001 From: Harald Anlauf <[email protected]> Date: Thu, 7 May 2026 22:34:52 +0200 Subject: [PATCH] Fortran: fix automatic deallocation with derived type IO [PR111952,PR125059] The implementation of derived type IO wrongly forced allocatable instances of the DT as static, which prevented automatic deallocation of local variables. The motivation was an attempt to prevent optimizations leading to certain testcase failures. Howver, the underlying reason of the problem was a wrong fnspec of _gfortran_transfer_derived that declared the IO variable as being only read ('r'). Declare the corresponding parameter as being written ('w'). PR fortran/111952 PR fortran/125059 gcc/fortran/ChangeLog: * trans-decl.cc (gfc_finish_var_decl): Remove bogus code forcing a DT variable with DTIO as static. * trans-io.cc (gfc_build_io_library_fndecls): Fix fnspec attribute. gcc/testsuite/ChangeLog: * gfortran.dg/dtio_37.f90: New test. --- gcc/fortran/trans-decl.cc | 10 -------- gcc/fortran/trans-io.cc | 2 +- gcc/testsuite/gfortran.dg/dtio_37.f90 | 36 +++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/dtio_37.f90 diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 4b3f75ced71..dcf4bbfdbf4 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -756,16 +756,6 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym) && sym->attr.codimension && !sym->attr.allocatable))) TREE_STATIC (decl) = 1; - /* If derived-type variables with DTIO procedures are not made static - some bits of code referencing them get optimized away. - TODO Understand why this is so and fix it. */ - if (!sym->attr.use_assoc - && ((sym->ts.type == BT_DERIVED - && sym->ts.u.derived->attr.has_dtio_procs) - || (sym->ts.type == BT_CLASS - && CLASS_DATA (sym)->ts.u.derived->attr.has_dtio_procs))) - TREE_STATIC (decl) = 1; - /* Treat asynchronous variables the same as volatile, for now. */ if (sym->attr.volatile_ || sym->attr.asynchronous) { diff --git a/gcc/fortran/trans-io.cc b/gcc/fortran/trans-io.cc index a18b2bca6aa..046fb57bcd0 100644 --- a/gcc/fortran/trans-io.cc +++ b/gcc/fortran/trans-io.cc @@ -416,7 +416,7 @@ gfc_build_io_library_fndecls (void) integer_type_node, gfc_charlen_type_node); iocall[IOCALL_X_DERIVED] = gfc_build_library_function_decl_with_spec ( - get_identifier (PREFIX("transfer_derived")), ". w r ", + get_identifier (PREFIX("transfer_derived")), ". w w ", void_type_node, 2, dt_parm_type, pvoid_type_node); /* Library entry points */ diff --git a/gcc/testsuite/gfortran.dg/dtio_37.f90 b/gcc/testsuite/gfortran.dg/dtio_37.f90 new file mode 100644 index 00000000000..021d0e180b2 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/dtio_37.f90 @@ -0,0 +1,36 @@ +! { dg-do run } +! { dg-additional-options "-O2" } +! +! PR fortran/125059 - derived type IO and automatic deallocation +! PR fortran/111952 + +module m + type t + integer :: i = 42 + contains + procedure :: w + generic :: write(formatted) => w + end type t +contains + subroutine w(dtv,unit,iotype,v_list,iostat,iomsg) + class(t), intent(in) :: dtv + integer, intent(in) :: unit + character(len=*),intent(in) :: iotype + integer, intent(in) :: v_list(:) + integer, intent(out) :: iostat + character(len=*),intent(inout) :: iomsg + write(unit,*,iostat=iostat,iomsg=iomsg) dtv%i + end subroutine w +end + +program p + use m + call f() + call f() +contains + subroutine f() + type(t), allocatable :: a(:) + allocate (a(1)) + print *, a(1) + end subroutine f +end -- 2.51.0
