Doctor Fortran Gets Explicit - Again!

Nearly 11 years ago (!) I wrote an item for the Visual Fortran Newsletter on explicit interfaces in Fortran. In recent weeks, I have had to refer quite a few customers to this article, suggesting that many Fortran programmers don't understand the role and rules of explicit interfaces. However, when I reread the item, I realized that things had changed a bit since Fortran 95, so I figured it was time to revisit the issue.

In Fortran-speak, an "interface" is information about a callable procedure. Fortran 77 had only "implicit interface" where the only thing you could say about a procedure was the datatype of a function result. While the language said that arguments in a call must match in number, order, type and rank (number of dimensions), there was no way to describe the arguments so that the compiler could check them. Furthermore, a compiler did not need to know these things because it didn't affect how arguments were passed.

Enter Fortran 90. Suddenly, things get a lot more complicated. For example, a dummy argument could be an assumed-shape array, requiring the call to supply information about the array bounds. Arguments could be OPTIONAL, requiring the caller to somehow indicate that an argument was omitted. Even more fun, a function could return an array or a character value whose length was dependent on some function of the arguments. All of these things, and more, required the ability to describe in detail the procedure and its arguments so that the compiler could call the procedure the right way. This information also helped correctness as the compiler could now check to make sure you were passing the correct arguments. This set of information is called an "explicit interface".

There are several ways to provide an explicit interface. The simplest and best way is to put the procedure in a module, or make it a CONTAINed procedure of the calling program or procedure. This has the advantage of not requiring you to write the information twice and thus increasing the chances of getting it wrong in one of the places. When you have a module procedure, or a contained procedure, its interface is automatically visible to everything else in the module or in the parent scope. Assuming the name hasn't been declared PRIVATE, the interface is also available to places where you USE a module containing a module procedure.

There is an additional way of declaring an explicit interface, an INTERFACE block. In most cases, you should avoid writing INTERFACE blocks for Fortran procedures as it duplicates information, but sometimes it can be handy to do so if you are updating an older program. Just remember that the language does not allow "interface to self" - that means, you can't have an interface visible in the scope where the procedure itself is defined. Note that my admonition to avoid INTERFACE blocks doesn't apply when you want to declare a generic interface as long as you use a MODULE PROCEDURE or PROCEDURE declaration in the list of specific routines in the generic interface.

In many cases, especially if you are sticking to abilities that were in Fortran 77, you don't have to provide explicit interfaces, though it's a good idea to do so. But, as I explained in my 2001 article, there are circumstances where the language requires you to have an explicit interface visible to the caller. The list of things that trigger this requirement grew in Fortran 2003 and again in Fortran 2008. Here is the current list (section 12.4.2.2 of Fortran 2008 if you want to follow along):

A procedure other than a statement function shall have an explicit interface if it is referenced and

  1. a reference to the procedure appears
    1. with an argument keyword, or,
    2. in a context that requires it to be pure,
  2. the procedure has a dummy argument that
    1. has the ALLOCATABLE, ASYNCHRONOUS, OPTIONAL, POINTER, TARGET, VALUE, or VOLATILE attributes,
    2. is an assumed-shape array,
    3. is a coarray,
    4. is of a parameterized derived type, or
    5. is polymorphic,
  3. the procedure has a result that
    1. is an array,
    2. is a pointer or is allocatable, or
    3. has a nonassumed type parameter value that is not a constant expression,
  4. the procedure is elemental, or
  5. the procedure has the BIND attribute.

(Statement functions and an assumed-size function result are features that are deemed obsolescent or "deprecated" )

The most common mistake made in not providing an explicit interface is when calling procedures with OPTIONAL or POINTER arguments. Programmers read about these features and decide to add them to their F77-style code, and then complain when the program dies with errors such as access violation. But how can you find the places where you need an explicit interface? Intel Fortran is here to help!

Since version 9.1, the Intel compiler has supported a feature called Generated Interface Checking. If this is enabled and the compiler sees an "external" procedure (one not in a module or otherwise CONTAINed), it generates an interface based on the attributes it sees and saves it in a compiled module file (.mod) with the name of the procedure followed by "__genmod.mod". It also generates a .f90 file with a human-readable version of this interface, but this is not used by the compiler. Then, when it comes across a call to a procedure for which there is not already an explicit interface, it looks to see if there is a generated one. NOT as a substitute for where the language requires it, but so that it can compare the call to the generated interface and complain if there are any errors. These errors could include calling with the wrong number or types of arguments, or a situation where the language requires an explicit interface but none is provided.

On Windows, Generated Interface Checking (Fortran > Diagnostics > Check Routine Interfaces) is on by default in the Debug configuration of newly created Visual Studio projects. From the command line, you can enable it with /warn:interface on Windows and with -warn interface on Linux and Mac OS. I highly recommend using this option in your builds. It is not perfect, however. In particular, it is sensitive to the order in which files were compiled. If a source that calls a routine is compiled before that of the source that defines the routine, there is no generated interface to check. There can also be an issue if you are editing sources and don't do a "clean" build as there may be an interface from an earlier version of the source still around. And then there are the occasional bugs, though these are rare nowadays.

In summary, it is good Fortran practice to have explicit interfaces for all your procedures. The best way to accomplish this is to have all procedures in modules or as contained procedures if they will be used in limited contexts.

Categories:
For more complete information about compiler optimizations, see our Optimization Notice.

Comments

's picture

Fortran without explicit interfaces was a debugging nightmare. This was also dreadful for large code bases where C/C++ interoperability is a reality you have to get to grips with. The issue largely addressed with 2003 ISO C bindings which finally allowed interfaces to be defined explicitly rather than the host of hacks everyone had to learn previously. Fortran users now just have to start using these nice features ;-)

's picture

Hi Steve,
We are using "Intel Visual Fortran Compiler Integration for Microsoft Visual Studio* 2008" just to compile old fortran codes and generate executables files.
We can see that this tool is too much powerful, it can access databases, create visual interfaces, etc.
Is there any kind of training to use this features?
Thanks in advance,
L.

's picture

I always thought the linker should do the argument checking, intead of making the programmer make more declarations. I could have six subroutines called SORT in a library, with different combinations of arguments, and the linker would pick the right one.

's picture

Okay, I understand now. How bad would it be just to add this to the caller?

USE procedure_with_optional_arg__genmod

As long as the procedure_with_optional_arg is compiled first (by, say, Makefile dependencies) this seems to be safe (if non-portable).

I suppose it would be easier to put them in a module instead of inventing a new way to hack around this requirement.

- Nooj

billsincl's picture

I still think this is more complicated than it needs to be -

A lot of the complexity can be avoided by allowing the CALLING routine to supply more info at execution time. This would take up more storage in the compiled code, but not very much compared to the entire body of code.

Example:
TYPE (integer*4, real*8, pointer, etc.)
address lower bound
address upper bound

This still allows one to have embedded arrays. For example, there are a lot
of places where you would to operate on the row or column of an array without
having to know the entire limits of it. But still it prevents the CALLED routine from going outside the proper storage area.

Bounds checking still eats up execution time though. I guess that's a penalty we are
accustomed to living with.

I think its a very good idea to have tha LINKER do argument checking rather than the compiler,
but that would probably require a major revision to it. However, it could then be more useful for
combination C++ and Fortran mixed applications.

Steve Lionel (Intel)'s picture

It's not complex at all if you use modules and contained procedures. Then all the hard work is done for you. You should strive to avoid "implicit interfaces" in your code, using modules and contained procedures everywhere. The problem is that implicit interfaces are still allowed in the language - some users have asked us to implement an option that forces an error should implicit interfaces be used.

Steve
Lauri J.'s picture

Hi Steve!

I don't know, if this is the right place for my question, but couldn't find better discussion thread for this.

My problem is, that I'm not sure how Subroutines work under Modules. In my program, there is one very big allocated array. I have allocated that array in a subroutine under module. The subroutine under module also initialize that array (puts data to that array). I have to use that big/ large array later in my program, many times in many subroutines. If i want to use that array in other subroutines (subroutines that arent under same module that allocation happens), I have to use USE statement for module and call "CALL subroutinename(largearray) in every subroutine that I want to use that largearray.

My concern is, that when I call that subroutine "subroutinename(largearray)" which is under a module, does it everytime perform that subroutine again from beginning till the end? If it does so, it takes a huge time always to initialize the array (stupid and noneconomical), because its done in same subroutine "subroutinename". It is said, that modules can share data like COMMON BLOCK structures, what does it really means? Is it so, that when program starts, modules are run automaticly, and after that you can use every data that you want from module, like COMMON BLOCK variables? In other words, it won't perform subroutines under modules everytime again when calling some variables with CALL statement?

Best regards: Lauri - Newbie with Modules

Steve Lionel (Intel)'s picture

Lauri,

Rather than replying to a blog post, I recommend you ask questions in our user forum at http://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows or http://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x , depending on which OS you use.

Your question isn't really related to explicit interfaces, though it's good that you are using modules. What matters here is where the array is declared, not where it is allocated or initialized. I am a bit confused about what you are doing as you say you are calling the subroutine and passing largearray as an argument. This implies that it is declared either in the calling procedure or maybe it's a module variable.

For a variable that you want to access in many places in the program, a simple method is to declare the array in the module, before the CONTAINS. This makes it visible to every routine that has a USE of the module (or is in that module already). Making it allocatable is good - you'd have one routine to do the allocation and initialization once, then that would not have to be done again in the program. Yes, each time you call a subroutine it executes all the logic until it returns.

The disadvantage of a module variable is that it can make it more difficult to add parallelism to the program, but with suitable use of OpenMP directives, or the compiler's auto-parallelism, it can work.

I don't recommend COMMON blocks in new code - use module variables instead. If you have further questions, please ask in one of our forums linked above, and I, or some of our many expert users, will be happy to help.

Steve

Steve
Lauri J.'s picture

Hi Steve!

Thank You very much, I got the point about using modules. I think the best way to pass allocated arrays (even with large arrays) to subroutines is do it just like with nondynamically allocated arrays (pass simply as arguments). I would want to get effort from Intel fortran compiler's autoparallelism capacity, so I wont use module variables. Only stupid thing to pass dynamic arrays via arguments is that I have to pass arrays' dimension variables to subroutines also. Using arrays as module variables would be much more "better looking" way.

Sorry for posting my subject to wrong thread, nextime I know the right channel, and thank you once again! You really have nice service from Intel!

- Lauri

Steve Lionel (Intel)'s picture

Lauri,

You don't have to pass the dimensions separately if you used "assumed-shape" arrays, with DIMENSION(:). This does require an explicit interface, which you get with modules.

Steve

Steve

Pages