Is this a valid way to alias an intrinsic?

Even though this MRE ran on four platforms, before reporting
this as a bug is it standard Fortran to alias an intrinsic
this way? I am starting to have doubts now.

program mre
implicit none
procedure(acos), pointer :: p
p => acos
print *, p(1.)
end mre
Compiler Explorer comparison ...
                         OUPUT  OUTPUT
COMPILER                  LINE
+aoccflang520         :     2	    0.000000    
+flangtrunk           :     2	 0.
+nvfortran_x86_26_3   :     2	    0.000000    
+ifxlatest            :     2	  0.0000000E+00
!ifxlatest            :     4	/app/example.f90(1): warning #8190: Argument checking is not yet supported for procedures declared with an intrinsic procedure as interface.   [ACOS]
!ifxlatest            :     5	procedure(acos), pointer :: p
!ifxlatest            :     6	----------^
!ifxlatest            :     7	/app/example.f90(1): warning #8190: Argument checking is not yet supported for procedures declared with an intrinsic procedure as interface.   [ACOS]
!ifxlatest            :     8	procedure(acos), pointer :: p
!ifxlatest            :     9	----------^
-lfortranlatest       :     3	Program terminated with signal: SIGSEGV
-gfortran161          :     4	    1 | procedure(acos), pointer :: p
-gfortran161          :     5	      |                            1~
-gfortran161          :     6	Error: Procedure pointer 'p' at (1) shall not be elemental
userland@localhost:~$ nano proctest2.f
gfortran proctest2.f -ffree-form -std=f2018 -Wall -o proctest2 
userland@localhost:~$ ./proctest
20.0000000000000000
userland@localhost:~$ cat proctest2.f

program mre
use iso_fortran_env, only : real64
implicit none
abstract interface
function unary_real64(x) result(y)
import :: real64
real(real64), intent(in) :: x
real(real64) :: y
end function unary_real64
end interface
intrinsic :: dacos
procedure(unary_real64), pointer :: p
p => dacos
print *, p(1.0_real64)
end program mre

1 Like

acos is a generic procedure name. Its use as in the above cannot be correct.

1 Like

In your example’s case, I think it’s okay, since the compiler should interpret acos as a specific intrinsic procedure (that happens to coincide with the generic name), and that specific intrinsic is in the list of unrestricted ones (Table 16.2).

The applicable constraint for procedure-declaration-stmt is

C1519 (R1518) The procedure-name shall be the name of a nonelemental external or module procedure, or a specific intrinsic function listed in Table 16.2.

The only problem is that any usage of specific names for intrinsic procedures is obsolescent.

So maybe gfortran and/or lfortran have a specific (no pun intended) flag for said usage?

2 Likes

Thanks to everyone! In this particular case it ended up being easier to call the intrinsic from a wrapper script that just handles real64 for unrelated reasons but I will hold off on a bug report unless the abstract type fails as well and then mention it in passing. This was encountered in third-party code so I will discuss this with them if they want to improve portability. I have aliased intrinsics but not for this reason I have put the intrinsics in modules so I can rename them by use association but I can see needing to do this in the future.

I think this is the typical solution to this problem, especially involving generic intrinsics. If you do this with an internal procedure, then the compiler can see the entire procedure and has the opportunity to optimize the pointer reference all the way down to the specific intrinsic. Also, the internal procedure (i.e. with contains) means that the global namespace is unaffected.

Btw, the end mre must be changed to end program mre, otherwise I think it’s definitely not valid Fortran.

1 Like

Correct - the PROGRAM keyword is required here if program-name appears.

1 Like