Check for loosely-strictured block instead of maintaining a flag
This commit is contained in:
parent
040a19d127
commit
16662ce212
@ -713,7 +713,6 @@ public:
|
||||
NODE(parser, OmpEndDirective)
|
||||
NODE(parser, OpenMPAtomicConstruct)
|
||||
NODE(parser, OpenMPBlockConstruct)
|
||||
NODE_ENUM(OpenMPBlockConstruct, Flags)
|
||||
NODE(parser, OpenMPCancelConstruct)
|
||||
NODE(parser, OpenMPCancellationPointConstruct)
|
||||
NODE(parser, OpenMPConstruct)
|
||||
|
@ -4783,25 +4783,15 @@ struct OmpEndDirective : public OmpDirectiveSpecification {
|
||||
// Common base class for block-associated constructs.
|
||||
struct OmpBlockConstruct {
|
||||
TUPLE_CLASS_BOILERPLATE(OmpBlockConstruct);
|
||||
ENUM_CLASS(Flags, None, MissingMandatoryEndDirective);
|
||||
|
||||
/// Constructor with defualt value for Flags.
|
||||
OmpBlockConstruct(OmpBeginDirective &&begin, Block &&block,
|
||||
std::optional<OmpEndDirective> &&end)
|
||||
: t(std::move(begin), std::move(block), std::move(end), Flags::None) {}
|
||||
|
||||
const OmpBeginDirective &BeginDir() const {
|
||||
return std::get<OmpBeginDirective>(t);
|
||||
}
|
||||
const std::optional<OmpEndDirective> &EndDir() const {
|
||||
return std::get<std::optional<OmpEndDirective>>(t);
|
||||
}
|
||||
bool isMissingMandatoryEndDirecitive() const {
|
||||
return std::get<Flags>(t) == Flags::MissingMandatoryEndDirective;
|
||||
}
|
||||
|
||||
CharBlock source;
|
||||
std::tuple<OmpBeginDirective, Block, std::optional<OmpEndDirective>, Flags> t;
|
||||
std::tuple<OmpBeginDirective, Block, std::optional<OmpEndDirective>> t;
|
||||
};
|
||||
|
||||
struct OmpMetadirectiveDirective {
|
||||
|
@ -1474,7 +1474,6 @@ struct OmpBlockConstructParser {
|
||||
constexpr OmpBlockConstructParser(llvm::omp::Directive dir) : dir_(dir) {}
|
||||
|
||||
std::optional<resultType> Parse(ParseState &state) const {
|
||||
using Flags = OmpBlockConstruct::Flags;
|
||||
if (auto &&begin{OmpBeginDirectiveParser(dir_).Parse(state)}) {
|
||||
if (auto &&body{attempt(StrictlyStructuredBlockParser{}).Parse(state)}) {
|
||||
// Try strictly-structured block with an optional end-directive
|
||||
@ -1503,8 +1502,7 @@ struct OmpBlockConstructParser {
|
||||
return OmpBlockConstruct{OmpBeginDirective(std::move(*begin)),
|
||||
std::move(*body),
|
||||
llvm::transformOptional(std::move(*end),
|
||||
[](auto &&s) { return OmpEndDirective(std::move(s)); }),
|
||||
endPresent ? Flags::None : Flags::MissingMandatoryEndDirective};
|
||||
[](auto &&s) { return OmpEndDirective(std::move(s)); })};
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
|
@ -788,7 +788,23 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
|
||||
|
||||
// Missing mandatory end block: this is checked in semantics because that
|
||||
// makes it easier to control the error messages.
|
||||
if (x.isMissingMandatoryEndDirecitive()) {
|
||||
// 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)) {
|
||||
context_.Say(
|
||||
x.BeginDir().source, "Expected OpenMP end directive"_err_en_US);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user