xref: /llvm-project/flang/lib/Semantics/program-tree.cpp (revision 4f2b65fb80a4b27e5fb88db816ed0ce174c9b1b4)
164ab3302SCarolineConcatto //===-- lib/Semantics/program-tree.cpp ------------------------------------===//
264ab3302SCarolineConcatto //
364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information.
564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
664ab3302SCarolineConcatto //
764ab3302SCarolineConcatto //===----------------------------------------------------------------------===//
864ab3302SCarolineConcatto 
9*4f2b65fbSPeter Klausler #include "flang/Semantics/program-tree.h"
1064ab3302SCarolineConcatto #include "flang/Common/idioms.h"
1164ab3302SCarolineConcatto #include "flang/Parser/char-block.h"
1264ab3302SCarolineConcatto #include "flang/Semantics/scope.h"
1368a27989SPeter Klausler #include "flang/Semantics/semantics.h"
1464ab3302SCarolineConcatto 
1564ab3302SCarolineConcatto namespace Fortran::semantics {
1664ab3302SCarolineConcatto 
17bed947f7SPeter Klausler static void GetEntryStmts(
18bed947f7SPeter Klausler     ProgramTree &node, const parser::SpecificationPart &spec) {
19bed947f7SPeter Klausler   const auto &implicitPart{std::get<parser::ImplicitPart>(spec.t)};
20bed947f7SPeter Klausler   for (const parser::ImplicitPartStmt &stmt : implicitPart.v) {
21bed947f7SPeter Klausler     if (const auto *entryStmt{std::get_if<
22bed947f7SPeter Klausler             parser::Statement<common::Indirection<parser::EntryStmt>>>(
23bed947f7SPeter Klausler             &stmt.u)}) {
24bed947f7SPeter Klausler       node.AddEntry(entryStmt->statement.value());
25bed947f7SPeter Klausler     }
26bed947f7SPeter Klausler   }
27bed947f7SPeter Klausler   for (const auto &decl :
28bed947f7SPeter Klausler       std::get<std::list<parser::DeclarationConstruct>>(spec.t)) {
29bed947f7SPeter Klausler     if (const auto *entryStmt{std::get_if<
30bed947f7SPeter Klausler             parser::Statement<common::Indirection<parser::EntryStmt>>>(
31bed947f7SPeter Klausler             &decl.u)}) {
32bed947f7SPeter Klausler       node.AddEntry(entryStmt->statement.value());
33bed947f7SPeter Klausler     }
34bed947f7SPeter Klausler   }
35bed947f7SPeter Klausler }
36bed947f7SPeter Klausler 
37bed947f7SPeter Klausler static void GetEntryStmts(
38bed947f7SPeter Klausler     ProgramTree &node, const parser::ExecutionPart &exec) {
39bed947f7SPeter Klausler   for (const auto &epConstruct : exec.v) {
40bed947f7SPeter Klausler     if (const auto *entryStmt{std::get_if<
41bed947f7SPeter Klausler             parser::Statement<common::Indirection<parser::EntryStmt>>>(
42bed947f7SPeter Klausler             &epConstruct.u)}) {
43bed947f7SPeter Klausler       node.AddEntry(entryStmt->statement.value());
44bed947f7SPeter Klausler     }
45bed947f7SPeter Klausler   }
46bed947f7SPeter Klausler }
47bed947f7SPeter Klausler 
48fc510998SPeter Klausler // Collects generics that define simple names that could include
49fc510998SPeter Klausler // identically-named subprograms as specific procedures.
50fc510998SPeter Klausler static void GetGenerics(
51fc510998SPeter Klausler     ProgramTree &node, const parser::SpecificationPart &spec) {
52fc510998SPeter Klausler   for (const auto &decl :
53fc510998SPeter Klausler       std::get<std::list<parser::DeclarationConstruct>>(spec.t)) {
54fc510998SPeter Klausler     if (const auto *spec{
55fc510998SPeter Klausler             std::get_if<parser::SpecificationConstruct>(&decl.u)}) {
56fc510998SPeter Klausler       if (const auto *generic{std::get_if<
57fc510998SPeter Klausler               parser::Statement<common::Indirection<parser::GenericStmt>>>(
58fc510998SPeter Klausler               &spec->u)}) {
59fc510998SPeter Klausler         const parser::GenericStmt &genericStmt{generic->statement.value()};
60fc510998SPeter Klausler         const auto &genericSpec{std::get<parser::GenericSpec>(genericStmt.t)};
61fc510998SPeter Klausler         node.AddGeneric(genericSpec);
62fc510998SPeter Klausler       } else if (const auto *interface{
63fc510998SPeter Klausler                      std::get_if<common::Indirection<parser::InterfaceBlock>>(
64fc510998SPeter Klausler                          &spec->u)}) {
65fc510998SPeter Klausler         const parser::InterfaceBlock &interfaceBlock{interface->value()};
66fc510998SPeter Klausler         const parser::InterfaceStmt &interfaceStmt{
67fc510998SPeter Klausler             std::get<parser::Statement<parser::InterfaceStmt>>(interfaceBlock.t)
68fc510998SPeter Klausler                 .statement};
69fc510998SPeter Klausler         const auto *genericSpec{
70fc510998SPeter Klausler             std::get_if<std::optional<parser::GenericSpec>>(&interfaceStmt.u)};
71fc510998SPeter Klausler         if (genericSpec && genericSpec->has_value()) {
72fc510998SPeter Klausler           node.AddGeneric(**genericSpec);
73fc510998SPeter Klausler         }
74fc510998SPeter Klausler       }
75fc510998SPeter Klausler     }
76fc510998SPeter Klausler   }
77fc510998SPeter Klausler }
78fc510998SPeter Klausler 
7964ab3302SCarolineConcatto template <typename T>
8068a27989SPeter Klausler static ProgramTree BuildSubprogramTree(
8168a27989SPeter Klausler     const parser::Name &name, SemanticsContext &context, const T &x) {
8264ab3302SCarolineConcatto   const auto &spec{std::get<parser::SpecificationPart>(x.t)};
8364ab3302SCarolineConcatto   const auto &exec{std::get<parser::ExecutionPart>(x.t)};
8464ab3302SCarolineConcatto   const auto &subps{
8564ab3302SCarolineConcatto       std::get<std::optional<parser::InternalSubprogramPart>>(x.t)};
8664ab3302SCarolineConcatto   ProgramTree node{name, spec, &exec};
87bed947f7SPeter Klausler   GetEntryStmts(node, spec);
88bed947f7SPeter Klausler   GetEntryStmts(node, exec);
89fc510998SPeter Klausler   GetGenerics(node, spec);
9064ab3302SCarolineConcatto   if (subps) {
9164ab3302SCarolineConcatto     for (const auto &subp :
9264ab3302SCarolineConcatto         std::get<std::list<parser::InternalSubprogram>>(subps->t)) {
93cd03e96fSPeter Klausler       common::visit(
9468a27989SPeter Klausler           [&](const auto &y) {
9568a27989SPeter Klausler             if (auto child{ProgramTree::Build(y.value(), context)}) {
9668a27989SPeter Klausler               node.AddChild(std::move(*child));
9768a27989SPeter Klausler             }
9868a27989SPeter Klausler           },
9964ab3302SCarolineConcatto           subp.u);
10064ab3302SCarolineConcatto     }
10164ab3302SCarolineConcatto   }
10264ab3302SCarolineConcatto   return node;
10364ab3302SCarolineConcatto }
10464ab3302SCarolineConcatto 
10564ab3302SCarolineConcatto static ProgramTree BuildSubprogramTree(
10668a27989SPeter Klausler     const parser::Name &name, SemanticsContext &, const parser::BlockData &x) {
10764ab3302SCarolineConcatto   const auto &spec{std::get<parser::SpecificationPart>(x.t)};
108bed947f7SPeter Klausler   return ProgramTree{name, spec};
10964ab3302SCarolineConcatto }
11064ab3302SCarolineConcatto 
11164ab3302SCarolineConcatto template <typename T>
11268a27989SPeter Klausler static ProgramTree BuildModuleTree(
11368a27989SPeter Klausler     const parser::Name &name, SemanticsContext &context, const T &x) {
11464ab3302SCarolineConcatto   const auto &spec{std::get<parser::SpecificationPart>(x.t)};
11564ab3302SCarolineConcatto   const auto &subps{std::get<std::optional<parser::ModuleSubprogramPart>>(x.t)};
11664ab3302SCarolineConcatto   ProgramTree node{name, spec};
117fc510998SPeter Klausler   GetGenerics(node, spec);
11864ab3302SCarolineConcatto   if (subps) {
11964ab3302SCarolineConcatto     for (const auto &subp :
12064ab3302SCarolineConcatto         std::get<std::list<parser::ModuleSubprogram>>(subps->t)) {
121cd03e96fSPeter Klausler       common::visit(
12268a27989SPeter Klausler           [&](const auto &y) {
12368a27989SPeter Klausler             if (auto child{ProgramTree::Build(y.value(), context)}) {
12468a27989SPeter Klausler               node.AddChild(std::move(*child));
12568a27989SPeter Klausler             }
12668a27989SPeter Klausler           },
12764ab3302SCarolineConcatto           subp.u);
12864ab3302SCarolineConcatto     }
12964ab3302SCarolineConcatto   }
13064ab3302SCarolineConcatto   return node;
13164ab3302SCarolineConcatto }
13264ab3302SCarolineConcatto 
133*4f2b65fbSPeter Klausler ProgramTree &ProgramTree::Build(
13468a27989SPeter Klausler     const parser::ProgramUnit &x, SemanticsContext &context) {
13568a27989SPeter Klausler   return common::visit(
136*4f2b65fbSPeter Klausler       [&](const auto &y) -> ProgramTree & {
13768a27989SPeter Klausler         auto node{Build(y.value(), context)};
13868a27989SPeter Klausler         CHECK(node.has_value());
139*4f2b65fbSPeter Klausler         return context.SaveProgramTree(std::move(*node));
14068a27989SPeter Klausler       },
14168a27989SPeter Klausler       x.u);
14264ab3302SCarolineConcatto }
14364ab3302SCarolineConcatto 
14468a27989SPeter Klausler std::optional<ProgramTree> ProgramTree::Build(
14568a27989SPeter Klausler     const parser::MainProgram &x, SemanticsContext &context) {
14664ab3302SCarolineConcatto   const auto &stmt{
14764ab3302SCarolineConcatto       std::get<std::optional<parser::Statement<parser::ProgramStmt>>>(x.t)};
14864ab3302SCarolineConcatto   const auto &end{std::get<parser::Statement<parser::EndProgramStmt>>(x.t)};
14964ab3302SCarolineConcatto   static parser::Name emptyName;
15068a27989SPeter Klausler   auto result{stmt
15168a27989SPeter Klausler           ? BuildSubprogramTree(stmt->statement.v, context, x).set_stmt(*stmt)
15268a27989SPeter Klausler           : BuildSubprogramTree(emptyName, context, x)};
15368a27989SPeter Klausler   return std::move(result.set_endStmt(end));
15464ab3302SCarolineConcatto }
15564ab3302SCarolineConcatto 
15668a27989SPeter Klausler std::optional<ProgramTree> ProgramTree::Build(
15768a27989SPeter Klausler     const parser::FunctionSubprogram &x, SemanticsContext &context) {
15864ab3302SCarolineConcatto   const auto &stmt{std::get<parser::Statement<parser::FunctionStmt>>(x.t)};
15964ab3302SCarolineConcatto   const auto &end{std::get<parser::Statement<parser::EndFunctionStmt>>(x.t)};
16064ab3302SCarolineConcatto   const auto &name{std::get<parser::Name>(stmt.statement.t)};
16172904a99SPeter Klausler   const parser::LanguageBindingSpec *bindingSpec{};
16272904a99SPeter Klausler   if (const auto &suffix{
16372904a99SPeter Klausler           std::get<std::optional<parser::Suffix>>(stmt.statement.t)}) {
16472904a99SPeter Klausler     if (suffix->binding) {
16572904a99SPeter Klausler       bindingSpec = &*suffix->binding;
16672904a99SPeter Klausler     }
16772904a99SPeter Klausler   }
16868a27989SPeter Klausler   return BuildSubprogramTree(name, context, x)
16972904a99SPeter Klausler       .set_stmt(stmt)
17072904a99SPeter Klausler       .set_endStmt(end)
17172904a99SPeter Klausler       .set_bindingSpec(bindingSpec);
17264ab3302SCarolineConcatto }
17364ab3302SCarolineConcatto 
17468a27989SPeter Klausler std::optional<ProgramTree> ProgramTree::Build(
17568a27989SPeter Klausler     const parser::SubroutineSubprogram &x, SemanticsContext &context) {
17664ab3302SCarolineConcatto   const auto &stmt{std::get<parser::Statement<parser::SubroutineStmt>>(x.t)};
17764ab3302SCarolineConcatto   const auto &end{std::get<parser::Statement<parser::EndSubroutineStmt>>(x.t)};
17864ab3302SCarolineConcatto   const auto &name{std::get<parser::Name>(stmt.statement.t)};
17972904a99SPeter Klausler   const parser::LanguageBindingSpec *bindingSpec{};
18072904a99SPeter Klausler   if (const auto &binding{std::get<std::optional<parser::LanguageBindingSpec>>(
18172904a99SPeter Klausler           stmt.statement.t)}) {
18272904a99SPeter Klausler     bindingSpec = &*binding;
18372904a99SPeter Klausler   }
18468a27989SPeter Klausler   return BuildSubprogramTree(name, context, x)
18572904a99SPeter Klausler       .set_stmt(stmt)
18672904a99SPeter Klausler       .set_endStmt(end)
18772904a99SPeter Klausler       .set_bindingSpec(bindingSpec);
18864ab3302SCarolineConcatto }
18964ab3302SCarolineConcatto 
19068a27989SPeter Klausler std::optional<ProgramTree> ProgramTree::Build(
19168a27989SPeter Klausler     const parser::SeparateModuleSubprogram &x, SemanticsContext &context) {
19264ab3302SCarolineConcatto   const auto &stmt{std::get<parser::Statement<parser::MpSubprogramStmt>>(x.t)};
19364ab3302SCarolineConcatto   const auto &end{
19464ab3302SCarolineConcatto       std::get<parser::Statement<parser::EndMpSubprogramStmt>>(x.t)};
19564ab3302SCarolineConcatto   const auto &name{stmt.statement.v};
19668a27989SPeter Klausler   return BuildSubprogramTree(name, context, x).set_stmt(stmt).set_endStmt(end);
19764ab3302SCarolineConcatto }
19864ab3302SCarolineConcatto 
19968a27989SPeter Klausler std::optional<ProgramTree> ProgramTree::Build(
20068a27989SPeter Klausler     const parser::Module &x, SemanticsContext &context) {
20164ab3302SCarolineConcatto   const auto &stmt{std::get<parser::Statement<parser::ModuleStmt>>(x.t)};
20264ab3302SCarolineConcatto   const auto &end{std::get<parser::Statement<parser::EndModuleStmt>>(x.t)};
20364ab3302SCarolineConcatto   const auto &name{stmt.statement.v};
20468a27989SPeter Klausler   return BuildModuleTree(name, context, x).set_stmt(stmt).set_endStmt(end);
20564ab3302SCarolineConcatto }
20664ab3302SCarolineConcatto 
20768a27989SPeter Klausler std::optional<ProgramTree> ProgramTree::Build(
20868a27989SPeter Klausler     const parser::Submodule &x, SemanticsContext &context) {
20964ab3302SCarolineConcatto   const auto &stmt{std::get<parser::Statement<parser::SubmoduleStmt>>(x.t)};
21064ab3302SCarolineConcatto   const auto &end{std::get<parser::Statement<parser::EndSubmoduleStmt>>(x.t)};
21164ab3302SCarolineConcatto   const auto &name{std::get<parser::Name>(stmt.statement.t)};
21268a27989SPeter Klausler   return BuildModuleTree(name, context, x).set_stmt(stmt).set_endStmt(end);
21364ab3302SCarolineConcatto }
21464ab3302SCarolineConcatto 
21568a27989SPeter Klausler std::optional<ProgramTree> ProgramTree::Build(
21668a27989SPeter Klausler     const parser::BlockData &x, SemanticsContext &context) {
21764ab3302SCarolineConcatto   const auto &stmt{std::get<parser::Statement<parser::BlockDataStmt>>(x.t)};
21864ab3302SCarolineConcatto   const auto &end{std::get<parser::Statement<parser::EndBlockDataStmt>>(x.t)};
21964ab3302SCarolineConcatto   static parser::Name emptyName;
22068a27989SPeter Klausler   auto result{stmt.statement.v
22168a27989SPeter Klausler           ? BuildSubprogramTree(*stmt.statement.v, context, x)
22268a27989SPeter Klausler           : BuildSubprogramTree(emptyName, context, x)};
22368a27989SPeter Klausler   return std::move(result.set_stmt(stmt).set_endStmt(end));
22464ab3302SCarolineConcatto }
22564ab3302SCarolineConcatto 
22668a27989SPeter Klausler std::optional<ProgramTree> ProgramTree::Build(
22768a27989SPeter Klausler     const parser::CompilerDirective &x, SemanticsContext &context) {
228505f6da1SPeter Klausler   if (context.ShouldWarn(common::UsageWarning::IgnoredDirective)) {
22968a27989SPeter Klausler     context.Say(x.source, "Compiler directive ignored here"_warn_en_US);
230505f6da1SPeter Klausler   }
23168a27989SPeter Klausler   return std::nullopt;
23213cee14bSpeter klausler }
23313cee14bSpeter klausler 
23468a27989SPeter Klausler std::optional<ProgramTree> ProgramTree::Build(
23568a27989SPeter Klausler     const parser::OpenACCRoutineConstruct &, SemanticsContext &) {
23682867439SValentin Clement (バレンタイン クレメン)   DIE("ProgramTree::Build() called for OpenACCRoutineConstruct");
23782867439SValentin Clement (バレンタイン クレメン) }
23882867439SValentin Clement (バレンタイン クレメン) 
23964ab3302SCarolineConcatto const parser::ParentIdentifier &ProgramTree::GetParentId() const {
24064ab3302SCarolineConcatto   const auto *stmt{
24164ab3302SCarolineConcatto       std::get<const parser::Statement<parser::SubmoduleStmt> *>(stmt_)};
24264ab3302SCarolineConcatto   return std::get<parser::ParentIdentifier>(stmt->statement.t);
24364ab3302SCarolineConcatto }
24464ab3302SCarolineConcatto 
24564ab3302SCarolineConcatto bool ProgramTree::IsModule() const {
24664ab3302SCarolineConcatto   auto kind{GetKind()};
24764ab3302SCarolineConcatto   return kind == Kind::Module || kind == Kind::Submodule;
24864ab3302SCarolineConcatto }
24964ab3302SCarolineConcatto 
25064ab3302SCarolineConcatto Symbol::Flag ProgramTree::GetSubpFlag() const {
25164ab3302SCarolineConcatto   return GetKind() == Kind::Function ? Symbol::Flag::Function
25264ab3302SCarolineConcatto                                      : Symbol::Flag::Subroutine;
25364ab3302SCarolineConcatto }
25464ab3302SCarolineConcatto 
25564ab3302SCarolineConcatto bool ProgramTree::HasModulePrefix() const {
256bfc39073SPeter Klausler   if (std::holds_alternative<
257bfc39073SPeter Klausler           const parser::Statement<parser::MpSubprogramStmt> *>(stmt_)) {
258bfc39073SPeter Klausler     return true; // MODULE PROCEDURE foo
259bfc39073SPeter Klausler   }
26064ab3302SCarolineConcatto   using ListType = std::list<parser::PrefixSpec>;
261cd03e96fSPeter Klausler   const auto *prefixes{common::visit(
262cd03e96fSPeter Klausler       common::visitors{
26364ab3302SCarolineConcatto           [](const parser::Statement<parser::FunctionStmt> *x) {
26464ab3302SCarolineConcatto             return &std::get<ListType>(x->statement.t);
26564ab3302SCarolineConcatto           },
26664ab3302SCarolineConcatto           [](const parser::Statement<parser::SubroutineStmt> *x) {
26764ab3302SCarolineConcatto             return &std::get<ListType>(x->statement.t);
26864ab3302SCarolineConcatto           },
26964ab3302SCarolineConcatto           [](const auto *) -> const ListType * { return nullptr; },
27064ab3302SCarolineConcatto       },
27164ab3302SCarolineConcatto       stmt_)};
27264ab3302SCarolineConcatto   if (prefixes) {
27364ab3302SCarolineConcatto     for (const auto &prefix : *prefixes) {
27464ab3302SCarolineConcatto       if (std::holds_alternative<parser::PrefixSpec::Module>(prefix.u)) {
27564ab3302SCarolineConcatto         return true;
27664ab3302SCarolineConcatto       }
27764ab3302SCarolineConcatto     }
27864ab3302SCarolineConcatto   }
27964ab3302SCarolineConcatto   return false;
28064ab3302SCarolineConcatto }
28164ab3302SCarolineConcatto 
28264ab3302SCarolineConcatto ProgramTree::Kind ProgramTree::GetKind() const {
283cd03e96fSPeter Klausler   return common::visit(
28464ab3302SCarolineConcatto       common::visitors{
28564ab3302SCarolineConcatto           [](const parser::Statement<parser::ProgramStmt> *) {
28664ab3302SCarolineConcatto             return Kind::Program;
28764ab3302SCarolineConcatto           },
28864ab3302SCarolineConcatto           [](const parser::Statement<parser::FunctionStmt> *) {
28964ab3302SCarolineConcatto             return Kind::Function;
29064ab3302SCarolineConcatto           },
29164ab3302SCarolineConcatto           [](const parser::Statement<parser::SubroutineStmt> *) {
29264ab3302SCarolineConcatto             return Kind::Subroutine;
29364ab3302SCarolineConcatto           },
29464ab3302SCarolineConcatto           [](const parser::Statement<parser::MpSubprogramStmt> *) {
29564ab3302SCarolineConcatto             return Kind::MpSubprogram;
29664ab3302SCarolineConcatto           },
29764ab3302SCarolineConcatto           [](const parser::Statement<parser::ModuleStmt> *) {
29864ab3302SCarolineConcatto             return Kind::Module;
29964ab3302SCarolineConcatto           },
30064ab3302SCarolineConcatto           [](const parser::Statement<parser::SubmoduleStmt> *) {
30164ab3302SCarolineConcatto             return Kind::Submodule;
30264ab3302SCarolineConcatto           },
30364ab3302SCarolineConcatto           [](const parser::Statement<parser::BlockDataStmt> *) {
30464ab3302SCarolineConcatto             return Kind::BlockData;
30564ab3302SCarolineConcatto           },
30664ab3302SCarolineConcatto       },
30764ab3302SCarolineConcatto       stmt_);
30864ab3302SCarolineConcatto }
30964ab3302SCarolineConcatto 
31064ab3302SCarolineConcatto void ProgramTree::set_scope(Scope &scope) {
31164ab3302SCarolineConcatto   scope_ = &scope;
31264ab3302SCarolineConcatto   CHECK(endStmt_);
31364ab3302SCarolineConcatto   scope.AddSourceRange(*endStmt_);
31464ab3302SCarolineConcatto }
31564ab3302SCarolineConcatto 
31664ab3302SCarolineConcatto void ProgramTree::AddChild(ProgramTree &&child) {
31764ab3302SCarolineConcatto   children_.emplace_back(std::move(child));
31864ab3302SCarolineConcatto }
31964ab3302SCarolineConcatto 
320bed947f7SPeter Klausler void ProgramTree::AddEntry(const parser::EntryStmt &entryStmt) {
321bed947f7SPeter Klausler   entryStmts_.emplace_back(entryStmt);
322bed947f7SPeter Klausler }
323bed947f7SPeter Klausler 
324fc510998SPeter Klausler void ProgramTree::AddGeneric(const parser::GenericSpec &generic) {
325fc510998SPeter Klausler   genericSpecs_.emplace_back(generic);
326fc510998SPeter Klausler }
327fc510998SPeter Klausler 
3281f879005STim Keith } // namespace Fortran::semantics
329