[Bug fortran/70739] New: VALUE attribute interpretation in a non-interoperable procedure

zmi007 at gmail dot com gcc-bugzilla@gcc.gnu.org
Wed Apr 20 13:56:00 GMT 2016


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70739

            Bug ID: 70739
           Summary: VALUE attribute interpretation in a non-interoperable
                    procedure
           Product: gcc
           Version: 6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: zmi007 at gmail dot com
  Target Milestone: ---

I see difference between ifort and gfortran interpretation of a
non-interoperable procedure (without BIND(C)) with VALUE attribute in dummy
argument. 

Actually gfortran gives (intuitively) expected result compared to ifort, but
this is something that is difficult to find out in standard to confirm. 
See details here 
https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/610807

(example)

/* test.c */
#include <stdint.h>
#include <stddef.h>
#include <stdio.h>

int32_t test (char* key, size_t len)
{
  int32_t hash = 666;
  printf("c key %s\n", key);
  printf("c len %zu\n", len); // expected 2
  return hash;
}


! test_main.f90

!-----------------------------------------------------------------------
!Module interface_module
!-----------------------------------------------------------------------
module interface_module
   implicit none

   interface
      function test(key, length) result(hash) bind(c, name="test")
         use iso_c_binding
         character(kind=c_char),dimension(*) :: key
         integer(c_size_t), value :: length
         integer(c_int32_t) :: hash
      end function test
   end interface

   abstract interface
      function function_hash_template(key, length) ! <===== missing  bind(c)
here !!!
         use iso_c_binding
         character(kind=c_char),dimension(*) :: key
         integer(c_size_t), value :: length
         integer(c_int32_t) :: function_hash_template
      end function function_hash_template
   end interface

contains

   !-----------------------------------------------------------------------
   !Function hash_wrap
   !-----------------------------------------------------------------------
   function  hash_wrap(text, fun) result(hash)
      use iso_c_binding
      implicit none
      character (len=*), target, intent(in) :: text
      procedure(function_hash_template), pointer :: fun
      integer(c_int32_t) :: hash
      character(kind=c_char), dimension(len_trim(text)+1) :: text_c
      integer(c_size_t) :: length

      text_c = f_to_c_string(text) ! convert to c string for compatibility

      length = len_trim(text) + 1
      write(*,*) "hash_wrap, length = ", length
      hash = fun(text_c,length)
   end function hash_wrap

   !-----------------------------------------------------------------------
   !Function f_to_c_string
   !-----------------------------------------------------------------------
   pure function f_to_c_string (f_string) result (c_string)
      use, intrinsic :: iso_c_binding, only: c_char, c_null_char
      implicit none
      character(len=*), intent(in) :: f_string
      character(len=1,kind=c_char), dimension(len_trim(f_string)+1) :: c_string
      integer :: n, i
      n = len_trim(f_string)
      do i = 1, n
         c_string(i) = f_string(i:i)
      end do
      c_string(n + 1) = c_null_char
   end function f_to_c_string

end module interface_module

!-----------------------------------------------------------------------
!Main program test_main
!-----------------------------------------------------------------------
program    test_main
   use interface_module
   implicit none

   write(*,*) test_wrap("1")

   contains

   !-----------------------------------------------------------------------
   !Function test_wrap
   !-----------------------------------------------------------------------
   function test_wrap(text) result(hash)
      use iso_fortran_env
      implicit none
      character(len=*),intent(in) :: text
      integer(int32) :: hash
      procedure(function_hash_template), pointer :: fun
      fun => test
      hash = int(hash_wrap(text, fun), int32)
   end function test_wrap

end program test_main



Results:

gfortran:
gcc version 5.3.1 20160301 [gcc-5-branch revision 233849] (SUSE Linux)
gcc version 6.0.0 20160324 (experimental) [trunk revision 234449] (SUSE Linux) 
 hash_wrap, length =                     2
c key 1
c len 2
         666

ifort:
ifort version 16.0.2
 hash_wrap, length =                      2
c key 1
c len 140730916351912
         666

Note the difference in len argument 

Steve Lionel's  comment to discuss here:
- [...]For a non-interoperable procedure, one without BIND(C), VALUE causes a
writable, temporary copy of the argument to be passed by reference. So in zmi's
case, the call through the procedure pointer, defined with an interface that
did not have BIND(C), caused the address of a copy of "length" to be passed.


More information about the Gcc-bugs mailing list