]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fortran: Set the vptr of a class typed result.
authorAndre Vehreschild <vehre@gcc.gnu.org>
Thu, 6 Jun 2024 12:01:13 +0000 (14:01 +0200)
committerAndre Vehreschild <vehre@gcc.gnu.org>
Wed, 19 Jun 2024 08:39:56 +0000 (10:39 +0200)
PR fortran/90076

gcc/fortran/ChangeLog:

* trans-decl.cc (gfc_generate_function_code): Set vptr for
results to declared class type.
* trans-expr.cc (gfc_reset_vptr): Allow to provide the typespec
instead of the expression.
* trans.h (gfc_reset_vptr): Same.

gcc/testsuite/ChangeLog:

* gfortran.dg/class_76.f90: Add declared vtab occurrence.
* gfortran.dg/class_78.f90: New test.

gcc/fortran/trans-decl.cc
gcc/fortran/trans-expr.cc
gcc/fortran/trans.h
gcc/testsuite/gfortran.dg/class_76.f90
gcc/testsuite/gfortran.dg/class_78.f90 [new file with mode: 0644]

index dca7779528bb5b099b5405165b4b8f6ae3c70e78..88538713a02b41a7aaace62d052819b3eb2b03f5 100644 (file)
@@ -7926,11 +7926,12 @@ gfc_generate_function_code (gfc_namespace * ns)
                   && CLASS_DATA (sym)->attr.dimension == 0
                   && sym->result == sym)
            {
-             tmp = CLASS_DATA (sym)->backend_decl;
-             tmp = fold_build3_loc (input_location, COMPONENT_REF,
-                                    TREE_TYPE (tmp), result, tmp, NULL_TREE);
-             gfc_add_modify (&init, tmp, fold_convert (TREE_TYPE (tmp),
-                                                       null_pointer_node));
+             tmp = gfc_class_data_get (result);
+             gfc_add_modify (&init, tmp,
+                             fold_convert (TREE_TYPE (tmp),
+                                           null_pointer_node));
+             gfc_reset_vptr (&init, nullptr, result,
+                             CLASS_DATA (sym->result)->ts.u.derived);
            }
          else if (sym->ts.type == BT_DERIVED
                   && !sym->attr.allocatable)
index d6f4d6bfe4575372291aa238dee996a123e50fbb..558a7380516966f50a1ad7128f3688367cbd1aee 100644 (file)
@@ -530,13 +530,14 @@ gfc_find_and_cut_at_last_class_ref (gfc_expr *e, bool is_mold,
   return base_expr;
 }
 
-
 /* Reset the vptr to the declared type, e.g. after deallocation.
    Use the variable in CLASS_CONTAINER if available.  Otherwise, recreate
-   one with E.  The generated assignment code is added at the end of BLOCK.  */
+   one with e or derived.  At least one of the two has to be set.  The generated
+   assignment code is added at the end of BLOCK.  */
 
 void
-gfc_reset_vptr (stmtblock_t *block, gfc_expr *e, tree class_container)
+gfc_reset_vptr (stmtblock_t *block, gfc_expr *e, tree class_container,
+               gfc_symbol *derived)
 {
   tree vptr = NULL_TREE;
 
@@ -546,6 +547,7 @@ gfc_reset_vptr (stmtblock_t *block, gfc_expr *e, tree class_container)
   if (vptr == NULL_TREE)
     {
       gfc_se se;
+      gcc_assert (e);
 
       /* Evaluate the expression and obtain the vptr from it.  */
       gfc_init_se (&se, NULL);
@@ -570,7 +572,7 @@ gfc_reset_vptr (stmtblock_t *block, gfc_expr *e, tree class_container)
       tree vtable;
 
       /* Return the vptr to the address of the declared type.  */
-      vtab = gfc_find_derived_vtab (e->ts.u.derived);
+      vtab = gfc_find_derived_vtab (derived ? derived : e->ts.u.derived);
       vtable = vtab->backend_decl;
       if (vtable == NULL_TREE)
        vtable = gfc_get_symbol_decl (vtab);
index f94fa601400485f27d13ad42ff4ae1798cdedf39..5e064af5ccbde5222ea82f2bcbd585517db3d92d 100644 (file)
@@ -451,7 +451,9 @@ tree gfc_vptr_def_init_get (tree);
 tree gfc_vptr_copy_get (tree);
 tree gfc_vptr_final_get (tree);
 tree gfc_vptr_deallocate_get (tree);
-void gfc_reset_vptr (stmtblock_t *, gfc_expr *, tree = NULL_TREE);
+void
+gfc_reset_vptr (stmtblock_t *, gfc_expr *, tree = NULL_TREE,
+               gfc_symbol * = nullptr);
 void gfc_reset_len (stmtblock_t *, gfc_expr *);
 tree gfc_get_class_from_gfc_expr (gfc_expr *);
 tree gfc_get_class_from_expr (tree);
index 1ee1e1fc25f2c0a169263d349013a0b2d565cddb..c9842a15feabc09cbb399343b810f9989b0bd572 100644 (file)
@@ -61,6 +61,6 @@ contains
     end function newContainer
 end program returned_memory_leak
 
-! { dg-final { scan-tree-dump-times "newabstract" 14 "original" } }
+! { dg-final { scan-tree-dump-times "newabstract" 15 "original" } }
 ! { dg-final { scan-tree-dump-times "__builtin_free" 8 "original" } }
 
diff --git a/gcc/testsuite/gfortran.dg/class_78.f90 b/gcc/testsuite/gfortran.dg/class_78.f90
new file mode 100644 (file)
index 0000000..3e2a024
--- /dev/null
@@ -0,0 +1,29 @@
+! { dg-do run }
+!
+! PR fortran/90076
+!
+! Contributed by Brad Richardson  <everythingfunctional@protonmail.com>
+! 
+
+program assignment_memory_leak
+    implicit none
+
+    type, abstract :: base
+    end type base
+
+    type, extends(base) :: extended
+    end type extended
+
+    call run()
+contains
+    subroutine run()
+        class(base), allocatable :: var
+
+        var = newVar() ! Crash fixed
+    end subroutine run
+
+    function newVar()
+        class(extended), allocatable :: newVar
+    end function newVar
+end program assignment_memory_leak
+