You missed that (I have added it lately):
If have already put compute
outside of a module and still get an argument mismatch, then try putting it in a separate file.
Moving it out to a separate file seems to do the trick!

If have already put
compute
outside of a module and still get an argument mismatch, then try putting it in a separate file.
Yes, it wasnât enough.

Yes, it wasnât enough.
All of this is (and was) obviously non standard conforming. In particular it violates the argument conformance when calling the routine. Fortran compilers are not required to check arguments when calling a routine that is outside of a module, but some of them do when possible, for instance when the called routine is in the same source file as the calling routine. Such compilers have generally an option to turn off the checking (but I donât know nagfor
at all)
It seemed to work fine on macos and nagfor, but now I get a segfault on windows/ifort
Always some more investigations needed
Thanks everyone
%VAL
is not the same as the VALUE
attribute, unless the procedure youâre calling has the BIND(C)
attribute; this is a point that eludes many. Without BIND(C)
, VALUE
causes a definable, temporary copy of the argument to be passed using the default passing mechanism, which is typically by-reference.
I agree that with a modern compiler, there is rarely a need to use %VAL
, a DEC VAX extension.
Maybe, but %VAL is quite simple, predictable and requires very little boilerplate code.
Why was it never in scope for addition to the standard, or if it was, rejected?
It was never considered, and that was the correct choice. Back in the 1970s, when VAX FORTRAN and VMS first appeared, %VAL, %REF and %DESCR were useful in the multi-language environment. The C interoperability features in Fortran 2003 were a vast improvement, in conjunction with explicit interfaces. You specify the passing mechanism when you declare the procedure, not on each call.

%VAL
is not the same as theVALUE
attribute, unless the procedure youâre calling has theBIND(C)
attribute; this is a point that eludes many. WithoutBIND(C)
,VALUE
causes a definable, temporary copy of the argument to be passed using the default passing mechanism, which is typically by-reference.
It seems that the OP has solved his problem with nagfor
by using the value
attribute in the interface block (and not in the routine itself), in place of %VAL
for the actual argument. bind(C)
is not used. Doesnât it mean that the compiler has effectively passed the values of X_PTR
and Y_PTR
and not their adresses?
What does %VAL
precisely when used with an actual argument?

using the
value
attribute in the interface block (and not in the routine itself), in place of%VAL
for the actual argument.bind(C)
is not used.
Unless nagfor has misimplemented it, which I seriously doubt, using VALUE in the interface block but not BIND(C) is not the equivalent of %VAL. I suspect the OP has misunderstood the results.
%VAL told the VAX compiler to pass the actual argument by value rather than by reference (address) or by descriptor (a VMS thing that was the default for character data). Some argument types (arrays, for example) could not be passed that way. That compiler did not have interface blocks. Later DEC compilers (and then Compaq and Intel) which did have interface blocks and the C interop features, still supported %VAL as an extension for compatibility with old code.
Here is a sample code in godbolt, tested with ifx, gfortran, and nvfortran (all of them have the loc
and %VAL
extensions):
subroutine foo1(x)
real x
print*, "address of x from foo1:", loc(x)
end subroutine
subroutine foo2(x)
real x
print*, "address of x from foo2:", loc(x)
end subroutine
program bar
real x
integer*8 x_ptr
interface
subroutine foo2(x_ptr)
integer*8, value :: x_ptr
end subroutine
end interface
x_ptr = loc(x)
print*, "address of x from main:", x_ptr
call foo1(%VAL(x_ptr))
call foo2(x_ptr)
end
gfortran (using -fallow-argument-mismatch
):
address of x from main: 140729065382908
address of x from foo1: 140729065382908
address of x from foo2: 140729065382908
nvfortran:
address of x from main: 140733433880508
address of x from foo1: 140733433880508
address of x from foo2: 140733433880508
ifx:
address of x from main: 140723206031428
address of x from foo1: 140723206031428
address of x from foo2: 140723206031376
So, among gfortran/nvfortran/ngafor/ifx, only ifx
does not effectively pass the argument by value in foo2
(but it does if the interface block is:
interface
subroutine foo2(x_ptr) bind(C,name="foo2_")
integer*8, value :: x_ptr
end subroutine
end interface
I donât know which one(s) is(are) right, or even if there is a âright behaviorâ at allâŚ
ifx is correct, the others are not, and yes, there is a âright behaviorâ.
Consider this variant of your test:
subroutine foo1(x)
real x
print*, "address of x from foo1:", loc(x)
print *,"vaue of x fron foo1:" , x
end subroutine
subroutine foo2(x)
real x
print*, "address of x from foo2:", loc(x)
print *,"vaue of x fron foo2:" , x
end subroutine
program bar
real x
integer*8 x_ptr
interface
subroutine foo2(x_ptr)
integer*8, value :: x_ptr
end subroutine
end interface
x = 3.14
x_ptr = loc(x)
print*, "address of x from main:", x_ptr
print *,"vaue of x fron main:" , x
call foo1(%VAL(x_ptr))
call foo2(x_ptr)
end
D:\Projects>ifx t.f90
Intel(R) Fortran Compiler for applications running on
Intel(R) 64, Version 2025.0.0 Build 20241008
Copyright (C) 1985-2024 Intel Corporation. All rights reserved.
Microsoft (R) Incremental Linker Version 14.41.34120.0
Copyright (C) Microsoft Corporation. All rights reserved.
-out:t.exe
-subsystem:console
t.obj
D:\Projects>t.exe
address of x from main: 221874485156
vaue of x fron main: 3.140000
address of x from foo1: 221874485156
vaue of x fron foo1: 3.140000
address of x from foo2: 221874485208
vaue of x fron foo2: -2.1312657E-14
I was thinking about this some more and I remembered - DEC implemented this the wrong way initially. When they changed it to conform to the standard, an option -assume nostd_value
was added to revert to the old way. It may be that the other compilers have an option to treat value
in the absence of BIND(C)
in the standard-conforming manner.

ifx is correct, the others are not, and yes, there is a âright behaviorâ.
Consider this variant of your test:
subroutine foo1(x) real x print*, "address of x from foo1:", loc(x) print *,"vaue of x fron foo1:" , x end subroutine subroutine foo2(x) real x print*, "address of x from foo2:", loc(x) print *,"vaue of x fron foo2:" , x end subroutine program bar real x integer*8 x_ptr interface subroutine foo2(x_ptr) integer*8, value :: x_ptr end subroutine end interface x = 3.14 x_ptr = loc(x) print*, "address of x from main:", x_ptr print *,"vaue of x fron main:" , x call foo1(%VAL(x_ptr)) call foo2(x_ptr) end
D:\Projects>ifx t.f90 Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2025.0.0 Build 20241008 Copyright (C) 1985-2024 Intel Corporation. All rights reserved. Microsoft (R) Incremental Linker Version 14.41.34120.0 Copyright (C) Microsoft Corporation. All rights reserved. -out:t.exe -subsystem:console t.obj D:\Projects>t.exe address of x from main: 221874485156 vaue of x fron main: 3.140000 address of x from foo1: 221874485156 vaue of x fron foo1: 3.140000 address of x from foo2: 221874485208 vaue of x fron foo2: -2.1312657E-14
That should explain the segfault I got with ifort for large arrays, and nonsense results for small arrays.

ifx is correct, the others are not, and yes, there is a âright behaviorâ.
Thereâs a note in the standard:
I understand that ifx is not wrong, but given the last sentence âThe actual mechanism by which this happens is determined by the processorâ, why is the by-value mechanism used by the other compilers wrong?
Read the second sentence.
I did. And it says âas ifâ, which opens many doors
The key is that a definable temporary variable is passed in the same way an ordinary variable actual argument would be. Another point is that any argument type (array, derived type, character) can be passed this way whereas there are severe limits on what you can do with %VAL.