I am working on an interface for a rather larger C library and I encounter a problem with gfortran. The attached code is accepted by Intel Fortran oneAPI and Flang, but not by gfortran. I wonder whether my approach is correct and gfortran is overzealous.
The thing is: the library uses several C structs that on the Fortran side are merely pointers, so type(c_ptr). I would like to use the renaming feature of the use statement to distinguish the pointers on the Fortran side. So:
module types
use iso_c_binding, c_ptr => c_ptr, pointer_x => c_ptr, pointer_y => c_ptr
end module types
(or variations)
As said both Intel Fortran oneAPI and Flang accept this, but gfortran comes up with the following messages:
46 | type(pointer_y) :: interp
| 1
Error: Type name 'pointer_y' at (1) is ambiguous
chk_ambiguous.f90:47:20:
47 | type(pointer_x) :: obj
| 1
Error: Type name 'pointer_x' at (1) is ambiguous
I have tried various ways of avoiding these error messages but to no avail.
So, my question is: is my approach valid or is it simply not allowed to have several “aliases” for the same type?
(Of course, given the current situation I will have to abandon the idea if I want to support gfortran with this.) chk_ambiguous.f90 (1.1 KB)
POINTER_X and POINTER_Y are accessible from both modules AMBIGUOUS_A and AMBIGUOUS_B. Good code hygiene says to always use the ONLY clause with USE.
Some compilers suppress the error by being able to analyze the modules at the same time as the main program unit, and determine that both modules provide identical associations.
Right, but in actual use both types would need to be accessible. The solution would be to hide them in the using modules and require that the user uses the types module in the program?
I’m a little surprised that this compilation fails too. Just out of curiosity, I compiled the code with flang and with nagfor and the compilations all succeed (with warnings about unused arguments, but that’s ok).
There is no problem with having multiple aliases to the same entity. I experimented with your code by defining multiple aliases to c_int (an integer parameter) instead of c_ptr (an intrinsic derived type). In this case, gfortran compiled the code with no problem. This looks perhaps like a problem that is specific to c_ptr? Here is that working code:
module types
use, intrinsic :: iso_c_binding, ik => c_int, jk => c_int
end module types
module ambiguous_a
use types
implicit none
contains
function func_a( i )
integer(ik) :: func_a
integer(jk), intent(in) :: i
func_a = i
end function func_a
end module ambiguous_a
module ambiguous_b
use types
implicit none
contains
function func_b( i )
integer(ik) :: func_b
integer(jk), intent(in) :: i
func_b = i
end function func_b
end module ambiguous_b
program use_ab
use ambiguous_a
use ambiguous_b
integer(ik) :: i = 1
integer(jk) :: j = 2
print *, func_a(i), func_b(j)
end program use_ab
I thought that maybe it was the odd looking alias c_ptr => c_ptr causing the problem, but when I did that with c_int, the code still worked.
I guess in that case, since they have the same name, you would need to rename or hide one of them in the module where they are both accessible. I’m unsure if this is required by the standard or if it is a workaround for a gfortran compiler bug.
Hm, funny that it should work with a kind parameter but not with a derived type. I guess it is easier to check that the names refer to the same entity than it is with derived types.