I have encountered a problem, when trying to pass an array with the target attribute as an actual argument to a procedure with a pointer, intent(in) dummy argument via a generic interface. The minimal working example below demonstrates the problem. Calling subptr_int1 directly works, but via the `subptr` interface does not, the compiler complains about not being to able to find a matching interface for the call. Also, it seems, that for scalars it works with the interface. As far as I can judge, the code is standard conforming, two other compilers have no problems to compile it.
end program test_target_program
An array descriptor is not a pointer. Your subroutine requires a reference to a pointer be passed.
Note, should you flip the arguments about (call with pointer to subroutine with array), the actual argument is that which the pointer points to and not the pointer itself.
module test_target implicit none interface subptr module procedure subptr_int1 end interface subptr contains subroutine subptr_int1(val) integer, pointer, intent(in) :: val(:) print *, "INTEGER1 PTR obtained", val(1) end subroutine subptr_int1 end module test_target program test_target_program use test_target implicit none integer, target :: int1val(1) integer, pointer :: p(:) int1val(1) = 42 p => int1val call subptr(p) end program test_target_program
The array in question (int1val) has the "target" attribute, therefore, according to the standard, it should be allowed to be an actual argument for a dummy argument with the 'pointer, intent(in)' argument. Consequently, the example above is correct and standard conforming.
Note, that if I directly call the routine with "call subptr_int1(int1val)", the code compiles and works as supposed without any further changes. It is only the generic interface, which confuses the Intel compiler. And, if I turn int1val and val into a scalar, the code again compiles and works without further changes. It is only the combination of using an array and the generic interface, where the compiler misbehaves.
I'm inclined to agree with @BalintAradi that the code should be accepted. Generic resolution isn't quite the same as argument association, but I think this cases passes the test. It's a fairly new thing in the language to allow passing a non-pointer to an INTENT(IN) pointer, and it's likely that the ifort developers overlooked adding a check for this in generic resolution.
>>I'm inclined to agree with @BalintAradi that the code should be accepted.
I disagree for this reason:
The interface has been declared. In this specific example, then subroutine dummy argument for the pointer had intent(in) ...
However, consider if the intent were instead intent(inout)
In this case, had the call passed a pointer into the subroutine, the caller's pointer could be modified with => as well as have the pointer's target altered with =.
Orthogonality should not be broken dependent upon INTENT(IN) verses INTENT(INOUT) IMHO
@jimdempseyatthecove I think, if a module procedure can be called directly with a given actual argument, one should be also able to call it with the same actual argument via the generic interface, if it is listed in that generic interface. The direct call works if the pointer dummy argument of the called subroutine is intent(in), and it does not work, if the pointer dummy argument is intent(inout) (as dictated by the standard). I'd expect the call via the generic interface to behave the same way.
Also, as I mentioned above the posted example can be compiled and is working perfectly even with the Intel compiler if the dummy and the formal arguments are changed to scalars. So, I'd guess, the array case was just simply overseen.
Jim, the standard already carves out an exception for this case:
If the dummy argument does not have INTENT (IN), the actual argument shall be a pointer. Otherwise, the actual argument shall be a pointer or a valid target for the dummy pointer in a pointer assignment statement. If the actual argument is not a pointer, the dummy pointer becomes pointer associated with the actual argument. (18.104.22.168p2)
If I read that correctly (correct me if I am wrong)...
"If the dummy argument does not have INTENT (IN), the actual argument shall be a pointer. " would apply to INTENT(OUT), INTENT(INOUT) and INTENT not specified.
The above is ambiguous (or maybe not). Is this a copy of the pointer of the caller or is this a reference to the caller's pointer?
My preference as to the decision made by the Fortran committee would be that this be a reference to the caller's pointer else how could you have a subroutine returning a pointer? Or, as an extension, a function returning a pointer?
Yes, any INTENT not (IN), including unspecified, requires that the actual argument be a pointer if the dummy is a pointer. I don't think it is ambiguous.
Subroutines don't "return" anything, and I don't see the connection with functions returning pointers. This feature allows you to pass a non-pointer to a pointer under conditions that disallow changes to the pointer (INTENT(IN)). The dummy pointer becomes associated with the actual argument (rather than the target of a pointer actual argument).