Skip to content

Commit 68a2798

Browse files
authored
[flang] Accept and ignore compiler directives between internal subpro… (#89810)
…grams The parser only recognizes compiler directives that appear within internal / module subprograms, not those that might appear between them. Extend to allow them between subprograms as well.
1 parent 0e1bb1d commit 68a2798

File tree

6 files changed

+91
-43
lines changed

6 files changed

+91
-43
lines changed

flang/include/flang/Parser/parse-tree.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,8 @@ struct SpecificationPart {
455455
struct InternalSubprogram {
456456
UNION_CLASS_BOILERPLATE(InternalSubprogram);
457457
std::variant<common::Indirection<FunctionSubprogram>,
458-
common::Indirection<SubroutineSubprogram>>
458+
common::Indirection<SubroutineSubprogram>,
459+
common::Indirection<CompilerDirective>>
459460
u;
460461
};
461462

flang/lib/Parser/Fortran-parsers.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ TYPE_PARSER(first(
123123
TYPE_CONTEXT_PARSER("internal subprogram"_en_US,
124124
(construct<InternalSubprogram>(indirect(functionSubprogram)) ||
125125
construct<InternalSubprogram>(indirect(subroutineSubprogram))) /
126-
forceEndOfStmt)
126+
forceEndOfStmt ||
127+
construct<InternalSubprogram>(indirect(compilerDirective)))
127128

128129
// R511 internal-subprogram-part -> contains-stmt [internal-subprogram]...
129130
TYPE_CONTEXT_PARSER("internal subprogram part"_en_US,

flang/lib/Semantics/program-tree.cpp

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "flang/Common/idioms.h"
1111
#include "flang/Parser/char-block.h"
1212
#include "flang/Semantics/scope.h"
13+
#include "flang/Semantics/semantics.h"
1314

1415
namespace Fortran::semantics {
1516

@@ -76,7 +77,8 @@ static void GetGenerics(
7677
}
7778

7879
template <typename T>
79-
static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) {
80+
static ProgramTree BuildSubprogramTree(
81+
const parser::Name &name, SemanticsContext &context, const T &x) {
8082
const auto &spec{std::get<parser::SpecificationPart>(x.t)};
8183
const auto &exec{std::get<parser::ExecutionPart>(x.t)};
8284
const auto &subps{
@@ -89,21 +91,26 @@ static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) {
8991
for (const auto &subp :
9092
std::get<std::list<parser::InternalSubprogram>>(subps->t)) {
9193
common::visit(
92-
[&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); },
94+
[&](const auto &y) {
95+
if (auto child{ProgramTree::Build(y.value(), context)}) {
96+
node.AddChild(std::move(*child));
97+
}
98+
},
9399
subp.u);
94100
}
95101
}
96102
return node;
97103
}
98104

99105
static ProgramTree BuildSubprogramTree(
100-
const parser::Name &name, const parser::BlockData &x) {
106+
const parser::Name &name, SemanticsContext &, const parser::BlockData &x) {
101107
const auto &spec{std::get<parser::SpecificationPart>(x.t)};
102108
return ProgramTree{name, spec};
103109
}
104110

105111
template <typename T>
106-
static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) {
112+
static ProgramTree BuildModuleTree(
113+
const parser::Name &name, SemanticsContext &context, const T &x) {
107114
const auto &spec{std::get<parser::SpecificationPart>(x.t)};
108115
const auto &subps{std::get<std::optional<parser::ModuleSubprogramPart>>(x.t)};
109116
ProgramTree node{name, spec};
@@ -112,28 +119,42 @@ static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) {
112119
for (const auto &subp :
113120
std::get<std::list<parser::ModuleSubprogram>>(subps->t)) {
114121
common::visit(
115-
[&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); },
122+
[&](const auto &y) {
123+
if (auto child{ProgramTree::Build(y.value(), context)}) {
124+
node.AddChild(std::move(*child));
125+
}
126+
},
116127
subp.u);
117128
}
118129
}
119130
return node;
120131
}
121132

122-
ProgramTree ProgramTree::Build(const parser::ProgramUnit &x) {
123-
return common::visit([](const auto &y) { return Build(y.value()); }, x.u);
133+
ProgramTree ProgramTree::Build(
134+
const parser::ProgramUnit &x, SemanticsContext &context) {
135+
return common::visit(
136+
[&](const auto &y) {
137+
auto node{Build(y.value(), context)};
138+
CHECK(node.has_value());
139+
return std::move(*node);
140+
},
141+
x.u);
124142
}
125143

126-
ProgramTree ProgramTree::Build(const parser::MainProgram &x) {
144+
std::optional<ProgramTree> ProgramTree::Build(
145+
const parser::MainProgram &x, SemanticsContext &context) {
127146
const auto &stmt{
128147
std::get<std::optional<parser::Statement<parser::ProgramStmt>>>(x.t)};
129148
const auto &end{std::get<parser::Statement<parser::EndProgramStmt>>(x.t)};
130149
static parser::Name emptyName;
131-
auto result{stmt ? BuildSubprogramTree(stmt->statement.v, x).set_stmt(*stmt)
132-
: BuildSubprogramTree(emptyName, x)};
133-
return result.set_endStmt(end);
150+
auto result{stmt
151+
? BuildSubprogramTree(stmt->statement.v, context, x).set_stmt(*stmt)
152+
: BuildSubprogramTree(emptyName, context, x)};
153+
return std::move(result.set_endStmt(end));
134154
}
135155

136-
ProgramTree ProgramTree::Build(const parser::FunctionSubprogram &x) {
156+
std::optional<ProgramTree> ProgramTree::Build(
157+
const parser::FunctionSubprogram &x, SemanticsContext &context) {
137158
const auto &stmt{std::get<parser::Statement<parser::FunctionStmt>>(x.t)};
138159
const auto &end{std::get<parser::Statement<parser::EndFunctionStmt>>(x.t)};
139160
const auto &name{std::get<parser::Name>(stmt.statement.t)};
@@ -144,13 +165,14 @@ ProgramTree ProgramTree::Build(const parser::FunctionSubprogram &x) {
144165
bindingSpec = &*suffix->binding;
145166
}
146167
}
147-
return BuildSubprogramTree(name, x)
168+
return BuildSubprogramTree(name, context, x)
148169
.set_stmt(stmt)
149170
.set_endStmt(end)
150171
.set_bindingSpec(bindingSpec);
151172
}
152173

153-
ProgramTree ProgramTree::Build(const parser::SubroutineSubprogram &x) {
174+
std::optional<ProgramTree> ProgramTree::Build(
175+
const parser::SubroutineSubprogram &x, SemanticsContext &context) {
154176
const auto &stmt{std::get<parser::Statement<parser::SubroutineStmt>>(x.t)};
155177
const auto &end{std::get<parser::Statement<parser::EndSubroutineStmt>>(x.t)};
156178
const auto &name{std::get<parser::Name>(stmt.statement.t)};
@@ -159,48 +181,56 @@ ProgramTree ProgramTree::Build(const parser::SubroutineSubprogram &x) {
159181
stmt.statement.t)}) {
160182
bindingSpec = &*binding;
161183
}
162-
return BuildSubprogramTree(name, x)
184+
return BuildSubprogramTree(name, context, x)
163185
.set_stmt(stmt)
164186
.set_endStmt(end)
165187
.set_bindingSpec(bindingSpec);
166188
}
167189

168-
ProgramTree ProgramTree::Build(const parser::SeparateModuleSubprogram &x) {
190+
std::optional<ProgramTree> ProgramTree::Build(
191+
const parser::SeparateModuleSubprogram &x, SemanticsContext &context) {
169192
const auto &stmt{std::get<parser::Statement<parser::MpSubprogramStmt>>(x.t)};
170193
const auto &end{
171194
std::get<parser::Statement<parser::EndMpSubprogramStmt>>(x.t)};
172195
const auto &name{stmt.statement.v};
173-
return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end);
196+
return BuildSubprogramTree(name, context, x).set_stmt(stmt).set_endStmt(end);
174197
}
175198

176-
ProgramTree ProgramTree::Build(const parser::Module &x) {
199+
std::optional<ProgramTree> ProgramTree::Build(
200+
const parser::Module &x, SemanticsContext &context) {
177201
const auto &stmt{std::get<parser::Statement<parser::ModuleStmt>>(x.t)};
178202
const auto &end{std::get<parser::Statement<parser::EndModuleStmt>>(x.t)};
179203
const auto &name{stmt.statement.v};
180-
return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end);
204+
return BuildModuleTree(name, context, x).set_stmt(stmt).set_endStmt(end);
181205
}
182206

183-
ProgramTree ProgramTree::Build(const parser::Submodule &x) {
207+
std::optional<ProgramTree> ProgramTree::Build(
208+
const parser::Submodule &x, SemanticsContext &context) {
184209
const auto &stmt{std::get<parser::Statement<parser::SubmoduleStmt>>(x.t)};
185210
const auto &end{std::get<parser::Statement<parser::EndSubmoduleStmt>>(x.t)};
186211
const auto &name{std::get<parser::Name>(stmt.statement.t)};
187-
return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end);
212+
return BuildModuleTree(name, context, x).set_stmt(stmt).set_endStmt(end);
188213
}
189214

190-
ProgramTree ProgramTree::Build(const parser::BlockData &x) {
215+
std::optional<ProgramTree> ProgramTree::Build(
216+
const parser::BlockData &x, SemanticsContext &context) {
191217
const auto &stmt{std::get<parser::Statement<parser::BlockDataStmt>>(x.t)};
192218
const auto &end{std::get<parser::Statement<parser::EndBlockDataStmt>>(x.t)};
193219
static parser::Name emptyName;
194-
auto result{stmt.statement.v ? BuildSubprogramTree(*stmt.statement.v, x)
195-
: BuildSubprogramTree(emptyName, x)};
196-
return result.set_stmt(stmt).set_endStmt(end);
220+
auto result{stmt.statement.v
221+
? BuildSubprogramTree(*stmt.statement.v, context, x)
222+
: BuildSubprogramTree(emptyName, context, x)};
223+
return std::move(result.set_stmt(stmt).set_endStmt(end));
197224
}
198225

199-
ProgramTree ProgramTree::Build(const parser::CompilerDirective &) {
200-
DIE("ProgramTree::Build() called for CompilerDirective");
226+
std::optional<ProgramTree> ProgramTree::Build(
227+
const parser::CompilerDirective &x, SemanticsContext &context) {
228+
context.Say(x.source, "Compiler directive ignored here"_warn_en_US);
229+
return std::nullopt;
201230
}
202231

203-
ProgramTree ProgramTree::Build(const parser::OpenACCRoutineConstruct &) {
232+
std::optional<ProgramTree> ProgramTree::Build(
233+
const parser::OpenACCRoutineConstruct &, SemanticsContext &) {
204234
DIE("ProgramTree::Build() called for OpenACCRoutineConstruct");
205235
}
206236

flang/lib/Semantics/program-tree.h

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
namespace Fortran::semantics {
2727

2828
class Scope;
29+
class SemanticsContext;
2930

3031
class ProgramTree {
3132
public:
@@ -34,16 +35,25 @@ class ProgramTree {
3435
std::list<common::Reference<const parser::GenericSpec>>;
3536

3637
// Build the ProgramTree rooted at one of these program units.
37-
static ProgramTree Build(const parser::ProgramUnit &);
38-
static ProgramTree Build(const parser::MainProgram &);
39-
static ProgramTree Build(const parser::FunctionSubprogram &);
40-
static ProgramTree Build(const parser::SubroutineSubprogram &);
41-
static ProgramTree Build(const parser::SeparateModuleSubprogram &);
42-
static ProgramTree Build(const parser::Module &);
43-
static ProgramTree Build(const parser::Submodule &);
44-
static ProgramTree Build(const parser::BlockData &);
45-
static ProgramTree Build(const parser::CompilerDirective &);
46-
static ProgramTree Build(const parser::OpenACCRoutineConstruct &);
38+
static ProgramTree Build(const parser::ProgramUnit &, SemanticsContext &);
39+
static std::optional<ProgramTree> Build(
40+
const parser::MainProgram &, SemanticsContext &);
41+
static std::optional<ProgramTree> Build(
42+
const parser::FunctionSubprogram &, SemanticsContext &);
43+
static std::optional<ProgramTree> Build(
44+
const parser::SubroutineSubprogram &, SemanticsContext &);
45+
static std::optional<ProgramTree> Build(
46+
const parser::SeparateModuleSubprogram &, SemanticsContext &);
47+
static std::optional<ProgramTree> Build(
48+
const parser::Module &, SemanticsContext &);
49+
static std::optional<ProgramTree> Build(
50+
const parser::Submodule &, SemanticsContext &);
51+
static std::optional<ProgramTree> Build(
52+
const parser::BlockData &, SemanticsContext &);
53+
static std::optional<ProgramTree> Build(
54+
const parser::CompilerDirective &, SemanticsContext &);
55+
static std::optional<ProgramTree> Build(
56+
const parser::OpenACCRoutineConstruct &, SemanticsContext &);
4757

4858
ENUM_CLASS(Kind, // kind of node
4959
Program, Function, Subroutine, MpSubprogram, Module, Submodule, BlockData)

flang/lib/Semantics/resolve-names.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8889,7 +8889,7 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {
88898889
}
88908890
}
88918891
} else {
8892-
Say(x.source, "Compiler directive was ignored"_warn_en_US);
8892+
Say(x.source, "Unrecognized compiler directive was ignored"_warn_en_US);
88938893
}
88948894
}
88958895

@@ -8904,7 +8904,7 @@ bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) {
89048904
ResolveAccParts(context(), x, &topScope_);
89058905
return false;
89068906
}
8907-
auto root{ProgramTree::Build(x)};
8907+
auto root{ProgramTree::Build(x, context())};
89088908
SetScope(topScope_);
89098909
ResolveSpecificationParts(root);
89108910
FinishSpecificationParts(root);
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
2-
!CHECK: warning: Compiler directive was ignored
2+
!CHECK: warning: Unrecognized compiler directive was ignored
33
!DIR$ Not a recognized directive
4+
program main
5+
contains
6+
!CHECK: warning: Compiler directive ignored here
7+
!DIR$ not in a subprogram
8+
subroutine s
9+
end
410
end

0 commit comments

Comments
 (0)