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

Argument checking is not working

bcartolo
Beginner
676 Views
Hi there,
I have an intel fortran project with a subroutine (Lets call it sub A) that calls another subroutine (sub B).
If I add a dummy argument to sub B, clean and rebuild, I get a nice Build succeeded, for example:
[fortran]subroutine A(l, j) implicit none integer, intent(in):: l, j call B(l,j) endsubroutine[/fortran]
but B now is something like
[fortran]subroutine B(l, j, k) implicit none integer, intent(in):: l, j integer, intent(out):: k k = l+j endsubroutine[/fortran]
Is there anyway the compiler can tell me about this?
I have/warn:interfaces and/gen-interfaces as is explained in this thread:
but still nothing!
I haveIntel Visual Fortran Compiler Professional 11.1.048
Any idea? it is really painfull to check by hand!
0 Kudos
1 Solution
IanH
Honored Contributor II
676 Views
Short answer - because that's what modules do.

Long answer - when you put a procedure in a module and then 'use' that module in another scope, then the procedure automatically gains in that other scope what is known as an explicit interface. Practically this means that the compiler must have compiled the source file containing the module before it sees the USE statement, consequently the compiler knows everything about how the procedure should be called when it see the call, consequently it can check that the right arguments have been provided.

("Guaranteed" in my example was a bit strong - I thought the standard required checking, but I might have been wrong. I suspect though, that if a compiler didn't check a call against an explicit interface then most compiler vendors would regard that as a compiler bug.)

If you use external subprograms, as you were originally doing, then there's no guarantee that the source for subroutine B will be compiled before the call, consequently there's no guarantee that the compiler can check the call.

(This lack of required compilation ordering with external subprograms is important in a few case, outside of those cases all procedures should either be module procedures or internal procedures.)

Thread safety is an orthogonal issue to use of modules. You can create thread-unsafe code without using modules, you can create thread-safe code using modules.

(There are multiple ways in which a program can be multi-threaded (automatic parallelization, coarrays, openmp, native threads...) - particularly when you start getting towards the end of that list (the stackoverflow example you link to is at the native thread level) then the whole program's design needs to be mindful of thread safety. Other traditionally non-threaded languages have exactly the same issues.)

View solution in original post

0 Kudos
9 Replies
Anonymous66
Valued Contributor I
676 Views

How are you compiling the program? Subroutine A needs to be able to see the interface for Subroutine B at compile time for warn interfaces find the problem. If the subroutines are compiled separately and subroutine A is compiled before subroutine B, theproblem will not be detected.

0 Kudos
bcartolo
Beginner
676 Views
I go to Build->Build Solution
Both subroutines are in the same project and solution.
Does that answer your question?
Thanks!
0 Kudos
Udit_P_Intel
Employee
676 Views
Hello,
warn:interfaces does seem to catch this inconsistency with a 12.1 compiler. I ran your program using:

x:\cq\testing>ifort /warn:interfaces a1.f90
Intel Visual Fortran Compiler XE for applications running on IA-32, Version 12.1 Beta Build x
Copyright (C) 1985-2012 Intel Corporation. All rights reserved.

a1.f90(5): error #6631: A non-optional actual argument must be present when invoking a procedure with an explicit interface.
call B(l,j)
---------^
compilation aborted for a1.f90 (code 1)

This functionality may have been provided later than the 11.1 compiler. I'd recommend using a newer compiler.
Best!
-Udit
0 Kudos
bcartolo
Beginner
676 Views
The code above was just an example, not my actual case. I sometimes get error #6631, but not always!
Can't use another version of fortran because of: Money, compatibility with abaqus.
0 Kudos
IanH
Honored Contributor II
676 Views
If you control the source of subroutines A and B, then put B in a module.

(If abaqus is calling B directly (not via A) then you won't be able to do this, but in that case adding arguments to B would also get you into trouble.)

[fortran]module my_module_name implicit none contains subroutine B(l,j,k) integer, intent(in) :: l, j integer, intent(out) :: k k = l + j end subroutine B end module my_module_name subroutine A(l, j) use my_module_name implicit none integer, intent(in):: l, j ! Missing argument error guaranteed to be reported for the following line. call B(l,j) end subroutine A [/fortran]
0 Kudos
bcartolo
Beginner
676 Views
Thanks!
But why putting the subroutine in a module will fix my problem?
Also, will I have multihreading issues with this?
My past experience with modules is that they are not thread safe.
Best
0 Kudos
IanH
Honored Contributor II
677 Views
Short answer - because that's what modules do.

Long answer - when you put a procedure in a module and then 'use' that module in another scope, then the procedure automatically gains in that other scope what is known as an explicit interface. Practically this means that the compiler must have compiled the source file containing the module before it sees the USE statement, consequently the compiler knows everything about how the procedure should be called when it see the call, consequently it can check that the right arguments have been provided.

("Guaranteed" in my example was a bit strong - I thought the standard required checking, but I might have been wrong. I suspect though, that if a compiler didn't check a call against an explicit interface then most compiler vendors would regard that as a compiler bug.)

If you use external subprograms, as you were originally doing, then there's no guarantee that the source for subroutine B will be compiled before the call, consequently there's no guarantee that the compiler can check the call.

(This lack of required compilation ordering with external subprograms is important in a few case, outside of those cases all procedures should either be module procedures or internal procedures.)

Thread safety is an orthogonal issue to use of modules. You can create thread-unsafe code without using modules, you can create thread-safe code using modules.

(There are multiple ways in which a program can be multi-threaded (automatic parallelization, coarrays, openmp, native threads...) - particularly when you start getting towards the end of that list (the stackoverflow example you link to is at the native thread level) then the whole program's design needs to be mindful of thread safety. Other traditionally non-threaded languages have exactly the same issues.)
0 Kudos
bcartolo
Beginner
676 Views
Thanks!
I suppose I will do one module for each subroutine.
Best
0 Kudos
IanH
Honored Contributor II
676 Views
Instead consider going through your source and grouping related procedures (particularly from the point of view of how they are used) together into a module. Having lots and lots of "little" modules (each with one subroutine) just creates complexity without any benefit.
0 Kudos
Reply