8

In Fortran language, providing an argument that has not the TARGET attribute to a procedure with a dummy argument that has the TARGET attribute should lead to an invalid code. However, when the following code is compiled with gfortran (5.1.0) or ifort (14.0.0), no error is detected and the program behaves like the argument actually has the TARGET attribute. Am I wrong when I say it is an invalid code or is this a compiler defect?

program pointerization
   implicit none

   integer, dimension(3) :: A
   integer, dimension(:), pointer :: ptr_A

   A = [1, 2, 3]
   call pointerize(A, ptr_A)
   print*, "A=", ptr_A

contains
    subroutine pointerize(tab, ptr_tab)
        integer, dimension(:), intent(in), target :: tab
        integer, dimension(:), pointer :: ptr_tab

        ptr_tab => tab
    end subroutine
end program
1

1 Answer 1

9

You are correct that you have invalid code. It isn't, though, for the reason you say.

Within a procedure, it is legal for a dummy argument to have the target attribute even though the associated actual argument hasn't. Essentially, we are allowed to have pointers targeting the entity within the procedure as long as the lifetime of this pointing doesn't exceed the lifetime of the procedure.

In the case of this question, the dummy argument tab is allowed to have the target attribute even though the associated actual argument A hasn't. Even the pointer assignment statement ptr_tab => tab within the procedure is legal.

What is important, however, is that outside the procedure, where the actual argument hasn't the target attribute, we can't affect that entity through a pointer. The Fortran standard ensures this doesn't happen in the following way (Fortran 2008 C.9.4, see also 12.5.2.4; similar exists in Fortran 2018):

If a nonpointer dummy argument has the TARGET attribute and the corresponding actual argument does not, any pointers that become associated with the dummy argument, and therefore with the actual argument, during execution of the procedure, become undefined when execution of the procedure completes.

That is, in the case of the question, on completion of pointerize ptr_A is no longer of defined association status. Deferencing this pointer in the main program's print statement is not allowed.

For interest, compiling the example code with nagfor results in the run-time diagnostic

Runtime Error: aaa.f90, line 9: Reference to dangling pointer PTR_A
Target was RETURNed from procedure POINTERIZATION:POINTERIZE
Program terminated by fatal error
Abort (core dumped)

But equally, just because the pointer association is undefined, this doesn't mean that you can't get the results you expect. Such checking is a nice thing from a compiler but it isn't required that it should fail.

Sign up to request clarification or add additional context in comments.

5 Comments

If you want to use a procedure to associate a pointer to a variable the best way is to use the auto-targetting feature of F08. You can define the dummy variable tab as: integer,pointer,intent(in) :: tab(:) . That way you can force your variable A to have the target attribute, limiting the possibility to have undefined pointers.
I guess it's the same for a type(c_ptr) argument (i.e. the return of c_loc)? In a sense, it is a pointer, but it's not a Fortran pointer.
@Jellby, yes. Or rather, I believe so: I think one has to read between the lines on that rather than it being explicitly stated. I'll have to dig through the standard again to convince myself. (Could be that I should reopen your question linked to this one.)
Without knowing the standard, my understanding is that a compiler is allowed to make a copy of the arguments, work on those, and copy them back if necessary. If that were the case, c_loc would point to the copy of A (which is a proper target), but not to A itself. If A itself had the target attribute, the compiler would know that anything pointing to its copy must point to the parent once the subroutine ends. As always, the point is: even if not allowed, it might work, but it's not guaranteed to.
@Jellby, if the dummy argument has the target attribute then you tell the compiler "you have to let me change the value of this variable even if I don't refer to it by the name I've given it". If the actual argument hasn't that attribute (or asychronous) you haven't warned the compiler about that variable and are severely constrained in how you can change its value. So, even if the c_loc result of the target dummy did remain defined it can't really be used in any meaningful way (in particular, you can't c_f_pointer with it).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.