[flang-commits] [flang] f7be1aa - [flang] Prohibit multiple separate module procedure definitions
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Fri Jan 27 14:43:08 PST 2023
Author: Peter Klausler
Date: 2023-01-27T14:34:03-08:00
New Revision: f7be1aadf2d040b943b96a9ed52bf654faf33f08
URL: https://github.com/llvm/llvm-project/commit/f7be1aadf2d040b943b96a9ed52bf654faf33f08
DIFF: https://github.com/llvm/llvm-project/commit/f7be1aadf2d040b943b96a9ed52bf654faf33f08.diff
LOG: [flang] Prohibit multiple separate module procedure definitions
Ensure that non-BIND(C) separate module procedures are not
defined more than once.
Differential Revision: https://reviews.llvm.org/D142750
Added:
flang/test/Semantics/separate-mp04.f90
Modified:
flang/lib/Semantics/check-declarations.cpp
flang/lib/Semantics/resolve-names.cpp
flang/lib/Semantics/scope.cpp
Removed:
################################################################################
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 6746d47a9b02..8b072999f82d 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -141,6 +141,7 @@ class CheckHelper {
};
void CheckAlreadySeenDefinedIo(const DerivedTypeSpec &,
GenericKind::DefinedIo, const Symbol &, const Symbol &generic);
+ void CheckModuleProcedureDef(const Symbol &);
SemanticsContext &context_;
evaluate::FoldingContext &foldingContext_{context_.foldingContext()};
@@ -155,6 +156,9 @@ class CheckHelper {
characterizeCache_;
// Collection of symbols with BIND(C) names
std::map<std::string, SymbolRef> bindC_;
+ // Collection of module procedure symbols with non-BIND(C)
+ // global names, qualified by their module.
+ std::map<std::pair<SourceName, const Symbol *>, SymbolRef> moduleProcs_;
// Derived types that have defined input/output procedures
std::vector<TypeWithDefinedIo> seenDefinedIoTypes_;
};
@@ -1052,6 +1056,7 @@ void CheckHelper::CheckSubprogram(
}
}
CheckLocalVsGlobal(symbol);
+ CheckModuleProcedureDef(symbol);
}
void CheckHelper::CheckLocalVsGlobal(const Symbol &symbol) {
@@ -1329,6 +1334,13 @@ void CheckHelper::CheckGeneric(
[](const auto &) {},
},
details.kind().u);
+ // Ensure that shadowed symbols are checked
+ if (details.specific()) {
+ Check(*details.specific());
+ }
+ if (details.derivedType()) {
+ Check(*details.derivedType());
+ }
}
// Check that the specifics of this generic are distinguishable from each other
@@ -2442,6 +2454,40 @@ void CheckHelper::CheckSymbolType(const Symbol &symbol) {
}
}
+void CheckHelper::CheckModuleProcedureDef(const Symbol &symbol) {
+ auto procClass{ClassifyProcedure(symbol)};
+ if (const auto *subprogram{symbol.detailsIf<SubprogramDetails>()};
+ subprogram &&
+ (procClass == ProcedureDefinitionClass::Module &&
+ symbol.attrs().test(Attr::MODULE)) &&
+ !subprogram->bindName() && !subprogram->isInterface()) {
+ const Symbol *module{nullptr};
+ if (const Scope * moduleScope{FindModuleContaining(symbol.owner())};
+ moduleScope && moduleScope->symbol()) {
+ if (const auto *details{
+ moduleScope->symbol()->detailsIf<ModuleDetails>()}) {
+ if (details->parent()) {
+ moduleScope = details->parent();
+ }
+ module = moduleScope->symbol();
+ }
+ }
+ if (module) {
+ std::pair<SourceName, const Symbol *> key{symbol.name(), module};
+ auto iter{moduleProcs_.find(key)};
+ if (iter == moduleProcs_.end()) {
+ moduleProcs_.emplace(std::move(key), symbol);
+ } else if (
+ auto *msg{messages_.Say(symbol.name(),
+ "Module procedure '%s' in module '%s' has multiple definitions"_err_en_US,
+ symbol.name(), module->name())}) {
+ msg->Attach(iter->second->name(), "Previous definition of '%s'"_en_US,
+ symbol.name());
+ }
+ }
+ }
+}
+
void SubprogramMatchHelper::Check(
const Symbol &symbol1, const Symbol &symbol2) {
const auto details1{symbol1.get<SubprogramDetails>()};
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index fdc3b3e350cc..d66b7592336c 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -3709,13 +3709,21 @@ Symbol *ScopeHandler::FindSeparateModuleProcedureInterface(
const parser::Name &name) {
auto *symbol{FindSymbol(name)};
if (symbol && symbol->has<SubprogramNameDetails>()) {
- symbol = FindSymbol(currScope().parent(), name);
+ const Scope *parent{nullptr};
+ if (currScope().IsSubmodule()) {
+ parent = currScope().symbol()->get<ModuleDetails>().parent();
+ }
+ symbol = parent ? FindSymbol(*parent, name) : nullptr;
}
if (symbol) {
if (auto *generic{symbol->detailsIf<GenericDetails>()}) {
symbol = generic->specific();
}
}
+ if (const Symbol * defnIface{FindSeparateModuleSubprogramInterface(symbol)}) {
+ // Error recovery in case of multiple definitions
+ symbol = const_cast<Symbol *>(defnIface);
+ }
if (!IsSeparateModuleProcedureInterface(symbol)) {
Say(name, "'%s' was not declared a separate module procedure"_err_en_US);
symbol = nullptr;
diff --git a/flang/lib/Semantics/scope.cpp b/flang/lib/Semantics/scope.cpp
index 387f8e7d4f10..bcffbd331280 100644
--- a/flang/lib/Semantics/scope.cpp
+++ b/flang/lib/Semantics/scope.cpp
@@ -88,6 +88,9 @@ Symbol *Scope::FindSymbol(const SourceName &name) const {
auto it{find(name)};
if (it != end()) {
return &*it->second;
+ } else if (IsSubmodule()) {
+ const Scope *parent{symbol_->get<ModuleDetails>().parent()};
+ return parent ? parent->FindSymbol(name) : nullptr;
} else if (CanImport(name)) {
return parent_.FindSymbol(name);
} else {
diff --git a/flang/test/Semantics/separate-mp04.f90 b/flang/test/Semantics/separate-mp04.f90
new file mode 100644
index 000000000000..32005edd91a3
--- /dev/null
+++ b/flang/test/Semantics/separate-mp04.f90
@@ -0,0 +1,57 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+! Checks for multiple module procedure definitions
+
+module m1
+ interface
+ module subroutine x001
+ end subroutine
+ module subroutine x002
+ end subroutine
+ module subroutine x003
+ end subroutine
+ end interface
+end
+
+submodule(m1) sm1
+ interface
+ module subroutine x004
+ end subroutine
+ end interface
+ contains
+ module procedure x001 ! fine
+ end procedure
+ module subroutine x002
+ end subroutine
+ module subroutine x003
+ end subroutine
+end
+
+submodule(m1) sm2
+ contains
+ !ERROR: Module procedure 'x002' in module 'm1' has multiple definitions
+ module subroutine x002
+ end subroutine
+end
+
+submodule(m1:sm2) sm3
+ contains
+ !ERROR: Module procedure 'x002' in module 'm1' has multiple definitions
+ module subroutine x002
+ end subroutine
+ !ERROR: Module procedure 'x003' in module 'm1' has multiple definitions
+ module subroutine x003
+ end subroutine
+end
+
+submodule(m1:sm1) sm4
+ contains
+ module subroutine x004
+ end subroutine
+end
+
+submodule(m1:sm1) sm5
+ contains
+ !ERROR: Module procedure 'x004' in module 'm1' has multiple definitions
+ module subroutine x004
+ end subroutine
+end
More information about the flang-commits
mailing list