[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