Fortran: Set the vptr of a class typed result.

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.
This commit is contained in:
Andre Vehreschild 2024-06-06 14:01:13 +02:00
parent 23141088e8
commit dbb718175d
5 changed files with 45 additions and 11 deletions

View 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)

View 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);

View 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);

View 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" } }

View file

@ -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