The following code, combining module procedures and external procedures:
module module_dummy
implicit none
contains
subroutine foo(a)
real, intent(inout) :: a(:)
call bar(a)
end subroutine foo
end module module_dummy
program main
use module_dummy
implicit none
integer, parameter :: nelems = 100000000
real, allocatable :: a(:)
allocate( a(nelems) )
a = 0.0
call foo(a)
print *, a(1:10)
deallocate(a)
end program main
subroutine bar(a)
implicit none
real, intent(inout) :: a(:)
a = 1.0
end subroutine bar
seems to fail either:
segmentation fault
0.000
instead of a block of 1.000
on any platform I have tried so far. The problem is related to the implicit interface declaration of bar
, and in fact the issue can be solved adding in any way an explicit interface, e.g. using:
module module_dummy
implicit none
contains
subroutine foo(a)
interface
subroutine bar(x)
real, intent(inout) :: x(:)
end subroutine bar
end interface
real, intent(inout) :: a(:)
call bar(a)
end subroutine foo
end module module_dummy
or declaring bar
inside a module to be used by module_dummy
.
Anyhow I really don't understand what is the error in the first place. What I have found on the Fortran 90 standard (sec. 12.3.2.4) says that:
The type, type parameters, and shape of dummy arguments of a procedure referenced from a scoping unit where the interface of the procedure is implicit must be such that the actual arguments are consistent with the characteristics of the dummy arguments.
In this case the rule seems to be respected, as a
is always declared as
real, intent(inout) :: a(:)
So, what am I missing in the interpretation of the standard that makes the previous code wrong?
Dummy arguments that are assumed shape must have an explicit interface at their point of reference. F90 12.3.1.1 item 2c.
Practically, assumed shape arrays are passed by passing a descriptor - a little structure that describes the bounds and the location of storage of the array. Ye-olde F77 explicit shape and assumed size arrays are passed simply by passing the address of the first element. Without the explicit interface the compiler doesn't know that it needs to build and pass the descriptor - hence chaos and confusion results.