Bug 40962 - Conversion problem for f-allocatable -> cptr -> fptr -> f-allocatable
Summary: Conversion problem for f-allocatable -> cptr -> fptr -> f-allocatable
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Thomas Koenig
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2009-08-04 14:23 UTC by Juergen Reuter
Modified: 2009-09-12 16:17 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.5.0 4.4.0 4.3.2
Last reconfirmed: 2009-08-20 17:16:12


Attachments
test program for the bug report (494 bytes, text/x-fortran)
2009-08-04 14:25 UTC, Juergen Reuter
Details
iso_varying_string.f90 needed for the example (6.88 KB, text/x-fortran)
2009-08-04 14:25 UTC, Juergen Reuter
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Juergen Reuter 2009-08-04 14:23:44 UTC
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
--------------------------------------------------
Comment 1 Juergen Reuter 2009-08-04 14:25:12 UTC
Created attachment 18297 [details]
test program for the bug report
Comment 2 Juergen Reuter 2009-08-04 14:25:47 UTC
Created attachment 18298 [details]
iso_varying_string.f90 needed for the example
Comment 3 Tobias Burnus 2009-08-04 16:09:45 UTC
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
Comment 4 Tobias Burnus 2009-08-17 21:41:19 UTC
Another report - presumably the same problem:
http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/b184bd431c8dd3da#
Comment 5 Thomas Koenig 2009-08-17 22:12:23 UTC
I'll look at this for a bit.
Comment 6 Thomas Koenig 2009-08-20 17:16:12 UTC
I have a patch.
Comment 7 Thomas Koenig 2009-08-20 20:16:39 UTC
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

Comment 8 Thomas Koenig 2009-08-20 20:42:55 UTC
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

Comment 9 Thomas Koenig 2009-08-20 20:56:00 UTC
Fixed on trunk and 4.4, closing.

If anybody wants to backport the fix to 4.3, be my guest :-)
Comment 10 Martin 2009-09-12 13:43:58 UTC
(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.
Comment 11 Thomas Koenig 2009-09-12 14:00:05 UTC
(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?
Comment 12 Martin 2009-09-12 16:17:23 UTC
(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.