Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions flang/include/flang/Parser/openmp-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ template <typename T> OmpDirectiveName GetOmpDirectiveName(const T &x) {
}

const OmpObjectList *GetOmpObjectList(const OmpClause &clause);
const BlockConstruct *GetFortranBlockConstruct(
const ExecutionPartConstruct &epc);

} // namespace Fortran::parser::omp

Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Semantics/openmp-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
14 changes: 3 additions & 11 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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) {
Expand Down Expand Up @@ -1280,16 +1282,6 @@ TYPE_PARSER(sourced(
maybe(Parser<OmpClauseList>{}),
pure(OmpDirectiveSpecification::Flags::None))))

static bool IsFortranBlockConstruct(const ExecutionPartConstruct &epc) {
// ExecutionPartConstruct -> ExecutableConstruct
// -> Indirection<BlockConstruct>
if (auto *ec{std::get_if<ExecutableConstruct>(&epc.u)}) {
return std::holds_alternative<common::Indirection<BlockConstruct>>(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 &&
Expand All @@ -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<ExecutionPartConstruct>{}.Parse(state)}) {
if (IsFortranBlockConstruct(*epc)) {
if (GetFortranBlockConstruct(*epc) != nullptr) {
Block body;
body.emplace_back(std::move(*epc));
return std::move(body);
Expand Down
13 changes: 13 additions & 0 deletions flang/lib/Parser/openmp-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -61,4 +62,16 @@ const OmpObjectList *GetOmpObjectList(const OmpClause &clause) {
clause.u);
}

const BlockConstruct *GetFortranBlockConstruct(
const ExecutionPartConstruct &epc) {
// ExecutionPartConstruct -> ExecutableConstruct
// -> Indirection<BlockConstruct>
if (auto *ec{std::get_if<ExecutableConstruct>(&epc.u)}) {
if (auto *ind{std::get_if<common::Indirection<BlockConstruct>>(&ec->u)}) {
return &ind->value();
}
}
return nullptr;
}

} // namespace Fortran::parser::omp
18 changes: 2 additions & 16 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<parser::ExecutableConstruct>(&contents.u)};
if (!executableConstruct) {
return false;
}
return std::holds_alternative<common::Indirection<parser::BlockConstruct>>(
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,
Expand Down
21 changes: 14 additions & 7 deletions flang/lib/Semantics/openmp-utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -37,6 +38,7 @@
#include <vector>

namespace Fortran::semantics::omp {
using namespace Fortran::parser::omp;

SourcedActionStmt GetActionStmt(const parser::ExecutionPartConstruct *x) {
if (x == nullptr) {
Expand Down Expand Up @@ -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<parser::ExecutableConstruct>(&ep.u)}) {
using BlockConstruct = common::Indirection<parser::BlockConstruct>;
if (auto *bc{std::get_if<BlockConstruct>(&exec->u)}) {
iter = &std::get<parser::Block>(bc->value().t);
continue;
}
if (auto *bc{GetFortranBlockConstruct(ep)}) {
iter = &std::get<parser::Block>(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
Loading