Fortran bind(C) bounds on arrays

Fortran bind(C) allows Fortran to call C functions and vice versa. However, Fortran arrays are one-based by default, while C arrays are zero-based. This can lead to confusion when passing arrays between Fortran and C. Adding to the confusion is multiple GCC Gfortran versions have known bugs that were not fixed as of their final release.

Specifically, the versions of Gfortran known to be working correctly are Gfortran ≤ 8.5 and Gfortran ≥ 12. Known broken GFortran versions are 9.x, 10.x, 11.x.

We show this by example:

program test_bounds
use iso_fortran_env, only : error_unit
implicit none

real, allocatable :: a(:)
integer :: L1,L2, U1,U2
allocate(a(1:2))

L1 = lbound(a,1)
U1 = ubound(a,1)

call c_bounder(a)

L2 = lbound(a,1)
U2 = ubound(a,1)

if (L1 /= L2 .or. U1 /= U2) then
  write(error_unit, '(a,2i2,a,2i2)') 'FAIL: bounds changed before/after lower:', L1,L2, " upper: ", U1,U2
  error stop
endif

print '(a)', "bounds check OK"

contains

subroutine c_bounder(a) bind(c)
real,  intent(inout) :: a(:)
end subroutine c_bounder

end program