flang-compiler/flang

The 'contiguous' attribute does not enforce an array passed to a subroutine to be contiguous

pawosm-arm opened this issue · 0 comments

In a simple subroutine like that:

    subroutine print_array(arr, m, n, h)
        use iso_c_binding
        implicit none
        integer(kind=4), target, contiguous, intent(in) :: arr(:,:)
        integer, intent(in) :: m, n, h
        integer :: err

        interface
          function print_array_c(data, m, n) result(error_code) BIND(c)
            import c_int, c_float, c_double, c_ptr
            integer(c_int), VALUE, intent(in) :: m
            integer(c_int), VALUE, intent(in) :: n
            type(c_ptr),    VALUE, intent(in) :: data
            integer(c_int)                    :: error_code
          end function print_array_c
        end interface

        err = print_array_c(c_loc(arr), m-h, n-h)
    end subroutine print_array

The array passed as the first parameter is expected to be contiguous. When passing entire arrays, this works. But when a piece of array is passed, a new array of the sliced size is not being created, what is passed in the memory is still of the size of the original array, and from the sliced portion point of view, it is not contiguous, which is clearly visible in the called C code (it doesn't have to be C code, similar experiment using c_loc and transfer can be replicated in Fortran)

  integer(kind=4), allocatable :: big_array(:, :)
  ...
  allocate(big_array(n, m))
  ...
  call print_array(big_array(1:n-h,1:m-h), m, n, h)
int print_array_c(const void *data, int m, int n)
{
    const int *data_i = (const int *)data;
    for(int i = 0; i < m; i++)
    {
        for(int j = 0; j < n; j++)
            printf("%d ", data_i[i * n + j]);
        printf("\n");
    }
    return 0;
}