[flang-commits] [flang] [flang] Preserve UseErrorDetails in module files (PR #189423)
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Mon Mar 30 12:58:21 PDT 2026
https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/189423
>From 259b82037012213eb1a4f9dd437e2c5ec6474d47 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Mon, 30 Mar 2026 09:22:18 -0700
Subject: [PATCH] [flang] Preserve UseErrorDetails in module files
When the same name is USE-associated with two or more distinct ultimate
symbols, and they are not both generic procedure interfaces, it's not
an error unless the name is actually referenced in the scope. But when
the scope is itself a module or submodule, our module files don't preserve
the error for later diagnosis -- instead, the UseErrorDetails symbol that
serves as a "poison pill" in case of later use is discarded when the
module file is generated. So emit additional USE statements to the
module file so that a UseErrorDetails symbol is created anew when the
module file is read.
---
flang/lib/Semantics/mod-file.cpp | 19 ++++++++++++++++---
flang/lib/Semantics/mod-file.h | 1 +
flang/lib/Semantics/resolve-names.cpp | 2 +-
flang/test/Semantics/Inputs/modfile84.f90 | 14 ++++++++++++++
flang/test/Semantics/modfile84.f90 | 19 +++++++++++++++++++
5 files changed, 51 insertions(+), 4 deletions(-)
create mode 100644 flang/test/Semantics/Inputs/modfile84.f90
create mode 100644 flang/test/Semantics/modfile84.f90
diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp
index 3bfe1e144f961..f880d33858f7e 100644
--- a/flang/lib/Semantics/mod-file.cpp
+++ b/flang/lib/Semantics/mod-file.cpp
@@ -528,7 +528,15 @@ void ModFileWriter::PutSymbol(
}
},
[&](const UseDetails &) { PutUse(symbol); },
- [](const UseErrorDetails &) {},
+ [&](const UseErrorDetails &x) {
+ for (const auto &[at, symptr] : x.occurrences()) {
+ if (symptr) {
+ UseDetails details{at, *symptr};
+ PutUseDetails(details);
+ uses_ << symbol.name() << "=>" << symptr->name() << '\n';
+ }
+ }
+ },
[&](const ProcBindingDetails &x) {
bool deferred{symbol.attrs().test(Attr::DEFERRED)};
typeBindings << "procedure";
@@ -852,8 +860,7 @@ void ModFileWriter::PutGeneric(const Symbol &symbol) {
}
}
-void ModFileWriter::PutUse(const Symbol &symbol) {
- auto &details{symbol.get<UseDetails>()};
+void ModFileWriter::PutUseDetails(const UseDetails &details) {
auto &use{details.symbol()};
const Symbol &module{GetUsedModule(details)};
if (use.owner().parent().IsIntrinsicModules()) {
@@ -863,9 +870,15 @@ void ModFileWriter::PutUse(const Symbol &symbol) {
usedNonIntrinsicModules_.insert(module);
}
uses_ << module.name() << ",only:";
+}
+
+void ModFileWriter::PutUse(const Symbol &symbol) {
+ const auto &details{symbol.get<UseDetails>()};
+ PutUseDetails(details);
PutGenericName(uses_, symbol);
// Can have intrinsic op with different local-name and use-name
// (e.g. `operator(<)` and `operator(.lt.)`) but rename is not allowed
+ auto &use{details.symbol()};
if (!IsIntrinsicOp(symbol) && use.name() != symbol.name()) {
PutGenericName(uses_ << "=>", use);
}
diff --git a/flang/lib/Semantics/mod-file.h b/flang/lib/Semantics/mod-file.h
index 9e5724089b3c5..f1a23394ef80b 100644
--- a/flang/lib/Semantics/mod-file.h
+++ b/flang/lib/Semantics/mod-file.h
@@ -83,6 +83,7 @@ class ModFileWriter {
void PutUserReduction(llvm::raw_ostream &, const Symbol &);
void PutSubprogram(const Symbol &);
void PutGeneric(const Symbol &);
+ void PutUseDetails(const UseDetails &);
void PutUse(const Symbol &);
void PutUseExtraAttr(Attr, const Symbol &, const Symbol &);
llvm::raw_ostream &PutAttrs(llvm::raw_ostream &, Attrs,
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index b6907cc792d76..e177363e4d440 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -9534,7 +9534,7 @@ void ResolveNamesVisitor::HandleProcedureName(
} else if (symbol->test(Symbol::Flag::Implicit)) {
Say(name,
"Use of '%s' as a procedure conflicts with its implicit definition"_err_en_US);
- } else {
+ } else if (!HadUseError(context(), name.source, symbol)) {
SayWithDecl(name, *symbol,
"Use of '%s' as a procedure conflicts with its declaration"_err_en_US);
}
diff --git a/flang/test/Semantics/Inputs/modfile84.f90 b/flang/test/Semantics/Inputs/modfile84.f90
new file mode 100644
index 0000000000000..d049749028509
--- /dev/null
+++ b/flang/test/Semantics/Inputs/modfile84.f90
@@ -0,0 +1,14 @@
+module modfile84A
+ contains
+ subroutine foo()
+ end subroutine
+end
+module modfile84B
+ contains
+ subroutine foo()
+ end
+end
+module modfile84AB
+ use modfile84A, only: foo, bar=>foo
+ use modfile84B, only: foo, bar=>foo
+end
diff --git a/flang/test/Semantics/modfile84.f90 b/flang/test/Semantics/modfile84.f90
new file mode 100644
index 0000000000000..d19e3813bd511
--- /dev/null
+++ b/flang/test/Semantics/modfile84.f90
@@ -0,0 +1,19 @@
+!RUN: rm -rf %t && mkdir -p %t
+!RUN: %flang_fc1 -fsyntax-only -J%t %S/Inputs/modfile84.f90
+!RUN: not %flang_fc1 -fsyntax-only -J%t %s 2>&1 | FileCheck %s
+
+!CHECK: error: Reference to 'foo' is ambiguous
+!CHECK: 'foo' was use-associated from module 'modfile84a'
+!CHECK: 'foo' was use-associated from module 'modfile84b'
+!CHECK: error: 'foo' is not a callable procedure
+!CHECK: 'foo' is USE-associated with 'foo' in module 'modfile84ab'
+!CHECK: error: Reference to 'bar' is ambiguous
+!CHECK: 'bar' was use-associated from module 'modfile84a'
+!CHECK: 'bar' was use-associated from module 'modfile84b'
+!CHECK: error: 'bar' is not a callable procedure
+!CHECK: 'bar' is USE-associated with 'bar' in module 'modfile84ab'
+
+use modfile84AB
+call foo()
+call bar()
+end
More information about the flang-commits
mailing list