Could you please examine the code below. The code constructs an array of structures, where the structure contains an array of integers. The code then attempts to pass the first element of each structure's array into an array in a subroutine - this step fails. It appears as though the memory locations being accessed to generate the temporary array in the subroutine has an incorrect stride. The stride appears to be 1, instead of the size of the structure. The code appears to run correctly when compiled with SGI and Cray compilers. Results are: ------------ Results when compiled with gfc compiler: Original: 1 11 21 Original: 2 12 22 Original: 3 13 23 Original: 4 14 24 Original: 5 15 25 Added 100 to a(1): 101 102 103 Added 100 to a(1): 104 105 22 Added 100 to a(1): 3 13 23 Added 100 to a(1): 4 14 24 Added 100 to a(1): 5 15 25 Results when compiled with SGI compiler, or Cray compiler: Original: 1, 11, 21 Original: 2, 12, 22 Original: 3, 13, 23 Original: 4, 14, 24 Original: 5, 15, 25 Added 100 to a(1): 101, 11, 21 Added 100 to a(1): 102, 12, 22 Added 100 to a(1): 103, 13, 23 Added 100 to a(1): 104, 14, 24 Added 100 to a(1): 105, 15, 25 Code is: -------- program test_f90 integer, parameter :: N = 5 type test_type integer a(3) end type type (test_type) s(N) integer i ! "s" is an array of structures,where the structure contains an array of length 3 do i=1, N s(i)%a(1) = i s(i)%a(2) = i + 10 s(i)%a(3) = i + 20 enddo ! "s" is initialised as follows: s(1)%a(1) = 1, s(1)%a(2) = 11, s(1)%a(3) = 21 ! s(2)%a(1) = 2, s(2)%a(2) = 12, s(2)%a(3) = 22 ! s(3)%a(1) = 3, s(3)%a(2) = 13, s(3)%a(3) = 23 ! s(4)%a(1) = 4, s(4)%a(2) = 14, s(4)%a(3) = 24 ! s(5)%a(1) = 5, s(5)%a(2) = 15, s(5)%a(3) = 25 do i=1, N write(*, *) 'Original: ', s(i)%a(1), s(i)%a(2), s(i)%a(3) enddo write(*, *) ' ' ! Add an offset to: s(1)%a(1), s(2)%a(1), s(3)%a(1), s(4)%a(1), s(5)%a(1) call test_sub(s%a(1), 100) ! "s" should now contain: s(1)%a(1) = 101, s(1)%a(2) = 11, s(1)%a(3) = 21 ! s(2)%a(1) = 102, s(2)%a(2) = 12, s(2)%a(3) = 22 ! s(3)%a(1) = 103, s(3)%a(2) = 13, s(3)%a(3) = 23 ! s(4)%a(1) = 104, s(4)%a(2) = 14, s(4)%a(3) = 24 ! s(5)%a(1) = 105, s(5)%a(2) = 15, s(5)%a(3) = 25 do i=1, N write(*, *) 'Added 100 to a(1): ', s(i)%a(1), s(i)%a(2), s(i)%a(3) enddo contains subroutine test_sub(array, offset) integer array(:), offset integer i do i=1, N array(i) = i + offset enddo end subroutine end program
I know I have seen a bug like this before.
Confirmed, we don't set the stride correctly as far as I can tell.
(In reply to comment #2) > Confirmed, we don't set the stride correctly as far as I can tell. This comes about because of the admitted kludge in the mechanism for passing components of derived type arrays. At line 1588 in trans-exp.c, you will find the comment: /* Returns a reference to a temporary array into which a component of an actual argument derived type array is copied and then returned after the function call. TODO Get rid of this kludge, when array descriptors are capable of handling aliased arrays. */ Maybe the time has come for byte size strides, although it will be a horrific job to implement. Paul
I am sorry but I realised on looking at this again that the stride has nothing to do with this one - the patch below regtests but has not been checked for correct-in-all-cases logic. Since the original was incorrect, give me a couple more days to get home and give this some clear thought... or what goes for clear thought. Paul Index: gcc/fortran/trans-expr.c =================================================================== *** gcc/fortran/trans-expr.c (revision 117860) --- gcc/fortran/trans-expr.c (working copy) *************** is_aliased_array (gfc_expr * e) *** 1840,1846 **** if (ref->type == REF_ARRAY) seen_array = true; ! if (ref->next == NULL && ref->type != REF_ARRAY) return seen_array; } --- 1845,1851 ---- if (ref->type == REF_ARRAY) seen_array = true; ! if (seen_array && ref->type != REF_ARRAY) return seen_array; }
Subject: Bug number PR29315 A patch for this bug has been added to the patch tracker. The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2006-11/msg00582.html
Subject: Bug 29315 Author: pault Date: Fri Nov 10 17:21:57 2006 New Revision: 118659 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=118659 Log: 2006-11-10 Paul Thomas <pault@gcc.gnu.org> PR fortran/29315 * trans-expr.c (is_aliased_array): Treat correctly the case where the component is itself and array or array reference. 2006-11-10 Paul Thomas <pault@gcc.gnu.org> PR fortran/29315 * gfortran.dg/aliasing_dummy_4.f90: New test. Added: trunk/gcc/testsuite/gfortran.dg/aliasing_dummy_4.f90 Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/trans-expr.c trunk/gcc/testsuite/ChangeLog
Subject: Bug 29315 Author: pault Date: Sun Nov 12 07:40:26 2006 New Revision: 118719 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=118719 Log: 2006-11-12 Paul Thomas <pault@gcc.gnu.org> PR fortran/29699 * trans-array.c (structure_alloc_comps): Detect pointers to arrays and use indirect reference to declaration. * resolve.c (resolve_fl_variable): Tidy up condition. (resolve_symbol): The same and only add initialization code if the symbol is referenced. * trans-decl.c (gfc_trans_deferred_vars): Call gfc_trans_ deferred_array before gfc_trans_auto_array_allocation. PR fortran/21730 * symbol.c (check_done): Remove. (gfc_add_attribute): Remove reference to check_done and remove the argument attr_intent. (gfc_add_allocatable, gfc_add_dimension, gfc_add_external, gfc_add_intrinsic, gfc_add_optional, gfc_add_pointer, gfc_add_cray_pointer, gfc_add_cray_pointee, gfc_add_result, gfc_add_target, gfc_add_in_common, gfc_add_elemental, gfc_add_pure, gfc_add_recursive, gfc_add_procedure, gfc_add_type): Remove references to check_done. * decl.c (attr_decl1): Eliminate third argument in call to gfc_add_attribute. * gfortran.h : Change prototype for gfc_add_attribute. PR fortran/29431 * trans-array.c (get_array_ctor_strlen): If we fall through to default, use a constant character length if it is available. PR fortran/29758 * check.c (gfc_check_reshape): Check that there are enough elements in the source array as to be able to fill an array defined by shape, when pad is absent. PR fortran/29315 * trans-expr.c (is_aliased_array): Treat correctly the case where the component is itself and array or array reference. 2006-11-12 Paul Thomas <pault@gcc.gnu.org> PR fortran/29699 * gfortran.dg/alloc_comp_auto_array_1.f90: New test. PR fortran/21730 * gfortran.dg/change_symbol_attributes_1.f90: New test. PR fortran/29431 * gfortran.dg/array_constructor_13.f90: New test. PR fortran/29758 * gfortran.dg/reshape_source_size_1.f90: New test. PR fortran/29315 * gfortran.dg/aliasing_dummy_4.f90: New test. Added: branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/aliasing_dummy_4.f90 branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/alloc_comp_auto_array_1.f90 branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/array_constructor_13.f90 branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/change_symbol_attributes_1.f90 branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/reshape_source_size_1.f90 Modified: branches/gcc-4_2-branch/gcc/fortran/ChangeLog branches/gcc-4_2-branch/gcc/fortran/check.c branches/gcc-4_2-branch/gcc/fortran/decl.c branches/gcc-4_2-branch/gcc/fortran/gfortran.h branches/gcc-4_2-branch/gcc/fortran/resolve.c branches/gcc-4_2-branch/gcc/fortran/symbol.c branches/gcc-4_2-branch/gcc/fortran/trans-array.c branches/gcc-4_2-branch/gcc/fortran/trans-decl.c branches/gcc-4_2-branch/gcc/fortran/trans-expr.c branches/gcc-4_2-branch/gcc/testsuite/ChangeLog
Fixed on trunk and 4.2. 4.1 will follow next weekend. Paul