As soon as the variable is passed (by reference)
Cautionary note: Fortran does not specify how variables are passed (by reference, by value, or in any other way). It depends on the implementation. Fortran is very different from C / C ++. Better stop thinking on the C-shaped path. This will be misleading.
1) Yes and no. It depends on the implementation. First of all, the INTENT attribute indicates your intentions. As you can see in the Fortran standard, section 5.3.10, NOTE 5.17 (you can get the final draft of the so-called Fortran 2008 from the link at the top of this page http://fortranwiki.org/fortran/show/Fortran+2008 ):
The argumentation goal specifications serve several purposes in addition to documenting the intended use of dummy arguments. The processor can check if the dummy argument INTENT (IN) is used in a way that could override it. [...]
the compiler (“processor”) can (should not) check such things.
Secondly (as I already mentioned) you cannot be sure that for the argument with INTENT (IN) the compiler will select the transmission by value, and not by reference. In this case, the choice was by reference. At least it seems that I was passed by reference in the test routine. The following routine. INTENT defaults to INOUT. That is why it is possible to change the value of argument i (with unspecified what, why is INTENT by default) in doSomethingNasty. Once again I was accepted by reference. Or perhaps it was even “copy / copy”. Such freedom exists to allow the compiler to perform optimizations.
2) No. If I understand you correctly, you need something similar to permalinks (to achieve the so-called "match accuracy"). But we don’t even have links in Fortran, so obviously there are no permalinks.
3) There is a way to protect local variables. As MSB pointed out in his answer, put your routines in MODULE (or in the CONTAINS section of the main program) and always specify the INTENT attributes for the variables. I tried compiling the code below with different Fortran compilers available to me
PROGRAM main INTEGER :: i i = 21 CALL test(i) WRITE (*,*) "21 expected, but is 42: ", i CONTAINS SUBROUTINE test(i) INTEGER, INTENT(IN) :: i CALL do_something_nasty(i) END SUBROUTINE test SUBROUTINE do_something_nasty(i) INTEGER, INTENT(INOUT) :: i i = 42 END SUBROUTINE do_something_nasty END PROGRAM main
and all compilers (GNU, Intel, Open64, Portland, and g95) issued an error message. I think other compilers (Pathscale, IBM) will behave the same.