Skip to content

Commit bed947f

Browse files
committed
[flang] Accept ENTRY names in generic interfaces
ENTRY statement names in module subprograms were not acceptable for use as a "module procedure" in a generic interface, but should be. ENTRY statements need to have symbols with place-holding SubprogramNameDetails created for them in order to be visible in generic interfaces. Those symbols are created from the "program tree" data structure. This patch adds ENTRY statement names to the program tree data structure and uses them to generate SubprogramNameDetails symbols. Differential Revision: https://reviews.llvm.org/D117345
1 parent 8dff860 commit bed947f

File tree

5 files changed

+88
-6
lines changed

5 files changed

+88
-6
lines changed

flang/include/flang/Semantics/symbol.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class SubprogramDetails : public WithBindName {
107107
};
108108

109109
// For SubprogramNameDetails, the kind indicates whether it is the name
110-
// of a module subprogram or internal subprogram.
110+
// of a module subprogram or an internal subprogram or ENTRY.
111111
ENUM_CLASS(SubprogramKind, Module, Internal)
112112

113113
// Symbol with SubprogramNameDetails is created when we scan for module and
@@ -121,10 +121,16 @@ class SubprogramNameDetails {
121121
SubprogramNameDetails() = delete;
122122
SubprogramKind kind() const { return kind_; }
123123
ProgramTree &node() const { return *node_; }
124+
bool isEntryStmt() const { return isEntryStmt_; }
125+
SubprogramNameDetails &set_isEntryStmt(bool yes = true) {
126+
isEntryStmt_ = yes;
127+
return *this;
128+
}
124129

125130
private:
126131
SubprogramKind kind_;
127132
common::Reference<ProgramTree> node_;
133+
bool isEntryStmt_{false};
128134
};
129135

130136
// A name from an entity-decl -- could be object or function.

flang/lib/Semantics/program-tree.cpp

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,46 @@
1313

1414
namespace Fortran::semantics {
1515

16+
static void GetEntryStmts(
17+
ProgramTree &node, const parser::SpecificationPart &spec) {
18+
const auto &implicitPart{std::get<parser::ImplicitPart>(spec.t)};
19+
for (const parser::ImplicitPartStmt &stmt : implicitPart.v) {
20+
if (const auto *entryStmt{std::get_if<
21+
parser::Statement<common::Indirection<parser::EntryStmt>>>(
22+
&stmt.u)}) {
23+
node.AddEntry(entryStmt->statement.value());
24+
}
25+
}
26+
for (const auto &decl :
27+
std::get<std::list<parser::DeclarationConstruct>>(spec.t)) {
28+
if (const auto *entryStmt{std::get_if<
29+
parser::Statement<common::Indirection<parser::EntryStmt>>>(
30+
&decl.u)}) {
31+
node.AddEntry(entryStmt->statement.value());
32+
}
33+
}
34+
}
35+
36+
static void GetEntryStmts(
37+
ProgramTree &node, const parser::ExecutionPart &exec) {
38+
for (const auto &epConstruct : exec.v) {
39+
if (const auto *entryStmt{std::get_if<
40+
parser::Statement<common::Indirection<parser::EntryStmt>>>(
41+
&epConstruct.u)}) {
42+
node.AddEntry(entryStmt->statement.value());
43+
}
44+
}
45+
}
46+
1647
template <typename T>
1748
static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) {
1849
const auto &spec{std::get<parser::SpecificationPart>(x.t)};
1950
const auto &exec{std::get<parser::ExecutionPart>(x.t)};
2051
const auto &subps{
2152
std::get<std::optional<parser::InternalSubprogramPart>>(x.t)};
2253
ProgramTree node{name, spec, &exec};
54+
GetEntryStmts(node, spec);
55+
GetEntryStmts(node, exec);
2356
if (subps) {
2457
for (const auto &subp :
2558
std::get<std::list<parser::InternalSubprogram>>(subps->t)) {
@@ -34,7 +67,7 @@ static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) {
3467
static ProgramTree BuildSubprogramTree(
3568
const parser::Name &name, const parser::BlockData &x) {
3669
const auto &spec{std::get<parser::SpecificationPart>(x.t)};
37-
return ProgramTree{name, spec, nullptr};
70+
return ProgramTree{name, spec};
3871
}
3972

4073
template <typename T>
@@ -193,4 +226,8 @@ void ProgramTree::AddChild(ProgramTree &&child) {
193226
children_.emplace_back(std::move(child));
194227
}
195228

229+
void ProgramTree::AddEntry(const parser::EntryStmt &entryStmt) {
230+
entryStmts_.emplace_back(entryStmt);
231+
}
232+
196233
} // namespace Fortran::semantics

flang/lib/Semantics/program-tree.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class Scope;
2929

3030
class ProgramTree {
3131
public:
32+
using EntryStmtList = std::list<common::Reference<const parser::EntryStmt>>;
33+
3234
// Build the ProgramTree rooted at one of these program units.
3335
static ProgramTree Build(const parser::ProgramUnit &);
3436
static ProgramTree Build(const parser::MainProgram &);
@@ -69,12 +71,17 @@ class ProgramTree {
6971
const parser::ExecutionPart *exec() const { return exec_; }
7072
std::list<ProgramTree> &children() { return children_; }
7173
const std::list<ProgramTree> &children() const { return children_; }
74+
const std::list<common::Reference<const parser::EntryStmt>> &
75+
entryStmts() const {
76+
return entryStmts_;
77+
}
7278
Symbol::Flag GetSubpFlag() const;
7379
bool IsModule() const; // Module or Submodule
7480
bool HasModulePrefix() const; // in function or subroutine stmt
7581
Scope *scope() const { return scope_; }
7682
void set_scope(Scope &);
7783
void AddChild(ProgramTree &&);
84+
void AddEntry(const parser::EntryStmt &);
7885

7986
template <typename T>
8087
ProgramTree &set_stmt(const parser::Statement<T> &stmt) {
@@ -94,6 +101,7 @@ class ProgramTree {
94101
const parser::SpecificationPart &spec_;
95102
const parser::ExecutionPart *exec_{nullptr};
96103
std::list<ProgramTree> children_;
104+
EntryStmtList entryStmts_;
97105
Scope *scope_{nullptr};
98106
const parser::CharBlock *endStmt_{nullptr};
99107
bool isSpecificationPartResolved_{false};

flang/lib/Semantics/resolve-names.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2796,7 +2796,7 @@ void InterfaceVisitor::ResolveSpecificsInGeneric(Symbol &generic) {
27962796
}
27972797
auto range{specificProcs_.equal_range(&generic)};
27982798
for (auto it{range.first}; it != range.second; ++it) {
2799-
auto *name{it->second.first};
2799+
const parser::Name *name{it->second.first};
28002800
auto kind{it->second.second};
28012801
const auto *symbol{FindSymbol(*name)};
28022802
if (!symbol) {
@@ -6915,13 +6915,21 @@ void ResolveNamesVisitor::ResolveSpecificationParts(ProgramTree &node) {
69156915
}
69166916
}
69176917

6918-
// Add SubprogramNameDetails symbols for module and internal subprograms
6918+
// Add SubprogramNameDetails symbols for module and internal subprograms and
6919+
// their ENTRY statements.
69196920
void ResolveNamesVisitor::AddSubpNames(ProgramTree &node) {
69206921
auto kind{
69216922
node.IsModule() ? SubprogramKind::Module : SubprogramKind::Internal};
69226923
for (auto &child : node.children()) {
69236924
auto &symbol{MakeSymbol(child.name(), SubprogramNameDetails{kind, child})};
69246925
symbol.set(child.GetSubpFlag());
6926+
for (const auto &entryStmt : child.entryStmts()) {
6927+
SubprogramNameDetails details{kind, child};
6928+
details.set_isEntryStmt();
6929+
auto &symbol{
6930+
MakeSymbol(std::get<parser::Name>(entryStmt->t), std::move(details))};
6931+
symbol.set(child.GetSubpFlag());
6932+
}
69256933
}
69266934
}
69276935

@@ -7125,7 +7133,8 @@ void ResolveSpecificationParts(
71257133
SemanticsContext &context, const Symbol &subprogram) {
71267134
auto originalLocation{context.location()};
71277135
ResolveNamesVisitor visitor{context, DEREF(sharedImplicitRulesMap)};
7128-
ProgramTree &node{subprogram.get<SubprogramNameDetails>().node()};
7136+
const auto &details{subprogram.get<SubprogramNameDetails>()};
7137+
ProgramTree &node{details.node()};
71297138
const Scope &moduleScope{subprogram.owner()};
71307139
visitor.SetScope(const_cast<Scope &>(moduleScope));
71317140
visitor.ResolveSpecificationParts(node);

flang/test/Semantics/entry01.f90

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,12 @@ subroutine externals
139139
end subroutine
140140

141141
module m2
142+
!ERROR: EXTERNAL attribute not allowed on 'm2entry2'
142143
external m2entry2
143144
contains
144145
subroutine m2subr1
145146
entry m2entry1 ! ok
146-
entry m2entry2 ! ok
147+
entry m2entry2 ! NOT ok
147148
entry m2entry3 ! ok
148149
end subroutine
149150
end module
@@ -173,6 +174,27 @@ subroutine m3subr1
173174
end subroutine
174175
end module
175176

177+
module m4
178+
interface generic1
179+
module procedure m4entry1
180+
end interface
181+
interface generic2
182+
module procedure m4entry2
183+
end interface
184+
interface generic3
185+
module procedure m4entry3
186+
end interface
187+
contains
188+
subroutine m4subr1
189+
entry m4entry1 ! in implicit part
190+
integer :: n = 0
191+
entry m4entry2 ! in specification part
192+
n = 123
193+
entry m4entry3 ! in executable part
194+
print *, n
195+
end subroutine
196+
end module
197+
176198
function inone
177199
implicit none
178200
integer :: inone

0 commit comments

Comments
 (0)