Use association of two ultimate entities

Hi,

I have put it in the “Help” category but maybe I misclassified and it should be in compilers.

I have stumbled on the following curiosity. Consider the code below:

module A 
  implicit none
contains 

subroutine foo()
  print *, "A"
end subroutine

end module A

module B 
implicit none

contains 
subroutine foo()
  print *, "B"
end subroutine

end module B

program main 
  use A, only: foo 
  use B, only: foo

  implicit none


end program main

On godbolt: Compiler Explorer

This code is accepted by gfortran,flang and LFortran, which is kind of consistent with my reading on the section 14.2.2 paragraph 8 of Fortran 2023 standard (https://j3-fortran.org/doc/year/24/24-007.pdf), which reads:

An ultimate entity is a module entity that is not accessed by use association. An accessed entity shall not be associated with two or more ultimate entities unless its identifier is not used, or the ultimate entities are generic interfaces. Generic interfaces are handled as described in 15.4.3.4.

However the above snippet is rejected by Intel compilers e.g. Compiler Explorer

Out of pure curiosity I just wonder what is the “correct” behavior in this case. Should explicitly specifying use association (? not sue I am using the term right) in use A, only: foo be considered “using an identifier”.

I was just hoping that people more knowledgeable about Fortran could have some extra insight :slight_smile:

Welcome to the forum!

You create an ambiguity this way and the compiler should warn about it at the very least. It cannot decide which one to use. Of course, since you do not use the subroutine, no harm is done, but I would say this is a situation that is to the discretion of the compiler. But that is my feeble attempt at understanding the standard :slight_smile:

Fortunately, Fortran provides for a way to avoid naming conflicts with module entities

You can do one of the following

USE A, ONLY : fooa=>foo
USE B, ONLY : foo

or

USE A,ONLY: foo
USE B, ONLY:foob=>foo

or

USE A, ONLY:fooa=>foo
USE B, ONLY:foob=>foo

The code is non-conforming but there is no obligation on a compiler to report it as non-conforming.

I think the issue is that the ONLY clause conveys intention to use.

Since ifort/ifx accepts the code then the ONLY clause is not involved (and the symbol is not referenced), it seems that clause means the symbol explicitly becomes part of the program-unit USEing it.

It’s the same as if instead of a main-program-unit you had a third module:

module A
  implicit none
contains
    subroutine foo()
      print *, "A"
    end subroutine
end module A

module B
    implicit none
contains
    subroutine foo()
      print *, "B"
    end subroutine
end module B

module C
  use A, only: foo
  use B, only: foo

  implicit none

end module C

In this case, which foo should be made public from C?

The way I read the standard, there is no need to decide, because foo is not “used” anywhere in module c, which I think means it is not invoked in any statements. This seems like a nice feature, because it would permit you to use two modules that have some conflicting names without needing to rename all the conflicts, rather only the ones you actually invoke.

For example,

module A
  implicit none
  real x, y, z, aaa
  integer i, j, k
contains
    subroutine foo()
      print *, "A"
    end subroutine
end module A

module B
  implicit none
  real x, y, z, bbb
  integer i, j, k
contains
    subroutine foo()
      print *, "B"
    end subroutine
end module B

module C
  use A
  use B

  implicit none
  real x, y, z, ccc
  integer i, j, k

  ! z = x + y ! would cause compiler error because of name conflicts
  aaa = sqrt(bbb**2 + ccc**2)  ! ok because names don't conflict

end module C

How is this line “aaa = sqrt(bbb2 + ccc2)” okay, because the variables aaa and bbb are not defined. There are variables of that name in the modules, but these are explicitly not imported.

I guess that is why it was not made an official constraint in the Fortran spec, and was not given a number.

On the other hand, others might think that this is a horrible feature.

Yes you’re right, my oversight. I copied the code and forgot to remove the “only”.

I’ll fix it.

Both gfortran and ifx complain about the additional scalars :slight_smile: . Not a big deal to correct it.

Yes, it’s not used anywhere in the module, but as I said, I think the ONLY clause makes it a public part of that module. Without the ONLY clause, the compiler will recursively search the modules USEd by C until it finds what it needs, when the module is eventually used.

A module is a compiled thing, so it cannot retroactively adjust itself depending on how it’s used.

(Btw, I’m just speculating in regards to ifort/ifx behavior.)

I think here is a better test example:

module A
  implicit none
contains

subroutine foo()
  print *, "A"
end subroutine

end module A

module B
implicit none

contains
subroutine foo()
  print *, "B"
end subroutine

end module B

program main
  use A
  use B

  implicit none

  call foo()

end program main

This is rejected by GFortran, Flang and ifx. LFortran right now accepts it, but we’ll fix it. An example error from Flang:

$ flang a.f90
error: Semantic errors in a.f90
./a.f90:27:8: error: Reference to 'foo' is ambiguous
    call foo()
         ^^^
./a.f90:22:7: 'foo' was use-associated from module 'a'
    use A
        ^
./a.f90:23:7: 'foo' was use-associated from module 'b'
    use B
        ^

I think you are correct that the variables aaa and bbb are undefined. One way to define them would be to initialize them within their modules.

real x, y, z, aaa = 42.0
...
real x, y, z, bbb = -1.0

However, the last statement is misleading. By default, all public entities are imported by a use statement, so those two variables are in fact imported into module C.

The part that I do not understand is where the error occurs regarding the conflicts. Suppose the three modules and the main program are all in separate files and they are all compiled separately. Suppose further that module C is supposed to be the only public module, and that modules A and B are supposed to be just implementation details of module C. I think modules A and B are correct, meaning standard conforming with no errors. But should module C show an error when compiled? I don’t think so, since it never references any of the entities that have a name conflict (specifically: x, y, z, i, j, k, foo). Similarly if the main program uses C (but not A or B directly) and never references any of those entities, then I think it is correct too. But if the main program does reference one of those entities, then there is a conflict, but that conflict cannot be resolved with the only clause in the main program. The error can only be corrected by modifying module C, which was already standard conforming and correct.

Maybe it is more correct to say that module C can be used correctly, but it has latent conflicts that can arise when it is used and if those conflicts are referenced?

Can the main program resolve those conflicts by using A and B directly?

use A, only: a_foo => foo
use B, only: b_foo => foo
use C
...
call a_foo()
call b_foo()
call foo()

I think the conflict within C is still triggered, right? However the first two calls are now alright. However, this violates the requirement that only C is known to the public, it requires the implementation details of C to be exposed.

Regarding the original question of whether the ONLY clause itself constitutes a reference, I do not know the answer to that part.

@Machalot already corrected some of the code - the original had the lines “use a/b, only: foo”. :slight_smile:

To get more information, I’ve tried compiling the following code

module A 
implicit none
contains 
  subroutine foo()
    print *, "A"
  end subroutine
end module

module B 
implicit none
contains 
  subroutine foo()
    print *, "B"
  end subroutine
end module

module AB 
  use A, only: foo   !! (L1)
  use B, only: foo   !! (L2)
  implicit none
end module

with gfortran-15 -c -fdump-fortran-original, then I get:

(...)
procedure name = ab
  symtree: 'a'           || symbol: 'a'            
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(a) USE-ONLY)
  symtree: 'ab'          || symbol: 'ab'           
    type spec : (UNKNOWN 0)
    attributes: (MODULE )
  symtree: 'b'           || symbol: 'b'            
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(b) USE-ONLY)
  symtree: 'foo'          Ambiguous|| symbol: 'foo'          
    type spec : (UNKNOWN 0)
    attributes: (PROCEDURE MODULE-PROC  USE-ASSOC(a) SUBROUTINE USE-ONLY USE-RENAME IFSRC-DECL)
(...)

So, it seems that gfortran embeds the information that foo is ambiguous into somewhere at compile time (I guess it is embedded in ab.mod file, but I cannot understand the format of the latter…) If I change Lines L1 and L2 as

  use A
  use B

then the output changes as follows:

procedure name = ab
  symtree: 'a'           || symbol: 'a'            
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(a))
  symtree: 'ab'          || symbol: 'ab'           
    type spec : (UNKNOWN 0)
    attributes: (MODULE )
  symtree: 'b'           || symbol: 'b'            
    type spec : (UNKNOWN 0)
    attributes: (MODULE  USE-ASSOC(b))
  symtree: 'foo'          Ambiguous|| symbol: 'foo'          
    type spec : (UNKNOWN 0)
    attributes: (PROCEDURE MODULE-PROC  USE-ASSOC(a) SUBROUTINE IFSRC-DECL)

so gfortran seems to treat the two codes similarly regardless of whether foo is declared with the only clause.

I hope I could try a similar thing for other compilers but don’t know how to…

Yes, and it seems that flang does not do this.

I created a main program like this:

program C
  use AB
  implicit none(type, external)
  call foo()
end program

and gfortran gave the same error as when the call to foo is in AB:

    4 |   call foo()
      |           1
Error: Name 'foo' at (1) is an ambiguous reference to 'foo' from module 'a'

flang seems to omit foo completely from ab.mod because of the name clash, so compiling the above results in it thinking that foo is an external procedure:

error: 'foo' is an external procedure without the EXTERNAL attribute in a scope with IMPLICIT NONE(EXTERNAL)
    call foo()
         ^^^

gfortran’s error is certainly more helpful, though it would be nice to mention foo from module b as well.

I meant it is nice in the sense that you could use two similar modules with conflicting entity names, without the obligation to rename every single conflict, so long as you don’t refer to any of the conflicting names. That is what is meant by the clause in the standard, “unless its identifier is not used,” isn’t it? The compiler would require you to rename the entities that conflict if you refer to them.

It’s often a good practice to write use, only : and explicitly bring in each entity you want, but if you don’t do that, you are still protected from name ambiguity by a compiler error in the even that you refer to one of the conflicting names.

Am I misunderstanding this? What makes you say it’s “horrible”?

ONLY is your only defence against typos. Without ONLY, and with modules A and B both making FOO accessible, with a nod from the compiler, the poor user will be faced with a strange error message at line 3776 for mentioning FOO.

It is recognised as a Vulnerability of the language, you can google “Fortran vulnerabilities”.

I was curious if the rename feature could be used to purposely disable access to entities in separate modules and with distinct variable names.

module a
   integer :: ai = 42
end module a

module b
   integer :: bi = -42
end module b

module ab
   use a, i=>ai
   use b, i=>bi
   implicit none
contains
   subroutine wab()
      use a
      use b
      write(*,*) 'wab() called: ai=', ai, ' bi=', bi
      !write(*,*) 'i=', i                ! error because of conflict
   end subroutine wab
end module ab

program usexxx
   use ab, only: wab, i
   implicit none
   call wab()
   !write(*,*) 'main: ai=', ai, ' bi=', bi
   !write(*,*) 'main: i=', i                ! error because of conflict
end program usexxx

The idea here is that the variables ai and bi are not accessible in the main program, but they are accessible in the wab() subroutine, and the variable i is in conflict wherever it is referenced. This works that way with gfortran:

$ gfortran usexxx.f90 && a.out
 wab() called: ai=          42  bi=         -42

and also with flang. However nagfor reports:

$ nagfor usexxx.f90 && a.out
NAG Fortran Compiler Release 7.2(Shin-Urayasu) Build 7203
Error: usexxx.f90, line 11: USE B, I=>BI invalid because it already refers to AI in A
       detected at =>@BI
Error: usexxx.f90, line 23: Symbol I resolves to AI in module A and to BI in module B
       detected at I@<end-of-statement>
Segmentation violation
Internal error - please report this bug

This gets back to the question of whether mentioning the variable in a use statement constitutes a reference. I guess nagfor thinks it does, while gfortran and flang don’t. Note that the segment violation is from the compiler, not from running the executable.

If any of the write statements are uncommented, then the expected compile time errors are generated with all three compilers.

In the case the write statements are commented out, then I don’t know which is the correct behavior. I was hoping for unanimous agreement. :wink:

Until this thread I thought that a subsequent module shadows what the previous module imports like Python does.

Instead the rule seems to be that modules cannot import the same symbol (whether via use A; use B or via use A, only i; use b, only i), but some compilers (like Flang / GFortran) allow to do it, as long as you don’t use i, kind of “pretending that no harm was done and looking the other way”, but if you use i, then they have no chance but to report it.

I am guessing the reason to “look the other way” is to make it easy for users to use modules with conflicting symbols, as long as you don’t use those symbols.