diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index 361d69e849213..19304d72bb0cb 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -107,7 +107,7 @@ class SubprogramDetails : public WithBindName { }; // For SubprogramNameDetails, the kind indicates whether it is the name -// of a module subprogram or internal subprogram. +// of a module subprogram or an internal subprogram or ENTRY. ENUM_CLASS(SubprogramKind, Module, Internal) // Symbol with SubprogramNameDetails is created when we scan for module and @@ -121,10 +121,16 @@ class SubprogramNameDetails { SubprogramNameDetails() = delete; SubprogramKind kind() const { return kind_; } ProgramTree &node() const { return *node_; } + bool isEntryStmt() const { return isEntryStmt_; } + SubprogramNameDetails &set_isEntryStmt(bool yes = true) { + isEntryStmt_ = yes; + return *this; + } private: SubprogramKind kind_; common::Reference node_; + bool isEntryStmt_{false}; }; // A name from an entity-decl -- could be object or function. diff --git a/flang/lib/Semantics/program-tree.cpp b/flang/lib/Semantics/program-tree.cpp index 9466a748567e1..e20299b2fb4c5 100644 --- a/flang/lib/Semantics/program-tree.cpp +++ b/flang/lib/Semantics/program-tree.cpp @@ -13,6 +13,37 @@ namespace Fortran::semantics { +static void GetEntryStmts( + ProgramTree &node, const parser::SpecificationPart &spec) { + const auto &implicitPart{std::get(spec.t)}; + for (const parser::ImplicitPartStmt &stmt : implicitPart.v) { + if (const auto *entryStmt{std::get_if< + parser::Statement>>( + &stmt.u)}) { + node.AddEntry(entryStmt->statement.value()); + } + } + for (const auto &decl : + std::get>(spec.t)) { + if (const auto *entryStmt{std::get_if< + parser::Statement>>( + &decl.u)}) { + node.AddEntry(entryStmt->statement.value()); + } + } +} + +static void GetEntryStmts( + ProgramTree &node, const parser::ExecutionPart &exec) { + for (const auto &epConstruct : exec.v) { + if (const auto *entryStmt{std::get_if< + parser::Statement>>( + &epConstruct.u)}) { + node.AddEntry(entryStmt->statement.value()); + } + } +} + template static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) { const auto &spec{std::get(x.t)}; @@ -20,6 +51,8 @@ static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) { const auto &subps{ std::get>(x.t)}; ProgramTree node{name, spec, &exec}; + GetEntryStmts(node, spec); + GetEntryStmts(node, exec); if (subps) { for (const auto &subp : std::get>(subps->t)) { @@ -34,7 +67,7 @@ static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) { static ProgramTree BuildSubprogramTree( const parser::Name &name, const parser::BlockData &x) { const auto &spec{std::get(x.t)}; - return ProgramTree{name, spec, nullptr}; + return ProgramTree{name, spec}; } template @@ -193,4 +226,8 @@ void ProgramTree::AddChild(ProgramTree &&child) { children_.emplace_back(std::move(child)); } +void ProgramTree::AddEntry(const parser::EntryStmt &entryStmt) { + entryStmts_.emplace_back(entryStmt); +} + } // namespace Fortran::semantics diff --git a/flang/lib/Semantics/program-tree.h b/flang/lib/Semantics/program-tree.h index 6b07452282017..798abd7ea8d6b 100644 --- a/flang/lib/Semantics/program-tree.h +++ b/flang/lib/Semantics/program-tree.h @@ -29,6 +29,8 @@ class Scope; class ProgramTree { public: + using EntryStmtList = std::list>; + // Build the ProgramTree rooted at one of these program units. static ProgramTree Build(const parser::ProgramUnit &); static ProgramTree Build(const parser::MainProgram &); @@ -69,12 +71,17 @@ class ProgramTree { const parser::ExecutionPart *exec() const { return exec_; } std::list &children() { return children_; } const std::list &children() const { return children_; } + const std::list> & + entryStmts() const { + return entryStmts_; + } Symbol::Flag GetSubpFlag() const; bool IsModule() const; // Module or Submodule bool HasModulePrefix() const; // in function or subroutine stmt Scope *scope() const { return scope_; } void set_scope(Scope &); void AddChild(ProgramTree &&); + void AddEntry(const parser::EntryStmt &); template ProgramTree &set_stmt(const parser::Statement &stmt) { @@ -94,6 +101,7 @@ class ProgramTree { const parser::SpecificationPart &spec_; const parser::ExecutionPart *exec_{nullptr}; std::list children_; + EntryStmtList entryStmts_; Scope *scope_{nullptr}; const parser::CharBlock *endStmt_{nullptr}; bool isSpecificationPartResolved_{false}; diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index b401ef2bf276f..8e22bb5dc4394 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -2796,7 +2796,7 @@ void InterfaceVisitor::ResolveSpecificsInGeneric(Symbol &generic) { } auto range{specificProcs_.equal_range(&generic)}; for (auto it{range.first}; it != range.second; ++it) { - auto *name{it->second.first}; + const parser::Name *name{it->second.first}; auto kind{it->second.second}; const auto *symbol{FindSymbol(*name)}; if (!symbol) { @@ -6915,13 +6915,21 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) { } } -// Add SubprogramNameDetails symbols for module and internal subprograms +// Add SubprogramNameDetails symbols for module and internal subprograms and +// their ENTRY statements. void ResolveNamesVisitor::AddSubpNames(ProgramTree &node) { auto kind{ node.IsModule() ? SubprogramKind::Module : SubprogramKind::Internal}; for (auto &child : node.children()) { auto &symbol{MakeSymbol(child.name(), SubprogramNameDetails{kind, child})}; symbol.set(child.GetSubpFlag()); + for (const auto &entryStmt : child.entryStmts()) { + SubprogramNameDetails details{kind, child}; + details.set_isEntryStmt(); + auto &symbol{ + MakeSymbol(std::get(entryStmt->t), std::move(details))}; + symbol.set(child.GetSubpFlag()); + } } } @@ -7125,7 +7133,8 @@ void ResolveSpecificationParts( SemanticsContext &context, const Symbol &subprogram) { auto originalLocation{context.location()}; ResolveNamesVisitor visitor{context, DEREF(sharedImplicitRulesMap)}; - ProgramTree &node{subprogram.get().node()}; + const auto &details{subprogram.get()}; + ProgramTree &node{details.node()}; const Scope &moduleScope{subprogram.owner()}; visitor.SetScope(const_cast(moduleScope)); visitor.ResolveSpecificationParts(node); diff --git a/flang/test/Semantics/entry01.f90 b/flang/test/Semantics/entry01.f90 index c9c48193c72f5..2a95d6cc5906f 100644 --- a/flang/test/Semantics/entry01.f90 +++ b/flang/test/Semantics/entry01.f90 @@ -139,11 +139,12 @@ subroutine externals end subroutine module m2 + !ERROR: EXTERNAL attribute not allowed on 'm2entry2' external m2entry2 contains subroutine m2subr1 entry m2entry1 ! ok - entry m2entry2 ! ok + entry m2entry2 ! NOT ok entry m2entry3 ! ok end subroutine end module @@ -173,6 +174,27 @@ subroutine m3subr1 end subroutine end module +module m4 + interface generic1 + module procedure m4entry1 + end interface + interface generic2 + module procedure m4entry2 + end interface + interface generic3 + module procedure m4entry3 + end interface + contains + subroutine m4subr1 + entry m4entry1 ! in implicit part + integer :: n = 0 + entry m4entry2 ! in specification part + n = 123 + entry m4entry3 ! in executable part + print *, n + end subroutine +end module + function inone implicit none integer :: inone