- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ifort 13.1.2.183 Build 20130514 gives the following warning:
warning #7937: The OPTIONAL attribute should not be used for arguments with the VALUE attribute.
when compiling this code:
[fortran]module test_mod
contains
subroutine test_routine(iopt)
integer, optional, value :: iopt
if (present(iopt)) then
print *, 'present'
else
print *, 'absent'
endif
end subroutine
end module
program test
use test_mod
call test_routine(iopt=1)
call test_routine()
end program[/fortran]
The executable does not give the expected result:
$ ./a.out
present
present
(the second time the routine is called, the argument is not present, therefore the present(iopt) should be .FALSE.)
This looks like a bug to me. If the standard says that we can't have OPTIONAL and VALUE together (I haven't checked), then ifort should throw an error, not a warning. If the standard does allow it, then the implementation is buggy. FWIW, NAGfor generates an executable with the expected behaviour.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Interesting. The standard doesn't have a restriction here. I agree that this is a bug and will escalate it.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
When passing by reference a pointer to the argument is passed. By convention, data cannot be positioned at location 0. Therefore a pointer to 0 can be used and interpreted as argument not present.
When passing integer by value, 0 is a valid value. Meaning there is no way to disambiguate present or not present. Thus the warning. What is unknown (to me) is when the subrouting has an interface with "integer, optional, value :: iopt" and the caller uses the interface and calls without an argument, then the question is: Is the value of iopt == 0 (regardless of report of test of present). If true, then reserve option value == 0 to indicate none.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I made an error in my earlier reply, since edited. The Fortran standard VALUE attribute does not necessarily mean pass-by-value. It does only if the called routine is declared as BIND(C).
Issue ID is DPD200244863.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think I need to explain more.
First of all, the Fortran VALUE attribute is not the same as !DEC$ ATTRIBUTES VALUE. For a routine that is not BIND(C), it effectively means that the called routine makes a local copy of the actual argument an any writes to it are discarded on exit. For a routine with BIND(C), it does mean pass-by-value.
In Fortran 2008, a BIND(C) routine is not allowed to have an OPTIONAL argument. There is a specification TS29113 for "Further Interoperability of Fortran with C" that does allow for OPTIONAL arguments, but it disallows the combination of OPTIONAL and VALUE.
So in the case in question, Intel Fortran should compile this without a warning and with the correct behavior.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve & Jim.
Steve, could you clarify the distinction you/Fortran makes between
the called routine makes a local copy of the actual argument and any writes to it are discarded on exit
and
pass-by-value
The two sound equivalent to me, so I must be missing something.
Thanks!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Pass by value is when the argument list (usually on the stack or a register) contains the actual value, not the address of the value. In C it's the difference between foo(x) and foo(&x). The Fortran standard VALUE attribute, in the absence of BIND(C), doesn't change how the argument is passed, but does make the called routine copy the argument into a local and use the copy. The net effect to the caller is like pass-by-value - the thing you pass can't be changed - but the mechanism is different.
If you DO have BIND(C), then VALUE means doing it like C without the & - the argument list contains the data, not the data's address.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve, that clears it up for me.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
We've fixed this for the 14.0 compiler release, due out in September, but the new behavior won't be enabled by default. We found that the change broke some of the modules we supply and we didn't have time to fix them.
For now, you will need to specify the new /assume:std_value option (or /standard-semantics) to get it so that non-BIND(C) routines with VALUE arguments have them passed by reference (and this will make OPTIONAL and PRESENT work). We also cleared up issues with specifying VALUE for arrays (ok for non-BIND(C) routines with the new option, disallowed otherwise.)
We may change the default behavior in a future release.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve,
Above (http://software.intel.com/en-us/comment/reply/393207/1737938?quote=1#comment-form), you said:
Steve Lionel wrote:
The Fortran standard VALUE attribute, in the absence of BIND(C), doesn't change how the argument is passed, but does make the called routine copy the argument into a local and use the copy. The net effect to the caller is like pass-by-value - the thing you pass can't be changed - but the mechanism is different.
I cannot reconcile this statement with what the compiler actually does. Let us restrict ourselves to scalar arguments of built-in-type, say INTEGER. The x86 as well as the x64 assembly outputs for the test program below show that, in fact, passing an argument with the VALUE attribute is implemented with pass-by-value. The x86 assembly code shows that the caller passes the value on the stack. The x64 code passes the value in the first register specified by the ABI (RDI in Linux, RCX in Windows). In both cases, the called subroutine takes the value off the stack/register. There is no creation of a local copy of the argument either in the caller or callee beyond the normal copying of the value to the stack or register according to the normal ABI conventions.
BIND(C) is not involved, I did not use any -std options in compiling to assembly.
As we know, the Fortran standard requires that an explicit interface be available to the caller for calling a subprogram one or more of whose dummy arguments have the VALUE attribute. This means that the caller as well as the callee know about the VALUE attribute. The standard does not specify the argument-passing mechanism, of course, but one needs to know the mechanism when doing mixed-language programming without recourse to ISO C-interoperability.
Please, therefore, clarify the issue.
[fortran]
program tstvalue
implicit none
integer :: a,b
!
interface
subroutine sub(v,x)
implicit none
integer, value :: v
integer, intent(out) :: x
end subroutine sub
end interface
!
a=3
call sub(a,b)
write(*,*)a,b
end program tstvalue
!
subroutine sub(v,x)
implicit none
integer, value :: v
integer, intent(out) :: x
x=v*v
v=0
return
end subroutine sub[/fortran]
Here are the assembly instructions for the subroutine (Linux IFort 13.1.163 Build 2, x64 version)
[bash]
imull %edi, %edi
movl %edi, (%rsi)
ret [/bash]
Had the first argument not been passed by value, the imull instruction would be doing the meaningless operation of multiplying two addresses.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The compiler currently does not implement VALUE for non-BIND(C) routines correctly. It treates VALUE the same as for BIND(C) - it passes and accepts the argument by value. That's not correct and is fixed in version 14, but only if you use the new switch.
The text of mine you quote is me explaining what the standard says - not what ifort is currently doing.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page