Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Bill1
Beginner
187 Views

Scope of USE statement within a module

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/t...

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
Black Belt
170 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.

mecej4
Black Belt
145 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
136 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.

FortranFan
Honored Contributor I
126 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 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...

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

 

Steve_Lionel
Black Belt Retired Employee
107 Views

And again, I have a Doctor Fortran post that relates to this topic! Doctor Fortran in "Think, Thank, Thunk" - Doctor Fortran (stevelionel.com)

 
JohnNichols
Valued Contributor I
102 Views

(lambda () (write '(b1)))

A real thunk.  

Bill1
Beginner
87 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.

Bill1
Beginner
69 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!

Steve_Lionel
Black Belt Retired Employee
64 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.

 
andrew_4619
Valued Contributor III
54 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