Hi Everyone, I am afraid that this is a rather long sad story, mainly due to my efforts with gfortran being interrupted by daytime work. I posted the first version of the patch nearly a year ago but this was derailed by Tobias's question at: https://gcc.gnu.org/legacy-ml/fortran/2019-11/msg00098.html
(i) The attached fixes the original problem and is tested by gfortran.dg/unlimited_polymorphic_32.f03. (ii) In fixing the original problem, a fair amount of effort was required to get the element length correct for class temporaries produced by dependencies in class assignment (see footnote). This is reflected in the changes to trans_array.c(gfc_alloc_allocatable_for_assignment). (iii) Tobias's testcase in the above posting to the list didn't address itself to class arrays of the original problem. However, it revealed that reallocation was not occuring at all for scalar assignments. This is fixed by the large chunk in trans-expr.c(trans_class_assignment). The array case is 'fixed' by testing for unequal element sizes between lhs and rhs before reallocation in gfc_alloc_allocatable_for_assignment. This is difficult to test for since, in most cases, the system returns that same address after reallocation. (iv) dependency_57.f90 segfaulted at runtime. The other work in trans_class_assignment was required to fix this. (v) A number of minor tidy ups were done including the new function gfc_resize_class_size_with_len to eliminate some repeated code. This all bootstraps and regtests on FC31/x86_64 - OK for master? Cheers Paul This patch fixes PR83118 and fixes one or two other niggles in handling class objects - most importantly class array temporaries required, where dependences occur in class assignment, and a correct implementation of reallocation on assignment. 2020-10-29 Paul Thomas <pa...@gcc.gnu.org> gcc/fortran PR fortran/83118 * resolve.c (resolve_ordinary_assign): Generate a vtable if necessary for scalar non-polymorphic rhs's to unlimited lhs's. * trans-array.c (gfc_trans_allocate_array_storage): Defer obtaining class element type until all sources of class exprs. are tried. Use class API rather than TREE_OPERAND. Look for class expressions in ss->info. After this, obtain the element size for class payloads. Cast the data as character(len=size) to overcome unlimited polymorphic problems. (structure_alloc_comps): Replace code that replicates the new function gfc_resize_class_size_with_len. (gfc_alloc_allocatable_for_assignment): Obtain element size for lhs in cases of deferred characters and class enitities. Move code for the element size of rhs to start of block. Clean up extraction of class parmateres throughout this function. After the shape check test whether or not the lhs and rhs element sizes are the same. Use earlier evaluation of 'cond_null'. Reallocation of lhs only to happen if siz changes or element size changes. * trans-expr.c (gfc_resize_class_size_with_len): New function. (gfc_conv_procedure_call): Ensure the vtable is present for passing a non-class actual to an unlimited formal. (trans_class_vptr_len_assignment): For expressions of type BT_CLASS, extract the class expression if necessary. Use a statement block outside the loop body. Ensure that 'rhs' is of the correct type. Obtain rhs vptr in all circumstances. (gfc_trans_assignment_1): Simplify some of the logic with 'realloc_flag'. Set 'vptr_copy' for all array assignments to unlimited polymorphic lhs. * trans-c (gfc_build_array_ref): Call gfc_resize_class_size_ with_len to correct span for unlimited polymorphic decls. * trans.h : Add prototype for gfc_resize_class_size_with_len. gcc/testsuite/ PR fortran/83118 * gfortran.dg/dependency_57.f90: Change to dg-run and test for correct result. * gfortran.dg/unlimited_polymorphic_32.f03: New test. Footnote: I have come to the conclusion that gfc_trans_allocate_array_storage is the last place that we should be dealing with class array temporaries, or directly at least. I will give some thought as to how to do it better. Also, chunks of code are coming within scalarization loops that should be outside: x->_vptr = (struct __vtype__STAR * {ref-all}) &__vtab_INTEGER_4_; x->_len = 0; D.3977 = x->_vptr->_size; D.3978 = x->_len; D.3979 = D.3978 > 0 ? D.3977 * D.3978 : D.3977;
Change2.Logs
Description: Binary data
unlimited_polymorphic_32.f03
Description: Binary data