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

--- Comment #14 from anlauf at gcc dot gnu.org ---
(In reply to Gavin Salam from comment #13)
> While waiting for the fix to propagate to a release and various
> distributions, do you have a suggestion for a reliable workaround? The scope
> here is a public software package that needs C++/Fortran interfacing for
> core functionality.
> 
> I have freedom to adapt the call signature on C/C++ end. When gfortran
> defaults back to guessing an interface, can one predict what signature it
> will choose? For example, will it be a standard fortran 77 type signature,
> i.e. the signature one would obtain without any interface block?

One option is to use Steve's workaround from comment#2.  You would then
specify an "ordinary" interface for each external procedure.  Or if you
want an abstract interface like in comment#0, you would declare the
arguments without the VALUE attribute, pretty much F77-like, but you can
at least keep the INTENT for checking on the Fortran side.

Example:

module test_example
  use, intrinsic :: iso_c_binding, only: c_double, c_int
  implicit none

  ! Using call-by-reference (works for all gfortran <= 15.2)
  abstract interface
     function simple_interface(iarg1, arg2) bind(c) result(res)
       import c_double, c_int
       integer(c_int), intent(in) :: iarg1
       real(c_double), intent(in) :: arg2
       real(c_double) :: res
     end function simple_interface
  end interface

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

  ! Can have VALUE here for all gfortran versions
  interface
     function other_function(iarg1, arg2) bind(c,name="other_function")
result(res)
       import c_double, c_int
       integer(c_int), value, intent(in) :: iarg1
       real(c_double), value, intent(in) :: arg2
       real(c_double) :: res
     end function other_function
  end interface

contains
  subroutine test_example_interface
    implicit none
    integer(c_int) :: iarg1 = 2
    real(c_double) :: arg2  = 10.
    real(c_double) :: val1, val2

    val1 = simple_function(iarg1, arg2)
    val2 = simple_function(iarg1, arg2)
    if (val1 /= val2) stop 1

    val1 = other_function(iarg1, arg2)
    val2 = other_function(iarg1, arg2)
    if (val1 /= val2) stop 2

  end subroutine test_example_interface
end module test_example


This works with all gfortran versions, also with 15.2.

While preparing this example, I saw that gfortran does not generate the
proper C prototype for simple_function:

% gfc-16 interfaces.f90 -c -fc-prototypes |grep '^double '
double other_function (int iarg1, double arg2);
double simple_function ();

(Changing the abstract interface to a normal interface produces the right
prototype for the interface.)

I need to check whether we have that already in bugzilla.

Reply via email to