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

            Bug ID: 122206
           Summary: abstract interface, passing arguments by value to C
           Product: gcc
           Version: 15.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: fortran
          Assignee: unassigned at gcc dot gnu.org
          Reporter: gavin.salam at physics dot ox.ac.uk
  Target Milestone: ---

Passing arguments by value to C/C++ with an abstract interface: in a second
call to a given C++ routine, the arguments that are passed appear to be
corrupted.

Here's the Fortran

```
module test_example
  use, intrinsic :: iso_c_binding
  implicit none


  integer, parameter  :: dp = kind(1.0d0)

  abstract interface
    function simple_interface(iarg1, arg2, arg3, arg4) bind(C) result(res)
      import c_double, c_int
      integer(c_int), value, intent(in) :: iarg1
      real(c_double), value, intent(in) :: arg2, arg3, arg4
      real(c_double) :: res
    end function
  end interface 

  procedure(simple_interface),     bind(C, name="simple_function"  ) ::
simple_function    

contains
  subroutine test_example_interface
    implicit none
    real(c_double) :: arg2, arg3, arg4
    character(len=*), parameter :: red=char(27)//"[31m", reset=char(27)//"[0m"
    integer(c_int) :: iarg1
    real(c_double) :: val1, val2

    ! Example values for testing
    arg2    = 10._dp
    arg3    = 3.0_dp
    arg4     = 0.1_dp

    ! request coefficients relative to min_power (0 -> first non-zero term)
    iarg1 = 2
    val1 = simple_function(iarg1, arg2, arg3, arg4)
    val2 = simple_function(iarg1, arg2, arg3, arg4)
    if (val1 /= val2) then
      print *, red//"mismatch between val1 and val2: ", val1, "/=", val2,reset
    end if

  end subroutine test_example_interface    
end module test_example

program tester
  use test_example
  implicit none

  call test_example_interface()

end program tester
```

and C++
```c++
#include <iostream>

extern "C" {
double simple_function(int iarg1, double arg2, double arg3, double arg4)
{
  // Debug: print incoming arguments and the available range
  std::cerr << "[debug] simple_function called: iarg1=" << iarg1
            << " arg2=" << arg2 << " arg3=" << arg3 << " arg4=" << arg4 <<
std::endl;
  double val = static_cast<double>(iarg1) + arg2 + arg3 + arg4;
  std::cerr << "[debug] simple_function returning: " << val << std::endl;
  return(val);
}
}
```

The expected output is:
```
[debug] simple_function called: iarg1=2 arg2=10 arg3=3 arg4=0.1
[debug] simple_function returning: 15.1
[debug] simple_function called: iarg1=2 arg2=10 arg3=3 arg4=0.1
[debug] simple_function returning: 15.1
```

The actual output is
```
[debug] simple_function called: iarg1=2 arg2=10 arg3=3 arg4=0.1
[debug] simple_function returning: 15.1
[debug] simple_function called: iarg1=-362132780 arg2=15.1 arg3=1.38524e-309
arg4=8.25667e-317
[debug] simple_function returning: -3.62133e+08
 mismatch between val1 and val2:    15.100000000000000      /= 
-362132764.89999998
```
One sees that the arguments in the second call to simple_function are corrupted
(e.g. arg2 is -- incorrectly -- the return value of the first call).

We see this in 15.1 on MacOS 15.7.1 (with clang for the c++), on intel linux
with gfortran+gcc 11.4.0, on aarch64 linux (6.10.14-linuxkit) with gfortran+gcc
15.2.0.

To help with testing, the files are also at
https://github.com/gavinsalam/gfortran-15.2-arg-issue/ 

Report developed with Arnd Behring.

Reply via email to