You can use zero-length variables to hold intermediate results that can be extracted from them via specification inquiries. Time for an example:
module mod_par
implicit none
contains
pure function par(x)
double precision par
integer, intent(in) :: x
par = 1+sqrt(real(1,kind(par))+x)
end function par
end module mod_par
module mod_foo
! use mod_par
implicit none
double precision par
contains
subroutine foo(p,v)
implicit none
integer p
double precision v
character(0) sv_i(floor(par(p)))
character(floor(par(p))) sv_j(0)
logical sv_k(floor(par(p)),0)
type t
! Intentionally empty
end type t
type(t) sv_L(floor(par(p)))
type u(len)
integer, len :: len
! intentionally empty
end type u
type(u(floor(par(p)))) sv_m
double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),sv_m%len,0)
! double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),0)
write(*,*) shape(z)
end subroutine foo
end module mod_foo
program bar
use mod_par
use mod_foo
implicit none
call foo(10,1.0d0)
end program bar
This fails on both ifort and gfortran because a specification function, here par, must be PURE and its interface must be explicit. Here par, though PURE has an implicit interface, so it's rejected. In fact both compilers seem to get confused:
specvar.f90:21:25:
character(floor(par(p))) sv_j(0)
1
Error: Function 'par' at (1) has no IMPLICIT type
For gfortran, and ifort says
specvar.f90(31): error #6404: This name does not have a type, and must have an e
xplicit type. [PAR]
type(u(floor(par(p)))) sv_m
----------------------^
So we fix this programming error...
module mod_par
implicit none
contains
pure function par(x)
double precision par
integer, intent(in) :: x
par = 1+sqrt(real(1,kind(par))+x)
end function par
end module mod_par
module mod_foo
use mod_par
implicit none
! double precision par
contains
subroutine foo(p,v)
implicit none
integer p
double precision v
character(0) sv_i(floor(par(p)))
character(floor(par(p))) sv_j(0)
logical sv_k(floor(par(p)),0)
type t
! Intentionally empty
end type t
type(t) sv_L(floor(par(p)))
type u(len)
integer, len :: len
! intentionally empty
end type u
type(u(floor(par(p)))) sv_m
double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),sv_m%len,0)
! double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),0)
write(*,*) shape(z)
end subroutine foo
end module mod_foo
program bar
use mod_par
use mod_foo
implicit none
call foo(10,1.0d0)
end program bar
But now gfortran says
specvar.f90:32:73:
double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),sv_m%l
en,0)
1
Error: Variable 'sv_m' cannot appear in the expression at (1)
And ifort:
specvar.f90(31): error #6279: A specification expression object must be a dummy
argument, a COMMON block object, or an object accessible through host or use ass
ociation. [SV_M]
type(u(floor(par(p)))) sv_m
--------------------------------^
So I don't have a sufficiently recent version of either compiler to support type parameter inquiries. Bummer. So we get rid of that last bit...
module mod_par
implicit none
contains
pure function par(x)
double precision par
integer, intent(in) :: x
par = 1+sqrt(real(1,kind(par))+x)
end function par
end module mod_par
module mod_foo
use mod_par
implicit none
! double precision par
contains
subroutine foo(p,v)
implicit none
integer p
double precision v
character(0) sv_i(floor(par(p)))
character(floor(par(p))) sv_j(0)
logical sv_k(floor(par(p)),0)
type t
! Intentionally empty
end type t
type(t) sv_L(floor(par(p)))
type u(len)
integer, len :: len
! intentionally empty
end type u
type(u(floor(par(p)))) sv_m
! double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),sv_m%len,0)
double precision z(size(sv_i),len(sv_j),size(sv_k,1),size(sv_L),0)
write(*,*) shape(z)
end subroutine foo
end module mod_foo
program bar
use mod_par
use mod_foo
implicit none
call foo(10,1.0d0)
end program bar
And now both compilers produce good code. So you can see that there are many ways to save a temporary integer variable in specifications of zero-length automatic variables that can be used in further specification expressions. Note that if you get too fancy with this kind of syntax you will crash the compiler a lot.