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

Scope of USE statement within a module

Bill1
Beginner
1,233 Views

I am using a module within a module and expected to get a compilation conflict error for variable IB in the sample shown below, but did not.  I looked in the forum and the problem seems similar to this recent post, but is not quite the same: https://community.intel.com/t5/Intel-Fortran-Compiler/Scope-of-USE-statement-in-an-INTERFACE-block/td-p/1252444/jump-to/first-unread-message

If IB is declared in subroutine DYN_IN, program compiles but IB declared within INPUT_DATA seems to be ignored (IB within main program remains 0).  If IB is not declared in DYN_IN, program functions as expected and IB becomes 1 in the main program.  Is this a bug or am I making an error?  Thank you!

PROGRAM MODTEST
   USE INPUT_DATA
   USE DYNAMICS_DATA
   IMPLICIT NONE
   IB = 0
   CALL DYN_IN
   STOP
END

MODULE INPUT_DATA
   INTEGER(4) IB
END MODULE INPUT_DATA

MODULE DYNAMICS_DATA
   IMPLICIT NONE
   INTERFACE
     MODULE SUBROUTINE DYN_IN
     END SUBROUTINE DYN_IN
   END INTERFACE
END MODULE DYNAMICS_DATA

SUBMODULE (DYNAMICS_DATA) DYNAMICS_SUBMOD
   USE INPUT_DATA
   IMPLICIT NONE
CONTAINS
   MODULE SUBROUTINE DYN_IN
     IMPLICIT NONE
     INTEGER(4) IB ! should this be an error due to conflict with INPUT_DATA?
     IB = 1
   END SUBROUTINE DYN_IN
END SUBMODULE DYNAMICS_SUBMOD

 

Labels (1)
0 Kudos
10 Replies
DavidWhite
Valued Contributor II
1,216 Views

I would expect that IB within DYN_IN would be a local variable and that you would have no access to IB in the module.

Local variables with the same name as a global entity take precedence.

0 Kudos
mecej4
Honored Contributor III
1,191 Views

Please consider the following line of thought.

Suppose there was no declaration of the variable IB in DYN_IN.  Would the variable still be available in the module subroutine because of host association or use association? IB is available by use association in the submodule that contains DYN_IN. Inside the contained subroutine DYN_IN, however, it is available by association from the immediate host, i.e., the submodule.

Local variable declarations override variables of the same name that are host-associated. Local variable declarations come into conflict with variables of the same name that are use-associated.

It would be instructive to move USE INPUT_DATA from the submodule into DYN_IN and try compiling the modified code. The compiler may alert you to the conflict between use-associated variables and the local variable.

Things may become more complicated if, instead of simple variables as in this example, we have some variables that have the pointer attribute.

Bill1
Beginner
1,182 Views

Thank you for the great explanation.  I had started in the habit of sometimes placing the USE statement one time in the specification portion of module above the CONTAINS statement rather than repeating it multiple times in perhaps several dozen subroutines below.  I can see that doing this can cause possible unexpected adverse behavior without error or warning in the compile.  By moving the USE statement within the subroutine I did get the error that I was looking for, so I will proceed in that fashion.

0 Kudos
FortranFan
Honored Contributor II
1,172 Views
@Bill1 wrote:
.. I had started in the habit of sometimes placing the USE statement one time in the specification portion of module above the CONTAINS statement rather than repeating it multiple times in perhaps several dozen subroutines below.  I can see that doing this can cause possible unexpected adverse behavior without error or warning in the compile.  By moving the USE statement within the subroutine I did get the error that I was looking for, so I will proceed in that fashion.

 

@Bill1 ,

What you've decided as per quoted comment above can prove rather onerous and limiting with library code, especially as the code tries to achieve more complex tasks.

I suggest you look into ", ONLY : " clause with your USE statements (look at only-list in the link below):

https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/language-reference/a-to-z-reference/t-to-z/use.html

And also study the IMPORT facility introduced starting with Fortran 2018 and the ONLY clause with it also:

https://software.intel.com/content/www/us/en/develop/documentation/fortran-compiler-oneapi-dev-guide-and-reference/top/language-reference/a-to-z-reference/h-to-i/import.html

The above combination can provide you with better control of associated entities (whether via use-association or host-association) and reduce "namespace pollution" and "collisions" as referred to in programming parlance.

Here's a variant of your code for a hypothetical scenario to show these options:

MODULE INPUT_DATA
   INTEGER(4) IB
   real :: x
END MODULE INPUT_DATA

MODULE DYNAMICS_DATA
   IMPLICIT NONE
   INTERFACE
     MODULE SUBROUTINE DYN_IN
     END SUBROUTINE DYN_IN
   END INTERFACE
END MODULE DYNAMICS_DATA

SUBMODULE (DYNAMICS_DATA) DYNAMICS_SUBMOD
   USE INPUT_DATA, only : x !<-- say, access is needed only to x in this submodule
   IMPLICIT NONE
CONTAINS
   MODULE SUBROUTINE DYN_IN
     IMPORT, NONE !<-- say "DYN_IN" is a simple routine and no access to module entities are needed
     INTEGER(4) IB 
     IB = 1
   END SUBROUTINE DYN_IN
   ! Additional procedures which consume 'x' from INPUT_DATA may be contained below
END SUBMODULE DYNAMICS_SUBMOD

PROGRAM MODTEST
   USE INPUT_DATA
   USE DYNAMICS_DATA
   IMPLICIT NONE
   IB = 0
   CALL DYN_IN
   print *, "IB = ", IB, "; expected is 0"
   STOP
END

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,153 Views
0 Kudos
JohnNichols
Valued Contributor III
1,147 Views
(lambda () (write '(b1)))

A real thunk.  

0 Kudos
Bill1
Beginner
1,115 Views

Steve-

Thanks for all of your insightful help through the years.  I have been reading your articles since the CVF days.  If Intel is open to user suggestions, I would suggest that the capability for issuing a compiler warning when this host-association conflict occurs would be very helpful, as this can cause erroneous results and be very difficult to track down.  When adding MODULES and IMPLICIT NONE into a 70,000 line legacy code application, it is very easy to trip up on this!

0 Kudos
Steve_Lionel
Honored Contributor III
1,110 Views

I have advocated in the past for "usage" warnings in cases where the usage is standard-conforming but might not be what the programmer expects. The case you cite would have to be something the user asked for explicitly, rather than default, as even informational diagnostics for standard code result in complaints to support. 

There is no "conflict" here - declaring a local variable that overrides a host-associated variable is something commonly done and is in the language for a good reason. I'd have a hard time justifying any sort of diagnostic for this.

 
0 Kudos
andrew_4619
Honored Contributor II
1,100 Views

@Bill1 then adding a USE to an existing code my motto is "only use USE with ONLY" this avoids possible confusions and give clear indication of what the programmer intended and what the routine might modify

Bill1
Beginner
1,133 Views

Thanks for the suggestion.  I have been using ONLY, but usually only in situations where I am adding a USE to an existing subroutine and I know specifically why I have added the USE and usually only when there are a few items to list.  I figure that this helps document the code as well, indicating the reason why the USE was included.  I will look at the IMPORT as well.

0 Kudos
Reply