%VAL in NAG Fortran Compiler?

What is the use case to have a behaviour like in your foo2 example?

This example has no other purpose than trying to understand how the different compilers handle the value attribute under the hood. To me, all the tested compilers (which includes nagfor that you have tested on your side) are correct, although they behave differently on such non-standard conforming examples.

In practice, you should keep the %VAL approach with ifx, use the value approach with nagfor (so you need conditionnal compilation there), and use any of these approaches with the other compilers.

ifx is allowing the argument mismatch to happen, but ultimately doing the right thing when it comes to value (i.e., protecting the actual argument for when the dummy argument is modified). gfortran is told, explicitly, to ignore the argument mismatch, which seems to also mean ā€œignore the value attributeā€?

subroutine foo2(x)
    real x
    x = x + 1
    print*, "address of x from foo2:", loc(x)
    print *,"value 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 *,"value of x before invocation:" , x
    call foo2(x_ptr)
    print *,"value of x after invocation:" , x
end
$ ifx definable_val.f90 && ./a.out 
 address of x from main:       140734550885124
 value of x before invocation:   3.140000    
 address of x from foo2:       140734550885128
 value of x fron foo2:  3.1374975E+10
 value of x after invocation:   3.140000    

$ gfortran -fallow-argument-mismatch definable_val.f90 && ./a.out 
definable_val.f90:14:23:

   14 |         subroutine foo2(x_ptr)
      |                       1
Warning: Interface mismatch in global procedure ā€˜foo2’ at (1): Type mismatch in argument 'x_ptr' (INTEGER(8)/REAL(4))
 address of x from main:      140720899691276
 value of x before invocation:   3.14000010    
 address of x from foo2:      140720899691276
 value of x fron foo2:   4.14000034    
 value of x after invocation:   4.14000034    

No, these are two fully different things. In the example above gfortran fully honors the interface block, including the value attribute (it is required to) in all cases. It ignores the argument mismatch because we ask it to do so, AND because it is not required to do so for a dangling routine (which is outside of a module).

Oh, I see.

But value means never modifying the actual argument —and gfortran fails at that. That’s why, imho, a copy must be involved.

That is because the actual subroutine dummy argument does NOT have the value attribute. The interface block says it does, but the actual argument association doesn’t.

I’m guessing that some compilers have the calling program to make the copy while other compilers have the called subroutine to make the copy, thus when the interface block is not consistent with the actual subroutine (nonconforming code), different compilers end up doing different things.

2 Likes

Ok. It makes sense, although in a disturbing way.

interface here means external, but by lacking bind(C) gfortran is assuming the argument will be copied on the callee side?

And it seems -fallow-argument-mismatch is only needed if the actual subroutine is in the same file:

gfortran definable_val_sub.f90 definable_val_main.f90 && ./a.out 
 address of x from main:      140727789293212
 value of x before invocation:   3.14000010    
 address of x from foo2:      140727789293212
 value of x fron foo2:   4.14000034    
 value of x after invocation:   4.14000034    

I don’t know how useful this will be, but I’ll second anyone else’s suggestion to use Home Brew and GFortran. On Apple silicon Home Brew installs GFortran very nicely and it works as expected. Even compiles with CAF if you install that too.