]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fortran: fix automatic deallocation with derived type IO [PR111952,PR125059]
authorHarald Anlauf <anlauf@gmx.de>
Thu, 7 May 2026 20:34:52 +0000 (22:34 +0200)
committerHarald Anlauf <anlauf@gmx.de>
Fri, 8 May 2026 16:57:21 +0000 (18:57 +0200)
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
gcc/fortran/trans-io.cc
gcc/testsuite/gfortran.dg/dtio_37.f90 [new file with mode: 0644]

index 4b3f75ced7101e97adff4703453b24d6dd3bf66e..dcf4bbfdbf4f01bf5f4e630b56446af3f9a0ebb3 100644 (file)
@@ -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)
     {
index a18b2bca6aa66bd05a570b15924189ff14105d5b..046fb57bcd0e6fe3636c091b0b951a5bda22567d 100644 (file)
@@ -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 (file)
index 0000000..021d0e1
--- /dev/null
@@ -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