[flang][OpenMP] Use OmpDirectiveSpecification in standalone directives (#131163)

This uses OmpDirectiveSpecification in the rest of the standalone
directives.
This commit is contained in:
Krzysztof Parzyszek
2025-03-20 06:50:43 -05:00
committed by GitHub
parent 82912fd620
commit 68180d8d16
17 changed files with 263 additions and 155 deletions

View File

@@ -127,18 +127,16 @@ std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) {
return std::visit(
Fortran::common::visitors{
[&](const OpenMPStandaloneConstruct &c) -> std::string {
return std::visit(
Fortran::common::visitors{
[&](const OpenMPSimpleStandaloneConstruct &d) {
return common::visit(
common::visitors{
[&](const OmpMetadirectiveDirective &d) {
return normalize_construct_name(d.source.ToString());
},
[&](auto &&d) {
const CharBlock &source{
std::get<OmpDirectiveName>(d.v.t).source};
return normalize_construct_name(source.ToString());
},
[&](const auto &c) {
// Get source from the directive or verbatim fields
const CharBlock &source{std::get<0>(c.t).source};
return normalize_construct_name(source.ToString());
},
},
c.u);
},

View File

@@ -484,6 +484,7 @@ public:
NODE(parser, OmpLocatorList)
NODE(parser, OmpReductionSpecifier)
NODE(parser, OmpArgument)
NODE(parser, OmpArgumentList)
NODE(parser, OmpMetadirectiveDirective)
NODE(parser, OmpMatchClause)
NODE(parser, OmpOtherwiseClause)

View File

@@ -3557,6 +3557,11 @@ struct OmpArgument {
OmpMapperSpecifier, OmpReductionSpecifier>
u;
};
struct OmpArgumentList {
WRAPPER_CLASS_BOILERPLATE(OmpArgumentList, std::list<OmpArgument>);
CharBlock source;
};
} // namespace arguments
inline namespace traits {
@@ -4511,10 +4516,11 @@ struct OmpDirectiveSpecification {
llvm::omp::Directive DirId() const { //
return std::get<OmpDirectiveName>(t).v;
}
const OmpArgumentList &Arguments() const;
const OmpClauseList &Clauses() const;
CharBlock source;
std::tuple<OmpDirectiveName, std::optional<std::list<OmpArgument>>,
std::tuple<OmpDirectiveName, std::optional<OmpArgumentList>,
std::optional<OmpClauseList>, Flags>
t;
};
@@ -4865,16 +4871,15 @@ struct OmpLoopDirective {
// 2.14.2 cancellation-point -> CANCELLATION POINT construct-type-clause
struct OpenMPCancellationPointConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPCancellationPointConstruct);
WRAPPER_CLASS_BOILERPLATE(
OpenMPCancellationPointConstruct, OmpDirectiveSpecification);
CharBlock source;
std::tuple<Verbatim, OmpClauseList> t;
};
// 2.14.1 cancel -> CANCEL construct-type-clause [ [,] if-clause]
struct OpenMPCancelConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPCancelConstruct);
WRAPPER_CLASS_BOILERPLATE(OpenMPCancelConstruct, OmpDirectiveSpecification);
CharBlock source;
std::tuple<Verbatim, OmpClauseList> t;
};
// Ref: [5.0:254-255], [5.1:287-288], [5.2:322-323]
@@ -4884,9 +4889,8 @@ struct OpenMPCancelConstruct {
// destroy-clause |
// update-clause
struct OpenMPDepobjConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPDepobjConstruct);
WRAPPER_CLASS_BOILERPLATE(OpenMPDepobjConstruct, OmpDirectiveSpecification);
CharBlock source;
std::tuple<Verbatim, OmpObject, OmpClause> t;
};
// Ref: [5.2: 200-201]
@@ -4927,11 +4931,8 @@ struct OpenMPDispatchConstruct {
// ACQ_REL | RELEASE | ACQUIRE | // since 5.0
// SEQ_CST // since 5.1
struct OpenMPFlushConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPFlushConstruct);
WRAPPER_CLASS_BOILERPLATE(OpenMPFlushConstruct, OmpDirectiveSpecification);
CharBlock source;
std::tuple<Verbatim, std::optional<OmpObjectList>,
std::optional<OmpClauseList>, /*TrailingClauses=*/bool>
t;
};
struct OpenMPSimpleStandaloneConstruct {

View File

@@ -132,6 +132,25 @@ Object makeObject(const parser::OmpObject &object,
return makeObject(std::get<parser::Designator>(object.u), semaCtx);
}
ObjectList makeObjects(const parser::OmpArgumentList &objects,
semantics::SemanticsContext &semaCtx) {
return makeList(objects.v, [&](const parser::OmpArgument &arg) {
return common::visit(
common::visitors{
[&](const parser::OmpLocator &locator) -> Object {
if (auto *object = std::get_if<parser::OmpObject>(&locator.u)) {
return makeObject(*object, semaCtx);
}
llvm_unreachable("Expecting object");
},
[](auto &&s) -> Object { //
llvm_unreachable("Expecting object");
},
},
arg.u);
});
}
std::optional<Object> getBaseObject(const Object &object,
semantics::SemanticsContext &semaCtx) {
// If it's just the symbol, then there is no base.

View File

@@ -143,6 +143,9 @@ inline ObjectList makeObjects(const parser::OmpObjectList &objects,
return makeList(objects.v, makeObjectFn(semaCtx));
}
ObjectList makeObjects(const parser::OmpArgumentList &objects,
semantics::SemanticsContext &semaCtx);
template <typename FuncTy, //
typename ArgTy, //
typename ResultTy = std::invoke_result_t<FuncTy, ArgTy>>

View File

@@ -3317,22 +3317,16 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPFlushConstruct &flushConstruct) {
const auto &verbatim = std::get<parser::Verbatim>(flushConstruct.t);
const auto &objectList =
std::get<std::optional<parser::OmpObjectList>>(flushConstruct.t);
const auto &clauseList =
std::get<std::optional<parser::OmpClauseList>>(flushConstruct.t);
ObjectList objects =
objectList ? makeObjects(*objectList, semaCtx) : ObjectList{};
const parser::OpenMPFlushConstruct &construct) {
const auto &argumentList = construct.v.Arguments();
const auto &clauseList = construct.v.Clauses();
ObjectList objects = makeObjects(argumentList, semaCtx);
List<Clause> clauses =
clauseList ? makeList(clauseList->v,
[&](auto &&s) { return makeClause(s, semaCtx); })
: List<Clause>{};
mlir::Location currentLocation = converter.genLocation(verbatim.source);
makeList(clauseList.v, [&](auto &&s) { return makeClause(s, semaCtx); });
mlir::Location currentLocation = converter.genLocation(construct.source);
ConstructQueue queue{buildConstructQueue(
converter.getFirOpBuilder().getModule(), semaCtx, eval, verbatim.source,
converter.getFirOpBuilder().getModule(), semaCtx, eval, construct.source,
llvm::omp::Directive::OMPD_flush, clauses)};
genFlushOp(converter, symTable, semaCtx, eval, currentLocation, objects,
queue, queue.begin());
@@ -3359,11 +3353,12 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
const parser::OpenMPDepobjConstruct &construct) {
// These values will be ignored until the construct itself is implemented,
// but run them anyway for the sake of testing (via a Todo test).
auto &ompObj = std::get<parser::OmpObject>(construct.t);
const Object &depObj = makeObject(ompObj, semaCtx);
Clause clause = makeClause(std::get<parser::OmpClause>(construct.t), semaCtx);
(void)depObj;
(void)clause;
ObjectList objects = makeObjects(construct.v.Arguments(), semaCtx);
assert(objects.size() == 1);
List<Clause> clauses = makeClauses(construct.v.Clauses(), semaCtx);
assert(clauses.size() == 1);
(void)objects;
(void)clauses;
TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct");
}

View File

@@ -236,6 +236,9 @@ TYPE_PARSER(sourced( //
TYPE_PARSER(construct<OmpLocatorList>(nonemptyList(Parser<OmpLocator>{})))
TYPE_PARSER(sourced( //
construct<OmpArgumentList>(nonemptyList(Parser<OmpArgument>{}))))
TYPE_PARSER( //
construct<OmpTypeSpecifier>(Parser<DeclarationTypeSpec>{}) ||
construct<OmpTypeSpecifier>(Parser<TypeSpec>{}))
@@ -1057,9 +1060,9 @@ TYPE_PARSER(sourced(construct<OmpErrorDirective>(
TYPE_PARSER(sourced(construct<OmpDirectiveName>(OmpDirectiveNameParser{})))
OmpDirectiveSpecification static makeFlushFromOldSyntax1(Verbatim &&text,
OmpDirectiveSpecification static makeFlushFromOldSyntax(Verbatim &&text,
std::optional<OmpClauseList> &&clauses,
std::optional<std::list<OmpArgument>> &&args,
std::optional<OmpArgumentList> &&args,
OmpDirectiveSpecification::Flags &&flags) {
return OmpDirectiveSpecification{OmpDirectiveName(text), std::move(args),
std::move(clauses), std::move(flags)};
@@ -1073,15 +1076,15 @@ TYPE_PARSER(sourced(
// lists absent in the parsed result.
// E.g. for FLUSH(x) SEQ_CST it would find no clauses following
// the directive name, parse the argument list "(x)" and stop.
applyFunction<OmpDirectiveSpecification>(makeFlushFromOldSyntax1,
applyFunction<OmpDirectiveSpecification>(makeFlushFromOldSyntax,
verbatim("FLUSH"_tok) / !lookAhead("("_tok),
maybe(Parser<OmpClauseList>{}),
maybe(parenthesized(nonemptyList(Parser<OmpArgument>{}))),
maybe(parenthesized(Parser<OmpArgumentList>{})),
pure(OmpDirectiveSpecification::Flags::DeprecatedSyntax))) ||
// Parse the standard syntax: directive [(arguments)] [clauses]
construct<OmpDirectiveSpecification>( //
sourced(OmpDirectiveNameParser{}),
maybe(parenthesized(nonemptyList(Parser<OmpArgument>{}))),
maybe(parenthesized(Parser<OmpArgumentList>{})),
maybe(Parser<OmpClauseList>{}),
pure(OmpDirectiveSpecification::Flags::None))))
@@ -1157,14 +1160,6 @@ TYPE_PARSER(sourced(construct<OmpLoopDirective>(first(
TYPE_PARSER(sourced(construct<OmpBeginLoopDirective>(
sourced(Parser<OmpLoopDirective>{}), Parser<OmpClauseList>{})))
// 2.14.2 Cancellation Point construct
TYPE_PARSER(sourced(construct<OpenMPCancellationPointConstruct>(
verbatim("CANCELLATION POINT"_tok), Parser<OmpClauseList>{})))
// 2.14.1 Cancel construct
TYPE_PARSER(sourced(construct<OpenMPCancelConstruct>(
verbatim("CANCEL"_tok), Parser<OmpClauseList>{})))
TYPE_PARSER(sourced(construct<OmpFailClause>(
parenthesized(indirect(Parser<OmpMemoryOrderClause>{})))))
@@ -1205,29 +1200,6 @@ TYPE_PARSER(sourced(construct<OmpAtomicClause>(
TYPE_PARSER(sourced(construct<OmpAtomicClauseList>(
many(maybe(","_tok) >> sourced(Parser<OmpAtomicClause>{})))))
TYPE_PARSER(sourced(construct<OpenMPDepobjConstruct>(verbatim("DEPOBJ"_tok),
parenthesized(Parser<OmpObject>{}), sourced(Parser<OmpClause>{}))))
static OpenMPFlushConstruct makeFlushFromOldSyntax(Verbatim &&text,
std::optional<OmpClauseList> &&clauses,
std::optional<OmpObjectList> &&objects) {
bool oldSyntax{
clauses && !clauses->v.empty() && objects && !objects->v.empty()};
return OpenMPFlushConstruct{std::move(text), std::move(objects),
std::move(clauses),
/*TrailingClauses=*/!oldSyntax};
}
TYPE_PARSER(sourced( //
construct<OpenMPFlushConstruct>( //
applyFunction<OpenMPFlushConstruct>(makeFlushFromOldSyntax,
verbatim("FLUSH"_tok), maybe(Parser<OmpClauseList>{}),
maybe(parenthesized(Parser<OmpObjectList>{})))) ||
construct<OpenMPFlushConstruct>( //
verbatim("FLUSH"_tok), maybe(parenthesized(Parser<OmpObjectList>{})),
Parser<OmpClauseList>{}, pure(/*TrailingClauses=*/true))))
static bool IsSimpleStandalone(const OmpDirectiveName &name) {
switch (name.v) {
case llvm::omp::Directive::OMPD_barrier:
@@ -1249,6 +1221,36 @@ TYPE_PARSER(sourced( //
predicated(OmpDirectiveNameParser{}, IsSimpleStandalone) >=
Parser<OmpDirectiveSpecification>{})))
static inline constexpr auto IsDirective(llvm::omp::Directive dir) {
return [dir](const OmpDirectiveName &name) -> bool { return dir == name.v; };
}
TYPE_PARSER(sourced( //
construct<OpenMPFlushConstruct>(
predicated(OmpDirectiveNameParser{},
IsDirective(llvm::omp::Directive::OMPD_flush)) >=
Parser<OmpDirectiveSpecification>{})))
// 2.14.2 Cancellation Point construct
TYPE_PARSER(sourced( //
construct<OpenMPCancellationPointConstruct>(
predicated(OmpDirectiveNameParser{},
IsDirective(llvm::omp::Directive::OMPD_cancellation_point)) >=
Parser<OmpDirectiveSpecification>{})))
// 2.14.1 Cancel construct
TYPE_PARSER(sourced( //
construct<OpenMPCancelConstruct>(
predicated(OmpDirectiveNameParser{},
IsDirective(llvm::omp::Directive::OMPD_cancel)) >=
Parser<OmpDirectiveSpecification>{})))
TYPE_PARSER(sourced( //
construct<OpenMPDepobjConstruct>(
predicated(OmpDirectiveNameParser{},
IsDirective(llvm::omp::Directive::OMPD_depobj)) >=
Parser<OmpDirectiveSpecification>{})))
// Standalone Constructs
TYPE_PARSER(
sourced( //

View File

@@ -337,6 +337,14 @@ llvm::omp::Clause OmpClause::Id() const {
return std::visit([](auto &&s) { return getClauseIdForClass(s); }, u);
}
const OmpArgumentList &OmpDirectiveSpecification::Arguments() const {
static OmpArgumentList empty{decltype(OmpArgumentList::v){}};
if (auto &arguments = std::get<std::optional<OmpArgumentList>>(t)) {
return *arguments;
}
return empty;
}
const OmpClauseList &OmpDirectiveSpecification::Clauses() const {
static OmpClauseList empty{decltype(OmpClauseList::v){}};
if (auto &clauses = std::get<std::optional<OmpClauseList>>(t)) {

View File

@@ -2075,6 +2075,8 @@ public:
}
// OpenMP Clauses & Directives
void Unparse(const OmpArgumentList &x) { Walk(x.v, ", "); }
void Unparse(const OmpTypeNameList &x) { //
Walk(x.v, ",");
}
@@ -2095,8 +2097,7 @@ public:
}
void Unparse(const OmpDirectiveSpecification &x) {
auto unparseArgs{[&]() {
using ArgList = std::list<parser::OmpArgument>;
if (auto &args{std::get<std::optional<ArgList>>(x.t)}) {
if (auto &args{std::get<std::optional<OmpArgumentList>>(x.t)}) {
Put("(");
Walk(*args);
Put(")");
@@ -2823,15 +2824,15 @@ public:
}
void Unparse(const OpenMPCancellationPointConstruct &x) {
BeginOpenMP();
Word("!$OMP CANCELLATION POINT ");
Walk(std::get<OmpClauseList>(x.t));
Word("!$OMP ");
Walk(x.v);
Put("\n");
EndOpenMP();
}
void Unparse(const OpenMPCancelConstruct &x) {
BeginOpenMP();
Word("!$OMP CANCEL ");
Walk(std::get<OmpClauseList>(x.t));
Word("!$OMP ");
Walk(x.v);
Put("\n");
EndOpenMP();
}
@@ -2858,23 +2859,21 @@ public:
}
void Unparse(const OpenMPDepobjConstruct &x) {
BeginOpenMP();
Word("!$OMP DEPOBJ");
Put("(");
Walk(std::get<OmpObject>(x.t));
Put(") ");
Walk(std::get<OmpClause>(x.t));
Word("!$OMP ");
Walk(x.v);
Put("\n");
EndOpenMP();
}
void Unparse(const OpenMPFlushConstruct &x) {
BeginOpenMP();
Word("!$OMP FLUSH");
if (std::get</*ClausesTrailing=*/bool>(x.t)) {
Walk("(", std::get<std::optional<OmpObjectList>>(x.t), ")");
Walk(" ", std::get<std::optional<OmpClauseList>>(x.t));
using Flags = OmpDirectiveSpecification::Flags;
if (std::get<Flags>(x.v.t) == Flags::DeprecatedSyntax) {
Walk("(", std::get<std::optional<OmpArgumentList>>(x.v.t), ")");
Walk(" ", std::get<std::optional<OmpClauseList>>(x.v.t));
} else {
Walk(" ", std::get<std::optional<OmpClauseList>>(x.t));
Walk(" (", std::get<std::optional<OmpObjectList>>(x.t), ")");
Walk(" ", std::get<std::optional<OmpClauseList>>(x.v.t));
Walk(" (", std::get<std::optional<OmpArgumentList>>(x.v.t), ")");
}
Put("\n");
EndOpenMP();

View File

@@ -1601,23 +1601,58 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &) {
}
void OmpStructureChecker::Enter(const parser::OpenMPDepobjConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_depobj);
const auto &dirName{std::get<parser::OmpDirectiveName>(x.v.t)};
PushContextAndClauseSets(dirName.source, llvm::omp::Directive::OMPD_depobj);
unsigned version{context_.langOptions().OpenMPVersion};
const parser::OmpArgumentList &arguments{x.v.Arguments()};
const parser::OmpClauseList &clauses{x.v.Clauses()};
// Ref: [6.0:505-506]
if (version < 60) {
if (arguments.v.size() != 1) {
parser::CharBlock source(
arguments.v.empty() ? dirName.source : arguments.source);
context_.Say(
source, "The DEPOBJ directive requires a single argument"_err_en_US);
}
}
if (clauses.v.size() != 1) {
context_.Say(
x.source, "The DEPOBJ construct requires a single clause"_err_en_US);
return;
}
auto &clause{clauses.v.front()};
if (version >= 60 && arguments.v.empty()) {
context_.Say(x.source,
"DEPOBJ syntax with no argument is not handled yet"_err_en_US);
return;
}
// [5.2:73:27-28]
// If the destroy clause appears on a depobj construct, destroy-var must
// refer to the same depend object as the depobj argument of the construct.
auto &clause{std::get<parser::OmpClause>(x.t)};
if (clause.Id() == llvm::omp::Clause::OMPC_destroy) {
auto getSymbol{[&](const parser::OmpObject &obj) {
auto getObjSymbol{[&](const parser::OmpObject &obj) {
return common::visit(
[&](auto &&s) { return GetLastName(s).symbol; }, obj.u);
}};
auto getArgSymbol{[&](const parser::OmpArgument &arg) {
if (auto *locator{std::get_if<parser::OmpLocator>(&arg.u)}) {
if (auto *object{std::get_if<parser::OmpObject>(&locator->u)}) {
return getObjSymbol(*object);
}
}
return static_cast<Symbol *>(nullptr);
}};
auto &wrapper{std::get<parser::OmpClause::Destroy>(clause.u)};
if (const std::optional<parser::OmpDestroyClause> &destroy{wrapper.v}) {
const Symbol *constrSym{getSymbol(std::get<parser::OmpObject>(x.t))};
const Symbol *clauseSym{getSymbol(destroy->v)};
const Symbol *constrSym{getArgSymbol(arguments.v.front())};
const Symbol *clauseSym{getObjSymbol(destroy->v)};
assert(constrSym && "Unresolved depobj construct symbol");
assert(clauseSym && "Unresolved destroy symbol on depobj construct");
if (constrSym != clauseSym) {
@@ -2210,27 +2245,34 @@ void OmpStructureChecker::Leave(
}
void OmpStructureChecker::Enter(const parser::OpenMPFlushConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_flush);
const auto &dirName{std::get<parser::OmpDirectiveName>(x.v.t)};
PushContextAndClauseSets(dirName.source, llvm::omp::Directive::OMPD_flush);
}
void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &x) {
auto &flushList{std::get<std::optional<parser::OmpObjectList>>(x.t)};
auto &flushList{std::get<std::optional<parser::OmpArgumentList>>(x.v.t)};
if (FindClause(llvm::omp::Clause::OMPC_acquire) ||
FindClause(llvm::omp::Clause::OMPC_release) ||
FindClause(llvm::omp::Clause::OMPC_acq_rel)) {
if (flushList) {
context_.Say(parser::FindSourceLocation(flushList),
"If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items "
"must not be specified on the FLUSH directive"_err_en_US);
if (flushList) {
for (const parser::OmpArgument &arg : flushList->v) {
if (auto *sym{GetArgumentSymbol(arg)}; sym && !IsVariableListItem(*sym)) {
context_.Say(arg.source,
"FLUSH argument must be a variable list item"_err_en_US);
}
}
if (FindClause(llvm::omp::Clause::OMPC_acquire) ||
FindClause(llvm::omp::Clause::OMPC_release) ||
FindClause(llvm::omp::Clause::OMPC_acq_rel)) {
context_.Say(flushList->source,
"If memory-order-clause is RELEASE, ACQUIRE, or ACQ_REL, list items must not be specified on the FLUSH directive"_err_en_US);
}
}
unsigned version{context_.langOptions().OpenMPVersion};
if (version >= 52) {
if (!std::get</*TrailingClauses=*/bool>(x.t)) {
context_.Say(parser::FindSourceLocation(flushList),
using Flags = parser::OmpDirectiveSpecification::Flags;
if (std::get<Flags>(x.v.t) == Flags::DeprecatedSyntax) {
context_.Say(x.source,
"The syntax \"FLUSH clause (object, ...)\" has been deprecated, use \"FLUSH(object, ...) clause\" instead"_warn_en_US);
}
}
@@ -2239,13 +2281,13 @@ void OmpStructureChecker::Leave(const parser::OpenMPFlushConstruct &x) {
}
void OmpStructureChecker::Enter(const parser::OpenMPCancelConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
const auto &clauses{std::get<parser::OmpClauseList>(x.t)};
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_cancel);
auto &dirName{std::get<parser::OmpDirectiveName>(x.v.t)};
auto &maybeClauses{std::get<std::optional<parser::OmpClauseList>>(x.v.t)};
PushContextAndClauseSets(dirName.source, llvm::omp::Directive::OMPD_cancel);
if (auto maybeConstruct{GetCancelType(
llvm::omp::Directive::OMPD_cancel, x.source, clauses)}) {
CheckCancellationNest(dir.source, *maybeConstruct);
llvm::omp::Directive::OMPD_cancel, x.source, maybeClauses)}) {
CheckCancellationNest(dirName.source, *maybeConstruct);
}
}
@@ -2318,14 +2360,15 @@ void OmpStructureChecker::Enter(
void OmpStructureChecker::Enter(
const parser::OpenMPCancellationPointConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
const auto &clauses{std::get<parser::OmpClauseList>(x.t)};
auto &dirName{std::get<parser::OmpDirectiveName>(x.v.t)};
auto &maybeClauses{std::get<std::optional<parser::OmpClauseList>>(x.v.t)};
PushContextAndClauseSets(
dir.source, llvm::omp::Directive::OMPD_cancellation_point);
dirName.source, llvm::omp::Directive::OMPD_cancellation_point);
if (auto maybeConstruct{GetCancelType(
llvm::omp::Directive::OMPD_cancellation_point, x.source, clauses)}) {
CheckCancellationNest(dir.source, *maybeConstruct);
if (auto maybeConstruct{
GetCancelType(llvm::omp::Directive::OMPD_cancellation_point, x.source,
maybeClauses)}) {
CheckCancellationNest(dirName.source, *maybeConstruct);
}
}
@@ -2336,13 +2379,16 @@ void OmpStructureChecker::Leave(
std::optional<llvm::omp::Directive> OmpStructureChecker::GetCancelType(
llvm::omp::Directive cancelDir, const parser::CharBlock &cancelSource,
const parser::OmpClauseList &clauses) {
const std::optional<parser::OmpClauseList> &maybeClauses) {
if (!maybeClauses) {
return std::nullopt;
}
// Given clauses from CANCEL or CANCELLATION_POINT, identify the construct
// to which the cancellation applies.
std::optional<llvm::omp::Directive> cancelee;
llvm::StringRef cancelName{llvm::omp::getOpenMPDirectiveName(cancelDir)};
for (const parser::OmpClause &clause : clauses.v) {
for (const parser::OmpClause &clause : maybeClauses->v) {
using CancellationConstructType =
parser::OmpClause::CancellationConstructType;
if (auto *cctype{std::get_if<CancellationConstructType>(&clause.u)}) {
@@ -5254,10 +5300,23 @@ llvm::StringRef OmpStructureChecker::getDirectiveName(
const Symbol *OmpStructureChecker::GetObjectSymbol(
const parser::OmpObject &object) {
// Some symbols may be missing if the resolution failed, e.g. when an
// undeclared name is used with implicit none.
if (auto *name{std::get_if<parser::Name>(&object.u)}) {
return &name->symbol->GetUltimate();
return name->symbol ? &name->symbol->GetUltimate() : nullptr;
} else if (auto *desg{std::get_if<parser::Designator>(&object.u)}) {
return &GetLastName(*desg).symbol->GetUltimate();
auto &last{GetLastName(*desg)};
return last.symbol ? &GetLastName(*desg).symbol->GetUltimate() : nullptr;
}
return nullptr;
}
const Symbol *OmpStructureChecker::GetArgumentSymbol(
const parser::OmpArgument &argument) {
if (auto *locator{std::get_if<parser::OmpLocator>(&argument.u)}) {
if (auto *object{std::get_if<parser::OmpObject>(&locator->u)}) {
return GetObjectSymbol(*object);
}
}
return nullptr;
}

View File

@@ -225,6 +225,7 @@ private:
std::optional<IterTy> FindDuplicate(RangeTy &&);
const Symbol *GetObjectSymbol(const parser::OmpObject &object);
const Symbol *GetArgumentSymbol(const parser::OmpArgument &argument);
std::optional<parser::CharBlock> GetObjectSource(
const parser::OmpObject &object);
void CheckDependList(const parser::DataRef &);
@@ -277,7 +278,7 @@ private:
void CheckTaskDependenceType(const parser::OmpTaskDependenceType::Value &x);
std::optional<llvm::omp::Directive> GetCancelType(
llvm::omp::Directive cancelDir, const parser::CharBlock &cancelSource,
const parser::OmpClauseList &clauses);
const std::optional<parser::OmpClauseList> &maybeClauses);
void CheckCancellationNest(
const parser::CharBlock &source, llvm::omp::Directive type);
std::int64_t GetOrdCollapseLevel(const parser::OpenMPLoopConstruct &x);

View File

@@ -398,8 +398,13 @@ public:
bool Pre(const parser::OpenMPDepobjConstruct &x) {
PushContext(x.source, llvm::omp::Directive::OMPD_depobj);
auto &object{std::get<parser::OmpObject>(x.t)};
ResolveOmpObject(object, Symbol::Flag::OmpDependObject);
for (auto &arg : x.v.Arguments().v) {
if (auto *locator{std::get_if<parser::OmpLocator>(&arg.u)}) {
if (auto *object{std::get_if<parser::OmpObject>(&locator->u)}) {
ResolveOmpObject(*object, Symbol::Flag::OmpDependObject);
}
}
}
return true;
}
void Post(const parser::OpenMPDepobjConstruct &) { PopContext(); }

View File

@@ -1814,13 +1814,13 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) {
// METADIRECTIVE, some semantic checks may not be applicable.
// Disable the semantic analysis for it in such cases to allow the compiler
// to parse METADIRECTIVE without flagging errors.
auto &maybeArgs{std::get<std::optional<std::list<parser::OmpArgument>>>(x.t)};
auto &maybeArgs{std::get<std::optional<parser::OmpArgumentList>>(x.t)};
auto &maybeClauses{std::get<std::optional<parser::OmpClauseList>>(x.t)};
switch (x.DirId()) {
case llvm::omp::Directive::OMPD_declare_mapper:
if (maybeArgs && maybeClauses) {
const parser::OmpArgument &first{maybeArgs->front()};
const parser::OmpArgument &first{maybeArgs->v.front()};
if (auto *spec{std::get_if<parser::OmpMapperSpecifier>(&first.u)}) {
ProcessMapperSpecifier(*spec, *maybeClauses);
}
@@ -1828,7 +1828,7 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) {
break;
case llvm::omp::Directive::OMPD_declare_reduction:
if (maybeArgs && maybeClauses) {
const parser::OmpArgument &first{maybeArgs->front()};
const parser::OmpArgument &first{maybeArgs->v.front()};
if (auto *spec{std::get_if<parser::OmpReductionSpecifier>(&first.u)}) {
ProcessReductionSpecifier(*spec, maybeClauses);
}

View File

@@ -11,10 +11,10 @@ end
!UNPARSE: !$OMP DEPOBJ(x) DEPEND(IN: y)
!UNPARSE: END SUBROUTINE
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
!PARSE-TREE: | Verbatim
!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClause -> Depend -> OmpDependClause -> TaskDep
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = depobj
!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Depend -> OmpDependClause -> TaskDep
!PARSE-TREE: | | Modifier -> OmpTaskDependenceType -> Value = In
!PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y'
@@ -28,10 +28,10 @@ end
!UNPARSE: !$OMP DEPOBJ(x) UPDATE(OUT)
!UNPARSE: END SUBROUTINE
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
!PARSE-TREE: | Verbatim
!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClause -> Update -> OmpUpdateClause -> OmpTaskDependenceType -> Value = Out
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = depobj
!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Update -> OmpUpdateClause -> OmpTaskDependenceType -> Value = Out
subroutine f02
integer :: x
@@ -43,10 +43,10 @@ end
!UNPARSE: !$OMP DEPOBJ(x) DESTROY(x)
!UNPARSE: END SUBROUTINE
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
!PARSE-TREE: | Verbatim
!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClause -> Destroy -> OmpDestroyClause -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = depobj
!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Destroy -> OmpDestroyClause -> OmpObject -> Designator -> DataRef -> Name = 'x'
subroutine f03
integer :: x
@@ -58,7 +58,7 @@ end
!UNPARSE: !$OMP DEPOBJ(x) DESTROY
!UNPARSE: END SUBROUTINE
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct
!PARSE-TREE: | Verbatim
!PARSE-TREE: | OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClause -> Destroy ->
!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPDepobjConstruct -> OmpDirectiveSpecification
!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = depobj
!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | OmpClauseList -> OmpClause -> Destroy ->

View File

@@ -26,7 +26,7 @@ end
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = allocate
!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpClauseList ->
subroutine f01(x)
@@ -52,7 +52,7 @@ end
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = critical
!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpClauseList ->
subroutine f02
@@ -77,7 +77,7 @@ end
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = declare mapper
!PARSE-TREE: | | | OmpArgument -> OmpMapperSpecifier
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpMapperSpecifier
!PARSE-TREE: | | | | Name = 'mymapper'
!PARSE-TREE: | | | | TypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec ->
!PARSE-TREE: | | | | Name = 'v'
@@ -121,7 +121,7 @@ end
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = declare reduction
!PARSE-TREE: | | | OmpArgument -> OmpReductionSpecifier
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier
!PARSE-TREE: | | | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
!PARSE-TREE: | | | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec
!PARSE-TREE: | | | | | Name = 'tt1'
@@ -164,7 +164,7 @@ end
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = declare simd
!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f04'
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f04'
!PARSE-TREE: | | | OmpClauseList ->
!PARSE-TREE: ImplicitPart ->
@@ -189,7 +189,7 @@ end
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = declare target
!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f05'
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f05'
!PARSE-TREE: | | | OmpClauseList ->
!PARSE-TREE: ImplicitPart ->
@@ -216,8 +216,8 @@ end
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = flush
!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'y'
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'y'
!PARSE-TREE: | | | OmpClauseList ->
subroutine f07
@@ -243,5 +243,5 @@ end
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = threadprivate
!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 't'
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 't'
!PARSE-TREE: | | | OmpClauseList ->

View File

@@ -23,7 +23,7 @@ end
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = flush
!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpClauseList -> OmpClause -> SeqCst
!PARSE-TREE: | | | Flags = DeprecatedSyntax
@@ -49,6 +49,6 @@ end
!PARSE-TREE: | | | | | | | bool = 'true'
!PARSE-TREE: | | OmpDirectiveSpecification
!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = flush
!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x'
!PARSE-TREE: | | | OmpClauseList -> OmpClause -> SeqCst
!PARSE-TREE: | | | Flags = None

View File

@@ -26,3 +26,20 @@ subroutine f03
!WARNING: The object parameter in DESTROY clause on DEPOPJ construct is not allowed in OpenMP v5.0, try -fopenmp-version=52
!$omp depobj(obj) destroy(jbo)
end
subroutine f04
integer :: obj1, obj2
!ERROR: The DEPOBJ directive requires a single argument
!$omp depobj(ob1, obj2) destroy
end
subroutine f05
!ERROR: The DEPOBJ directive requires a single argument
!$omp depobj update(in)
end
subroutine f06
integer :: obj
!ERROR: The DEPOBJ construct requires a single clause
!$omp depobj(obj) update(in) destroy
end