%VAL in NAG Fortran Compiler?

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!

1 Like

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 :frowning:
Always some more investigations needed :stuck_out_tongue:

Thanks everyone :slight_smile:

%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.

2 Likes

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.

1 Like

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?

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.

That should explain the segfault I got with ifort for large arrays, and nonsense results for small arrays.

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.