Off-by-one-error in array access when using array slice in BIND(C) subroutine

Once again something I believe is a compiler bug from me… Take the following example:

PROGRAM main
    IMPLICIT NONE

    INTEGER :: my_array(10)
    my_array = 0

    WRITE(*, *) "CALL check_array(my_array(2:5))"
    CALL check_array(my_array(2:5))
    WRITE(*, *) "my_array: ", my_array
    WRITE(*, *) ""

    WRITE(*, *) "CALL check_array(my_array(8:9))"
    CALL check_array(my_array(8:9))
    WRITE(*, *) "my_array: ", my_array
    WRITE(*, *) ""

    WRITE(*, *) "CALL check_array(my_array(:))"
    CALL check_array(my_array(:))
    WRITE(*, *) "my_array: ", my_array
    WRITE(*, *) ""

    WRITE(*, *) "CALL check_array(my_array)"
    CALL check_array(my_array)
    WRITE(*, *) "my_array: ", my_array
CONTAINS
    SUBROUTINE check_array(res) BIND(C)
        INTEGER, INTENT(out) :: res(:)
        INTEGER :: i

        WRITE(*, *) "SIZE(res): ", SIZE(res)
        DO i = 1, SIZE(res)
            res(i) = i
        END DO
    END SUBROUTINE check_array
END PROGRAM main

With gfortran, ifx, ifort and nagfor I get results I expect:

 CALL check_array(my_array(2:5))
 SIZE(res):  4
 my_array:  0 1 2 3 4 0 0 0 0 0
 
 CALL check_array(my_array(8:9))
 SIZE(res):  2
 my_array:  0 1 2 3 4 0 0 1 2 0
 
 CALL check_array(my_array(:))
 SIZE(res):  10
 my_array:  1 2 3 4 5 6 7 8 9 10
 
 CALL check_array(my_array)
 SIZE(res):  10
 my_array:  1 2 3 4 5 6 7 8 9 10

With nvfortran version 24.7 I get:

 CALL check_array(my_array(2:5))
 SIZE(res):             4
 my_array:             0            0            1            2            3 
            4            0            0            0            0
 
 CALL check_array(my_array(8:9))
 SIZE(res):             2
 my_array:             0            0            1            2            3 
            4            0            0            1            2
 
 CALL check_array(my_array(:))
 SIZE(res):            10
 my_array:             0            1            2            3            4 
            5            6            7            8            9
 
 CALL check_array(my_array)
 SIZE(res):            10
 my_array:             1            2            3            4            5 
            6            7            8            9           10

I.e. the result after the three first calls to check_array, when array slices are used, is wrong. check_array “see” the right array size, but the results are stored in a off-by-one position (i.e. shifted one location to the right)!! I cannot rule out a possibility for an invalid memory access in this example (where is the last number 10 stored in the third example, in a memory location outside the array??? This could trigger a segfault).

Also, when the INTENT(out) is changed to INTENT(inout) in check_array it seems to work. However, check_array completely define the entire output independent on any initial values in the array, so I believe INTENT(out) is correct wrt. the Fortran language and allowed here (it is a great workaround and temporary solution, though!!).

Please note the BIND(C) on the subroutine check_array. When this is taken away everything also works. However, my application is the usage of the CFI_cdesc_t array descriptors and BIND(C) routines/interfaces, therefore this is important.

Hi Hakostra! I’ll take a look at this along with your other two issues and get you an engineering report number if I’m able to determine it’s actually a compiler issue (which it, like the other two, appear to be).

Hey Hakostra - I have reported this issue to engineering as TPR#36128. Thank you for bringing it to our attention! As always, please let us know if you run into any other issues. I’ll let you know about a fix when engineering gets to the issue.

Cheers,

Seth.

One of our engineers is looking at this and has suggested you might be able to use the compiler flag “-Mnocfi” (from ‘nvfortran --help’, this “Disables Fortran 2018 CFI Descriptor support”. However, in a larger code where you have a lot of C and Fortran interoperability, I imagine this could possibly break things, but I’m not sure of the full effects of the flag in a larger use case.