diff options
author | Peter Klausler <35819229+klausler@users.noreply.github.com> | 2024-04-24 15:25:19 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-24 15:25:19 -0700 |
commit | 68a27989d0c8d58a64dcbb1c78b7002c68a723b2 (patch) | |
tree | 1f887a73b500d97f95749a32db56ae7a10f5e17e | |
parent | 0e1bb1d8352ce21808523357d315b73da0d53560 (diff) | |
download | llvm-68a27989d0c8d58a64dcbb1c78b7002c68a723b2.zip llvm-68a27989d0c8d58a64dcbb1c78b7002c68a723b2.tar.gz llvm-68a27989d0c8d58a64dcbb1c78b7002c68a723b2.tar.bz2 |
[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.
-rw-r--r-- | flang/include/flang/Parser/parse-tree.h | 3 | ||||
-rw-r--r-- | flang/lib/Parser/Fortran-parsers.cpp | 3 | ||||
-rw-r--r-- | flang/lib/Semantics/program-tree.cpp | 86 | ||||
-rw-r--r-- | flang/lib/Semantics/program-tree.h | 30 | ||||
-rw-r--r-- | flang/lib/Semantics/resolve-names.cpp | 4 | ||||
-rw-r--r-- | flang/test/Parser/unrecognized-dir.f90 | 8 |
6 files changed, 91 insertions, 43 deletions
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index d7c2375..4641f9d 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -455,7 +455,8 @@ struct SpecificationPart { struct InternalSubprogram { UNION_CLASS_BOILERPLATE(InternalSubprogram); std::variant<common::Indirection<FunctionSubprogram>, - common::Indirection<SubroutineSubprogram>> + common::Indirection<SubroutineSubprogram>, + common::Indirection<CompilerDirective>> u; }; diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp index 2bdb8e3..ff01974 100644 --- a/flang/lib/Parser/Fortran-parsers.cpp +++ b/flang/lib/Parser/Fortran-parsers.cpp @@ -123,7 +123,8 @@ TYPE_PARSER(first( TYPE_CONTEXT_PARSER("internal subprogram"_en_US, (construct<InternalSubprogram>(indirect(functionSubprogram)) || construct<InternalSubprogram>(indirect(subroutineSubprogram))) / - forceEndOfStmt) + forceEndOfStmt || + construct<InternalSubprogram>(indirect(compilerDirective))) // R511 internal-subprogram-part -> contains-stmt [internal-subprogram]... TYPE_CONTEXT_PARSER("internal subprogram part"_en_US, diff --git a/flang/lib/Semantics/program-tree.cpp b/flang/lib/Semantics/program-tree.cpp index bf773f3..13c85c1 100644 --- a/flang/lib/Semantics/program-tree.cpp +++ b/flang/lib/Semantics/program-tree.cpp @@ -10,6 +10,7 @@ #include "flang/Common/idioms.h" #include "flang/Parser/char-block.h" #include "flang/Semantics/scope.h" +#include "flang/Semantics/semantics.h" namespace Fortran::semantics { @@ -76,7 +77,8 @@ static void GetGenerics( } template <typename T> -static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) { +static ProgramTree BuildSubprogramTree( + const parser::Name &name, SemanticsContext &context, const T &x) { const auto &spec{std::get<parser::SpecificationPart>(x.t)}; const auto &exec{std::get<parser::ExecutionPart>(x.t)}; const auto &subps{ @@ -89,7 +91,11 @@ static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) { for (const auto &subp : std::get<std::list<parser::InternalSubprogram>>(subps->t)) { common::visit( - [&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); }, + [&](const auto &y) { + if (auto child{ProgramTree::Build(y.value(), context)}) { + node.AddChild(std::move(*child)); + } + }, subp.u); } } @@ -97,13 +103,14 @@ static ProgramTree BuildSubprogramTree(const parser::Name &name, const T &x) { } static ProgramTree BuildSubprogramTree( - const parser::Name &name, const parser::BlockData &x) { + const parser::Name &name, SemanticsContext &, const parser::BlockData &x) { const auto &spec{std::get<parser::SpecificationPart>(x.t)}; return ProgramTree{name, spec}; } template <typename T> -static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) { +static ProgramTree BuildModuleTree( + const parser::Name &name, SemanticsContext &context, const T &x) { const auto &spec{std::get<parser::SpecificationPart>(x.t)}; const auto &subps{std::get<std::optional<parser::ModuleSubprogramPart>>(x.t)}; ProgramTree node{name, spec}; @@ -112,28 +119,42 @@ static ProgramTree BuildModuleTree(const parser::Name &name, const T &x) { for (const auto &subp : std::get<std::list<parser::ModuleSubprogram>>(subps->t)) { common::visit( - [&](const auto &y) { node.AddChild(ProgramTree::Build(y.value())); }, + [&](const auto &y) { + if (auto child{ProgramTree::Build(y.value(), context)}) { + node.AddChild(std::move(*child)); + } + }, subp.u); } } return node; } -ProgramTree ProgramTree::Build(const parser::ProgramUnit &x) { - return common::visit([](const auto &y) { return Build(y.value()); }, x.u); +ProgramTree ProgramTree::Build( + const parser::ProgramUnit &x, SemanticsContext &context) { + return common::visit( + [&](const auto &y) { + auto node{Build(y.value(), context)}; + CHECK(node.has_value()); + return std::move(*node); + }, + x.u); } -ProgramTree ProgramTree::Build(const parser::MainProgram &x) { +std::optional<ProgramTree> ProgramTree::Build( + const parser::MainProgram &x, SemanticsContext &context) { const auto &stmt{ std::get<std::optional<parser::Statement<parser::ProgramStmt>>>(x.t)}; const auto &end{std::get<parser::Statement<parser::EndProgramStmt>>(x.t)}; static parser::Name emptyName; - auto result{stmt ? BuildSubprogramTree(stmt->statement.v, x).set_stmt(*stmt) - : BuildSubprogramTree(emptyName, x)}; - return result.set_endStmt(end); + auto result{stmt + ? BuildSubprogramTree(stmt->statement.v, context, x).set_stmt(*stmt) + : BuildSubprogramTree(emptyName, context, x)}; + return std::move(result.set_endStmt(end)); } -ProgramTree ProgramTree::Build(const parser::FunctionSubprogram &x) { +std::optional<ProgramTree> ProgramTree::Build( + const parser::FunctionSubprogram &x, SemanticsContext &context) { const auto &stmt{std::get<parser::Statement<parser::FunctionStmt>>(x.t)}; const auto &end{std::get<parser::Statement<parser::EndFunctionStmt>>(x.t)}; const auto &name{std::get<parser::Name>(stmt.statement.t)}; @@ -144,13 +165,14 @@ ProgramTree ProgramTree::Build(const parser::FunctionSubprogram &x) { bindingSpec = &*suffix->binding; } } - return BuildSubprogramTree(name, x) + return BuildSubprogramTree(name, context, x) .set_stmt(stmt) .set_endStmt(end) .set_bindingSpec(bindingSpec); } -ProgramTree ProgramTree::Build(const parser::SubroutineSubprogram &x) { +std::optional<ProgramTree> ProgramTree::Build( + const parser::SubroutineSubprogram &x, SemanticsContext &context) { const auto &stmt{std::get<parser::Statement<parser::SubroutineStmt>>(x.t)}; const auto &end{std::get<parser::Statement<parser::EndSubroutineStmt>>(x.t)}; const auto &name{std::get<parser::Name>(stmt.statement.t)}; @@ -159,48 +181,56 @@ ProgramTree ProgramTree::Build(const parser::SubroutineSubprogram &x) { stmt.statement.t)}) { bindingSpec = &*binding; } - return BuildSubprogramTree(name, x) + return BuildSubprogramTree(name, context, x) .set_stmt(stmt) .set_endStmt(end) .set_bindingSpec(bindingSpec); } -ProgramTree ProgramTree::Build(const parser::SeparateModuleSubprogram &x) { +std::optional<ProgramTree> ProgramTree::Build( + const parser::SeparateModuleSubprogram &x, SemanticsContext &context) { const auto &stmt{std::get<parser::Statement<parser::MpSubprogramStmt>>(x.t)}; const auto &end{ std::get<parser::Statement<parser::EndMpSubprogramStmt>>(x.t)}; const auto &name{stmt.statement.v}; - return BuildSubprogramTree(name, x).set_stmt(stmt).set_endStmt(end); + return BuildSubprogramTree(name, context, x).set_stmt(stmt).set_endStmt(end); } -ProgramTree ProgramTree::Build(const parser::Module &x) { +std::optional<ProgramTree> ProgramTree::Build( + const parser::Module &x, SemanticsContext &context) { const auto &stmt{std::get<parser::Statement<parser::ModuleStmt>>(x.t)}; const auto &end{std::get<parser::Statement<parser::EndModuleStmt>>(x.t)}; const auto &name{stmt.statement.v}; - return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end); + return BuildModuleTree(name, context, x).set_stmt(stmt).set_endStmt(end); } -ProgramTree ProgramTree::Build(const parser::Submodule &x) { +std::optional<ProgramTree> ProgramTree::Build( + const parser::Submodule &x, SemanticsContext &context) { const auto &stmt{std::get<parser::Statement<parser::SubmoduleStmt>>(x.t)}; const auto &end{std::get<parser::Statement<parser::EndSubmoduleStmt>>(x.t)}; const auto &name{std::get<parser::Name>(stmt.statement.t)}; - return BuildModuleTree(name, x).set_stmt(stmt).set_endStmt(end); + return BuildModuleTree(name, context, x).set_stmt(stmt).set_endStmt(end); } -ProgramTree ProgramTree::Build(const parser::BlockData &x) { +std::optional<ProgramTree> ProgramTree::Build( + const parser::BlockData &x, SemanticsContext &context) { const auto &stmt{std::get<parser::Statement<parser::BlockDataStmt>>(x.t)}; const auto &end{std::get<parser::Statement<parser::EndBlockDataStmt>>(x.t)}; static parser::Name emptyName; - auto result{stmt.statement.v ? BuildSubprogramTree(*stmt.statement.v, x) - : BuildSubprogramTree(emptyName, x)}; - return result.set_stmt(stmt).set_endStmt(end); + auto result{stmt.statement.v + ? BuildSubprogramTree(*stmt.statement.v, context, x) + : BuildSubprogramTree(emptyName, context, x)}; + return std::move(result.set_stmt(stmt).set_endStmt(end)); } -ProgramTree ProgramTree::Build(const parser::CompilerDirective &) { - DIE("ProgramTree::Build() called for CompilerDirective"); +std::optional<ProgramTree> ProgramTree::Build( + const parser::CompilerDirective &x, SemanticsContext &context) { + context.Say(x.source, "Compiler directive ignored here"_warn_en_US); + return std::nullopt; } -ProgramTree ProgramTree::Build(const parser::OpenACCRoutineConstruct &) { +std::optional<ProgramTree> ProgramTree::Build( + const parser::OpenACCRoutineConstruct &, SemanticsContext &) { DIE("ProgramTree::Build() called for OpenACCRoutineConstruct"); } diff --git a/flang/lib/Semantics/program-tree.h b/flang/lib/Semantics/program-tree.h index d49b040..ab00261 100644 --- a/flang/lib/Semantics/program-tree.h +++ b/flang/lib/Semantics/program-tree.h @@ -26,6 +26,7 @@ namespace Fortran::semantics { class Scope; +class SemanticsContext; class ProgramTree { public: @@ -34,16 +35,25 @@ public: std::list<common::Reference<const parser::GenericSpec>>; // Build the ProgramTree rooted at one of these program units. - static ProgramTree Build(const parser::ProgramUnit &); - static ProgramTree Build(const parser::MainProgram &); - static ProgramTree Build(const parser::FunctionSubprogram &); - static ProgramTree Build(const parser::SubroutineSubprogram &); - static ProgramTree Build(const parser::SeparateModuleSubprogram &); - static ProgramTree Build(const parser::Module &); - static ProgramTree Build(const parser::Submodule &); - static ProgramTree Build(const parser::BlockData &); - static ProgramTree Build(const parser::CompilerDirective &); - static ProgramTree Build(const parser::OpenACCRoutineConstruct &); + static ProgramTree Build(const parser::ProgramUnit &, SemanticsContext &); + static std::optional<ProgramTree> Build( + const parser::MainProgram &, SemanticsContext &); + static std::optional<ProgramTree> Build( + const parser::FunctionSubprogram &, SemanticsContext &); + static std::optional<ProgramTree> Build( + const parser::SubroutineSubprogram &, SemanticsContext &); + static std::optional<ProgramTree> Build( + const parser::SeparateModuleSubprogram &, SemanticsContext &); + static std::optional<ProgramTree> Build( + const parser::Module &, SemanticsContext &); + static std::optional<ProgramTree> Build( + const parser::Submodule &, SemanticsContext &); + static std::optional<ProgramTree> Build( + const parser::BlockData &, SemanticsContext &); + static std::optional<ProgramTree> Build( + const parser::CompilerDirective &, SemanticsContext &); + static std::optional<ProgramTree> Build( + const parser::OpenACCRoutineConstruct &, SemanticsContext &); ENUM_CLASS(Kind, // kind of node Program, Function, Subroutine, MpSubprogram, Module, Submodule, BlockData) diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index c21cf1b..7bd1f4e 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -8889,7 +8889,7 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) { } } } else { - Say(x.source, "Compiler directive was ignored"_warn_en_US); + Say(x.source, "Unrecognized compiler directive was ignored"_warn_en_US); } } @@ -8904,7 +8904,7 @@ bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) { ResolveAccParts(context(), x, &topScope_); return false; } - auto root{ProgramTree::Build(x)}; + auto root{ProgramTree::Build(x, context())}; SetScope(topScope_); ResolveSpecificationParts(root); FinishSpecificationParts(root); diff --git a/flang/test/Parser/unrecognized-dir.f90 b/flang/test/Parser/unrecognized-dir.f90 index ba6fff7..91fbfc9 100644 --- a/flang/test/Parser/unrecognized-dir.f90 +++ b/flang/test/Parser/unrecognized-dir.f90 @@ -1,4 +1,10 @@ ! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s -!CHECK: warning: Compiler directive was ignored +!CHECK: warning: Unrecognized compiler directive was ignored !DIR$ Not a recognized directive +program main + contains + !CHECK: warning: Compiler directive ignored here + !DIR$ not in a subprogram + subroutine s + end end |