Unfortunately, a more containerized version (with the actual storage within a derived type) won’t work with ifx (or with nvfortran) with the pointer function on the LHS. It works with gfortran (even when enforcing -std=f2018 -pedantic) or flang, though. I don’t know which compiler is right?
You are right, at least ifx 2025.0.0 does not accept it. I do not see why this should be prohibited, though, but I am not an expert in the standard either. Maybe this is a matter of oversight? I will ask on the Intel Forum. And if anybody here knows the answer, please share it.
Marc Grodent found a workaround after I posted the issue on the Intel Fortran forum. By declaring a separate result variable in the function v, the Intel compiler is happy to oblige.
Code along these lines:
function v(this,i) result(res) class(container_t), target, intent(inout) :: this integer, intent(in) :: i real, pointer :: res res => this%a(i) end function
Slightly inconvenient, but only slightly ![]()
Wow… Do we agree it’s a compiler bug ?
Yes, this is a good point and I agree. There is another approach too. I’ve avoided this technique because it’s portability is questionable, but I’ve seen build systems that do this in an automatic way. The idea is to compile the code with one fortran compiler, and then partially link that code against that fortran’s library. This resolves the compiler dependence at that point in the build process. The output is an object file, typically *.o, rather than an executable file or a library file. The other parts of the code are compiled and partially linked with the other fortran compiler(s). The only remaining unresolved symbols at this time are those involving one *.o file calling routines in another *.o file. A final load step then performs that task. This approach also handles the situation where two different libraries have the same symbol but with different functionality or interface, so that the appropriate symbols are bound at the appropriate places in the codes. Look to see if your loader has a -r option. That is how this works.
In the case of a regular procedure (not a type bound procedure), I think that combination of pointer and intent(in) attributes has already been given a special meaning, and it does not require that the actual argument has the target or pointer attributes. it has the same meaning as, for example,
integer, intent(in), target :: m
integer, pointer :: pm
pm => m
In other words, it is a shorthand way of declaring a local pointer assigned to a dummy target. In this case, the pointer is undefined upon return unless the actual argument has the target or pointer attribute, so it is up to the programmer to ensure that consistency with no help from the compiler. If this seems confusing, just for the sake of eliminating a few keystrokes of typing, then you are not alone.
If a different meaning were given to this same attribute combination for the type bound procedure argument case, one might argue that it would be even more confusing to a programmer. Then, if the pointer is not local, but, say, a function result, even further confusion can ensue.
Yes, that is the consensus on the Intel forum.
By the way, I don’t really understand why the possibility to associate an actual target to a dummy pointer (in the regular non-TB procedures) is limited to the case where the dummy pointer is intent(in) ?
I don’t think, pointer, intent(in) has any special meaning. If I understand it right, It expresses the need of the subroutine for a pointer argument and the promise, that the association status of the pointer won’t change within the routine. And the actual argument definitely requires the target or pointer attribute for the actual argument.
Take the following code as example:
program test
implicit none
integer :: i1
integer, target :: ti1
integer, pointer :: pi1
!! Uncommenting following call raises compiler error
! call pointer_demo(i1)
call pointer_demo(ti1)
pi1 => ti1
call pointer_demo(pi1)
contains
subroutine pointer_demo(ptr)
integer, pointer, intent(in) :: ptr
print *, "associated(ptr):", associated(ptr)
end subroutine pointer_demo
end program test
Uncommenting the call with i1 (which has neither pointer nor target attribute) would trigger a compiler error. GFortran, for example stops with
Error: Actual argument for ‘ptr’ at (1) must be a pointer or a valid target for the dummy pointer in a pointer assignment statement
Because if the pointer formal argument had the intent(out) or the intent(inout)attribute, the subroutine would be allowed to change the association status of the pointer. This does not really makes sense for automatic pointer targeting, where the subroutine basically gets a “temporary pointer” generated by the compiler (and pointing to the actual variable with the target attribute).
Right… I am always confused about intent applying to the pointer association or to the content…