The following test code below (which works with the NAG 5.2 Fortran Compiler) seems to choke over the conversion f-allocatable -> cptr -> fptr -> f-allocatable. With NAG the output should be: -------------------------------------------------- nagfor tab3.f90 -o tab3 && ./tab3 NAG Fortran Compiler Release 5.2(686) [NAG Fortran Compiler normal termination] In: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 Tmp: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 Out: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 ------------------------------------------------- For gfortran 4.5.0 the result is: In: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 Tmp: 1 2 3 -1 -2 -3 -1 -2 -3 -4 -5 -6 Out: 1 2 3 -1 -2 -3 -4 -5 -6 0 0 0 while for gfortran 4.3.2 the result is: ------------------------------------------------- In: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 Tmp: 1 2 3 -1 -2 -3 -1 -2 -3 -4 -5 -6 Out: 1 2 3 -1 -2 -3 -4 -5 -6 ** ** 0 It looks as if the order of indices gets confused by gfortran in changing the corresponding pointers. According to the F2003 Handbook this code should be allowed. TEST PROGRAM: ---------------------------------------------------------- program main use iso_c_binding implicit none character(*), parameter :: fmt = "(A,40(1x,I2))" integer, parameter :: n1 = 2 integer, parameter :: n2 = 3 integer, parameter :: n3 = 2 integer, dimension(2), parameter :: shape2 = (/ n1, n2 /) integer, dimension(3), parameter :: shape3 = (/ n1, n2, n3 /) integer, dimension(n1, n2), parameter :: & c0001 = reshape ( (/ 1, 2, 3, 4, 5, 6 /), shape2) integer, dimension(n1, n2), parameter :: & c0002 = reshape ( (/ -1,-2, -3,-4, -5,-6 /), shape2) integer, dimension(n1, n2, n3), parameter :: & table_in = reshape ( (/ c0001, c0002 /), shape3) integer, dimension(:,:,:), allocatable, target :: table_out print fmt, "In: ", table_in ! Allocate table_out with shape=shape3 allocate (table_out (n1, n2, n3)) ! Set table_out via a C pointer call set_table (c_loc (table_out)) print fmt, "Out:", table_out contains subroutine set_table (cptr) type(c_ptr), intent(in) :: cptr integer, dimension(:,:,:), pointer :: table_tmp ! This should make table_tmp an alias to table_out call c_f_pointer (cptr, table_tmp, shape3) ! Now set the value of table_tmp table_tmp = table_in print fmt, "Tmp:", table_tmp end subroutine set_table end program main --------------------------------------------------
Created attachment 18297 [details] test program for the bug report
Created attachment 18298 [details] iso_varying_string.f90 needed for the example
Thomas, as you know a bit about the array descriptor, can you have a look? The problem seems to be in libgfortran/intrinsics/iso_c_binding.c's c_f_pointer* Simplified test case: One: 1 2 -1 -2 Two: 1 2 2 -1 ^^^^^ The dump is trival: D.1581 = (void *) &table; D.1582 = D.1581; set_table (&D.1582); and c_f_pointer_i4 (*cptr, &table_tmp, &parm.1); Thus the issue must be in c_f_pointer_i4 program main use iso_c_binding, only: c_ptr, c_loc, c_f_pointer implicit none integer, dimension(2,1,2), target :: table table = reshape ( (/ 1,2,-1,-2/), (/2,1,2/)) ! print '(a,12i3)', "One:", table call set_table (c_loc (table)) contains subroutine set_table (cptr) type(c_ptr), intent(in) :: cptr integer, dimension(:,:,:), pointer :: table_tmp call c_f_pointer (cptr, table_tmp, (/2,1,2/)) ! print '(a,12i3)', "Two:", table_tmp end subroutine set_table end program main
Another report - presumably the same problem: http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/b184bd431c8dd3da#
I'll look at this for a bit.
I have a patch.
Subject: Bug 40962 Author: tkoenig Date: Thu Aug 20 20:16:15 2009 New Revision: 150974 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=150974 Log: 2009-08-20 Thomas Koenig <tkoenig@gcc.gnu.org> PR libfortran/40962 * iso_c_binding.c (c_f_pointer_u0): Multiply stride by previous stride. 2009-08-20 Thomas Koenig <tkoenig@gcc.gnu.org> PR libfortran/40962 * c_f_pointer_tests_4.f90: New test. Added: trunk/gcc/testsuite/gfortran.dg/c_f_pointer_tests_4.f90 Modified: trunk/gcc/testsuite/ChangeLog trunk/libgfortran/ChangeLog trunk/libgfortran/intrinsics/iso_c_binding.c
Subject: Bug 40962 Author: tkoenig Date: Thu Aug 20 20:42:38 2009 New Revision: 150975 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=150975 Log: 2009-08-20 Thomas Koenig <tkoenig@gcc.gnu.org> PR libfortran/40962 * iso_c_binding.c (c_f_pointer_u0): Multiply stride by previous stride. 2009-08-20 Thomas Koenig <tkoenig@gcc.gnu.org> PR libfortran/40962 * c_f_pointer_tests_4.f90: New test. Added: branches/gcc-4_4-branch/gcc/testsuite/gfortran.dg/c_f_pointer_tests_4.f90 Modified: branches/gcc-4_4-branch/gcc/testsuite/ChangeLog branches/gcc-4_4-branch/libgfortran/ChangeLog branches/gcc-4_4-branch/libgfortran/intrinsics/iso_c_binding.c
Fixed on trunk and 4.4, closing. If anybody wants to backport the fix to 4.3, be my guest :-)
(In reply to comment #8) > Subject: Bug 40962 > > Author: tkoenig > Date: Thu Aug 20 20:42:38 2009 > New Revision: 150975 > > URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=150975 > Log: > 2009-08-20 Thomas Koenig <tkoenig@gcc.gnu.org> > > PR libfortran/40962 > * iso_c_binding.c (c_f_pointer_u0): Multiply stride by > previous stride. > > 2009-08-20 Thomas Koenig <tkoenig@gcc.gnu.org> > > PR libfortran/40962 > * c_f_pointer_tests_4.f90: New test. > > > Added: > branches/gcc-4_4-branch/gcc/testsuite/gfortran.dg/c_f_pointer_tests_4.f90 > Modified: > branches/gcc-4_4-branch/gcc/testsuite/ChangeLog > branches/gcc-4_4-branch/libgfortran/ChangeLog > branches/gcc-4_4-branch/libgfortran/intrinsics/iso_c_binding.c > It doesn't work if the 3rd dimension is > 2 The test case only shows the array shape. It should fill the sample arrays and compares.
(In reply to comment #10) > It doesn't work if the 3rd dimension is > 2 > The test case only shows the array shape. > It should fill the sample arrays and > compares. The test case is: ! { dg-do run } program main use iso_c_binding, only: c_ptr, c_loc, c_f_pointer implicit none integer, dimension(2,1,2), target :: table table = reshape ( (/ 1,2,-1,-2/), (/2,1,2/)) call set_table (c_loc (table)) contains subroutine set_table (cptr) type(c_ptr), intent(in) :: cptr integer, dimension(:,:,:), pointer :: table_tmp call c_f_pointer (cptr, table_tmp, (/2,1,2/)) if (any(table_tmp /= table)) call abort ! ^^^^^^^^^^^^^^^^^^^^^^ ! comparison happens here end subroutine set_table end program main Output for the original test case is: $ gfortran original.f90 $ ./a.out In: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 Tmp: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 Out: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 Do you have a failing test case? If so, please post it. Are you using the wrong libraries, possibly?
(In reply to comment #11) > (In reply to comment #10) > > > It doesn't work if the 3rd dimension is > 2 > > The test case only shows the array shape. > > It should fill the sample arrays and > > compares. > > The test case is: > > ! { dg-do run } > program main > use iso_c_binding, only: c_ptr, c_loc, c_f_pointer > implicit none > integer, dimension(2,1,2), target :: table > table = reshape ( (/ 1,2,-1,-2/), (/2,1,2/)) > call set_table (c_loc (table)) > contains > subroutine set_table (cptr) > type(c_ptr), intent(in) :: cptr > integer, dimension(:,:,:), pointer :: table_tmp > call c_f_pointer (cptr, table_tmp, (/2,1,2/)) > if (any(table_tmp /= table)) call abort > ! ^^^^^^^^^^^^^^^^^^^^^^ > ! comparison happens here > end subroutine set_table > end program main > > Output for the original test case is: > > $ gfortran original.f90 > $ ./a.out > In: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 > Tmp: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 > Out: 1 2 3 4 5 6 -1 -2 -3 -4 -5 -6 > > > Do you have a failing test case? If so, please > post it. Are you using the wrong libraries, possibly? > I was using the wrong libraries. Thank you.