[flang-commits] [flang] 43e98b2 - [flang] Do not implicitly use module when processing the module (#208582)

via flang-commits flang-commits at lists.llvm.org
Thu Jul 9 20:21:00 PDT 2026


Author: Valentin Clement (バレンタイン クレメン)
Date: 2026-07-09T20:20:55-07:00
New Revision: 43e98b2e08ec8d012e4aa442392c1d204650d471

URL: https://github.com/llvm/llvm-project/commit/43e98b2e08ec8d012e4aa442392c1d204650d471
DIFF: https://github.com/llvm/llvm-project/commit/43e98b2e08ec8d012e4aa442392c1d204650d471.diff

LOG: [flang] Do not implicitly use module when processing the module (#208582)

https://github.com/llvm/llvm-project/pull/207824 Added ability to use
implicitly a module. The use should not happen while processing the
module used implicitly.

Added: 
    

Modified: 
    flang/lib/Semantics/resolve-names.cpp
    flang/test/Driver/bbc-implicit-use-module.f90
    flang/tools/bbc/bbc.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 6079cfced9151..5a92cfd738ef4 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_;
@@ -3916,16 +3920,44 @@ 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;
     }
     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;
+    }
+    bool isContainedInImplicitModule{false};
+    for (const Scope *scope{&currScope()}; !scope->IsTopLevel();
+        scope = &scope->parent()) {
+      if (scope->kind() == Scope::Kind::Module) {
+        if (std::optional<SourceName> scopeName{scope->GetName()};
+            scopeName && scopeName->ToString() == module) {
+          // Do not implicitly USE a module while resolving anything contained
+          // in that module; doing so would be a self USE.
+          isContainedInImplicitModule = true;
+          break;
+        }
+      }
+    }
+    if (isContainedInImplicitModule) {
       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 +11039,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 +11084,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 +11094,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 +11118,7 @@ bool ResolveNamesVisitor::Pre(const parser::Program &x) {
       uses.insert(used);
     }
   }
+  implicitUseModulesInCurrentProgram_ = std::move(moduleNamesInCurrentProgram);
   if (!disordered) {
     return true;
   }
@@ -11174,6 +11213,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..c7c1af9b64231 100644
--- a/flang/test/Driver/bbc-implicit-use-module.f90
+++ b/flang/test/Driver/bbc-implicit-use-module.f90
@@ -1,7 +1,10 @@
 ! 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: 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
@@ -10,17 +13,30 @@ 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
 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>>
-! CHECK-DAG: acc.copyin varPtr(%[[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"}

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);
 


        


More information about the flang-commits mailing list