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