1 //===-- lib/Semantics/program-tree.cpp ------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "flang/Semantics/program-tree.h"
10 #include "flang/Common/idioms.h"
11 #include "flang/Parser/char-block.h"
12 #include "flang/Semantics/scope.h"
13 #include "flang/Semantics/semantics.h"
15 namespace Fortran::semantics
{
17 static void GetEntryStmts(
18 ProgramTree
&node
, const parser::SpecificationPart
&spec
) {
19 const auto &implicitPart
{std::get
<parser::ImplicitPart
>(spec
.t
)};
20 for (const parser::ImplicitPartStmt
&stmt
: implicitPart
.v
) {
21 if (const auto *entryStmt
{std::get_if
<
22 parser::Statement
<common::Indirection
<parser::EntryStmt
>>>(
24 node
.AddEntry(entryStmt
->statement
.value());
27 for (const auto &decl
:
28 std::get
<std::list
<parser::DeclarationConstruct
>>(spec
.t
)) {
29 if (const auto *entryStmt
{std::get_if
<
30 parser::Statement
<common::Indirection
<parser::EntryStmt
>>>(
32 node
.AddEntry(entryStmt
->statement
.value());
37 static void GetEntryStmts(
38 ProgramTree
&node
, const parser::ExecutionPart
&exec
) {
39 for (const auto &epConstruct
: exec
.v
) {
40 if (const auto *entryStmt
{std::get_if
<
41 parser::Statement
<common::Indirection
<parser::EntryStmt
>>>(
43 node
.AddEntry(entryStmt
->statement
.value());
48 // Collects generics that define simple names that could include
49 // identically-named subprograms as specific procedures.
50 static void GetGenerics(
51 ProgramTree
&node
, const parser::SpecificationPart
&spec
) {
52 for (const auto &decl
:
53 std::get
<std::list
<parser::DeclarationConstruct
>>(spec
.t
)) {
55 std::get_if
<parser::SpecificationConstruct
>(&decl
.u
)}) {
56 if (const auto *generic
{std::get_if
<
57 parser::Statement
<common::Indirection
<parser::GenericStmt
>>>(
59 const parser::GenericStmt
&genericStmt
{generic
->statement
.value()};
60 const auto &genericSpec
{std::get
<parser::GenericSpec
>(genericStmt
.t
)};
61 node
.AddGeneric(genericSpec
);
62 } else if (const auto *interface
{
63 std::get_if
<common::Indirection
<parser::InterfaceBlock
>>(
65 const parser::InterfaceBlock
&interfaceBlock
{interface
->value()};
66 const parser::InterfaceStmt
&interfaceStmt
{
67 std::get
<parser::Statement
<parser::InterfaceStmt
>>(interfaceBlock
.t
)
69 const auto *genericSpec
{
70 std::get_if
<std::optional
<parser::GenericSpec
>>(&interfaceStmt
.u
)};
71 if (genericSpec
&& genericSpec
->has_value()) {
72 node
.AddGeneric(**genericSpec
);
80 static ProgramTree
BuildSubprogramTree(
81 const parser::Name
&name
, SemanticsContext
&context
, const T
&x
) {
82 const auto &spec
{std::get
<parser::SpecificationPart
>(x
.t
)};
83 const auto &exec
{std::get
<parser::ExecutionPart
>(x
.t
)};
85 std::get
<std::optional
<parser::InternalSubprogramPart
>>(x
.t
)};
86 ProgramTree node
{name
, spec
, &exec
};
87 GetEntryStmts(node
, spec
);
88 GetEntryStmts(node
, exec
);
89 GetGenerics(node
, spec
);
91 for (const auto &subp
:
92 std::get
<std::list
<parser::InternalSubprogram
>>(subps
->t
)) {
95 if (auto child
{ProgramTree::Build(y
.value(), context
)}) {
96 node
.AddChild(std::move(*child
));
105 static ProgramTree
BuildSubprogramTree(
106 const parser::Name
&name
, SemanticsContext
&, const parser::BlockData
&x
) {
107 const auto &spec
{std::get
<parser::SpecificationPart
>(x
.t
)};
108 return ProgramTree
{name
, spec
};
111 template <typename T
>
112 static ProgramTree
BuildModuleTree(
113 const parser::Name
&name
, SemanticsContext
&context
, const T
&x
) {
114 const auto &spec
{std::get
<parser::SpecificationPart
>(x
.t
)};
115 const auto &subps
{std::get
<std::optional
<parser::ModuleSubprogramPart
>>(x
.t
)};
116 ProgramTree node
{name
, spec
};
117 GetGenerics(node
, spec
);
119 for (const auto &subp
:
120 std::get
<std::list
<parser::ModuleSubprogram
>>(subps
->t
)) {
123 if (auto child
{ProgramTree::Build(y
.value(), context
)}) {
124 node
.AddChild(std::move(*child
));
133 ProgramTree
&ProgramTree::Build(
134 const parser::ProgramUnit
&x
, SemanticsContext
&context
) {
135 return common::visit(
136 [&](const auto &y
) -> ProgramTree
& {
137 auto node
{Build(y
.value(), context
)};
138 CHECK(node
.has_value());
139 return context
.SaveProgramTree(std::move(*node
));
144 std::optional
<ProgramTree
> ProgramTree::Build(
145 const parser::MainProgram
&x
, SemanticsContext
&context
) {
147 std::get
<std::optional
<parser::Statement
<parser::ProgramStmt
>>>(x
.t
)};
148 const auto &end
{std::get
<parser::Statement
<parser::EndProgramStmt
>>(x
.t
)};
149 static parser::Name emptyName
;
151 ? BuildSubprogramTree(stmt
->statement
.v
, context
, x
).set_stmt(*stmt
)
152 : BuildSubprogramTree(emptyName
, context
, x
)};
153 return std::move(result
.set_endStmt(end
));
156 std::optional
<ProgramTree
> ProgramTree::Build(
157 const parser::FunctionSubprogram
&x
, SemanticsContext
&context
) {
158 const auto &stmt
{std::get
<parser::Statement
<parser::FunctionStmt
>>(x
.t
)};
159 const auto &end
{std::get
<parser::Statement
<parser::EndFunctionStmt
>>(x
.t
)};
160 const auto &name
{std::get
<parser::Name
>(stmt
.statement
.t
)};
161 const parser::LanguageBindingSpec
*bindingSpec
{};
162 if (const auto &suffix
{
163 std::get
<std::optional
<parser::Suffix
>>(stmt
.statement
.t
)}) {
164 if (suffix
->binding
) {
165 bindingSpec
= &*suffix
->binding
;
168 return BuildSubprogramTree(name
, context
, x
)
171 .set_bindingSpec(bindingSpec
);
174 std::optional
<ProgramTree
> ProgramTree::Build(
175 const parser::SubroutineSubprogram
&x
, SemanticsContext
&context
) {
176 const auto &stmt
{std::get
<parser::Statement
<parser::SubroutineStmt
>>(x
.t
)};
177 const auto &end
{std::get
<parser::Statement
<parser::EndSubroutineStmt
>>(x
.t
)};
178 const auto &name
{std::get
<parser::Name
>(stmt
.statement
.t
)};
179 const parser::LanguageBindingSpec
*bindingSpec
{};
180 if (const auto &binding
{std::get
<std::optional
<parser::LanguageBindingSpec
>>(
181 stmt
.statement
.t
)}) {
182 bindingSpec
= &*binding
;
184 return BuildSubprogramTree(name
, context
, x
)
187 .set_bindingSpec(bindingSpec
);
190 std::optional
<ProgramTree
> ProgramTree::Build(
191 const parser::SeparateModuleSubprogram
&x
, SemanticsContext
&context
) {
192 const auto &stmt
{std::get
<parser::Statement
<parser::MpSubprogramStmt
>>(x
.t
)};
194 std::get
<parser::Statement
<parser::EndMpSubprogramStmt
>>(x
.t
)};
195 const auto &name
{stmt
.statement
.v
};
196 return BuildSubprogramTree(name
, context
, x
).set_stmt(stmt
).set_endStmt(end
);
199 std::optional
<ProgramTree
> ProgramTree::Build(
200 const parser::Module
&x
, SemanticsContext
&context
) {
201 const auto &stmt
{std::get
<parser::Statement
<parser::ModuleStmt
>>(x
.t
)};
202 const auto &end
{std::get
<parser::Statement
<parser::EndModuleStmt
>>(x
.t
)};
203 const auto &name
{stmt
.statement
.v
};
204 return BuildModuleTree(name
, context
, x
).set_stmt(stmt
).set_endStmt(end
);
207 std::optional
<ProgramTree
> ProgramTree::Build(
208 const parser::Submodule
&x
, SemanticsContext
&context
) {
209 const auto &stmt
{std::get
<parser::Statement
<parser::SubmoduleStmt
>>(x
.t
)};
210 const auto &end
{std::get
<parser::Statement
<parser::EndSubmoduleStmt
>>(x
.t
)};
211 const auto &name
{std::get
<parser::Name
>(stmt
.statement
.t
)};
212 return BuildModuleTree(name
, context
, x
).set_stmt(stmt
).set_endStmt(end
);
215 std::optional
<ProgramTree
> ProgramTree::Build(
216 const parser::BlockData
&x
, SemanticsContext
&context
) {
217 const auto &stmt
{std::get
<parser::Statement
<parser::BlockDataStmt
>>(x
.t
)};
218 const auto &end
{std::get
<parser::Statement
<parser::EndBlockDataStmt
>>(x
.t
)};
219 static parser::Name emptyName
;
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
));
226 std::optional
<ProgramTree
> ProgramTree::Build(
227 const parser::CompilerDirective
&x
, SemanticsContext
&context
) {
228 if (context
.ShouldWarn(common::UsageWarning::IgnoredDirective
)) {
229 context
.Say(x
.source
, "Compiler directive ignored here"_warn_en_US
);
234 std::optional
<ProgramTree
> ProgramTree::Build(
235 const parser::OpenACCRoutineConstruct
&, SemanticsContext
&) {
236 DIE("ProgramTree::Build() called for OpenACCRoutineConstruct");
239 const parser::ParentIdentifier
&ProgramTree::GetParentId() const {
241 std::get
<const parser::Statement
<parser::SubmoduleStmt
> *>(stmt_
)};
242 return std::get
<parser::ParentIdentifier
>(stmt
->statement
.t
);
245 bool ProgramTree::IsModule() const {
246 auto kind
{GetKind()};
247 return kind
== Kind::Module
|| kind
== Kind::Submodule
;
250 Symbol::Flag
ProgramTree::GetSubpFlag() const {
251 return GetKind() == Kind::Function
? Symbol::Flag::Function
252 : Symbol::Flag::Subroutine
;
255 bool ProgramTree::HasModulePrefix() const {
256 if (std::holds_alternative
<
257 const parser::Statement
<parser::MpSubprogramStmt
> *>(stmt_
)) {
258 return true; // MODULE PROCEDURE foo
260 using ListType
= std::list
<parser::PrefixSpec
>;
261 const auto *prefixes
{common::visit(
263 [](const parser::Statement
<parser::FunctionStmt
> *x
) {
264 return &std::get
<ListType
>(x
->statement
.t
);
266 [](const parser::Statement
<parser::SubroutineStmt
> *x
) {
267 return &std::get
<ListType
>(x
->statement
.t
);
269 [](const auto *) -> const ListType
* { return nullptr; },
273 for (const auto &prefix
: *prefixes
) {
274 if (std::holds_alternative
<parser::PrefixSpec::Module
>(prefix
.u
)) {
282 ProgramTree::Kind
ProgramTree::GetKind() const {
283 return common::visit(
285 [](const parser::Statement
<parser::ProgramStmt
> *) {
286 return Kind::Program
;
288 [](const parser::Statement
<parser::FunctionStmt
> *) {
289 return Kind::Function
;
291 [](const parser::Statement
<parser::SubroutineStmt
> *) {
292 return Kind::Subroutine
;
294 [](const parser::Statement
<parser::MpSubprogramStmt
> *) {
295 return Kind::MpSubprogram
;
297 [](const parser::Statement
<parser::ModuleStmt
> *) {
300 [](const parser::Statement
<parser::SubmoduleStmt
> *) {
301 return Kind::Submodule
;
303 [](const parser::Statement
<parser::BlockDataStmt
> *) {
304 return Kind::BlockData
;
310 void ProgramTree::set_scope(Scope
&scope
) {
313 scope
.AddSourceRange(*endStmt_
);
316 void ProgramTree::AddChild(ProgramTree
&&child
) {
317 children_
.emplace_back(std::move(child
));
320 void ProgramTree::AddEntry(const parser::EntryStmt
&entryStmt
) {
321 entryStmts_
.emplace_back(entryStmt
);
324 void ProgramTree::AddGeneric(const parser::GenericSpec
&generic
) {
325 genericSpecs_
.emplace_back(generic
);
328 } // namespace Fortran::semantics