For anyone that is curious about the current portability of C_F_POINTER()
and SELECT_RANK() and the proposed pointer rank remapping extension for
Fortran f202y:
Using the compilers available on Compiler Explorer AOCC flang, gfortran,
lfortran, ifx, nvfortran and flang all worked with C_F_POINTER(). AOCC
flang, lfortran, and nvfortran failed with SELECT RANK however; and only
two supported the proposed pointer rank remapping extension for f202y.
gfortran requires a special flag to evoke the extension – perhaps other
compilers do as well(?). Note there is a good chance a more recent
version of lfortran works with the SELECT RANK method.
I thought I had used C_F_POINTER() and SELECT RANK according to the standard both here and GitHub - urbanjost/M_flatten: return a rank one array pointer to a scalar or array of any rank · GitHub but now I need to revisit that.
Fortran source
click to see more...
module m_cast
use,intrinsic :: iso_fortran_env, only : real32, real64, int32, int64
use, intrinsic :: iso_c_binding
implicit none
private
public :: singleton ! promote
interface singleton
module procedure enlist_int32
module procedure enlist_int64
module procedure enlist_real32
module procedure enlist_real64
end interface singleton
contains
function enlist_int32(value) result(p_arr)
integer(kind=int32),target :: value
integer(kind=int32),pointer :: p_arr(:)
call c_f_pointer( c_loc(value), p_arr, [1] )
end function enlist_int32
function enlist_int64(value) result(p_arr)
integer(kind=int64),target :: value
integer(kind=int64),pointer :: p_arr(:)
call c_f_pointer( c_loc(value), p_arr, [1] )
end function enlist_int64
function enlist_real32(value) result(p_arr)
real(kind=real32),target :: value
real(kind=real32),pointer :: p_arr(:)
call c_f_pointer( c_loc(value), p_arr, [1] )
end function enlist_real32
function enlist_real64(value) result(p_arr)
real(kind=real64),target :: value
real(kind=real64),pointer :: p_arr(:)
call c_f_pointer( c_loc(value), p_arr, [1] )
end function enlist_real64
end module m_cast
program testit
use M_cast, only : lift=> singleton
real,allocatable :: a(:), b(:), c(:)
real :: ra, rb, rc
character(len=*),parameter :: nl=new_line('A'), g='(*(g0,1x))'
! call normally
A=[1000,2000,3000,4000]
B=a*10
C=a*100
call arrs(a,b,c)
write(*,g) a, nl, b, nl, c
! pass scalar to array arguments using C_F_POINTER()
ra=1000
rb=2000
rc=3000
call arrs(lift(ra),lift(rb),lift(rc))
write(*,g)ra, rb, rc
! Try SELECT_RANK(): The hard way for the called procedure, the easy way for the caller
ra=10;rb=20;a(:)=30;b(:)=40
call either(ra,b)
call either(a,rb)
write(*,g)ra, rb, a, b
contains
subroutine arrs(a,b,c)
real,dimension(:) :: a, b, c
a=a+1
b=b+10
c=c+100
end subroutine arrs
#ifdef MAPPED
subroutine either( a, b)
! compile with : gfortran xx.f90 -std=f202y -DMAPPED
! This technique is known as pointer rank remapping (introduced in
! Fortran 2003 and expanded in Fortran 2008).
! requires the multi-dimensional target array is simply contiguous.
real,target, contiguous :: a(..), b(..)
integer :: i, n
real,pointer :: p_a(:), p_b(:)
! NOTE: The assumed rank target is an experimental F202y feature.
! NOTE: Explicit bounds are required. That is, you must
! specify the explicit upper and lower bounds
! on the left-hand side of the pointer assignment.
n=size(b)
p_b(1:n)=>b
n=size(a)
p_a(1:n)=>a
do i=1,size(p_b)
p_b(i) = p_b(i)*2
enddo
do i=1,size(p_a)
p_a(i) = p_a(i)*3
enddo
end subroutine either
#else
subroutine either( a, b)
real,target, contiguous :: a(..), b(..)
integer :: i
real,pointer :: p_a(:), p_b(:)
select rank (b)
rank (0); p_b=>lift(b)
rank (1); p_b=>b
rank (*); print *, 'assumed size is unsupported'; stop 1
rank default; print *, 'unsupported rank'; stop 2
end select
select rank (a)
rank (0); p_a=>lift(a)
rank (1); p_a=>a
rank (*); print *, 'assumed size is unsupported'; stop 1
rank default; print *, 'unsupported rank'; stop 2
end select
do i=1,size(p_b)
p_b(i) = p_b(i)*2
enddo
do i=1,size(p_a)
p_a(i) = p_a(i)*3
enddo
end subroutine either
#endif
end program testit
Everyone passed using singleton():
click to see more...
+aoccflang520 : 2 1001.000 2001.000 3001.000 4001.000
+aoccflang520 : 3 10010.00 20010.00 30010.00 40010.00
+aoccflang520 : 4 100100.0 200100.0 300100.0 400100.0
+aoccflang520 : 5 1001.000 2010.000 3100.000
+flangtrunk : 2 1001. 2001. 3001. 4001.
+flangtrunk : 3 10010. 20010. 30010. 40010.
+flangtrunk : 4 100100. 200100. 300100. 400100.
+flangtrunk : 5 1001. 2010. 3100.
+ifxlatest : 2 1001.000 2001.000 3001.000 4001.000
+ifxlatest : 3 10010.00 20010.00 30010.00 40010.00
+ifxlatest : 4 100100.0 200100.0 300100.0 400100.0
+ifxlatest : 5 1001.000 2010.000 3100.000
+lfortranlatest : 2 1001.00000 2001.00000 3001.00000 4001.00000
+lfortranlatest : 3 10010.0000 20010.0000 30010.0000 40010.0000
+lfortranlatest : 4 100100.000 200100.000 300100.000 400100.000
+lfortranlatest : 5 1001.00000 2010.00000 3100.00000
+nvfortran_x86_26_3 : 2 1001.000 2001.000 3001.000 4001.000
+nvfortran_x86_26_3 : 3 10010.00 20010.00 30010.00 40010.00
+nvfortran_x86_26_3 : 4 100100.0 200100.0 300100.0 400100.0
+nvfortran_x86_26_3 : 5 1001.000 2010.000 3100.000
+gfortran161 : 2 1001.00000 2001.00000 3001.00000 4001.00000
+gfortran161 : 3 10010.0000 20010.0000 30010.0000 40010.0000
+gfortran161 : 4 100100.000 200100.000 300100.000 400100.000
+gfortran161 : 5 1001.00000 2010.00000 3100.00000
but adding the EITHER() procedure with SELECT RANK caused AOOC flang, lfortran, and nvfortran to fail
click to see more...
-aoccflang520 SELECT RANK not supported
-aoccflang520 : 2 F90-S-0034-Syntax error at or near identifier rank (/app/example.f90: 103)
-aoccflang520 : 12 F90/x86-64 Linux AOCCAOCC_5.2.0-Build#2035 2026_04_10: compilation completed with severe errors
-lfortranlatest : 2 ; ModuleID = 'LFortran'
-lfortranlatest : 3 source_filename = "LFortran"
-lfortranlatest : 4 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
-lfortranlatest : 5
-lfortranlatest : 6 %string_descriptor = type <{ i8*, i64 }>
-lfortranlatest : 7 %array.1 = type { float*, i64, i32, i8, i8, i8, i8, i64, [1 x %dimension_descriptor] }
-lfortranlatest : 8 %dimension_descriptor = type { i64, i64, i64 }
-lfortranlatest : 9 %array.15 = type { float*, i64, i32, i8, i8, i8, i8, i64, [15 x %dimension_descriptor] }
-lfortranlatest : 10
-lfortranlatest : 7675 code generation error: asr_to_llvm: module failed verification. Error:
-lfortranlatest : 7676 Stored value type does not match pointer operand type!
-lfortranlatest : 7677 store float* %63, %array.1** %p_b, align 8
-lfortranlatest : 7678 %array.1*Stored value type does not match pointer operand type!
-lfortranlatest : 7679 store float* %109, %array.1** %p_a, align 8
-lfortranlatest : 7680 %array.1*
-lfortranlatest : 7681
-lfortranlatest : 7682
-lfortranlatest : 7683 Note: Please report unclear, confusing or incorrect messages as bugs at
-lfortranlatest : 7684 https://github.com/lfortran/lfortran/issues.
-nvfortran_x86_26_3 : 2 NVFORTRAN-S-0034-Syntax error at or near identifier rank (/app/example.f90: 103)
-nvfortran_x86_26_3 : 3 NVFORTRAN-S-0034-Syntax error at or near end of line (/app/example.f90: 104)
-nvfortran_x86_26_3 : 4 NVFORTRAN-S-0034-Syntax error at or near end of line (/app/example.f90: 105)
-nvfortran_x86_26_3 : 5 NVFORTRAN-S-0034-Syntax error at or near ) (/app/example.f90: 106)
-nvfortran_x86_26_3 : 6 NVFORTRAN-S-0034-Syntax error at or near identifier default (/app/example.f90: 107)
-nvfortran_x86_26_3 : 7 NVFORTRAN-S-0034-Syntax error at or near identifier rank (/app/example.f90: 109)
-nvfortran_x86_26_3 : 8 NVFORTRAN-S-0034-Syntax error at or near end of line (/app/example.f90: 110)
-nvfortran_x86_26_3 : 9 NVFORTRAN-S-0034-Syntax error at or near end of line (/app/example.f90: 111)
-nvfortran_x86_26_3 : 10 NVFORTRAN-S-0034-Syntax error at or near ) (/app/example.f90: 112)
-nvfortran_x86_26_3 : 11 NVFORTRAN-S-0034-Syntax error at or near identifier default (/app/example.f90: 113)
-nvfortran_x86_26_3 : 12 NVFORTRAN/x86-64 Linux 26.3-0: compilation completed with severe errors
Only two (AOCC flang and gfortran) passed the proposed assumed rank target (an experimental F202y feature).
click to see more...
-flangtrunk : 2 error: loc("/app/example.f90":86:7): 'fir.rebox' op box operand must not have unknown rank or type
-flangtrunk : 3 error: verification of lowering to FIR failed
-ifxlatest : 2 /app/example.f90(86): error #8793: This assumed-rank variable must not appear in a designator or expression in this context. [B]
-
-ifxlatest : 3 p_b(1:n)=>b
-ifxlatest : 4 ----------------^
-ifxlatest : 5 /tmp/ifx1323433118B5EApm/ifxUaUoEw.i90(99): catastrophic error: Too many errors, exiting
-ifxlatest : 6 compilation aborted for /app/example.f90 (code 1)
-
-lfortranlatest : 3 Internal Compiler Error: Unhandled exception
-lfortranlatest : 4 Traceback (most recent call last):
-lfortranlatest : 5 Binary file "/cefs/98/98ce3ae339272c6faa61ecc8_consolidated/compilers_fortran_lfortran_0.64.0/bin/lfortran", local address: 0x7577e4
-lfortranlatest : 17 LCompilersException: Cannot extract the physical type of 2 type.
-
-nvfortran_x86_26_3 : 2 Program terminated with signal SIGSEGV (11)
-
+aoccflang520 : 1 STDOUT:
+aoccflang520 : 2 1001.000 2001.000 3001.000 4001.000
+aoccflang520 : 3 10010.00 20010.00 30010.00 40010.00
+aoccflang520 : 4 100100.0 200100.0 300100.0 400100.0
+aoccflang520 : 5 1001.000 2010.000 3100.000
+aoccflang520 : 6 10.00000 20.00000 90.00000 90.00000 90.00000 90.00000 80.00000 80.00000 80.00000 80.00000
+gfortran161 : 1 1001.00000 2001.00000 3001.00000 4001.00000
+gfortran161 : 2 10010.0000 20010.0000 30010.0000 40010.0000
+gfortran161 : 3 100100.000 200100.000 300100.000 400100.000
+gfortran161 : 4 1001.00000 2010.00000 3100.00000
+gfortran161 : 5 30.0000000 40.0000000 90.0000000 90.0000000 90.0000000 90.0000000 80.0000000 80.0000000 80.0000000 80.0000000