Outside of the rules, any result is as good as any other.
Count yourself lucky, because now you know you did not follow the rules. Count yourself doubly lucky if this has prompted you to invest in better tools for the next time you will inadvertently not follow the rules.
If a handyman turned up to do a job for you but only brought whatever tools were lying around on the street and then makes a hash of the job, would you hire him again?
Would you know whether NAG Fortran compiler alerts the paying customer re: the scenario below when -C=alias option is specified? Not sure whether you have continued access to that compiler.
module m
contains
subroutine sub1(arg1, arg2)
real, intent(in) :: arg1
real, intent(out) :: arg2
arg2 = arg1*10.0
end subroutine
subroutine sub2()
real, target :: t
real, pointer :: p1, p2
p1 => t ; p2 => t
call sub1( p1, p2 )
end subroutine
end module
The website suggests it is a run-time option and for scalar received arguments which is quite limiting.
The point by @tyranids then remains valid the compilers cannot offer much of any compile-time help here but which is understandable.
The counterargument to @tyranids is, as always with many things in Fortran, it is kind of like a honor code signed up to by the program author to not alias and thus the processor is permitted to attempt further code optimizations - take it or leave it.
Thanks. But a run-time error and scalar arguments is rather limiting. Those who are unable or unwilling to procure a commercial product in NAG Fortran can figure out a preprocessor based option to first replicate and then automate across large codes the same facility, say along the following lines:
module m
contains
subroutine sub1(arg1, arg2)
integer, intent(in) :: arg1(:)
integer, intent(out) :: arg2(:)
#ifdef DEBUG
if ( aliased(arg1, arg2 ) ) error stop "sub1: arg1 and arg2 are aliased; assignment to one affects the other"
#endif
arg2 = arg1*10.0
#ifdef DEBUG
contains
function aliased( a1, a2 ) result(r)
use, intrinsic :: iso_c_binding, only : c_loc, c_associated
! Argument list
type(*), intent(in), target :: a1(..)
type(*), intent(in), target :: a2(..)
! Function result
logical :: r
r = c_associated( c_loc(a1), c_loc(a2) )
end function
#endif
end subroutine
subroutine sub2()
integer, target :: t(2)
integer, pointer :: p1(:), p2(:)
t = [ 1, 2 ]
p1 => t ; p2 => t
call sub1( p1, p2 )
print *, u
end subroutine
end module
use m
call sub2()
end
C:\temp>gfortran -cpp -ffree-form -DDEBUG p.f -o p.exe
C:\temp>p.exe
ERROR STOP sub1: arg1 and arg2 are aliased; assignment to one affects the other
Error termination. Backtrace:
...
I wonder about this difference in semantics. I know some of the issues but only superficially. Is there any reference for this? I am interested to know more, out of basic curiosity, nothing else.
A reference to differences between C and Fortran semantics? I donât know of one. What I recall is efforts by the Fortran team to work around C-centric concepts baked into the back-end (this happened with the migration of DEC Fortran to Intel Fortran too, discarding the DEC-developed GEM multi-language back-end and switching to the Intel C-centric IL0 backend.) With LLVM, I recall in the early days that it didnât even have the concept of a complex datatype. Fortran COMMON is another thing that isnât exactly like C extern. Sometimes the back-end needs additional IL to support Fortran.
Re: âFortran COMMON is another thing that isnât exactly like C externâ, but BIND(C) clause indeed makes it like a C extern to a struct datatype.
#include <stdio.h>
typedef struct {
int n;
} foo_c;
extern foo_c foo;
// Fortran function
void Fsub();
int main()
{
Fsub();
printf("In C main: foo.n = %d\n", foo.n);
return 0;
}
subroutine Fsub() bind(C, name="Fsub")
use, intrinsic :: iso_c_binding, only : c_int
integer(c_int) :: n
common / foo / n
bind(C, name="foo") :: / foo /
n = 42
return
end subroutine
C:\temp>gfortran -ffree-form c.c s.f -o c.exe
cc1.exe: warning: command-line option '-ffree-form' is valid for Fortran but not for C
C:\temp>c.exe
In C main: foo.n = 42
With some restrictions, yes, but most uses of COMMON are not BIND(C) and there are additional quirks. Consider blank common, for example. My general point was that back ends written initially to target C usually need some work to accommodate Fortran.
Yes, common can be quite tricky in the backend. There are several ways to implement it, but my experience generally mirrors what @sblionel wrote as well.