Fixing the original problem in the module took a few minutes. Making the module do something useful took rather longer! The testcase in the patch compiles with 6-branch but segfaults in runtime.
Bootstrapped and regtested on FC30/x86_64 - OK to commit and go steadily back through the branches over some weeks? Regards Paul 2019-09-22 Paul Thomas <pa...@gcc.gnu.org> PR fortran/91726 * resolve.c (gfc_expr_to_initialize): Bail out with a copy of the original expression if the array ref is a scalar and the array_spec has corank. * trans-array.c (gfc_conv_array_ref): Such expressions are OK even if the array ref codimen is zero. * trans-expr.c (gfc_get_class_from_expr): New function taken from gfc_get_vptr_from_expr. (gfc_get_vptr_from_expr): Call new function. * trans-stmt.c (trans_associate_var): If one of these is a target expression, extract the class expression from the target and copy its fields to a new target variable. * trans.h : Add prototype for gfc_get_class_from_expr. 2019-09-22 Paul Thomas <pa...@gcc.gnu.org> PR fortran/91726 * gfortran.dg/coarray_poly_9.f90 : New test.
Index: gcc/fortran/resolve.c =================================================================== *** gcc/fortran/resolve.c (revision 275799) --- gcc/fortran/resolve.c (working copy) *************** gfc_expr_to_initialize (gfc_expr *e) *** 7433,7438 **** --- 7433,7442 ---- for (ref = result->ref; ref; ref = ref->next) if (ref->type == REF_ARRAY && ref->next == NULL) { + if (ref->u.ar.dimen == 0 + && ref->u.ar.as && ref->u.ar.as->corank) + return result; + ref->u.ar.type = AR_FULL; for (i = 0; i < ref->u.ar.dimen; i++) Index: gcc/fortran/trans-array.c =================================================================== *** gcc/fortran/trans-array.c (revision 275799) --- gcc/fortran/trans-array.c (working copy) *************** gfc_conv_array_ref (gfc_se * se, gfc_arr *** 3609,3615 **** if (ar->dimen == 0) { ! gcc_assert (ar->codimen || sym->attr.select_rank_temporary); if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr))) se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr)); --- 3609,3616 ---- if (ar->dimen == 0) { ! gcc_assert (ar->codimen || sym->attr.select_rank_temporary ! || (ar->as && ar->as->corank)); if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr))) se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr)); Index: gcc/fortran/trans-expr.c =================================================================== *** gcc/fortran/trans-expr.c (revision 275799) --- gcc/fortran/trans-expr.c (working copy) *************** gfc_reset_len (stmtblock_t *block, gfc_e *** 472,482 **** } ! /* Obtain the vptr of the last class reference in an expression. Return NULL_TREE if no class reference is found. */ tree ! gfc_get_vptr_from_expr (tree expr) { tree tmp; tree type; --- 472,482 ---- } ! /* Obtain the last class reference in an expression. Return NULL_TREE if no class reference is found. */ tree ! gfc_get_class_from_expr (tree expr) { tree tmp; tree type; *************** gfc_get_vptr_from_expr (tree expr) *** 487,493 **** while (type) { if (GFC_CLASS_TYPE_P (type)) ! return gfc_class_vptr_get (tmp); if (type != TYPE_CANONICAL (type)) type = TYPE_CANONICAL (type); else --- 487,493 ---- while (type) { if (GFC_CLASS_TYPE_P (type)) ! return tmp; if (type != TYPE_CANONICAL (type)) type = TYPE_CANONICAL (type); else *************** gfc_get_vptr_from_expr (tree expr) *** 501,506 **** --- 501,523 ---- tmp = build_fold_indirect_ref_loc (input_location, tmp); if (GFC_CLASS_TYPE_P (TREE_TYPE (tmp))) + return tmp; + + return NULL_TREE; + } + + + /* Obtain the vptr of the last class reference in an expression. + Return NULL_TREE if no class reference is found. */ + + tree + gfc_get_vptr_from_expr (tree expr) + { + tree tmp; + + tmp = gfc_get_class_from_expr (expr); + + if (tmp != NULL_TREE) return gfc_class_vptr_get (tmp); return NULL_TREE; Index: gcc/fortran/trans-stmt.c =================================================================== *** gcc/fortran/trans-stmt.c (revision 275799) --- gcc/fortran/trans-stmt.c (working copy) *************** trans_associate_var (gfc_symbol *sym, gf *** 2099,2105 **** --- 2099,2141 ---- } else { + tree ctree = gfc_get_class_from_expr (se.expr); tmp = TREE_TYPE (sym->backend_decl); + + /* Coarray scalar component expressions can emerge from + the front end as array elements of the _data field. */ + if (sym->ts.type == BT_CLASS + && e->ts.type == BT_CLASS && e->rank == 0 + && !GFC_CLASS_TYPE_P (TREE_TYPE (se.expr)) && ctree) + { + tree stmp; + tree dtmp; + + se.expr = ctree; + dtmp = TREE_TYPE (TREE_TYPE (sym->backend_decl)); + ctree = gfc_create_var (dtmp, "class"); + + stmp = gfc_class_data_get (se.expr); + gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (stmp))); + + /* Set the fields of the target class variable. */ + stmp = gfc_conv_descriptor_data_get (stmp); + dtmp = gfc_class_data_get (ctree); + stmp = fold_convert (TREE_TYPE (dtmp), stmp); + gfc_add_modify (&se.pre, dtmp, stmp); + stmp = gfc_class_vptr_get (se.expr); + dtmp = gfc_class_vptr_get (ctree); + stmp = fold_convert (TREE_TYPE (dtmp), stmp); + gfc_add_modify (&se.pre, dtmp, stmp); + if (UNLIMITED_POLY (sym)) + { + stmp = gfc_class_len_get (se.expr); + dtmp = gfc_class_len_get (ctree); + stmp = fold_convert (TREE_TYPE (dtmp), stmp); + gfc_add_modify (&se.pre, dtmp, stmp); + } + se.expr = ctree; + } tmp = gfc_build_addr_expr (tmp, se.expr); } Index: gcc/fortran/trans.h =================================================================== *** gcc/fortran/trans.h (revision 275799) --- gcc/fortran/trans.h (working copy) *************** tree gfc_vptr_final_get (tree); *** 434,439 **** --- 434,440 ---- tree gfc_vptr_deallocate_get (tree); void gfc_reset_vptr (stmtblock_t *, gfc_expr *); void gfc_reset_len (stmtblock_t *, gfc_expr *); + tree gfc_get_class_from_expr (tree); tree gfc_get_vptr_from_expr (tree); tree gfc_get_class_array_ref (tree, tree, tree, bool); tree gfc_copy_class_to_class (tree, tree, tree, bool); Index: gcc/testsuite/gfortran.dg/coarray_poly_9.f90 =================================================================== *** gcc/testsuite/gfortran.dg/coarray_poly_9.f90 (nonexistent) --- gcc/testsuite/gfortran.dg/coarray_poly_9.f90 (working copy) *************** *** 0 **** --- 1,38 ---- + ! { dg-do run } + ! { dg-options "-fcoarray=single" } + ! + ! Test the fix for PR91726. + ! + ! Contributed by Gerhardt Steinmetz <gs...@t-online.de> + ! + module m + type s + class(*), allocatable :: a[:] ! This ICEd + end type + type t + class(*), allocatable :: a(:)[:] ! This was OK + end type + end + + use m + call foo + call bar + contains + subroutine foo + type (s) :: a + integer(4) :: i = 42_4 + allocate (a%a[*], source = i) ! This caused runtime segfaults + select type (z => a%a) ! ditto + type is (integer(4)) + if (z .ne. 42_4) stop 1 + end select + end subroutine + subroutine bar ! Arrays always worked + type (t) :: a + allocate (a%a(3)[*], source = [1_4, 2_4, 3_4]) + select type (z => a%a) + type is (integer(4)) + if (any (z .ne. [1_4, 2_4, 3_4])) stop 2 + end select + end subroutine + end