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