[flang-commits] [flang] [flang] Accept and ignore compiler directives between internal subpro… (PR #89810)
via flang-commits
flang-commits at lists.llvm.org
Tue Apr 23 12:29:51 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-parser
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
…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.
---
Full diff: https://github.com/llvm/llvm-project/pull/89810.diff
6 Files Affected:
- (modified) flang/include/flang/Parser/parse-tree.h (+2-1)
- (modified) flang/lib/Parser/Fortran-parsers.cpp (+2-1)
- (modified) flang/lib/Semantics/program-tree.cpp (+58-28)
- (modified) flang/lib/Semantics/program-tree.h (+20-10)
- (modified) flang/lib/Semantics/resolve-names.cpp (+2-2)
- (modified) flang/test/Parser/unrecognized-dir.f90 (+7-1)
``````````diff
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index d7c23755c57b2b..4641f9d20d5b95 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 2bdb8e38db95da..ff01974b549a1e 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 bf773f3810c847..13c85c17459e12 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 d49b0405d8b122..ab00261a964a13 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 @@ class ProgramTree {
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 b941f257a95ea3..f2981b31a6f4c9 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -8886,7 +8886,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);
}
}
@@ -8901,7 +8901,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 ba6fff7562e2d5..91fbfc9ee3c378 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
``````````
</details>
https://github.com/llvm/llvm-project/pull/89810
More information about the flang-commits
mailing list