diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h index 3d3dfae290d96..8205d25647916 100644 --- a/flang/include/flang/Parser/openmp-utils.h +++ b/flang/include/flang/Parser/openmp-utils.h @@ -155,6 +155,8 @@ template OmpDirectiveName GetOmpDirectiveName(const T &x) { } const OmpObjectList *GetOmpObjectList(const OmpClause &clause); +const BlockConstruct *GetFortranBlockConstruct( + const ExecutionPartConstruct &epc); } // namespace Fortran::parser::omp diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h index 1c54124a5738a..68318d6093a1e 100644 --- a/flang/include/flang/Semantics/openmp-utils.h +++ b/flang/include/flang/Semantics/openmp-utils.h @@ -83,6 +83,7 @@ const SomeExpr *HasStorageOverlap( bool IsAssignment(const parser::ActionStmt *x); bool IsPointerAssignment(const evaluate::Assignment &x); const parser::Block &GetInnermostExecPart(const parser::Block &block); +bool IsStrictlyStructuredBlock(const parser::Block &block); } // namespace omp } // namespace Fortran::semantics diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 68e0acdf91fe2..78a5746bb0bf8 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -15,6 +15,7 @@ #include "stmt-parser.h" #include "token-parsers.h" #include "type-parser-implementation.h" +#include "flang/Parser/openmp-utils.h" #include "flang/Parser/parse-tree.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" @@ -24,6 +25,7 @@ // OpenMP Directives and Clauses namespace Fortran::parser { +using namespace Fortran::parser::omp; // Helper function to print the buffer contents starting at the current point. [[maybe_unused]] static std::string ahead(const ParseState &state) { @@ -1280,16 +1282,6 @@ TYPE_PARSER(sourced( maybe(Parser{}), pure(OmpDirectiveSpecification::Flags::None)))) -static bool IsFortranBlockConstruct(const ExecutionPartConstruct &epc) { - // ExecutionPartConstruct -> ExecutableConstruct - // -> Indirection - if (auto *ec{std::get_if(&epc.u)}) { - return std::holds_alternative>(ec->u); - } else { - return false; - } -} - static bool IsStandaloneOrdered(const OmpDirectiveSpecification &dirSpec) { // An ORDERED construct is standalone if it has DOACROSS or DEPEND clause. return dirSpec.DirId() == llvm::omp::Directive::OMPD_ordered && @@ -1307,7 +1299,7 @@ struct StrictlyStructuredBlockParser { // Detect BLOCK construct without parsing the entire thing. if (lookAhead(skipStuffBeforeStatement >> "BLOCK"_tok).Parse(state)) { if (auto epc{Parser{}.Parse(state)}) { - if (IsFortranBlockConstruct(*epc)) { + if (GetFortranBlockConstruct(*epc) != nullptr) { Block body; body.emplace_back(std::move(*epc)); return std::move(body); diff --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp index ef7e4fcdbbd07..937a17f29f221 100644 --- a/flang/lib/Parser/openmp-utils.cpp +++ b/flang/lib/Parser/openmp-utils.cpp @@ -12,6 +12,7 @@ #include "flang/Parser/openmp-utils.h" +#include "flang/Common/indirection.h" #include "flang/Common/template.h" #include "flang/Common/visit.h" @@ -61,4 +62,16 @@ const OmpObjectList *GetOmpObjectList(const OmpClause &clause) { clause.u); } +const BlockConstruct *GetFortranBlockConstruct( + const ExecutionPartConstruct &epc) { + // ExecutionPartConstruct -> ExecutableConstruct + // -> Indirection + if (auto *ec{std::get_if(&epc.u)}) { + if (auto *ind{std::get_if>(&ec->u)}) { + return &ind->value(); + } + } + return nullptr; +} + } // namespace Fortran::parser::omp diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index d1654a3adcc9c..b7f72756c9530 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -874,22 +874,8 @@ void OmpStructureChecker::Enter(const parser::OmpBlockConstruct &x) { // Missing mandatory end block: this is checked in semantics because that // makes it easier to control the error messages. // The end block is mandatory when the construct is not applied to a strictly - // structured block (aka it is applied to a loosely structured block). In - // other words, the body doesn't contain exactly one parser::BlockConstruct. - auto isStrictlyStructuredBlock{[](const parser::Block &block) -> bool { - if (block.size() != 1) { - return false; - } - const parser::ExecutionPartConstruct &contents{block.front()}; - auto *executableConstruct{ - std::get_if(&contents.u)}; - if (!executableConstruct) { - return false; - } - return std::holds_alternative>( - executableConstruct->u); - }}; - if (!endSpec && !isStrictlyStructuredBlock(block)) { + // structured block (aka it is applied to a loosely structured block). + if (!endSpec && !IsStrictlyStructuredBlock(block)) { llvm::omp::Directive dirId{beginSpec.DirId()}; auto &msg{context_.Say(beginSpec.source, "Expected OpenMP END %s directive"_err_en_US, diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp index e8df346ccdc3e..2980f827d3ef3 100644 --- a/flang/lib/Semantics/openmp-utils.cpp +++ b/flang/lib/Semantics/openmp-utils.cpp @@ -21,6 +21,7 @@ #include "flang/Evaluate/traverse.h" #include "flang/Evaluate/type.h" #include "flang/Evaluate/variable.h" +#include "flang/Parser/openmp-utils.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" #include "flang/Semantics/semantics.h" @@ -37,6 +38,7 @@ #include namespace Fortran::semantics::omp { +using namespace Fortran::parser::omp; SourcedActionStmt GetActionStmt(const parser::ExecutionPartConstruct *x) { if (x == nullptr) { @@ -397,16 +399,21 @@ const parser::Block &GetInnermostExecPart(const parser::Block &block) { const parser::Block *iter{&block}; while (iter->size() == 1) { const parser::ExecutionPartConstruct &ep{iter->front()}; - if (auto *exec{std::get_if(&ep.u)}) { - using BlockConstruct = common::Indirection; - if (auto *bc{std::get_if(&exec->u)}) { - iter = &std::get(bc->value().t); - continue; - } + if (auto *bc{GetFortranBlockConstruct(ep)}) { + iter = &std::get(bc->t); + } else { + break; } - break; } return *iter; } +bool IsStrictlyStructuredBlock(const parser::Block &block) { + if (block.size() == 1) { + return GetFortranBlockConstruct(block.front()) != nullptr; + } else { + return false; + } +} + } // namespace Fortran::semantics::omp