https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120637

--- Comment #3 from Antony Lewis <antony at cosmologist dot info> ---
I tested just removing the was_finalization test, and it seems to work. This is
basically reverting the change in 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94109
https://gcc.gnu.org/cgit/gcc/commit/?id=1af22e455584ef5fcad2b4474c1efc3fd26f6cb3
- but the test case there no longer leaks memory in 15.1.1 with this patch: 

----------------
The was_finalized tracking in finalize_component was intended to prevent
duplicate finalization of the same expression+component combination within
a namespace. However, this mechanism had a fundamental flaw: it stored
gfc_expr* pointers that could become stale, leading to use-after-free bugs
and memory leaks as reported in PR120637.

Upon analysis, this tracking mechanism is redundant because the finalization
logic already handles proper scoping and lifetime management through other
means. Removing this mechanism eliminates the memory leak while maintaining
correct finalization behavior.

This change removes unnecessary overhead and complexity without affecting
functionality, providing better performance through elimination of
unnecessary memory allocations and list traversals.

    PR fortran/120637

gcc/fortran/ChangeLog:

    * class.cc (finalize_component): Remove redundant was_finalized
    check and tracking code.
    * gfortran.h (gfc_was_finalized): Remove structure definition.
    (gfc_namespace): Remove was_finalized field.
    * symbol.cc (gfc_free_namespace): Remove was_finalized cleanup code.
---
 gcc/fortran/class.cc   | 16 ----------------
 gcc/fortran/gfortran.h | 11 -----------
 gcc/fortran/symbol.cc  | 10 ----------
 3 files changed, 37 deletions(-)

diff --git a/gcc/fortran/class.cc b/gcc/fortran/class.cc
index df18601e45b..af6ac3c1e99 100644
--- a/gcc/fortran/class.cc
+++ b/gcc/fortran/class.cc
@@ -1041,19 +1041,10 @@ finalize_component (gfc_expr *expr, gfc_symbol
*derived, gfc_component *comp,
 {
   gfc_expr *e;
   gfc_ref *ref;
-  gfc_was_finalized *f;

   if (!comp_is_finalizable (comp))
     return;

-  /* If this expression with this component has been finalized
-     already in this namespace, there is nothing to do.  */
-  for (f = sub_ns->was_finalized; f; f = f->next)
-    {
-      if (f->e == expr && f->c == comp)
-   return;
-    }
-
   e = gfc_copy_expr (expr);
   if (!e->ref)
     e->ref = ref = gfc_get_ref ();
@@ -1227,13 +1218,6 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived,
gfc_component *comp,
                sub_ns);
       gfc_free_expr (e);
     }
-
-  /* Record that this was finalized already in this namespace.  */
-  f = sub_ns->was_finalized;
-  sub_ns->was_finalized = XCNEW (gfc_was_finalized);
-  sub_ns->was_finalized->e = expr;
-  sub_ns->was_finalized->c = comp;
-  sub_ns->was_finalized->next = f;
 }

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index f73b5f9c23f..97cbac4f5d9 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2205,15 +2205,7 @@ gfc_oacc_routine_name;

 #define gfc_get_oacc_routine_name() XCNEW (gfc_oacc_routine_name)

-/* Node in linked list to see what has already been finalized
-   earlier.  */

-typedef struct gfc_was_finalized {
-  gfc_expr *e;
-  gfc_component *c;
-  struct gfc_was_finalized *next;
-}
-gfc_was_finalized;

 /* A namespace describes the contents of procedure, module, interface block
    or BLOCK construct.  */
@@ -2317,10 +2309,7 @@ typedef struct gfc_namespace
   struct gfc_omp_assumptions *omp_assumes;
   struct gfc_omp_namelist *omp_allocate;

-  /* A hash set for the gfc expressions that have already
-     been finalized in this namespace.  */

-  gfc_was_finalized *was_finalized;

   /* Set to 1 if namespace is a BLOCK DATA program unit.  */
   unsigned is_block_data:1;
diff --git a/gcc/fortran/symbol.cc b/gcc/fortran/symbol.cc
index 81aa81df2ee..29c5deeb6d2 100644
--- a/gcc/fortran/symbol.cc
+++ b/gcc/fortran/symbol.cc
@@ -4198,7 +4198,6 @@ gfc_free_namespace (gfc_namespace *&ns)
 {
   gfc_namespace *p, *q;
   int i;
-  gfc_was_finalized *f;

   if (ns == NULL)
     return;
@@ -4233,15 +4232,6 @@ gfc_free_namespace (gfc_namespace *&ns)

   gfc_free_data (ns->data);

-  /* Free all the expr + component combinations that have been
-     finalized.  */
-  f = ns->was_finalized;
-  while (f)
-    {
-      gfc_was_finalized* current = f;
-      f = f->next;
-      free (current);
-    }
   if (ns->omp_assumes)
     {
       free (ns->omp_assumes->absent);
--
2.49.0

Reply via email to