Bug 70739 - VALUE attribute interpretation in a non-interoperable procedure
Summary: VALUE attribute interpretation in a non-interoperable procedure
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 6.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-04-20 13:56 UTC by zmi
Modified: 2019-03-09 16:41 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2016-04-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description zmi 2016-04-20 13:56:16 UTC
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.
Comment 1 Dominique d'Humieres 2016-04-22 14:11:26 UTC
> 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.

This interpretation looks very weird. I had a quick look to the standard, but did not find anything to support it. Would it be possible to have an exact pointer to where it is stated?
Comment 2 zmi 2016-05-12 15:33:39 UTC
This was also my wish but I couldn't find it too and assume now as an Intel's interpretation of standard. Would be interesting to see if such interpretation confirmed by another vendors (I don't have access to actual compilers from Cray, IBM etc.)
Comment 3 janus 2019-03-09 16:41:45 UTC
(In reply to zmi from comment #0)
> I see difference between ifort and gfortran interpretation of a
> non-interoperable procedure (without BIND(C)) with VALUE attribute in dummy
> argument. 

IMHO using a non-interoperable procedure to interface with C code is basically a user error. You can do it, but the result will be highly compiler-dependent (as you saw).

If you want mixed C/Fortran code to be compiler-independent, just use BIND(C)!

I'll close this PR as invalid.