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