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

Seemingly unnoticed multiple declarations through USE statements

acar
Beginner
1,510 Views
I have a subroutine that uses an array defined elsewhere in the program and accessed through a USE statement. I have found that if the same array name is defined in two different modules and accessed by two USE statements then no warning is flagged up. This is the case even when the arrays (both with the same name) are defined with different sizes. This may be a result of my programming style in which I have assumed that the compiler would protect against such issues rather than explicitly protect myself. Intel's advice would be appreceated. Thanks, ACAR.
0 Kudos
18 Replies
Steven_L_Intel1
Employee
1,510 Views
When you say "accessed by two USE statements" you mean that you have two USEs that make names from those modules visible. This is legal as long as you don't actually reference the array in that program unit. If you do, you will get an error. If you have a test case that shows otherwise, please let us know.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,510 Views
ACAR,

Examine the following program

[fortran]module once
  real :: A(100)
end module once

module twice
  real :: A(200)
end module twice

program UseTwice
  call one
  call two
  call onetwo
end program UseTwice

subroutine one()
  use once
  write(*,*) size(A)
end subroutine one

subroutine two()
  use twice
  write(*,*) size(A)
end subroutine two

subroutine onetwo()
  use once, Aone => A
  use twice, Atwo => A
  write(*,*) size(Aone)
  write(*,*) size(Atwo)
end subroutine onetwo


[/fortran]

Jim Dempsey
0 Kudos
acar
Beginner
1,510 Views
The following is a model of what I think is being allowed:
MODULE MODA
REAL(8)::BORIS(2,2)
END MODULE
MODULE MODB
REAL(8)::BORIS(2,5)
END MODULE
SUBROUTINE TEST
USE MODA
USE MODB
RETURN
END
Two modules somewhere or other in my application with the same variable name (BORIS). The subroutine USEs these two modules and seems to allow the fact that both modules contain the same variable BORIS. Is this expected behaviour since?
0 Kudos
Steven_L_Intel1
Employee
1,510 Views
Yes, that is permitted by the language, as long as subroutine TEST doesn't try to reference BORIS. If I take your example and add a READ of BORIS in TEST, I get this:

t.f90(10): error #6405: The same named entity from different modules and/or program units cannot be referenced. [BORIS]
read (*,*) BORIS
-----------^

It is very common that different modules may declare things of the same name. As long as you don't try to use them, that's fine.
0 Kudos
acar
Beginner
1,510 Views
Thanks Jim, yes that is one solution to the problem but I was rather hoping I would get some warning or error from the compiler that an ambiguity existed. Perhaps in naivety I had assumed that to be the case.
0 Kudos
acar
Beginner
1,510 Views
I should have added an operation to the subroutine using BORIS because that is what I am experiencing in my application - ambiguity being allowed. Actually for the case in question my equivalent to the subroutine TEST doesn't explicitly operate on BORIS, rather it passes it to another subroutine which then operates on BORIS.
0 Kudos
Steven_L_Intel1
Employee
1,510 Views
If it so much as names BORIS you should get an error. Please show me an example where it doesn't.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,510 Views
You also have to include local variable names

module foo
real :: BORIS(123)
end module foo

module foofoo
real :: BORIS(456)
end module foofoo

subroutine one
real :: BORIS(789)
call test(BORIS) ! local scope
end subroutine one

subroutine two
use foo
call test(BORIS) ! BORIS within foo
end subroutine two

subroutine three
use foofoo
call test(BORIS) ! BORIS within foofoo
end subroutine three

It is not unusual for modules and subroutines to potentially contain conflicting names (e.g. TEMP, X, Y, Z, etc...)

I do not have a newer version of IVF (currently on 11.0.66) so I do not know if the newer versions permit scoping operators, which would permit something like the following:

subroutine four
use foo
use foofoo
call test(foo::BORIS)
call test(foofoo::BORIS)
end subroutine four

*** the above only valid if compiler supports scoping operator

Maybe Steve can comment on scoping operators, as to if present or if considered.

Jim Dempsey

0 Kudos
Steven_L_Intel1
Employee
1,510 Views
There are no "scoping operators" in Fortran.

A local variable does not hide a name made visible from a module - that gets you an error. However, a local variable DOES hide variables that are defined in an outer scope.
0 Kudos
acar
Beginner
1,510 Views
Okay, I've looked in further detail at my code. What I have is not quite what I suggested, it is as follows:
MODULE MODA
USE MODB
REAL(8)::BORIS(2,2)
END MODULE
MODULE MODB
REAL(8)::BORIS(3,3)
END MODULE
SUBROUTINE TEST
USE MODA
RETURN
END
So MODA makes two forms of BORIS available to the routine TEST which does not pick up the ambiguity.
0 Kudos
Steven_L_Intel1
Employee
1,510 Views
Your actual source probably doesn't look like that. If I take your test case and correct it so that MODB is compiled first, I get:

t.f90(6): error #6401: The attributes of this name conflict with those made accessible by a USE statement. [BORIS]
REAL(8)::BORIS(2,2)
---------^
0 Kudos
krishnabc
Beginner
1,510 Views
When I moved the COMMON BLOCKs ofa legacy code to MODULEs and access the variables via USE statements, I did getnumerous error #6401 and error #6405 that STEVE described for the locally declared variables/multiple declarations.
0 Kudos
acar
Beginner
1,510 Views
Well, this opens up a further question Steve. I have numerous module spread around my application all in seperate files. I don't tell the compiler the order of compilation. So maybe this is the issue I am having? This issue harks back to a question I raised about a month ago on managing modules. My application has grown over a number of years and with it my skill at programming. I'm sure I have redundant USE statements in the application but no practical way of eliminating them.
What happens if you compile without modifying my example - perhaps putting the two modules in seperate files?
0 Kudos
Steven_L_Intel1
Employee
1,510 Views
If you are using Visual Studio and have the modules in separate files, they will be compiled in the correct order. As you had the source, the module with the USE was before the module it USEd. What might happen is that if the USEd module had been compiled previously, that earlier definition would be used. Intel's compiler requires that a module be compiled before any USE of it is seen, so if the module and the USE are in the same source, the module must come first. If they are in separate files, as I mentioned earlier, Visual Studio's project dependence analyzer will cause the files to be compiled in the proper order (as long as you don't have circular dependencies.)

Redundant USEs aren't harmful - if you're concerned about this, comment out ones you thing may be unnecessary and see if the source still compiles (and does the right thing.)
0 Kudos
acar
Beginner
1,510 Views
Okay thanks Steve. I'll ignore redundant USEs if they arn't harmful - I can't face the task of going rount 5000 subroutines with the comment/compile check just at the moment.
With regard to the original question regarding multiple declarations I must admit that I'm baffled. It is certainly happening in my application. It has happened before and I've just ignored it but this time it was blatent since the two instances of the array in question where of different sizes. Its a pity I can't send you my application to help sort this out. Probably best thing is for me to keep a note of this and see if I can find the reason - probably something odd that I'm doing!!
0 Kudos
John_B__Walter
Beginner
1,510 Views

Something to keep in mind is that the variables in the different modules are completely independent, even if you use the same name. The actual variable name in the symbol table also includes a reference to the module the variable is in. So it is only when you use two of the modules in the same routine and reference that variable (without explicitly specifying from which module from which to use it) that there is a problem for the compiler to figure out which you mean to access.

They are separate variables even though they have the same name in your mind.

0 Kudos
acar
Beginner
1,510 Views
Thanks John. I did assume that to be the case hence my confusion when my routine appeared to be picking up the wrong instance of the same named variable. I think there is something fishy going on here but need some time to sort this out. I'll report back when I find out what on earth I've done!!
0 Kudos
dannycat
New Contributor I
1,510 Views
I've run into similar problems where modules are not necessarrily compiled in the correct order, in VS,even though they are in separate files. What sometimes happens is that the compiler will attempt to compile a module and fail because of a syntax error BUT the build will continue and complete with the link. However the link must pick up the older object file of the one that failed. This can cause strange things to happen such as the stepping through debug code will be on lines that don't have any executable code. I've looked for a switch thatwill makea build sequence in VSstop once an error has occured (I used to assume this was always the case).

PS I don't think this is the cause of my problem in my recent thread about the strange debug behaviour.
0 Kudos
Reply