Hello world, the attached patch fixes a regression where a segfault occured at runtime for the attached test case. The regression made it out into the wild with the 8.3 release. Unfortunately, it was discovered too late before release to do anything about it.
In effect, this patch reverts a part of r265171 for one special case: If the argument to gfc_find_and_cut_at_last_class_ref is the MOLD argument to allocate. Of course, there could also be a more profound way of fixing this bug :-) Regression-tested on x86_64-pc-linux-gnu. OK for trunk and gcc-8? Regards Thomas 2019-02-24 Thomas Koenig <tkoe...@gcc.gnu.org> PR fortran/89174 * trans-expr.c (gfc_find_and_cut_at_last_class_ref): Add is_mold to garguments. If we are dealing with a MOLD, call gfc_expr_to_initialize(). * trans-stmt.c (gfc_trans_allocate): For MOLD, pass is_mold=true to gfc_find_and_cut_at_last_class_ref. * trans.h (gfc_find_and_cut_at_last_class_ref): Add optional argument is_mold with default false. 2019-02-24 Thomas Koenig <tkoe...@gcc.gnu.org> PR fortran/89174 * gfortran.dg/allocate_with_mold_3.f90: New test.
Index: trans-expr.c =================================================================== --- trans-expr.c (Revision 269161) +++ trans-expr.c (Arbeitskopie) @@ -352,7 +352,7 @@ gfc_vptr_size_get (tree vptr) of refs following. */ gfc_expr * -gfc_find_and_cut_at_last_class_ref (gfc_expr *e) +gfc_find_and_cut_at_last_class_ref (gfc_expr *e, bool is_mold) { gfc_expr *base_expr; gfc_ref *ref, *class_ref, *tail = NULL, *array_ref; @@ -394,7 +394,10 @@ gfc_expr * e->ref = NULL; } - base_expr = gfc_copy_expr (e); + if (is_mold) + base_expr = gfc_expr_to_initialize (e); + else + base_expr = gfc_copy_expr (e); /* Restore the original tail expression. */ if (class_ref) Index: trans-stmt.c =================================================================== --- trans-stmt.c (Revision 269161) +++ trans-stmt.c (Arbeitskopie) @@ -6641,7 +6641,7 @@ gfc_trans_allocate (gfc_code * code) /* Use class_init_assign to initialize expr. */ gfc_code *ini; ini = gfc_get_code (EXEC_INIT_ASSIGN); - ini->expr1 = gfc_find_and_cut_at_last_class_ref (expr); + ini->expr1 = gfc_find_and_cut_at_last_class_ref (expr, true); tmp = gfc_trans_class_init_assign (ini); gfc_free_statements (ini); gfc_add_expr_to_block (&block, tmp); Index: trans.h =================================================================== --- trans.h (Revision 269161) +++ trans.h (Arbeitskopie) @@ -412,7 +412,7 @@ tree gfc_class_data_get (tree); tree gfc_class_vptr_get (tree); tree gfc_class_len_get (tree); tree gfc_class_len_or_zero_get (tree); -gfc_expr * gfc_find_and_cut_at_last_class_ref (gfc_expr *); +gfc_expr * gfc_find_and_cut_at_last_class_ref (gfc_expr *, bool is_mold = false); /* Get an accessor to the class' vtab's * field, when a class handle is available. */ tree gfc_class_vtab_hash_get (tree);
! { dg-do run } ! PR fortran/89174 - this used to segfault on execution. ! Test case by Neil Carlson. module mod type :: array_data class(*), allocatable :: mold contains procedure :: push end type contains subroutine push(this, value) class(array_data), intent(inout) :: this class(*), intent(in) :: value allocate(this%mold, mold=value) ! <== SEGFAULTS HERE end subroutine end module use mod type(array_data) :: foo call foo%push(42) end