[flang-commits] [flang] [flang] Add ability to implicitly use a module (PR #207824)
Valentin Clement バレンタイン クレメン via flang-commits
flang-commits at lists.llvm.org
Mon Jul 6 17:00:48 PDT 2026
https://github.com/clementval updated https://github.com/llvm/llvm-project/pull/207824
>From 2d7740b4648f13d20f3967d709bd0bffc07d677b Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Mon, 6 Jul 2026 12:55:01 -0700
Subject: [PATCH 1/3] [flang] Add ability to implicitly use a module
---
flang/include/flang/Parser/options.h | 1 +
flang/include/flang/Semantics/semantics.h | 8 ++
flang/lib/Semantics/resolve-names.cpp | 87 ++++++++++++++-----
flang/test/Driver/bbc-implicit-use-module.f90 | 20 +++++
flang/tools/bbc/bbc.cpp | 8 ++
5 files changed, 102 insertions(+), 22 deletions(-)
create mode 100644 flang/test/Driver/bbc-implicit-use-module.f90
diff --git a/flang/include/flang/Parser/options.h b/flang/include/flang/Parser/options.h
index e65f253748d26..8a9fcd0568652 100644
--- a/flang/include/flang/Parser/options.h
+++ b/flang/include/flang/Parser/options.h
@@ -28,6 +28,7 @@ struct Options {
common::LanguageFeatureControl features;
std::vector<std::string> searchDirectories;
std::vector<std::string> intrinsicModuleDirectories;
+ std::vector<std::string> implicitUseModules;
std::vector<Predefinition> predefinitions;
bool instrumentedParse{false};
bool isModuleFile{false};
diff --git a/flang/include/flang/Semantics/semantics.h b/flang/include/flang/Semantics/semantics.h
index 575851920aa9f..b5bccac599973 100644
--- a/flang/include/flang/Semantics/semantics.h
+++ b/flang/include/flang/Semantics/semantics.h
@@ -101,6 +101,9 @@ class SemanticsContext {
const std::vector<std::string> &intrinsicModuleDirectories() const {
return intrinsicModuleDirectories_;
}
+ const std::vector<std::string> &implicitUseModules() const {
+ return implicitUseModules_;
+ }
const std::string &moduleDirectory() const { return moduleDirectory_; }
const std::string &moduleFileSuffix() const { return moduleFileSuffix_; }
bool underscoring() const { return underscoring_; }
@@ -145,6 +148,10 @@ class SemanticsContext {
intrinsicModuleDirectories_ = x;
return *this;
}
+ SemanticsContext &set_implicitUseModules(const std::vector<std::string> &x) {
+ implicitUseModules_ = x;
+ return *this;
+ }
SemanticsContext &set_moduleDirectory(const std::string &x) {
moduleDirectory_ = x;
return *this;
@@ -391,6 +398,7 @@ class SemanticsContext {
std::optional<parser::CharBlock> location_;
std::vector<std::string> searchDirectories_;
std::vector<std::string> intrinsicModuleDirectories_;
+ std::vector<std::string> implicitUseModules_;
std::string moduleDirectory_{"."s};
std::string moduleFileSuffix_{".mod"};
std::string targetTriple_;
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 9ddda9a92471b..6079cfced9151 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -825,6 +825,7 @@ class ModuleVisitor : public virtual ScopeHandler {
Symbol &AddGenericUse(GenericDetails &, const SourceName &, const Symbol &);
void AddAndCheckModuleUse(SourceName, bool isIntrinsic);
void CollectUseRenames(const parser::UseStmt &);
+ void AddImplicitUseModules();
void ClearUseRenames() { useRenames_.clear(); }
void ClearUseOnly() { useOnly_.clear(); }
void ClearModuleUses() {
@@ -855,6 +856,8 @@ class ModuleVisitor : public virtual ScopeHandler {
// Record a use from useModuleScope_ of use Name/Symbol as local Name/Symbol
SymbolRename AddUse(const SourceName &localName, const SourceName &useName);
SymbolRename AddUse(const SourceName &, const SourceName &, Symbol *);
+ void AddUseForPublicSymbols(SourceName, const std::set<SourceName> &);
+ void AddUseForCommonBlocks();
void DoAddUse(
SourceName, SourceName, Symbol &localSymbol, const Symbol &useSymbol);
void AddUse(const GenericSpecInfo &);
@@ -3862,30 +3865,40 @@ void ModuleVisitor::Post(const parser::UseStmt &x) {
},
rename.u);
}
- for (const auto &[name, symbol] : *useModuleScope_) {
- // Default USE imports public names, excluding intrinsic-only and most
- // miscellaneous details. Allow OpenMP mapper identifiers represented
- // as MapperDetails, and also legacy MiscDetails::ConstructName.
- bool isMapper{symbol->has<MapperDetails>()};
- if (!isMapper) {
- if (const auto *misc{symbol->detailsIf<MiscDetails>()}) {
- isMapper = misc->kind() == MiscDetails::Kind::ConstructName;
- }
- }
- if (symbol->attrs().test(Attr::PUBLIC) && !IsUseRenamed(symbol->name()) &&
- (!symbol->implicitAttrs().test(Attr::INTRINSIC) ||
- symbol->has<UseDetails>()) &&
- (!symbol->has<MiscDetails>() || isMapper) &&
- useNames.count(name) == 0) {
- SourceName location{x.moduleName.source};
- if (auto *localSymbol{FindInScope(name)}) {
- DoAddUse(location, localSymbol->name(), *localSymbol, *symbol);
- } else {
- DoAddUse(location, location, CopySymbol(name, *symbol), *symbol);
- }
+ AddUseForPublicSymbols(x.moduleName.source, useNames);
+ }
+ AddUseForCommonBlocks();
+
+ useModuleScope_ = nullptr;
+}
+
+void ModuleVisitor::AddUseForPublicSymbols(
+ SourceName location, const std::set<SourceName> &useNames) {
+ for (const auto &[name, symbol] : *useModuleScope_) {
+ // Default USE imports public names, excluding intrinsic-only and most
+ // miscellaneous details. Allow OpenMP mapper identifiers represented
+ // as MapperDetails, and also legacy MiscDetails::ConstructName.
+ bool isMapper{symbol->has<MapperDetails>()};
+ if (!isMapper) {
+ if (const auto *misc{symbol->detailsIf<MiscDetails>()}) {
+ isMapper = misc->kind() == MiscDetails::Kind::ConstructName;
+ }
+ }
+ if (symbol->attrs().test(Attr::PUBLIC) && !IsUseRenamed(symbol->name()) &&
+ (!symbol->implicitAttrs().test(Attr::INTRINSIC) ||
+ symbol->has<UseDetails>()) &&
+ (!symbol->has<MiscDetails>() || isMapper) &&
+ useNames.count(name) == 0) {
+ if (auto *localSymbol{FindInScope(name)}) {
+ DoAddUse(location, localSymbol->name(), *localSymbol, *symbol);
+ } else {
+ DoAddUse(location, location, CopySymbol(name, *symbol), *symbol);
}
}
}
+}
+
+void ModuleVisitor::AddUseForCommonBlocks() {
// Go through the list of COMMON block symbols in the module scope and add
// their USE association to the current scope's USE-associated COMMON blocks.
for (const auto &[name, symbol] : useModuleScope_->commonBlocks()) {
@@ -3900,8 +3913,37 @@ void ModuleVisitor::Post(const parser::UseStmt &x) {
for (const auto &[name, symbol] : useModuleScope_->commonBlockUses()) {
currScope().AddCommonBlockUse(name, symbol->attrs(), symbol->GetUltimate());
}
+}
- useModuleScope_ = nullptr;
+void ModuleVisitor::AddImplicitUseModules() {
+ 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) {
+ continue;
+ }
+ parser::Name name{moduleName};
+ std::optional<bool> isIntrinsic;
+ if (currScope().IsModule() && currScope().symbol() &&
+ currScope().symbol()->attrs().test(Attr::INTRINSIC)) {
+ // Intrinsic modules USE only other intrinsic modules.
+ isIntrinsic = true;
+ }
+ useModuleScope_ = FindModule(name, isIntrinsic);
+ if (!useModuleScope_) {
+ continue;
+ }
+ AddAndCheckModuleUse(moduleName,
+ useModuleScope_->parent().kind() == Scope::Kind::IntrinsicModules);
+ useModuleScope_->symbol()->ReplaceName(moduleName);
+ AddUseForPublicSymbols(moduleName, {});
+ AddUseForCommonBlocks();
+ useModuleScope_ = nullptr;
+ }
}
ModuleVisitor::SymbolRename ModuleVisitor::AddUse(
@@ -10297,6 +10339,7 @@ bool ResolveNamesVisitor::Pre(const parser::SpecificationPart &x) {
CollectUseRenames(useStmt.statement.value());
}
Walk(useStmts);
+ AddImplicitUseModules();
UseCUDABuiltinNames();
ClearUseRenames();
ClearUseOnly();
diff --git a/flang/test/Driver/bbc-implicit-use-module.f90 b/flang/test/Driver/bbc-implicit-use-module.f90
new file mode 100644
index 0000000000000..c9eb6ce444df8
--- /dev/null
+++ b/flang/test/Driver/bbc-implicit-use-module.f90
@@ -0,0 +1,20 @@
+! Test bbc's test-only implicit USE module hook.
+
+! RUN: split-file %s %t
+! RUN: bbc -module %t %t/implicit_mod.f90 -o /dev/null
+! RUN: bbc -emit-hlfir -I %t -implicit-use-module implicit_mod %t/use_implicit.f90 -o - | FileCheck %s
+
+!--- implicit_mod.f90
+module implicit_mod
+ implicit none
+ integer :: module_value = 42
+end module
+
+!--- use_implicit.f90
+subroutine use_implicit
+ integer :: x
+ x = module_value
+end subroutine
+
+! CHECK-LABEL: func.func @_QPuse_implicit()
+! CHECK: fir.address_of(@_QMimplicit_modEmodule_value) : !fir.ref<i32>
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 23e7af238198f..1f3a280438134 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -95,6 +95,10 @@ static llvm::cl::alias includeAlias("module-directory",
static llvm::cl::list<std::string>
intrinsicIncludeDirs("J", llvm::cl::desc("intrinsic module search paths"));
+static llvm::cl::list<std::string> implicitUseModules(
+ "implicit-use-module",
+ llvm::cl::desc("implicitly USE the named module for testing"));
+
static llvm::cl::alias
intrinsicIncludeAlias("intrinsic-module-directory",
llvm::cl::desc("intrinsic module directory"),
@@ -621,6 +625,9 @@ int main(int argc, char **argv) {
}
Fortran::parser::Options options;
+ options.implicitUseModules.insert(options.implicitUseModules.end(),
+ implicitUseModules.begin(),
+ implicitUseModules.end());
options.predefinitions.emplace_back("__flang__"s, "1"s);
options.predefinitions.emplace_back("__flang_major__"s,
std::string{FLANG_VERSION_MAJOR_STRING});
@@ -691,6 +698,7 @@ int main(int argc, char **argv) {
.set_moduleFileSuffix(moduleSuffix)
.set_searchDirectories(includeDirs)
.set_intrinsicModuleDirectories(intrinsicIncludeDirs)
+ .set_implicitUseModules(options.implicitUseModules)
.set_warnOnNonstandardUsage(warnStdViolation)
.set_warningsAreErrors(warnIsError);
>From c89213d50a12d865ffd8c971ef1ebef9edee8058 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Mon, 6 Jul 2026 13:45:03 -0700
Subject: [PATCH 2/3] Add common block
---
flang/test/Driver/bbc-implicit-use-module.f90 | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/flang/test/Driver/bbc-implicit-use-module.f90 b/flang/test/Driver/bbc-implicit-use-module.f90
index c9eb6ce444df8..733ad69580c1c 100644
--- a/flang/test/Driver/bbc-implicit-use-module.f90
+++ b/flang/test/Driver/bbc-implicit-use-module.f90
@@ -2,19 +2,25 @@
! RUN: split-file %s %t
! RUN: bbc -module %t %t/implicit_mod.f90 -o /dev/null
-! RUN: bbc -emit-hlfir -I %t -implicit-use-module implicit_mod %t/use_implicit.f90 -o - | FileCheck %s
+! RUN: bbc -emit-hlfir -fopenacc -I %t -implicit-use-module implicit_mod %t/use_implicit.f90 -o - | FileCheck %s
!--- implicit_mod.f90
module implicit_mod
implicit none
+ integer :: common_value
integer :: module_value = 42
+ common /implicit_common/ common_value
end module
!--- use_implicit.f90
subroutine use_implicit
integer :: x
- x = module_value
+ !$acc data copy(/implicit_common/)
+ x = module_value + common_value
+ !$acc end data
end subroutine
! CHECK-LABEL: func.func @_QPuse_implicit()
-! CHECK: fir.address_of(@_QMimplicit_modEmodule_value) : !fir.ref<i32>
+! 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]]
>From 71fbbccb64c6b19aaabc0dfabb0ceb4a37011560 Mon Sep 17 00:00:00 2001
From: Valentin Clement <clementval at gmail.com>
Date: Mon, 6 Jul 2026 14:02:41 -0700
Subject: [PATCH 3/3] Simplify
---
flang/include/flang/Parser/options.h | 1 -
flang/tools/bbc/bbc.cpp | 5 +----
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/flang/include/flang/Parser/options.h b/flang/include/flang/Parser/options.h
index 8a9fcd0568652..e65f253748d26 100644
--- a/flang/include/flang/Parser/options.h
+++ b/flang/include/flang/Parser/options.h
@@ -28,7 +28,6 @@ struct Options {
common::LanguageFeatureControl features;
std::vector<std::string> searchDirectories;
std::vector<std::string> intrinsicModuleDirectories;
- std::vector<std::string> implicitUseModules;
std::vector<Predefinition> predefinitions;
bool instrumentedParse{false};
bool isModuleFile{false};
diff --git a/flang/tools/bbc/bbc.cpp b/flang/tools/bbc/bbc.cpp
index 1f3a280438134..88fa43c748e2f 100644
--- a/flang/tools/bbc/bbc.cpp
+++ b/flang/tools/bbc/bbc.cpp
@@ -625,9 +625,6 @@ int main(int argc, char **argv) {
}
Fortran::parser::Options options;
- options.implicitUseModules.insert(options.implicitUseModules.end(),
- implicitUseModules.begin(),
- implicitUseModules.end());
options.predefinitions.emplace_back("__flang__"s, "1"s);
options.predefinitions.emplace_back("__flang_major__"s,
std::string{FLANG_VERSION_MAJOR_STRING});
@@ -698,7 +695,7 @@ int main(int argc, char **argv) {
.set_moduleFileSuffix(moduleSuffix)
.set_searchDirectories(includeDirs)
.set_intrinsicModuleDirectories(intrinsicIncludeDirs)
- .set_implicitUseModules(options.implicitUseModules)
+ .set_implicitUseModules(implicitUseModules)
.set_warnOnNonstandardUsage(warnStdViolation)
.set_warningsAreErrors(warnIsError);
More information about the flang-commits
mailing list