Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29390 Discussions

Implicit interfaces with optional arguments release/debug issue/question

acar
Beginner
3,900 Views
I'm converting my application written in debug mode to release mode and am noticing an issue. The issue seems to be occurring in a routine that has optional arguments but no explicit interface. It works fine in debug mode but in release mode, whilst the routine is entered, it appears to crash when I do a check for the presence of one of the optional arguments (if(present(opt_arg))then.... Is this behaviour to be expected? I have attached the compiler command lines for both debug and release versions and also the routine in question. The call to this routine that causes the crash is with no optional arguments.
0 Kudos
23 Replies
mecej4
Honored Contributor III
3,168 Views
The Fortran 2003 standard says (boldface added):

22 12.3.1.1 Explicit interface
23 A procedure other than a statement function shall have an explicit interface if it is referenced and
24 (1) A reference to the procedure appears
25 (a) With an argument keyword (12.4.1),
26 (b) As a reference by its generic name (12.3.2.1),
27 (c) As a defined assignment (subroutines only),
28 (d) In an expression as a defined operator (functions only), or
29 (e) In a context that requires it to be pure,

30 (2) The procedure has a dummy argument that
31 (a) has the ALLOCATABLE, ASYNCHRONOUS, OPTIONAL, POINTER, TARGET,
0 Kudos
acar
Beginner
3,168 Views
Thanks but not sure what you are saying. If you're saying that I'm somehow violating the standard then why does it work in debug mode and not in release mode?
0 Kudos
mecej4
Honored Contributor III
3,168 Views
You stated in your post that there is no explicit interface, for a case where the standard requires one. In such circumstances, the code is "non-conforming" and the behavior at run time is "undefined".

In standard-speak, "undefined" is a catch-all phrase. Giving correct results is covered by the term, as are other consequences such as causing reactor melt-downs, spreading E-coli, etc.

Why are you evading the requirement? Provide the needed interface, or have the compiler generate a draft of one for you. In my opinion, probing the behavior of a compiler when it is given non-conforming code is best left to compiler writers.

0 Kudos
acar
Beginner
3,168 Views
I didn't think there was a need for an explicit interface - I was following the example under OPTIONAL in the Intel documentation where the second example doesn't specify an explicit interface. And presumably the compiler should have flagged an error if this were the case. Is my logic flawed?
0 Kudos
TimP
Honored Contributor III
3,168 Views
If you have set options implying /gen-interfaces (which may be implied by debug), the compiler would need to know whether the requirements of the standard are satisfied only by this option in order to complain.
In principle, the compiler should complain about missing required interface when the /stand option is set, but it may not be possible in the case of separate compilation without /gen-interfaces.
0 Kudos
mecej4
Honored Contributor III
3,168 Views
It is risky to draw conclusions from program snippets. On the same page, you can find the statement, "Optional arguments must have explicit procedure interfaces so that appropriate argument associations can be made."

Let me try to describe the reason for the requirement in another way. In standard Fortran 77, there were no optional arguments and no keyword arguments, and an explicit interface was needed only in a small number of cases.

Now consider a subroutine/function reference in Fortran 9X code, together with the requirement of separately compiled source files. How does the compiler know whether the reference is to a Fortran-77 style procedure with a fixed number of arguments, or to a 9X style procedure, possibly with arguments with optional and keyword attributes? It cannot distinguish between the two categories, unless an explicit interface to the callee is available. The standard simply canonizes this requirement.
0 Kudos
IanH
Honored Contributor III
3,168 Views
To rephrase Tim, the interface is what tells the compiler how many arguments a procedure has and which of the arguments is optional. Typically optional arguments are implemented by the compiler passing a marker (often a NULL pointer) in place of the argument. If at the point of call If there's no explicit interface then the compiler doesn't know to pass that marker. Without magic interface checking type features it also doesn't know that you've forgotten to provide an interface. Bingo - welcome to the world of random chance of failure.

Note that if the procedure was a module procedure, then you'd be USE'ing the module (or your link would have failed with a reasonably obvious missing symbol), and the explicit interface would have come for free. Each to their own, but the potential for this sort of bug (or all the other sorts of argument mismatch fun) to be flailing around in my code scares me enough that I'm more than happy to accept any inconvenience associated with compilation cascades due to use of modules.

I think there is a bit of an interfacing checking issue here though - I can trigger an error 8055 (optional, etc, but missing interface) on a small test example with /check:all /warn:all if a call to a procedure with optional arguments has the arguments there, but no error is generated if the optional argument is missing. Odd.

[fortran]! Compile with /warn:all /check:all

SUBROUTINE ITakeAnOptionalArg(a, b)
  IMPLICIT NONE
  INTEGER, INTENT(IN) :: a
  INTEGER, INTENT(OUT), OPTIONAL :: b
  IF (PRESENT(b)) THEN
    b = a
    PRINT "('Present')"
  ELSE
    PRINT "('Not present')"
  END IF
END SUBROUTINE ITakeAnOptionalArg

PROGRAM abc
  IMPLICIT NONE
  INTEGER :: a, b
  a = 1
  ! No explicit interface to the proc.
  CALL ITakeAnOptionalArg(a)      ! No complaint
  CALL ITakeAnOptionalArg(a, b)   ! #8055
END PROGRAM abc[/fortran]
0 Kudos
acar
Beginner
3,168 Views
I've just taken a look in the release and debug directories. Both contain compiler generated interfaces for the routine of interest. I have not explicitly or knowingly changed the /gen_interfaces or /stand compiler options.
0 Kudos
Steven_L_Intel1
Employee
3,168 Views
Yes, I can see that the compiler fails to diagnose the case of just one argument. I will pass that on to the developers. Issue ID is DPD200170308.
0 Kudos
acar
Beginner
3,168 Views
Thanks for that IanH. Your example is of the form I have in my program and I have been using some calls with and other calls without the optional arguments. I have now got to the bottom of this issue and it is that the /warn:[no]interfaces compiler option is more than a warning switch, it actually takes action and automatically generates interfaces for every routine in the project. Somewhat odd since in my mind there is a difference between warning and taking action! So what was happening to me was that for the debug version I had this warning switched on and for the release version it was switched off. For your example, where you have the warning switched on you should be seeing automatically generated interfaces if my theory is correct? Point taken about modularised procedures - I've taken a decision not to go that way for the time being but down the line I may rethink.
0 Kudos
Steven_L_Intel1
Employee
3,168 Views
No - /warn:interfaces IS just a warning switch. It is not a substitute for a required explicit interface. The generated interface blocks are used for error checking only.
0 Kudos
acar
Beginner
3,168 Views
Well that is not what I've just experienced with my code and it doesn't explain why I have been getting away without a user written explicit interface in my application. But let me check again!
0 Kudos
Steven_L_Intel1
Employee
3,168 Views
If you have a test case where, in a current compiler, /warn:interface changes the running code behavior, I want to see it. We have had such bugs in the past, but that's what they are, bugs.
0 Kudos
acar
Beginner
3,168 Views
Just checked again. In the release version of my program I restored a call to the routine which sends no optional arguments. I rebuilt the application with the interface warning off. I ran the application and it crashed within the routine with the optional arguments. Further investigation shows that it crashed because it erroneously thought one of the optional arguments was actually present - see attached code. So, sorry if I'm missing a trick, but I think there is still an issue here.
In the attached code the value of local_selected_numerical_output_format is non-zero at the end of the if clause indicating that the routine is thinking that either number_type or selected_numerical_output_format is present.
0 Kudos
Steven_L_Intel1
Employee
3,168 Views
I would need a compilable version of the routine that calls the routine at issue. Which compiler version are you using?
0 Kudos
acar
Beginner
3,168 Views
Okay, I've managed to recreate the issue in a very small program - VS solution attached. First thing to note is that, presumably this should not compile as there is no explicit interface. Using this simple program I see now that the issue is not the switch for warning about interfaces, it is the switch for Debug Information Format which is changing the results. With this switch on one gets 1 3 from the program (the expected result) however with this switch off we get 1 1 which is the behaviour I was getting with my application. The compiler comes from w_fcompxe_2011.3.175.
0 Kudos
Steven_L_Intel1
Employee
3,168 Views
When you call with fewer arguments, you get whatever is on the stack where the arguments are supposed to be. Anything that pertturbs the memory usage can change the behavior.

The bug we used to see was that a generated interface would sometimes convince the compiler to pass an array by descriptor instead of by reference, when the dummy was assumed shape - for example. It shouls never do that.
0 Kudos
acar
Beginner
3,168 Views
So are you saying that this is expected behaviour or is that a preliminary observation?
0 Kudos
Steven_L_Intel1
Employee
3,168 Views
The expected behavior is that with /warn:interface, it should complain. But in the absence of that, the behavior is unpredictable since this is a coding error.
0 Kudos
mecej4
Honored Contributor III
3,083 Views
>First thing to note is that, presumably this should not compile as there is no explicit interface.

Incorrect presumption. Because of separate compilation, when the required explicit interface is missing the compiler has no way to detect that fact. It will compile but the resulting program is probably going to be defective, as you saw in "Release Mode".

That the explicit interface is missing can only be detected if the subroutine is compiled first, the interface memorized and used when compiling the calling code -- which is what the /warn:interfaces option attempts to perform for you.
0 Kudos
Reply