The following program, which is an extension of testsuite/gfortran.dg/class_48.f90 and thus PR 51972 fails to correctly set the value via SOURCE: allocate (two%a(2), source=[t(4), t(6)]) Should give for two%a(1)%x and two%a(2)%x the values 4 and 6, but one gets 0 0. If one uses not a class component but a class variable, the result is 4 0. There is a similar PR for polymorphic sources, cf. PR 51864. subroutine test3 () type t integer :: x end type t type t2 class(t), allocatable :: a(:) end type t2 type(t2) :: one, two one = two if (allocated (one%a)) call abort () allocate (two%a(2), source=[t(4), t(6)]) one = two if (.not.allocated (one%a)) call abort () print *, one%a(1)%x print *, one%a(6)%x if ((one%a(1)%x /= 4)) call abort () if ((one%a(2)%x /= 6)) call abort () deallocate (two%a) one = two if (allocated (one%a)) call abort () end subroutine test3
(In reply to comment #0) > Should give for two%a(1)%x and two%a(2)%x the values 4 and 6, but one gets > 0 0. If one uses not a class component but a class variable, the result > is 4 0. Correction: The latter works "4 6", thus, only CLASS components are affected. > print *, one%a(1)%x > print *, one%a(6)%x The last line should use "(2)" not "(6)". [It only should print "6" at run time.]
From the dump: two.a._data.data = (void * restrict) __builtin_malloc (8); __builtin_memset (two.a._data.data, 0, 8); two.a._data.offset = -1; { struct t D.1891; D.1891 = (*(struct t[0:] * restrict) two.a._data.data)[two.a._data.offset + 2]; The "D.1891 = " line looks odd: One should get the address of "two.a._data" and not the value. Additionally, one gets the address of element "[-1]" which is invalid. Also the loop is odd: One iterates through the elements of the SOURCE-expr, but one always writes to the same dst (here: the temporary variable D.1893): while (1) { if (S.6 > 1) goto L.1; { struct t D.1893; D.1893 = (*(struct t[2] * restrict) atmp.1.data)[S.6]; __vtab_MAIN___T._copy (&D.1893, &D.1891); By contrast, for: class(t), allocatable :: two(:) allocate (two(2), source=[t(4), t(6)]) One has in the loop D.1892 = (*(struct t[2] * restrict) atmp.1.data)[S.6]; __vtab_MAIN___T._copy (&D.1892, (struct t *) D.1882 + (sizetype) (((S.6 + 1) + D.1883) * (integer(kind=8)) two._vptr->_size)); with struct t[0:] * restrict D.1882; D.1882 = (struct t[0:] * restrict) two._data.data;
Related issue with MOLD=, here one gets with "x = 5" default initialization and allocate (two%a(8), mold=t(4)) print '(*(i2))', two%a(:)%x the result: 0 0 0 0 0 0 0 5 That is: only the last element gets the value. From the dump: two.a._data.offset = -1; ... struct t t.2; t.2.x = 5; D.1886 = t.2; __vtab_MAIN___T._copy (&D.1886, &(*(struct t[0:] * restrict) two.a._data.data)[two.a._data.offset + 8]); Note the constant offset of "8", which matches the ubound. Note further that the _copy construct is *not* in a scalarizing loop but only called once for the last element. * * * The following looks odd: gfc_trans_allocate (gfc_code * code) { ... if (code->expr3 && !code->expr3->mold) { ... /* Do a polymorphic deep copy. */ ... actual->next->expr = gfc_copy_expr (al->expr); dataref = actual->next->expr->ref; if (dataref->u.c.component->as) The latter makes no sense in this case as the base object is not the class container. We need to access the last component ref on the ref list.
Author: pault Date: Sun Feb 5 19:56:09 2012 New Revision: 183915 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=183915 Log: 2012-02-05 Paul Thomas <pault@gcc.gnu.org> * trans-array.c (gfc_array_allocate): Zero memory for all class array allocations. * trans-stmt.c (gfc_trans_allocate): Ditto for class scalars. PR fortran/52102 * trans-stmt.c (gfc_trans_allocate): Before correcting a class array reference, ensure that 'dataref' points to the _data component that is followed by the array reference.. 2012-02-05 Paul Thomas <pault@gcc.gnu.org> PR fortran/52102 * gfortran.dg/class_48.f90 : Add test of allocate class array component with source in subroutine test3. Remove commenting out in subroutine test4, since branching on unitialized variable is now fixed (no PR for this last.). Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/trans-array.c trunk/gcc/fortran/trans-stmt.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gfortran.dg/class_48.f90
Fixed on trunk. Thanks for the report Paul