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

Reply via email to