https://gcc.gnu.org/g:a50d2acc48f45c6bbf256e51440d181794079a0f

commit r13-9209-ga50d2acc48f45c6bbf256e51440d181794079a0f
Author: Paul Thomas <pa...@gcc.gnu.org>
Date:   Mon Nov 11 09:01:11 2024 +0000

    Fortran: Suppress invalid finalization of artificial variable [PR116388]
    
    2024-11-11  Tomas Trnka  <tr...@scm.com>
                Paul Thomas  <pa...@gcc.gnu.org>
    
    gcc/fortran
            PR fortran/116388
            * class.cc (finalize_component): Leading underscore in the name
            of 'byte_stride' to suppress invalid finalization.
    
    gcc/testsuite/
            PR fortran/116388
            * gfortran.dg/finalize_58.f90: New test.
    
    (cherry picked from commit 42a2df0b7985b2a4732ba1c29726ac7aabd5eeae)

Diff:
---
 gcc/fortran/class.cc                      |  5 +-
 gcc/testsuite/gfortran.dg/finalize_58.f90 | 77 +++++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc
index bffc0ffff3a3..ddf840761605 100644
--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -1084,8 +1084,9 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, 
gfc_component *comp,
 
       gcc_assert (c);
 
-      /* Set scalar argument for storage_size.  */
-      gfc_get_symbol ("comp_byte_stride", sub_ns, &byte_stride);
+      /* Set scalar argument for storage_size. A leading underscore in
+        the name prevents an unwanted finalization.  */
+      gfc_get_symbol ("_comp_byte_stride", sub_ns, &byte_stride);
       byte_stride->ts = e->ts;
       byte_stride->attr.flavor = FL_VARIABLE;
       byte_stride->attr.value = 1;
diff --git a/gcc/testsuite/gfortran.dg/finalize_58.f90 
b/gcc/testsuite/gfortran.dg/finalize_58.f90
new file mode 100644
index 000000000000..54960e6b0305
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/finalize_58.f90
@@ -0,0 +1,77 @@
+! { dg-do run }
+!
+! Test fix for PR116388 in which an artificial variable in the finalization
+! wrapper was generating an invalid finalization.
+!
+! Contributed by Tomas Trnka  <tr...@scm.com>
+!
+module FinalizerTestModule
+
+   use, intrinsic :: ISO_C_BINDING
+
+   implicit none
+
+   type, public :: AType
+      type(C_ptr) :: cptr = C_null_ptr
+      logical     :: cptr_invalid = .true.
+      integer, allocatable :: x(:)
+   contains
+      final              :: FinalizerA
+   end type
+
+   type, public :: BType
+      type(C_ptr) :: cptr = C_null_ptr
+      type(AType) :: a
+   contains
+      procedure, public  :: New => NewB
+      final              :: FinalizerB
+   end type
+
+   type, public :: CType
+      type(BType) :: b
+   contains
+      procedure, public :: New => NewC
+   end type
+
+   integer :: final_A = 0
+   integer :: final_B = 0
+contains
+
+   impure elemental subroutine FinalizerA(self)
+      type(AType), intent(inout) :: self
+      final_A = final_A + 1
+      if (.not. self%cptr_invalid) stop 1
+   end subroutine
+
+   subroutine NewB(self)
+      class(BType),     intent(out)           :: self
+
+   end subroutine
+
+   impure elemental subroutine FinalizerB(self)
+      type(BType), intent(inout) :: self
+      final_B = final_B + 1
+      if (transfer (self%cptr, C_LONG_LONG) /= 0) stop 2
+   end subroutine
+
+   subroutine NewC(self, b)
+      class(CType),  intent(out) :: self
+      type(BType),   intent(in)  :: b
+
+      self%b = b
+   end subroutine
+
+end module
+
+program finalizing_uninitialized
+   use FinalizerTestModule
+   implicit none
+
+   type(BType) :: b
+   type(CType) :: c
+
+   call b%New()
+   call c%New(b)
+   if (final_A /= 3) stop 3
+   if (final_B /= 3) stop 4
+end program

Reply via email to