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.