The relevant part of the constraint you come up against (C12831) is
In a pure subprogram any designator with a base object that is .. a dummy argument with the INTENT (IN) attribute .. shall not be used
The note below that constraint description motivates it
The above constraints are designed to guarantee that a pure procedure is free from side effects
What you want to say is "I guarantee that there are no side effects, we don't need the constraints for that". The constraints are sufficient but not necessary for this guarantee and you can analyse your code well.
However, a conforming processor/compiler must be able to detect breaches of constraints not just the overall goal of the constraints, so you don't just need to say "it's pure
really", but also "and I don't need to be told of violations of C1283". That seems like a lot of effort for the compiler vendor to go to for very little benefit.
I guess, then, that the answer is "no": there isn't a way to compile your code. This isn't definitive, as we're really into implementation-specific areas. You asked about gfortran and ifort in particular, so a "use -nocheck c1283
" refutes my "answer".
Now, if there is an option you're in the realms of "trust me" (and non-standard Fortran). So, let's go there anyway. It's just that we're going to lie. As usual, interface blocks will be our means.
module list_mod
implicit none
! Node
type n_list
integer :: val
type(n_list),pointer :: next => NULL()
end type
! Linked list
type t_list
type(n_list),pointer :: head
end type
interface
pure logical function in_list(list, val)
import t_list
class(t_list), intent(in) :: list
integer, intent(in) :: val
end function
end interface
end module
! Interface mismatch in the external function
function in_list(list, val) result(res)
use list_mod, only : t_list, n_list
implicit none
class(t_list),intent(in) :: list
integer,intent(in) :: val
logical :: res
type(n_list),pointer :: cur
res = .true.
! Traverse the list
cur => list%head
do while ( associated(cur) )
if ( cur%val == val ) return
cur => cur%next
enddo
! Not found
res = .false.
end function
use list_mod
type(t_list) testlist
type(n_list), pointer :: ptr
integer i
logical :: res(5) = .FALSE.
allocate(testlist%head)
ptr => testlist%head
do i=1,5
allocate(ptr%next)
ptr => ptr%next
ptr%val = i
end do
! in_list is pure, isn't it?
forall(i=1:5:2) res(i)=in_list(testlist,i)
print*, res
end
This is pure nastiness and is limiting: you no longer have a module procedure; you're not standard conforming; the compiler may be clever and check interfaces (even though it needn't). If the compiler hates you as a result you have only yourself to blame.
Finally, it's all rather a lot of effort to get the procedure pure
.
1 This is in Fortran 2008 corresponding to the language revision at the time of asking. In Fortran 2018 the corresponding constraint is C1594.