I'm wondering if it is legal/safe to modify intent(in)
dummy arguments through pointers associated with corresponding actual arguments. Specifically when the pointer association was established before the subroutine call.
For example, is the following OK (it seems to work fine with gfortran)?
program test
implicit none
type compound
integer, allocatable :: A1(:)
integer, pointer :: A2(:,:)
end type compound
type(compound), target :: my
integer :: n=5, i
allocate(my%A1(n**2))
my%A2(1:n,1:n) => my%A1(:)
do i=1,n**2
my%A1(i) = i
end do
do i=1,n
print *, my%A2(i,:)
end do
call assign_A(my)
do i=1,n
print *, my%A2(i,:)
end do
contains
subroutine assign_A(var)
type(compound), intent(in) :: var
var%A2(:,:) = 42
end subroutine
end program test
The trick is a user-defined type that contains a pointer and a target, the former pointing to the latter. An instance of this is passed as intent(in)
and in the subroutine it is modified through the pointer component (the values pointed by intent(in)
pointers can be modified). I'm a bit surprised that this works, but maybe it's just a missing diagnostic by the compiler. If I was changing var%A1
directly that would of course fail.
EDIT: Output from the above program (compiled with gfortran 7.5.0):
1 6 11 16 21
2 7 12 17 22
3 8 13 18 23
4 9 14 19 24
5 10 15 20 25
42 42 42 42 42
42 42 42 42 42
42 42 42 42 42
42 42 42 42 42
42 42 42 42 42
You are not allowed to change the value of an intent(in)
object in this way. The compiler does not have to (be able to) tell you that you are doing something wrong. (Further, it is an unreasonable expectation to have on a compiler that it should be able to detect all cases where an illegal change is made.)
The dummy argument var
is a non-pointer object, and this means that its components also have the same intent attribute. You are trying to define var
and its component var%A1
by the assignment var%A2(:,:) = 42
because var%A2
is pointer associated with my%A1
(through the argument association of var
with my
); through argument association of var
and my
, definition of my%A1
is definition of var%A1
.
This is a violation of the statement that (F2018 8.5.10 p2):
The INTENT (IN) attribute for a nonpointer dummy argument specifies that it shall neither be defined nor become undefined during the invocation and execution of the procedure.
However, this is not a numbered constraint or syntax rule so the compiler is not required to be capable of diagnosing the violation. Where a compiler is required to be capable of diagnosing a violation for changing var
is in (F2018 C844 (R826)):
A nonpointer object with the INTENT (IN) attribute shall not appear in a variable definition context (19.6.7).
A variable definition context is specific, and the assignment statement of the question is not a variable definition context for var
or var%A1
. An assignment such as var%A1=42
(which you note your compiler complains about) is appearance, of var%A1
(but not var
), in a variable definition context.
You can also wonder whether the aliasing restrictions come into play.
In summary, it is possible to hide changes to a dummy variable with intent(in)
from your compiler. Just as programmers don't like being tricked, your compiler doesn't have to still be your friend if you do this. The compiler can assume var
doesn't change value during the subroutine and it owes you nothing if you find a way to subvert that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With