Flang fails when compiling an application under certain scenarios involving same-named modules
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
#################
Issue Summarize
#################
When there exist modules with same name but different functionality,
if an unintended same-named module is indirectly referenced via another module at the time of USE,
and the intended same-named module is USEd afterwards, the intended module will not be re-parsed.
This results in missing symbols and triggers compilation errors.
The issue is firstly found in Amber Project.
-----------------------------------------------------------------------------------------------------------
NOTE: flang version as below:
```
$ flang --version
flang version 24.0.0git (https://github.com/llvm/llvm-project.git 257e81f2e9a67cb857bd6f801e1708c96bee99e4)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /module/caiwei/rep/llvm-project/build-flang-release/install/bin
Build config: +assertions
```
Here we simplify the reproduced cases as testcase_1 and testcase_2
Both case can successfully build by gfortran
##################################################
case 1: (related reproduce case is testcase_1)
#################################################
scenario describe:
We have two same-named modules "module_data", but they have different functionality,
one is in data/module_data.F90 and the other is in mydata/module_data.F90, like below
testcase_1
├── data
│ ├── module_data.F90
│ └── my_routine.F90
├── Makefile
├── mydata
│ ├── module_data.F90
│ └── other_module.F90
└── test.F90
In our build unit "data/my_routine.F90",
it firstly "use other_module" which wants to access its function 'other_calc',
then it "use module_data" (refer to: data/module_data.mod), which wants to access its variable 'PI' and 'isOther',
but in "other_module" it indirectly "use module_data" (refer to: mydata/module_data.mod)
This cause the application compile issue, like below:
```
flang -fPIC -std=f2018 -I./data -I./mydata -O3 -module-dir ./data -c data/module_data.F90 -o data/module_data.o
flang -fPIC -std=f2018 -O0 -module-dir ./mydata -c mydata/module_data.F90 -o mydata/module_data.o
flang -fPIC -std=f2018 -O0 -module-dir ./mydata -c mydata/other_module.F90 -o mydata/other_module.o
flang -fPIC -std=f2018 -I./data -I./mydata -O3 -module-dir ./data -c data/my_routine.F90 -o data/my_routine.o
error: Semantic errors in data/my_routine.F90
data/my_routine.F90:14:10: error: No explicit type declared for 'pi'
area = PI * radius**2
^^
data/my_routine.F90:16:7: error: No explicit type declared for 'isother'
if (isOther) then
^^^^^^^
make: *** [Makefile:27: data/my_routine.o] Error 1
```
Related code as below: (Complete reproduce project can use testcase_1)
```fortran
!--------------------------------------------------
! data/my_routine.F90
!--------------------------------------------------
subroutine calc(radius, area)
use other_module
use module_data
implicit none
real, intent(in) :: radius
real, intent(out) :: area
area = PI * radius**2
if (isOther) then
call other_calc(area)
print *, "use other module calc area = ", area
end if
end subroutine calc
!-------------------------------------------------
! data/module_data.F90
!-------------------------------------------------
module module_data
implicit none
public :: PI, isDone, set_done, isOther
real, parameter :: PI = 3.141592653589793
logical :: isDone = .false.
logical :: isOther = .true.
contains
subroutine set_done()
isDone = .true.
end subroutine set_done
end module module_data
!------------------------------------------------
! mydata/other_module.F90
!------------------------------------------------
module other_module
use module_data
contains
subroutine other_calc(area)
implicit none
real, intent(out) :: area
area = 3.1415926 * 1**2
end subroutine other_calc
subroutine other_get_r(radio)
implicit none
real, intent(out) :: radio
radio = R
end subroutine
end module other_module
!-----------------------------------------------
! mydata/module_data.F90
!-----------------------------------------------
module module_data
implicit none
public :: R
real, parameter :: R = 1
end module module_data
```
##################################################
Case 2: (related reproduce case is testcase_2)
##################################################
Looks like similar build issue, but just different case
This cause the application (testcase_2) compile issue, like below:
```
flang -fPIC -std=f2018 -I./data -I./mydata -O3 -module-dir ./data -c data/module_data.F90 -o data/module_data.o
flang -fPIC -std=f2018 -I./data -I./mydata -O3 -module-dir ./data -c data/indirect_module_data.F90 -o data/indirect_module_data.o
flang -fPIC -std=f2018 -O0 -module-dir ./mydata -c mydata/module_data.F90 -o mydata/module_data.o
flang -fPIC -std=f2018 -O0 -module-dir ./mydata -c mydata/other_module.F90 -o mydata/other_module.o
flang -fPIC -std=f2018 -I./data -I./mydata -O3 -module-dir ./data -c data/my_routine.F90 -o data/my_routine.o
error: Semantic errors in data/my_routine.F90
data/my_routine.F90:13:10: error: No explicit type declared for 'pi'
area = PI * radius**2
^^
data/my_routine.F90:15:7: error: No explicit type declared for 'isother'
if (isOther) then
^^^^^^^
make: *** [Makefile:32: data/my_routine.o] Error 1
```
The mainly different place compare to case 1 is as below:
```fortran
!-------------------------------------------------
! data/my_routine.F90
!-------------------------------------------------
subroutine calc(radius, area)
use indirect_module_data !!!==> "indirect_module_data" indirectly use data/module_data before "use other_module"
use other_module ! same as case 1
use module_data ! same as case 1
implicit none
real, intent(in) :: radius
real, intent(out) :: area
area = PI * radius**2
if (isOther) then
call other_calc(area)
print *, "use other module calc area = ", area
end if
print *, "D_PI: ", D_PI
end subroutine calc
!-----------------------------------------------
! data/indirect_module_data.F90
!-----------------------------------------------
module indirect_module_data
use module_data
implicit none
private !!!==> it will private all the symbols from data/module_data.mod, if remove it, build is ok
public :: D_PI
real, parameter :: D_PI = 2 * PI
end module indirect_module_data
```
The full reproduce two cases can be obtained via the attached files below:
Contributor guide
Research direction
Start by reproducing testcase_1 and testcase_2 with the Makefile and the listed Flang commands, focusing on the USE statements in data/my_routine.F90, data/indirect_module_data.F90, and mydata/other_module.F90. Trace how same-named module files are selected and cached when indirect and direct USE statements occur. Done means both reproductions compile successfully and PI and isOther resolve from the intended module.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- fortran
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100