Skip to content

Commit 40ad00b

Browse files
authored
[flang] Define array named constants from the iso_fortran_env intrins… (#201190)
…ic module createIntrinsicModuleDefinitions() only emitted definitions for array named constants belonging to the __fortran_ieee_exceptions intrinsic module. Array constants declared directly in the iso_fortran_env intrinsic module -- in practice character_kinds -- were therefore only lowered as bodyless `fir.global` external declarations at their use site and never defined anywhere, producing an undefined reference at link time. This is usually hidden because scalar iso_fortran_env parameters fold to immediates and constant-shape array accesses are folded away, so the dangling external symbol is DCE'd before linking. It surfaces when the address of the array genuinely escapes to runtime, e.g.: ``` use iso_fortran_env integer :: i, x(1) do i = 1, size(character_kinds) x = findloc(character_kinds, character_kinds(i)) end do ``` which fails with: undefined reference to `_QMiso_fortran_envECcharacter_kinds' Fix by also processing the iso_fortran_env scope in createIntrinsicModuleDefinitions(), so its array constants are emitted as linkonce_odr definitions with initializers. Note that integer_kinds/real_kinds/logical_kinds are unaffected: they are renamed from iso_fortran_env_impl, a non-intrinsic module that is compiled into the runtime, so their definitions already exist there. Assisted-by: AI
1 parent 162076f commit 40ad00b

2 files changed

Lines changed: 21 additions & 1 deletion

File tree

flang/lib/Lower/Bridge.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6526,7 +6526,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
65266526
return;
65276527
for (const auto &scope : intrinsicModuleScope->children()) {
65286528
llvm::StringRef modName = toStringRef(scope.symbol()->name());
6529-
if (modName != "__fortran_ieee_exceptions")
6529+
if (modName != "__fortran_ieee_exceptions" &&
6530+
modName != "iso_fortran_env")
65306531
continue;
65316532
for (auto &var : Fortran::lower::pft::getScopeVariableList(scope)) {
65326533
const Fortran::semantics::Symbol &sym = var.getSymbol();
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
! Regression test: array named constants declared directly in the intrinsic
2+
! iso_fortran_env module (e.g. character_kinds) must be emitted as a DEFINITION
3+
! with an initializer, not as a bodyless external declaration. Otherwise the
4+
! reference is undefined at link time.
5+
! See createIntrinsicModuleDefinitions in lib/Lower/Bridge.cpp.
6+
7+
! RUN: bbc -emit-hlfir -o - %s | FileCheck %s
8+
9+
subroutine test_character_kinds(i, r)
10+
use iso_fortran_env, only: character_kinds
11+
integer :: i, r
12+
r = character_kinds(i)
13+
end subroutine
14+
15+
! The global must be DEFINED (linkonce_odr linkage + a parenthesized
16+
! initializer), not a bodyless "fir.global @_QM...character_kinds ... constant"
17+
! external declaration.
18+
! CHECK: fir.global linkonce_odr @_QMiso_fortran_envECcharacter_kinds({{.*}}) {{.*}}constant : !fir.array<{{[0-9]+}}xi32>
19+
! CHECK-NOT: fir.global @_QMiso_fortran_envECcharacter_kinds {{.*}}constant

0 commit comments

Comments
 (0)