[flang-commits] [flang] [flang] Do not implicitly use module when processing the module (PR #208582)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Thu Jul 9 16:48:35 PDT 2026
https://github.com/clementval updated https://github.com/llvm/llvm-project/pull/208582
>From b1c2e9f19cc2a5255baac567c8c56fab60935dba Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Thu, 9 Jul 2026 15:58:11 -0700
Subject: [PATCH 1/3] [flang] Do not implicitly use module when processing the
module
---
flang/lib/Semantics/resolve-names.cpp | 36 +++++++++++++++++--
flang/test/Driver/bbc-implicit-use-module.f90 | 11 ++++--
flang/tools/bbc/bbc.cpp | 22 +++++++++++-
3 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 6079cfced9151..4608163924d25 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -833,6 +833,10 @@ class ModuleVisitor : public virtual ScopeHandler {
nonIntrinsicUses_.clear();
}
+protected:
+ std::optional<std::string> implicitUseModuleBeingResolved_;
+ std::set<std::string> implicitUseModulesInCurrentProgram_;
+
private:
// The location of the last AccessStmt without access-ids, if any.
std::optional<SourceName> prevAccessStmt_;
@@ -3921,11 +3925,26 @@ void ModuleVisitor::AddImplicitUseModules() {
continue;
}
SourceName moduleName{module};
- std::optional<SourceName> currModuleName{currScope().GetName()};
- if (currScope().IsModule() && currModuleName &&
- *currModuleName == moduleName) {
+ if (implicitUseModulesInCurrentProgram_.count(module) != 0) {
+ continue;
+ }
+ if (implicitUseModuleBeingResolved_ &&
+ *implicitUseModuleBeingResolved_ == module) {
+ continue;
+ }
+ const Scope *containingModule{FindModuleOrSubmoduleContaining(currScope())};
+ std::optional<SourceName> currModuleName{
+ containingModule ? containingModule->GetName() : std::nullopt};
+ if (currModuleName && *currModuleName == moduleName) {
continue;
}
+ if (auto it{context().globalScope().find(moduleName)};
+ it != context().globalScope().end()) {
+ if (Scope *scope{it->second->scope()};
+ scope && DoesScopeContain(scope, currScope())) {
+ continue;
+ }
+ }
parser::Name name{moduleName};
std::optional<bool> isIntrinsic;
if (currScope().IsModule() && currScope().symbol() &&
@@ -11007,6 +11026,10 @@ bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) {
return false;
}
ProgramTree &root{ProgramTree::Build(x, context())};
+ auto implicitUseModuleBeingResolvedRestorer{
+ common::ScopedSet(implicitUseModuleBeingResolved_,
+ root.IsModule() ? std::optional<std::string>{root.name().ToString()}
+ : implicitUseModuleBeingResolved_)};
SetScope(topScope_);
ResolveSpecificationParts(root);
FinishSpecificationParts(root);
@@ -11048,6 +11071,7 @@ bool ResolveNamesVisitor::Pre(const parser::Program &x) {
ImplicitRulesVisitor::BeginScope(*hermetic);
}
std::map<SourceName, const parser::ProgramUnit *> modules;
+ std::set<std::string> moduleNamesInCurrentProgram;
std::set<SourceName> uses;
bool disordered{false};
for (const auto &progUnit : x.v) {
@@ -11057,6 +11081,7 @@ bool ResolveNamesVisitor::Pre(const parser::Program &x) {
const auto &moduleStmt{
std::get<parser::Statement<parser::ModuleStmt>>(mod.t)};
const SourceName &name{moduleStmt.statement.v.source};
+ moduleNamesInCurrentProgram.insert(name.ToString());
if (auto iter{modules.find(name)}; iter != modules.end()) {
Say(name,
"Module '%s' appears multiple times in a compilation unit"_err_en_US)
@@ -11080,6 +11105,7 @@ bool ResolveNamesVisitor::Pre(const parser::Program &x) {
uses.insert(used);
}
}
+ implicitUseModulesInCurrentProgram_ = std::move(moduleNamesInCurrentProgram);
if (!disordered) {
return true;
}
@@ -11174,6 +11200,10 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) {
if (node.isSpecificationPartResolved()) {
return; // been here already
}
+ auto implicitUseModuleBeingResolvedRestorer{
+ common::ScopedSet(implicitUseModuleBeingResolved_,
+ node.IsModule() ? std::optional<std::string>{node.name().ToString()}
+ : implicitUseModuleBeingResolved_)};
node.set_isSpecificationPartResolved();
if (!BeginScopeForNode(node)) {
return; // an error prevented scope from being created
diff --git a/flang/test/Driver/bbc-implicit-use-module.f90 b/flang/test/Driver/bbc-implicit-use-module.f90
index 733ad69580c1c..c792fad84a917 100644
--- a/flang/test/Driver/bbc-implicit-use-module.f90
+++ b/flang/test/Driver/bbc-implicit-use-module.f90
@@ -1,6 +1,8 @@
! Test bbc's test-only implicit USE module hook.
! RUN: split-file %s %t
+! RUN: mkdir -p %t/self
+! RUN: bbc -module %t/self -implicit-use-module implicit_mod %t/implicit_mod.f90 -o /dev/null
! RUN: bbc -module %t %t/implicit_mod.f90 -o /dev/null
! RUN: bbc -emit-hlfir -fopenacc -I %t -implicit-use-module implicit_mod %t/use_implicit.f90 -o - | FileCheck %s
@@ -10,11 +12,16 @@ module implicit_mod
integer :: common_value
integer :: module_value = 42
common /implicit_common/ common_value
+contains
+ subroutine contained
+ integer :: x
+ x = module_value
+ end subroutine
end module
!--- use_implicit.f90
subroutine use_implicit
- integer :: x
+ real :: x
!$acc data copy(/implicit_common/)
x = module_value + common_value
!$acc end data
@@ -23,4 +30,4 @@ subroutine use_implicit
! CHECK-LABEL: func.func @_QPuse_implicit()
! CHECK-DAG: fir.address_of(@_QMimplicit_modEmodule_value) : !fir.ref<i32>
! CHECK-DAG: %[[COMMON:.*]] = fir.address_of(@implicit_common_) : !fir.ref<!fir.array<4xi8>>
-! CHECK-DAG: acc.copyin varPtr(%[[COMMON]]
+! CHECK-DAG: acc.copyin varPtr(%[[COMMON]] : !fir.ref<!fir.array<4xi8>>) -> !fir.ref<!fir.array<4xi8>> {name = "implicit_common"}
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 88fa43c748e2f..124c566bc6b13 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -428,6 +428,27 @@ static llvm::LogicalResult convertFortranSourceToMLIR(
// run semantics
auto &parseTree = *parsing.parseTree();
+ std::vector<std::string> implicitUseModuleNames;
+ for (const std::string &module : implicitUseModules) {
+ bool moduleIsDefinedInInput{false};
+ for (const Fortran::parser::ProgramUnit &unit : parseTree.v) {
+ if (const auto *indirectModule{std::get_if<
+ Fortran::common::Indirection<Fortran::parser::Module>>(
+ &unit.u)}) {
+ const auto &moduleStmt{
+ std::get<Fortran::parser::Statement<Fortran::parser::ModuleStmt>>(
+ indirectModule->value().t)};
+ if (moduleStmt.statement.v.source.ToString() == module) {
+ moduleIsDefinedInInput = true;
+ break;
+ }
+ }
+ }
+ if (!moduleIsDefinedInInput) {
+ implicitUseModuleNames.push_back(module);
+ }
+ }
+ semanticsContext.set_implicitUseModules(implicitUseModuleNames);
Fortran::semantics::Semantics semantics(semanticsContext, parseTree);
semantics.Perform();
semantics.EmitMessages(llvm::errs());
@@ -695,7 +716,6 @@ int main(int argc, char **argv) {
.set_moduleFileSuffix(moduleSuffix)
.set_searchDirectories(includeDirs)
.set_intrinsicModuleDirectories(intrinsicIncludeDirs)
- .set_implicitUseModules(implicitUseModules)
.set_warnOnNonstandardUsage(warnStdViolation)
.set_warningsAreErrors(warnIsError);
>From 01d59a3d6ad3e77a257a4b0d70aec44d8efaa676 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Thu, 9 Jul 2026 16:23:16 -0700
Subject: [PATCH 2/3] Fix test
---
flang/test/Driver/bbc-implicit-use-module.f90 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/flang/test/Driver/bbc-implicit-use-module.f90 b/flang/test/Driver/bbc-implicit-use-module.f90
index c792fad84a917..a7ff3928a0324 100644
--- a/flang/test/Driver/bbc-implicit-use-module.f90
+++ b/flang/test/Driver/bbc-implicit-use-module.f90
@@ -30,4 +30,4 @@ subroutine use_implicit
! CHECK-LABEL: func.func @_QPuse_implicit()
! CHECK-DAG: fir.address_of(@_QMimplicit_modEmodule_value) : !fir.ref<i32>
! CHECK-DAG: %[[COMMON:.*]] = fir.address_of(@implicit_common_) : !fir.ref<!fir.array<4xi8>>
-! CHECK-DAG: acc.copyin varPtr(%[[COMMON]] : !fir.ref<!fir.array<4xi8>>) -> !fir.ref<!fir.array<4xi8>> {name = "implicit_common"}
+! CHECK-DAG: acc.copyin varPtr(%[[COMMON]] : !fir.ref<!fir.array<4xi8>>) -> !fir.ref<!fir.array<4xi8>> {dataClause = #acc<data_clause acc_copy>, name = "implicit_common"}
>From 2e5f87290a9f58286e12616da80244c6505bb27e Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Thu, 9 Jul 2026 16:48:18 -0700
Subject: [PATCH 3/3] Restrict to subroutine and not read module
---
flang/lib/Semantics/resolve-names.cpp | 3 +++
flang/test/Driver/bbc-implicit-use-module.f90 | 9 +++++++++
2 files changed, 12 insertions(+)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 4608163924d25..e25cf1dc2793c 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -3920,6 +3920,9 @@ void ModuleVisitor::AddUseForCommonBlocks() {
}
void ModuleVisitor::AddImplicitUseModules() {
+ if (InModuleFile() || currScope().kind() != Scope::Kind::Subprogram) {
+ return;
+ }
for (const std::string &module : context().implicitUseModules()) {
if (module.empty()) {
continue;
diff --git a/flang/test/Driver/bbc-implicit-use-module.f90 b/flang/test/Driver/bbc-implicit-use-module.f90
index a7ff3928a0324..c7c1af9b64231 100644
--- a/flang/test/Driver/bbc-implicit-use-module.f90
+++ b/flang/test/Driver/bbc-implicit-use-module.f90
@@ -4,6 +4,7 @@
! RUN: mkdir -p %t/self
! RUN: bbc -module %t/self -implicit-use-module implicit_mod %t/implicit_mod.f90 -o /dev/null
! RUN: bbc -module %t %t/implicit_mod.f90 -o /dev/null
+! RUN: not bbc -emit-hlfir -I %t -implicit-use-module implicit_mod %t/use_in_module.f90 -o - 2>&1 | FileCheck %s --check-prefix=MODULE-SCOPE
! RUN: bbc -emit-hlfir -fopenacc -I %t -implicit-use-module implicit_mod %t/use_implicit.f90 -o - | FileCheck %s
!--- implicit_mod.f90
@@ -27,6 +28,14 @@ subroutine use_implicit
!$acc end data
end subroutine
+!--- use_in_module.f90
+module use_in_module
+ implicit none
+ integer :: x = module_value
+end module
+
+! MODULE-SCOPE: No explicit type declared for 'module_value'
+
! CHECK-LABEL: func.func @_QPuse_implicit()
! CHECK-DAG: fir.address_of(@_QMimplicit_modEmodule_value) : !fir.ref<i32>
! CHECK-DAG: %[[COMMON:.*]] = fir.address_of(@implicit_common_) : !fir.ref<!fir.array<4xi8>>
More information about the flang-commits
mailing list