[flang-commits] [flang] [flang][Semantics] Preserve ambiguous USE-error through whole-module USE (PR #229707)
via flang-commits
flang-commits at lists.llvm.org
Wed Oct 7 04:29:12 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: mleair
<details>
<summary>Changes</summary>
Per F2023 14.2.2 p8, an accessed entity may be associated with two or more distinct ultimate entities as long as its identifier is never referenced; this is recorded internally as `UseErrorDetails`, a poison-pill symbol that triggers an error if the name is ever used.
When a module scope contains such an ambiguous (and never referenced) name, a whole-module `USE` of that module resolved the ambiguous entity into an ordinary `UseDetails` pointing at the origin module's own (unwritten) `UseErrorDetails` symbol. Since the mod-file writer omits `UseErrorDetails` symbols from the module file it produces, the re-exporting module's `.mod` file ended up with a `use ...,only:name` line naming an entity the origin module's own `.mod` file does not actually provide, so compiling a client of the re-exporting module failed with `'name' not found in module`.
This propagates the ambiguity instead of resolving it: the local symbol also becomes `UseErrorDetails`, so it is (like the origin symbol) omitted from the module file, keeping the round trip consistent.
The added test exercises this through several independent paths into `ModuleVisitor::DoAddUse`: a bare whole-module `USE`, an explicit only-list `USE`, a renaming only-list `USE`, and a second, independent way of creating the ambiguous symbol (two distinct derived types of the same name) handled by a different branch of `DoAddUse`.
Assisted-By: AI
---
Full diff: https://github.com/llvm/llvm-project/pull/229707.diff
2 Files Affected:
- (modified) flang/lib/Semantics/resolve-names.cpp (+12)
- (added) flang/test/Semantics/modfile89.f90 (+111)
``````````diff
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 67690d6f47d06..37789a69c3829 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -4421,6 +4421,18 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
// be copied.
localSymbol->set_details(GenericDetails{});
localSymbol->get<GenericDetails>().set_kind(useGeneric->kind());
+ } else if (const auto *useError{useSymbol.detailsIf<UseErrorDetails>()}) {
+ // The module being use-associated wholesale already has an ambiguous
+ // name at this position (e.g. two distinct USEs of the same name that
+ // are themselves never referenced there, which F2023 14.2.2 p8 allows).
+ // Propagate that ambiguity to the local symbol rather than silently
+ // resolving it to one of the ambiguous module's own USE details; the
+ // latter would produce a local UseDetails whose target module file
+ // omits the name, so it would not survive a module file round trip.
+ localSymbol->set_details(UseErrorDetails{*useError});
+ localSymbol->attrs() =
+ useSymbol.attrs() & ~Attrs{Attr::PUBLIC, Attr::PRIVATE, Attr::SAVE};
+ return;
} else { // just create UseDetails
localSymbol->set_details(UseDetails{localName, useSymbol});
localSymbol->attrs() =
diff --git a/flang/test/Semantics/modfile89.f90 b/flang/test/Semantics/modfile89.f90
new file mode 100644
index 0000000000000..bd051de92e525
--- /dev/null
+++ b/flang/test/Semantics/modfile89.f90
@@ -0,0 +1,111 @@
+! RUN: split-file %s %t
+! RUN: %flang_fc1 -fsyntax-only -module-dir %t %t/defs.f90
+! RUN: %flang_fc1 -fsyntax-only -module-dir %t %t/use.f90
+! RUN: FileCheck --check-prefix=PK --input-file=%t/pk.mod %s
+! RUN: FileCheck --check-prefix=VM --input-file=%t/vm.mod %s
+! RUN: FileCheck --check-prefix=MIDDLE --input-file=%t/middle.mod %s
+! RUN: FileCheck --check-prefix=DOWN --input-file=%t/down.mod %s
+! RUN: FileCheck --check-prefix=ONLYMOD --input-file=%t/down_only.mod %s
+! RUN: FileCheck --check-prefix=RENMOD --input-file=%t/down_rename.mod %s
+! RUN: FileCheck --check-prefix=DTMID --input-file=%t/dtmiddle.mod %s
+! RUN: FileCheck --check-prefix=DTDOWN --input-file=%t/dtdown.mod %s
+
+! Regression test: a module that re-exports another module's ambiguous
+! (never-referenced, and therefore legal per F2023 14.2.2 p8) USE-associated
+! name must not name that entity in its own module file, because the
+! originating module's module file does not provide it.
+!
+! MIDDLE combines two distinct USEs of the same name (JPRB) that is never
+! itself referenced within MIDDLE, so MIDDLE's module file correctly omits
+! the ambiguous name. DOWN re-exports MIDDLE via a whole-module USE; its
+! module file must likewise omit JPRB. Before the fix, compiling use.f90
+! failed with "'jprb' not found in module 'middle'".
+!
+! DOWN_ONLY and DOWN_RENAME cover the same ambiguity reached through
+! use middle,only:jprb and use middle,only:myjprb=>jprb, which resolve
+! through ModuleVisitor::AddUse rather than the whole-module
+! AddUseForPublicSymbols path that DOWN exercises.
+!
+! DTMIDDLE/DTDOWN cover a second, independent way of creating the
+! ambiguous poison-pill symbol: two distinct derived types of the same
+! name, handled by the "many possible combinations" tail of DoAddUse
+! rather than its early-return whole-module path. DTMIDDLE only pins
+! the precondition (its module file omits the ambiguous name either way);
+! DTDOWN is the one that catches a regression.
+
+!--- defs.f90
+module pk
+ integer jprb
+end module
+module vm
+ integer jprb
+end module
+module middle
+ use pk
+ use vm
+end module
+module down
+ use middle
+end module
+module down_only
+ use middle, only: jprb
+end module
+module down_rename
+ use middle, only: myjprb => jprb
+end module
+module dtpk
+ type :: dt
+ integer a
+ end type
+end module
+module dtvm
+ type :: dt
+ real b
+ end type
+end module
+module dtmiddle
+ use dtpk
+ use dtvm
+end module
+module dtdown
+ use dtmiddle
+end module
+
+!--- use.f90
+use down
+use down_only
+use down_rename
+use dtdown
+end
+
+! PK: module pk
+! PK: jprb
+! PK: end
+
+! VM: module vm
+! VM: jprb
+! VM: end
+
+! MIDDLE: module middle
+! MIDDLE-NOT: jprb
+! MIDDLE: end
+
+! DOWN: module down
+! DOWN-NOT: jprb
+! DOWN: end
+
+! ONLYMOD: module down_only
+! ONLYMOD-NOT: jprb
+! ONLYMOD: end
+
+! RENMOD: module down_rename
+! RENMOD-NOT: jprb
+! RENMOD: end
+
+! DTMID: module dtmiddle
+! DTMID-NOT: dt
+! DTMID: end
+
+! DTDOWN: module dtdown
+! DTDOWN-NOT: dt
+! DTDOWN: end
``````````
</details>
https://github.com/llvm/llvm-project/pull/229707
More information about the flang-commits
mailing list