Hi All, This patch makes sure that offsets and bounds are correct in passing derived types to class formal arrays. It is straightforward enough as not to require explanation.
Bootstraps and regtests on FC25/x86_64 - OK for trunk? Paul 2018-02-11 Paul Thomas <pa...@gcc.gnu.org> PR fortran/84074 * trans-expr.c (gfc_conv_derived_to_class): Set the use_offset flag. If the is a vector subscript or the expression is not a variable, make the descriptor one-based. 2018-02-11 Paul Thomas <pa...@gcc.gnu.org> PR fortran/84074 * gfortran.dg/type_to_class_5.f03: New test.
Index: gcc/fortran/trans-expr.c =================================================================== *** gcc/fortran/trans-expr.c (revision 257549) --- gcc/fortran/trans-expr.c (working copy) *************** gfc_conv_derived_to_class (gfc_se *parms *** 547,552 **** --- 547,553 ---- tree ctree; tree var; tree tmp; + int dim; /* The derived type needs to be converted to a temporary CLASS object. */ *************** gfc_conv_derived_to_class (gfc_se *parms *** 636,645 **** --- 637,670 ---- { stmtblock_t block; gfc_init_block (&block); + gfc_ref *ref; parmse->ss = ss; + parmse->use_offset = 1; gfc_conv_expr_descriptor (parmse, e); + /* Detect any vector array references. */ + for (ref = e->ref; ref; ref = ref->next) + if (ref->type == REF_ARRAY + && ref->u.ar.type != AR_ELEMENT + && ref->u.ar.type != AR_FULL) + { + for (dim = 0; dim < ref->u.ar.dimen; dim++) + if (ref->u.ar.dimen_type[dim] == DIMEN_VECTOR) + break; + if (dim < ref->u.ar.dimen) + break; + } + + /* Vector array references and non-variable expressions need be + coverted to one-based descriptors. */ + if (ref || e->expr_type != EXPR_VARIABLE) + { + for (dim = 0; dim < e->rank; ++dim) + gfc_conv_shift_descriptor_lbound (&block, parmse->expr, dim, + gfc_index_one_node); + } + if (e->rank != class_ts.u.derived->components->as->rank) { gcc_assert (class_ts.u.derived->components->as->type *************** gfc_trans_assignment_1 (gfc_expr * expr1 *** 10105,10111 **** &expr1->where, msg); } ! /* Deallocate the lhs parameterized components if required. */ if (dealloc && expr2->expr_type == EXPR_FUNCTION && !expr1->symtree->n.sym->attr.associate_var) { --- 10130,10136 ---- &expr1->where, msg); } ! /* Deallocate the lhs parameterized components if required. */ if (dealloc && expr2->expr_type == EXPR_FUNCTION && !expr1->symtree->n.sym->attr.associate_var) { Index: gcc/testsuite/gfortran.dg/type_to_class_5.f03 =================================================================== *** gcc/testsuite/gfortran.dg/type_to_class_5.f03 (nonexistent) --- gcc/testsuite/gfortran.dg/type_to_class_5.f03 (working copy) *************** *** 0 **** --- 1,29 ---- + ! { dg-do run } + ! + ! Test the fix for PR84074 + ! + ! Contributed by Vladimir Fuka <vladimir.f...@gmail.com> + ! + type :: t + integer :: n + end type + + type(t) :: array(4) = [t(1),t(2),t(3),t(4)] + + call sub(array((/3,1/)), [3,1,0,0]) ! Does not increment any elements of 'array'. + call sub(array(1:3:2), [1,3,0,0]) + call sub(array(3:1:-2), [4,2,0,0]) + call sub(array, [3,2,5,4]) ! Elements 1 and 3 should have been incremented twice. + + contains + + subroutine sub(a, iarray) + class(t) :: a(:) + integer :: iarray(4) + integer :: i + do i=1,size(a) + if (a(i)%n .ne. iarray(i)) call abort + a(i)%n = a(i)%n+1 + enddo + end subroutine + end program