Hello All,

The attached patch fixes the memory leak in pdt_77.f03. The problem
was diagnosed by the addition of the final subroutine, which appears
in the updated version of the pdt_77.f03 test case. Once it was
understood that the _vptr of the class component 'p' was not being set
correctly, the use of a VIEW_CONVERT_EXPR to pass the component
expression to alloc_navier_stokes was a clear signal that the
conversion to a class type was not being done correctly and so the
offending error in decl.cc was quickly found.

The patch regression tests correctly with FC44/x86_64. OK for mainline
and beckporting to 16-branch after an interval?

Cheers

Paul
From 630aa7d21a45ee821f2f425db29fc404ddd26579 Mon Sep 17 00:00:00 2001
From: Paul Thomas <[email protected]>
Date: Mon, 22 Jun 2026 10:21:47 +0100
Subject: [PATCH] Fortran: Fix memory leaks in PDT tests. [PR121972]

2026-06-22  Paul Thomas  <[email protected]>

gcc/fortran
	PR fortran/121972
	* decl.cc (build_struct): Convert the PDT template before the
	call to gcc/testsuite/gfortran.dg/pdt_77.f03.

gcc/testsuite/
	PR fortran/121972
	* gfortran.dg/pdt_77.f03: Add 'finalalize_navier_stokes', which
	tests that the 'navier_stokes' component 'p' is pointed to the
	correct vtable in both tests. Check that VIEW_CONVERT_EXPR does
	not appear in the tree dump.
---
 gcc/fortran/decl.cc                  | 18 ++++++++++++++++++
 gcc/testsuite/gfortran.dg/pdt_77.f03 | 18 ++++++++++++++++--
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index 9c124cb103d..63941edebd9 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -2546,6 +2546,24 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
 
   gfc_apply_init (&c->ts, &c->attr, c->initializer);
 
+  /* Convert a class, PDT component of a non-derived type to a specific instance
+     before gfc_build_class_symbol gets to work on it.  */
+  if (c->ts.type == BT_CLASS
+      && !(gfc_current_block ()->attr.pdt_template
+	   || gfc_current_block ()->attr.pdt_type)
+      && c->ts.u.derived->attr.pdt_template)
+    {
+      match m = gfc_get_pdt_instance (decl_type_param_list, &c->ts.u.derived, NULL);
+      if (m != MATCH_YES)
+	{
+	  if (!gfc_error_check ())
+	    gfc_error ("Parameterized component of a non-parameterized "
+		       "derived type at %C could not be converted to a valid "
+		       "instance");
+	  return false;
+	}
+    }
+
   /* Check array components.  */
   if (!c->attr.dimension)
     goto scalar;
diff --git a/gcc/testsuite/gfortran.dg/pdt_77.f03 b/gcc/testsuite/gfortran.dg/pdt_77.f03
index 627c0f0de80..f24e7fc49f0 100644
--- a/gcc/testsuite/gfortran.dg/pdt_77.f03
+++ b/gcc/testsuite/gfortran.dg/pdt_77.f03
@@ -1,6 +1,12 @@
 ! { dg-do run }
+! { dg-options "-fdump-tree-original" }
 !
 ! Test the fix for PR110012, which failed to compile with an ICE.
+! Later, it was found that mfe_disc_test was leaking memory because
+! the 'navier_stokes' component p was given the PDT template dynamic
+! type, rather than that of the correct instance. This is detected
+! by the added, final subroutine being called twice, rather than
+! once (PR121972).
 !
 ! Contributed by Neil Carlson  <[email protected]>
 !
@@ -14,7 +20,10 @@ module navier_stokes_type
   use pde_class
   type, extends(pde) :: navier_stokes
     integer, allocatable :: data_(:)
+  contains
+    final :: finalIze_navier_stokes
   end type
+  integer :: ctr = 0
 contains
   subroutine alloc_navier_stokes(p , n)
     class(pde(:)), allocatable :: p
@@ -25,6 +34,10 @@ contains
         p%data_ = [(i, i = 1, p%npde)]
     end select
   end subroutine
+  impure elemental subroutine finalIze_navier_stokes (self)
+    type(navier_stokes), intent(inout) :: self
+    ctr = ctr + 1
+  end
 end module
 
 module mfe_disc_type
@@ -35,11 +48,12 @@ module mfe_disc_type
 end module
 
 program test
+  use navier_stokes_type
   call navier_stokes_test
   call mfe_disc_test
+  if (ctr /= 2) stop 3
 contains
   subroutine navier_stokes_test
-    use navier_stokes_type
     class (pde(:)), allocatable :: x
     call alloc_navier_stokes (x, 4)
     select type (x)
@@ -49,7 +63,6 @@ contains
   end subroutine
 
   subroutine mfe_disc_test
-    use navier_stokes_type
     use mfe_disc_type
     type (foo), allocatable :: x
     allocate (x)
@@ -61,3 +74,4 @@ contains
     if (allocated (x) .and. allocated (x%p)) deallocate (x%p)
   end subroutine
 end program
+! { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 0 "original" } }
-- 
2.54.0

Reply via email to