With -C checking turned on I am getting a spurious shape mismatch runtime error for an absent optional argument. Here a reproducer:
program main real :: a(2) a = [1,2] if (foo(a) /= 2) stop 1 contains real function foo(x, m) real, intent(in) :: x(:) logical, intent(in), optional :: m(:) foo = maxval(x, m) end function end program
When compiled like this:
ifort -C -standard-semantics -traceback foo.f90
I get this when I run:
$ ./a.out forrtl: severe (408): fort: (33): Shape mismatch: The extent of dimension 1 of array X is 2 and the corresponding extent of array M is 0 Image PC Routine Line Source a.out 00000000004064DF Unknown Unknown Unknown a.out 000000000040391C MAIN__ 4 foo.f90 a.out 0000000000403862 Unknown Unknown Unknown libc-2.32.so 00007F7C899081E2 __libc_start_main Unknown Unknown a.out 000000000040376E Unknown Unknown Unknown
This seems to effect just the intrinsic minval, maxval, minloc, and maxloc (and perhaps others).
It is curious that there is no runtime error if the array A is of type integer instead of real. And without -C the executable runs without error (and gets the correct result).
if ( present(m) )then foo = maxval(x, m) else foo = maxval(x) endif
Not pretty but surely you need something like the above. The optional maxval arg cannot be a not present optional dummy arg. It is also not that surprising that the compiler does not complain and you get a run time error. In many cases it would not be possible to for the compiler to easily unpick the logic to know if there was a possible problem
The optional maxval arg cannot be a not present optional dummy arg.
Can you point to where the standard says this? I was suspicious this might be the case, but I've looked and I can't find this restriction. 126.96.36.199 seems to be the relevant section and it isn't listed there, nor with the description of maxval itself. FWIW, both the NAG compiler and gfortran handle the presence and non-presence of the optional mask dummy argument in this usage pattern without error, and compute the expected result. So too does the Intel compiler if the "-C" option isn't used. If maxval were my own function and not an intrinsic, then this usage pattern is definitely valid.
I reviewed the standard's text about "argument presence" (188.8.131.52.12) and see nothing to suggest that MAXVAL should not support a not-present optional argument. It takes a bit of extra run-time code to handle this, but not much.
I can see it would be desirable for an intrinsic to ignore this in this example. However, looking at it the other way around there may be an absence of a prohibition but does the standard prescribe the behaviour or is it undefined? I have always assumed that it was down to me to sort out the presence or not of optional args.
After the long list of restrictions on "argument presence" in 184.108.40.206, p4 states "Except as noted in the list above, it may be supplied as an actual argument corresponding to an optional dummy argument, which is then also considered not to be present." So my understanding is that the behavior I expected is prescribed, and not undefined.
Passing non-present optional arguments as actual arguments seems to be rather complex and the cause of confusion in usage as well as likely to expose compiler bugs. We can see such problems in a seven-year old thread in this forum.
I do appreciate that lots of IF (PRESENT(opt_arg)) THEN ... ELSE ... ENDIF blocks would be required if this were not allowed, but sometimes it is not clear which option is worse.
@JohnNichols says "My friends say my definition of interesting is not normal. "
“The only glory most of us have to hope for is the glory of being normal.”
Katherine Fullerton Gerould
Doc (not an Intel employee or contractor)
[Waiting for Windows 12]
That was an in interesting old thread! I have just always assumed when using optional args that if present(arg) is not true then it is no touch, end of thinking. That seems a safe assumption with all these edges cases that may or may not be legal or defined. I must admit to never having cascades of present() checks because a frequent usage case for me is adding an extra arg to an existing routine without breaking (or having to look at) existing usage. If present I set a local variable to the value of the arg else I set the local var to a default value that does not effect the previous uses of the routine. A little bit of thinking at the design stage finds ways to work around these things without too much effort.
For whatever it's worth, I think the code in the original post conforms and Intel Fortran would do well to support it also under the circumstances mentioned i.e., with the check conditions in effect during run-time with -check (or -C) compiler option.
As illustrated in the posts by @Steve_Lionel , the standard supports the case of an optional dummy argument to be an actual argument in calls to both intrinsic and nonintrinsic procedures where it will be considered absent if not present in the caller.
And the standard spikes out the situations with a few intrinsics such as COUNT, LBOUND, UBOUND (and its coarray variants) where with DIM optional argument, the above facility doesn't make sense and thus it states in the rules for each of these intrinsics, "The corresponding actual argument shall not be an optional dummy argument, a disassociated pointer, or an unallocated allocatable."
@NCarlson , you may want to submit a request at Intel OSC if you have support subscription, or wait for an Intel team member to pick up the incident from here.
Thanks much @Barbara_P_Intel for picking this up.
For whatever it's worth, please try the case in the original post (say in file p.f90) with the *UX equivalent of Windows:
"ifort /check:all /check:noshape p.f90"
The point being something you and the Intel Fortran team may be well aware that it is the check:shape option that may be at the root of it here also. /check:shape was a very nice thought for the users of Intel Fortran but it appears to require a thorough review and overhaul of the implementation from what I can "tell" from a distance.
This brings memories: with a team I had worked with a while ago, they had preferred to employ the -check:all option during a certain debugging phase, however -check:shape had posed way too many problems than it had helped with what was otherwise good, conforming code. I had suggested -check:noshape to the team as a companion compiler option to be considered with such problematic cases - they had accepted that and followed it. (That the team has since moved away from Fortran unfortunately is another sad story).