! { dg-do run { target c99_runtime } } ! { dg-additional-sources ISO_Fortran_binding_1.c } ! ! Test F2008 18.5: ISO_Fortran_binding.h functions. ! USE, INTRINSIC :: ISO_C_BINDING TYPE, BIND(C) :: T REAL(C_DOUBLE) :: X complex(C_DOUBLE_COMPLEX) :: Y END TYPE type :: mytype integer :: i integer :: j end type INTERFACE FUNCTION elemental_mult(a, b, c) BIND(C, NAME="elemental_mult_c") RESULT(err) USE, INTRINSIC :: ISO_C_BINDING INTEGER(C_INT) :: err type(*), DIMENSION(..) :: a, b, c END FUNCTION elemental_mult FUNCTION c_deallocate(a) BIND(C, NAME="deallocate_c") RESULT(err) USE, INTRINSIC :: ISO_C_BINDING INTEGER(C_INT) :: err INTEGER(C_INT), DIMENSION(..), allocatable :: a END FUNCTION c_deallocate FUNCTION c_allocate(a, lower, upper) BIND(C, NAME="allocate_c") RESULT(err) USE, INTRINSIC :: ISO_C_BINDING INTEGER(C_INT) :: err INTEGER(C_INT), DIMENSION(..), allocatable :: a integer(C_INTPTR_T), DIMENSION(15) :: lower, upper END FUNCTION c_allocate FUNCTION c_establish(a) BIND(C, NAME="establish_c") RESULT(err) USE, INTRINSIC :: ISO_C_BINDING import INTEGER(C_INT) :: err type (T), pointer, DIMENSION(..), intent(out) :: a END FUNCTION c_establish FUNCTION c_contiguous(a) BIND(C, NAME="contiguous_c") RESULT(err) USE, INTRINSIC :: ISO_C_BINDING INTEGER(C_INT) :: err type(*), DIMENSION(..) :: a END FUNCTION c_contiguous FUNCTION c_section(std_case, a, lower, strides) BIND(C, NAME="section_c") RESULT(ans) USE, INTRINSIC :: ISO_C_BINDING real(C_FLOAT) :: ans INTEGER(C_INT) :: std_case INTEGER(C_INT), dimension(15) :: lower INTEGER(C_INT), dimension(15) :: strides type(*), DIMENSION(..) :: a END FUNCTION c_section FUNCTION c_select_part(a) BIND(C, NAME="select_part_c") RESULT(ans) USE, INTRINSIC :: ISO_C_BINDING real(C_DOUBLE) :: ans type(*), DIMENSION(..) :: a END FUNCTION c_select_part FUNCTION c_setpointer(a, lbounds) BIND(C, NAME="setpointer_c") RESULT(err) USE, INTRINSIC :: ISO_C_BINDING INTEGER(C_INT) :: err INTEGER(C_INT), dimension(2) :: lbounds INTEGER(C_INT), DIMENSION(..), pointer :: a END FUNCTION c_setpointer FUNCTION c_assumed_size(a) BIND(C, NAME="assumed_size_c") RESULT(err) USE, INTRINSIC :: ISO_C_BINDING INTEGER(C_INT) :: err type(*), DIMENSION(..) :: a END FUNCTION c_assumed_size END INTERFACE integer, dimension(:,:), allocatable :: x, y, z integer, dimension(2,2) :: a, b, c integer, dimension(4,4) :: d integer :: i = 42, j, k integer(C_INTPTR_T), dimension(15) :: lower, upper real, dimension(10,10) :: arg type (mytype), dimension(2,2) :: der allocate (x, source = reshape ([4,3,2,1], [2,2])) allocate (y, source = reshape ([2,3,4,5], [2,2])) allocate (z, source = reshape ([0,0,0,0], [2,2])) call test_CFI_address call test_CFI_deallocate call test_CFI_allocate call test_CFI_establish call test_CFI_contiguous (a) call test_CFI_section (arg) call test_CFI_select_part call test_CFI_setpointer call test_assumed_size (a) contains subroutine test_CFI_address ! Basic test that CFI_desc_t can be passed and that CFI_address works if (elemental_mult (z, x, y) .ne. 0) stop 1 if (any (z .ne. reshape ([8,9,8,5], [2,2]))) stop 2 a = reshape ([4,3,2,1], [2,2]) b = reshape ([2,3,4,5], [2,2]) c = 0 ! Verify that components of arrays of derived types are OK. der%j = a ! Check that non-pointer/non-allocatable arguments are OK if (elemental_mult (c, der%j, b) .ne. 0) stop 3 if (any (c .ne. reshape ([8,9,8,5], [2,2]))) stop 4 ! Check array sections d = 0 d(4:2:-2, 1:3:2) = b if (elemental_mult (c, a, d(4:2:-2, 1:3:2)) .ne. 0) stop 5 if (any (c .ne. reshape ([8,9,8,5], [2,2]))) stop 6 ! If a scalar result is passed to 'elemental_mult' it is returned ! as the function result and then zeroed. This tests that scalars ! are correctly converted to CF_desc_t. if ((elemental_mult (i, a, b) .ne. 42) & .or. (i .ne. 0)) stop 7 deallocate (y,z) end subroutine test_CFI_address subroutine test_CFI_deallocate ! Test CFI_deallocate. if (c_deallocate (x) .ne. 0) stop 8 if (allocated (x)) stop 9 end subroutine test_CFI_deallocate subroutine test_CFI_allocate ! Test CFI_allocate. lower(1:2) = [2,2] upper(1:2) = [10,10] if (c_allocate (x, lower, upper) .ne. 0) stop 10 if (.not.allocated (x)) stop 11 if (any (lbound (x) .ne. lower(1:2))) stop 12 if (any (ubound (x) .ne. upper(1:2))) stop 13 ! Elements are filled by 'c_allocate' with the product of the fortran indices do j = lower(1) , upper(1) do k = lower(2) , upper(2) x(j,k) = x(j,k) - j * k end do end do if (any (x .ne. 0)) stop 14 deallocate (x) end subroutine test_CFI_allocate subroutine test_CFI_establish ! Test CFI_establish. type(T), pointer :: case2(:) => null() if (c_establish(case2) .ne. 0) stop 14 if (ubound(case2, 1) .ne. 9) stop 15 if (.not.associated(case2)) stop 16 if (sizeof(case2) .ne. 240) stop 17 if (int (sum (case2%x)) .ne. 55) stop 18 if (int (sum (imag (case2%y))) .ne. 110) stop 19 deallocate (case2) end subroutine test_CFI_establish subroutine test_CFI_contiguous (arg) integer, dimension (2,*) :: arg character(4), dimension(2) :: chr ! These are contiguous if (c_contiguous (arg) .ne. 1) stop 20 if (.not.allocated (x)) allocate (x(2, 2)) if (c_contiguous (x) .ne. 1) stop 22 deallocate (x) if (c_contiguous (chr) .ne. 1) stop 23 ! These are not contiguous if (c_contiguous (der%i) .eq. 1) stop 24 if (c_contiguous (arg(1:1,1:2)) .eq. 1) stop 25 if (c_contiguous (d(4:2:-2, 1:3:2)) .eq. 1) stop 26 if (c_contiguous (chr(:)(2:3)) .eq. 1) stop 27 end subroutine test_CFI_contiguous subroutine test_CFI_section (arg) real, dimension (100) :: a real, dimension (10,*) :: arg integer, dimension(15) :: lower, strides integer :: i ! Case (i) from F2018:18.5.5.7. a = [(real(i), i = 1, 100)] lower(1) = 10 strides(1) = 5 ! Remember, 'a' being non pointer, non-allocatable, the C descriptor ! lbounds are set to zero. if (int (sum(a(lower(1)+1::strides(1))) & - c_section(1, a, lower, strides)) .ne. 0) stop 28 ! Case (ii) from F2018:18.5.5.7. arg(:,1:10) = reshape ([(real(i), i = 1, 100)], [10,10]) lower(1) = 1 lower(2) = 5 strides(1) = 1 strides(2) = 0 if (int (sum(arg(:,5)) & - c_section (2, arg, lower, strides)) .ne. 0) stop 29 end subroutine test_CFI_section subroutine test_CFI_select_part ! Test the example from F2018:18.5.5.8. ! Modify to take rank 2 and sum the section type_t(5, :)%y%im ! Note that sum_z_5 = sum (type_t(5, :)%y%im) is broken on Darwin. ! type (t), dimension(10, 10) :: type_t real(kind(type_t%x)) :: v, sum_z_5 = 0.0 complex(kind(type_t%y)) :: z ! Set the array 'type_t'. do j = 1, 10 do k = 1, 10 v = dble (j * k) z = cmplx (2 * v, 3 * v) type_t(j, k) = t (v, z) if (j .eq. 5) sum_z_5 = sum_z_5 + imag (z) end do end do ! Now do the test. if (int (c_select_part (type_t) - sum_z_5) .ne. 0) stop 30 end subroutine test_CFI_select_part subroutine test_CFI_setpointer ! Test the example from F2018:18.5.5.9. integer, dimension(:,:), pointer :: ptr => NULL () integer, dimension(2,2), target :: tgt integer, dimension(2) :: lbounds = [-1, -2] ! The C-function resets the lbounds ptr(1:, 1:) => tgt if (c_setpointer (ptr, lbounds) .ne. 0) stop 31 if (any (lbound(ptr) .ne. lbounds)) stop 32 end subroutine test_CFI_setpointer subroutine test_assumed_size (arg) integer, dimension(2,*) :: arg ! The C-function checks contiguousness and that extent[1] == -1. if (c_assumed_size (arg) .ne. 0) stop 33 end subroutine end