Fortran 2008 and 2018 specify that dummy argument attribute “contiguous” shall make the actual argument contiguous, for pointer, assumed shape arrays (but not coarrays). Here are minimal examples that work on GCC >= 9, Intel oneAPI, etc. but not Nvidia HPC 23.1. The examples error stop with Nvidia HPC SDK.
The compiler should use temporary arrays with copy-in, copy-out to make a contiguous array when contiguous attribute is given.
program contiguous_pointer
implicit none
integer, pointer :: p(:)
integer, target :: t(6) = [1, 2, 3, 4, 5, 6]
p => t(::2)
call psub(p)
print *, "OK: contiguous_pointer"
contains
pure subroutine psub(a)
integer, contiguous, intent(in) :: a(:)
if(.not.is_contiguous(a)) error stop "a was not made contiguous as per Fortran standard"
end subroutine
end program
program contiguous_assumed_shape
implicit none
integer, parameter :: N = 10
real, allocatable :: x(:,:)
allocate(x(2,N))
call asub(x(:, ::2))
contains
pure subroutine asub(x)
real, contiguous, intent(inout) :: x(:,:)
if (.not. is_contiguous(x)) error stop "should be contiguous per Fortran 2008 standard"
end subroutine
end program
Thanks mhirsch. I confirm with engineering that this was an oversight in our interpretation of the standard. I’ve filed a problem report, TPR #33110.
As a work around for our compiler, you can drop the contiguous attribute on the dummy argument and nvfortran will generate the desired copy-in/copy-out in this case
Example:
% cat test1a.F90
program contiguous_pointer
implicit none
integer, pointer :: p(:)
integer, target :: t(6) = [1, 2, 3, 4, 5, 6]
p => t(::2)
call psub(p)
print *, "OK: contiguous_pointer"
contains
pure subroutine psub(a)
#ifndef __NVCOMPILER
integer, contiguous, intent(in) :: a(:)
#else
integer, intent(in) :: a(:)
#endif
if(.not.is_contiguous(a)) error stop "a was not made contiguous as per Fortran standard"
end subroutine
end program
% nvfortran test1a.F90 ; a.out
OK: contiguous_pointer
% nvfortran test1.f90 -V23.3 ; a.out
ERROR STOP a was not made contiguous as per Fortran standard
% nvfortran test1.f90 -V23.5 ; a.out
OK: contiguous_pointer
%
% nvfortran test2.f90 -V23.3 ; a.out
ERROR STOP should be contiguous per Fortran 2008 standard
% nvfortran test2.f90 -V23.5 ; a.out
%