-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[flang][OpenMP] Use OmpDirectiveSpecification in DECLARE_TARGET #160573
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…sing The DECLARE_VARIANT directive takes two names separated by a colon as an argument: base-name:variant-name. Define OmpBaseVariantNames to represent this, since no existing argument alternative matches it. However, there is an issue. The syntax "name1:name2" can be the argument to DECLARE_VARIANT (if both names are OmpObjects), but it can also be a reduction-specifier if "name2" is a type. This conflict can only be resolved once we know what the names are, which is after name resolution has visited them. The problem is that name resolution has side-effects that may be (practically) impossible to undo (e.g. creating new symbols, emitting diagnostic messages). To avoid this problem this PR makes the parsing of OmpArgument directive- sensitive: when the directive is DECLARE_VARIANT, don't attempt to parse a reduction-specifier, consider OmpBaseVariantNames instead. Otherwise ignore OmpBaseVariantNames in favor of reduction-specifier.
@llvm/pr-subscribers-flang-semantics @llvm/pr-subscribers-flang-parser Author: Krzysztof Parzyszek (kparzysz) ChangesPatch is 39.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/160573.diff 16 Files Affected:
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 4b8fe6a5b49f0..bf54f970a7d3a 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -41,7 +41,6 @@ struct ConstructId {
MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPDeclarativeAssumes, D::OMPD_assumes);
MAKE_CONSTR_ID(OpenMPDeclareReductionConstruct, D::OMPD_declare_reduction);
-MAKE_CONSTR_ID(OpenMPDeclareTargetConstruct, D::OMPD_declare_target);
MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPRequiresConstruct, D::OMPD_requires);
@@ -97,7 +96,6 @@ struct DirectiveNameScope {
} else if constexpr (std::is_same_v<T, OpenMPDeclarativeAllocate> ||
std::is_same_v<T, OpenMPDeclarativeAssumes> ||
std::is_same_v<T, OpenMPDeclareReductionConstruct> ||
- std::is_same_v<T, OpenMPDeclareTargetConstruct> ||
std::is_same_v<T, OpenMPExecutableAllocate> ||
std::is_same_v<T, OpenMPRequiresConstruct>) {
return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id);
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index be30a95763208..e7593d9875097 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4961,10 +4961,16 @@ struct OmpDeclareTargetSpecifier {
std::variant<OmpDeclareTargetWithList, OmpDeclareTargetWithClause> u;
};
+// Ref: [4.5:110-113], [5.0:180-185], [5.1:210-216], [5.2:206-207],
+// [6.0:346-348]
+//
+// declare-target-directive -> // since 4.5
+// DECLARE_TARGET[(extended-list)] |
+// DECLARE_TARGET clause-list
struct OpenMPDeclareTargetConstruct {
- TUPLE_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct);
+ WRAPPER_CLASS_BOILERPLATE(
+ OpenMPDeclareTargetConstruct, OmpDirectiveSpecification);
CharBlock source;
- std::tuple<Verbatim, OmpDeclareTargetSpecifier> t;
};
// OMP v5.2: 5.8.8
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index d2e865b3e1d0c..1cb3335abbd06 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -761,19 +761,17 @@ static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr(
static void getDeclareTargetInfo(
lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
- const parser::OpenMPDeclareTargetConstruct &declareTargetConstruct,
+ const parser::OpenMPDeclareTargetConstruct &construct,
mlir::omp::DeclareTargetOperands &clauseOps,
llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &symbolAndClause) {
- const auto &spec =
- std::get<parser::OmpDeclareTargetSpecifier>(declareTargetConstruct.t);
- if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
- ObjectList objects{makeObjects(*objectList, semaCtx)};
+
+ if (!construct.v.Arguments().v.empty()) {
+ ObjectList objects{makeObjects(construct.v.Arguments(), semaCtx)};
// Case: declare target(func, var1, var2)
gatherFuncAndVarSyms(objects, mlir::omp::DeclareTargetCaptureClause::to,
symbolAndClause, /*automap=*/false);
- } else if (const auto *clauseList{
- parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
- List<Clause> clauses = makeClauses(*clauseList, semaCtx);
+ } else {
+ List<Clause> clauses = makeClauses(construct.v.Clauses(), semaCtx);
if (clauses.empty()) {
Fortran::lower::pft::FunctionLikeUnit *owningProc =
eval.getOwningProcedure();
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 0085576292ff5..bd080386c0aea 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1773,23 +1773,11 @@ TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
IsDirective(llvm::omp::Directive::OMPD_declare_reduction)) >=
Parser<OmpDirectiveSpecification>{})))
-// declare-target with list
-TYPE_PARSER(sourced(construct<OmpDeclareTargetWithList>(
- parenthesized(Parser<OmpObjectList>{}))))
-
-// declare-target with clause
-TYPE_PARSER(
- sourced(construct<OmpDeclareTargetWithClause>(Parser<OmpClauseList>{})))
-
-// declare-target-specifier
-TYPE_PARSER(
- construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithList>{}) ||
- construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithClause>{}))
-
// 2.10.6 Declare Target Construct
TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
- verbatim("DECLARE TARGET"_tok) || verbatim("DECLARE_TARGET"_tok),
- Parser<OmpDeclareTargetSpecifier>{})))
+ predicated(Parser<OmpDirectiveName>{},
+ IsDirective(llvm::omp::Directive::OMPD_declare_target)) >=
+ Parser<OmpDirectiveSpecification>{})))
static OmpMapperSpecifier ConstructOmpMapperSpecifier(
std::optional<Name> &&mapperName, TypeSpec &&typeSpec, Name &&varName) {
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index c9774dd137d2b..be166bcb743ba 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2582,8 +2582,8 @@ class UnparseVisitor {
}
void Unparse(const OpenMPDeclareTargetConstruct &x) {
BeginOpenMP();
- Word("!$OMP DECLARE TARGET ");
- Walk(std::get<parser::OmpDeclareTargetSpecifier>(x.t));
+ Word("!$OMP ");
+ Walk(x.v);
Put("\n");
EndOpenMP();
}
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index cf89d305e3cb2..05ff541657b1a 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -624,11 +624,6 @@ template <typename Checker> struct DirectiveSpellingVisitor {
checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_assumes);
return false;
}
- bool Pre(const parser::OpenMPDeclareTargetConstruct &x) {
- checker_(
- std::get<parser::Verbatim>(x.t).source, Directive::OMPD_declare_target);
- return false;
- }
bool Pre(const parser::OpenMPGroupprivate &x) {
checker_(x.v.DirName().source, Directive::OMPD_groupprivate);
return false;
@@ -1615,38 +1610,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
}
}
-void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithClause &x) {
- SetClauseSets(llvm::omp::Directive::OMPD_declare_target);
-}
-
-void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) {
- if (x.v.v.size() > 0) {
- const parser::OmpClause *enterClause =
- FindClause(llvm::omp::Clause::OMPC_enter);
- const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to);
- const parser::OmpClause *linkClause =
- FindClause(llvm::omp::Clause::OMPC_link);
- const parser::OmpClause *indirectClause =
- FindClause(llvm::omp::Clause::OMPC_indirect);
- if (!enterClause && !toClause && !linkClause) {
- context_.Say(x.source,
- "If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause"_err_en_US);
- }
- if (indirectClause && !enterClause) {
- context_.Say(x.source,
- "The INDIRECT clause cannot be used without the ENTER clause with the DECLARE TARGET directive."_err_en_US);
- }
- unsigned version{context_.langOptions().OpenMPVersion};
- if (toClause && version >= 52) {
- context_.Warn(common::UsageWarning::OpenMPUsage, toClause->source,
- "The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
- }
- if (indirectClause) {
- CheckAllowedClause(llvm::omp::Clause::OMPC_indirect);
- }
- }
-}
-
void OmpStructureChecker::Enter(const parser::OpenMPDeclareMapperConstruct &x) {
const parser::OmpDirectiveName &dirName{x.v.DirName()};
PushContextAndClauseSets(dirName.source, dirName.v);
@@ -1698,42 +1661,6 @@ void OmpStructureChecker::Leave(
dirContext_.pop_back();
}
-void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) {
- const auto &dir{std::get<parser::Verbatim>(x.t)};
- PushContext(dir.source, llvm::omp::Directive::OMPD_declare_target);
-}
-
-void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithList &x) {
- SymbolSourceMap symbols;
- GetSymbolsInObjectList(x.v, symbols);
- for (auto &[symbol, source] : symbols) {
- const GenericDetails *genericDetails = symbol->detailsIf<GenericDetails>();
- if (genericDetails) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be a generic name."_err_en_US,
- symbol->name());
- genericDetails->specific();
- }
- if (IsProcedurePointer(*symbol)) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be a procedure pointer."_err_en_US,
- symbol->name());
- }
- const SubprogramDetails *entryDetails =
- symbol->detailsIf<SubprogramDetails>();
- if (entryDetails && entryDetails->entryScope()) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be an entry name."_err_en_US,
- symbol->name());
- }
- if (IsStmtFunction(*symbol)) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be a statement function."_err_en_US,
- symbol->name());
- }
- }
-}
-
void OmpStructureChecker::CheckSymbolName(
const parser::CharBlock &source, const parser::OmpObject &object) {
common::visit(
@@ -1766,62 +1693,138 @@ void OmpStructureChecker::CheckSymbolNames(
}
}
+void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) {
+ const parser::OmpDirectiveName &dirName{x.v.DirName()};
+ PushContext(dirName.source, dirName.v);
+
+ // Check if arguments are extended-list-items.
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ const Symbol *symbol{GetArgumentSymbol(arg)};
+ if (!symbol) {
+ context_.Say(arg.source,
+ "An argument to the DECLARE TARGET directive should be an extended-list-item"_err_en_US);
+ continue;
+ }
+ const GenericDetails *genericDetails = symbol->detailsIf<GenericDetails>();
+ if (genericDetails) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be a generic name."_err_en_US,
+ symbol->name());
+ genericDetails->specific();
+ }
+ if (IsProcedurePointer(*symbol)) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be a procedure pointer."_err_en_US,
+ symbol->name());
+ }
+ const SubprogramDetails *entryDetails =
+ symbol->detailsIf<SubprogramDetails>();
+ if (entryDetails && entryDetails->entryScope()) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be an entry name."_err_en_US,
+ symbol->name());
+ }
+ if (IsStmtFunction(*symbol)) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be a statement function."_err_en_US,
+ symbol->name());
+ }
+ }
+
+ // Check if there are arguments or clauses, but not both.
+ if (!x.v.Clauses().v.empty()) {
+ if (!x.v.Arguments().v.empty()) {
+ context_.Say(x.source,
+ "DECLARE TARGET directive can have argument or clauses, but not both"_err_en_US);
+ }
+ SetClauseSets(llvm::omp::Directive::OMPD_declare_target);
+ }
+}
+
void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
- const auto &dir{std::get<parser::Verbatim>(x.t)};
- const auto &spec{std::get<parser::OmpDeclareTargetSpecifier>(x.t)};
+ const parser::OmpDirectiveName &dirName{x.v.DirName()};
+
// Handle both forms of DECLARE TARGET.
// - Extended list: It behaves as if there was an ENTER/TO clause with the
// list of objects as argument. It accepts no explicit clauses.
// - With clauses.
- if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
- deviceConstructFound_ = true;
- CheckSymbolNames(dir.source, *objectList);
- CheckVarIsNotPartOfAnotherVar(dir.source, *objectList);
- CheckThreadprivateOrDeclareTargetVar(*objectList);
- } else if (const auto *clauseList{
- parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
- bool toClauseFound{false}, deviceTypeClauseFound{false},
- enterClauseFound{false};
- for (const auto &clause : clauseList->v) {
- common::visit(
- common::visitors{
- [&](const parser::OmpClause::To &toClause) {
- toClauseFound = true;
- auto &objList{std::get<parser::OmpObjectList>(toClause.v.t)};
- CheckSymbolNames(dir.source, objList);
- CheckVarIsNotPartOfAnotherVar(dir.source, objList);
- CheckThreadprivateOrDeclareTargetVar(objList);
- },
- [&](const parser::OmpClause::Link &linkClause) {
- CheckSymbolNames(dir.source, linkClause.v);
- CheckVarIsNotPartOfAnotherVar(dir.source, linkClause.v);
- CheckThreadprivateOrDeclareTargetVar(linkClause.v);
- },
- [&](const parser::OmpClause::Enter &enterClause) {
- enterClauseFound = true;
- auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)};
- CheckSymbolNames(dir.source, objList);
- CheckVarIsNotPartOfAnotherVar(dir.source, objList);
- CheckThreadprivateOrDeclareTargetVar(objList);
- },
- [&](const parser::OmpClause::DeviceType &deviceTypeClause) {
- deviceTypeClauseFound = true;
- if (deviceTypeClause.v.v !=
- parser::OmpDeviceTypeClause::DeviceTypeDescription::Host) {
- // Function / subroutine explicitly marked as runnable by the
- // target device.
- deviceConstructFound_ = true;
- }
- },
- [&](const auto &) {},
- },
- clause.u);
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ if (auto *object{GetArgumentObject(arg)}) {
+ deviceConstructFound_ = true;
+ CheckSymbolName(dirName.source, *object);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, *object);
+ CheckThreadprivateOrDeclareTargetVar(*object);
+ }
+ }
- if ((toClauseFound || enterClauseFound) && !deviceTypeClauseFound) {
- deviceConstructFound_ = true;
- }
+ if (!x.v.Clauses().v.empty()) {
+ const parser::OmpClause *enterClause =
+ FindClause(llvm::omp::Clause::OMPC_enter);
+ const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to);
+ const parser::OmpClause *linkClause =
+ FindClause(llvm::omp::Clause::OMPC_link);
+ const parser::OmpClause *indirectClause =
+ FindClause(llvm::omp::Clause::OMPC_indirect);
+ if (!enterClause && !toClause && !linkClause) {
+ context_.Say(x.source,
+ "If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause"_err_en_US);
+ }
+ if (indirectClause && !enterClause) {
+ context_.Say(x.source,
+ "The INDIRECT clause cannot be used without the ENTER clause with the DECLARE TARGET directive."_err_en_US);
+ }
+ unsigned version{context_.langOptions().OpenMPVersion};
+ if (toClause && version >= 52) {
+ context_.Warn(common::UsageWarning::OpenMPUsage, toClause->source,
+ "The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
+ }
+ if (indirectClause) {
+ CheckAllowedClause(llvm::omp::Clause::OMPC_indirect);
}
}
+
+ bool toClauseFound{false}, deviceTypeClauseFound{false},
+ enterClauseFound{false};
+ for (const parser::OmpClause &clause : x.v.Clauses().v) {
+ common::visit(
+ common::visitors{
+ [&](const parser::OmpClause::To &toClause) {
+ toClauseFound = true;
+ auto &objList{std::get<parser::OmpObjectList>(toClause.v.t)};
+ CheckSymbolNames(dirName.source, objList);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
+ CheckThreadprivateOrDeclareTargetVar(objList);
+ },
+ [&](const parser::OmpClause::Link &linkClause) {
+ CheckSymbolNames(dirName.source, linkClause.v);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, linkClause.v);
+ CheckThreadprivateOrDeclareTargetVar(linkClause.v);
+ },
+ [&](const parser::OmpClause::Enter &enterClause) {
+ enterClauseFound = true;
+ auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)};
+ CheckSymbolNames(dirName.source, objList);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
+ CheckThreadprivateOrDeclareTargetVar(objList);
+ },
+ [&](const parser::OmpClause::DeviceType &deviceTypeClause) {
+ deviceTypeClauseFound = true;
+ if (deviceTypeClause.v.v !=
+ parser::OmpDeviceTypeClause::DeviceTypeDescription::Host) {
+ // Function / subroutine explicitly marked as runnable by the
+ // target device.
+ deviceConstructFound_ = true;
+ }
+ },
+ [&](const auto &) {},
+ },
+ clause.u);
+
+ if ((toClauseFound || enterClauseFound) && !deviceTypeClauseFound) {
+ deviceConstructFound_ = true;
+ }
+ }
+
dirContext_.pop_back();
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 176f6568814c5..193784555a887 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -113,9 +113,6 @@ class OmpStructureChecker
void Leave(const parser::OpenMPDeclareTargetConstruct &);
void Enter(const parser::OpenMPDepobjConstruct &);
void Leave(const parser::OpenMPDepobjConstruct &);
- void Enter(const parser::OmpDeclareTargetWithList &);
- void Enter(const parser::OmpDeclareTargetWithClause &);
- void Leave(const parser::OmpDeclareTargetWithClause &);
void Enter(const parser::OpenMPDispatchConstruct &);
void Leave(const parser::OpenMPDispatchConstruct &);
void Enter(const parser::OmpErrorDirective &);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 218e3e7266ca9..7ef211c8b428c 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2324,22 +2324,17 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPCriticalConstruct &x) {
bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareTargetConstruct &x) {
PushContext(x.source, llvm::omp::Directive::OMPD_declare_target);
- const auto &spec{std::get<parser::OmpDeclareTargetSpecifier>(x.t)};
- if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
- ResolveOmpObjectList(*objectList, Symbol::Flag::OmpDeclareTarget);
- } else if (const auto *clauseList{
- parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
- for (const auto &clause : clauseList->v) {
- if (const auto *toClause{std::get_if<parser::OmpClause::To>(&clause.u)}) {
- auto &objList{std::get<parser::OmpObjectList>(toClause->v.t)};
- ResolveOmpObjectList(objList, Symbol::Flag::OmpDeclareTarget);
- } else if (const auto *linkClause{
- std::get_if<parser::OmpClause::Link>(&clause.u)}) {
- ResolveOmpObjectList(linkClause->v, Symbol::Flag::OmpDeclareTarget);
- } else if (const auto *enterClause{
- std::get_if<parser::OmpClause::Enter>(&clause.u)}) {
- ResolveOmpObjectList(std::get<parser::OmpObjectList>(enterClause->v.t),
- Symbol::Flag::OmpDeclareTarget);
+
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ if (auto *object{omp::GetArgumentObject(arg)}) {
+ ResolveOmpObject(*object, Symbol::Flag::OmpDeclareTarget);
+ }
+ }
+
+ fo...
[truncated]
|
@llvm/pr-subscribers-flang-openmp Author: Krzysztof Parzyszek (kparzysz) ChangesPatch is 39.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/160573.diff 16 Files Affected:
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 4b8fe6a5b49f0..bf54f970a7d3a 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -41,7 +41,6 @@ struct ConstructId {
MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPDeclarativeAssumes, D::OMPD_assumes);
MAKE_CONSTR_ID(OpenMPDeclareReductionConstruct, D::OMPD_declare_reduction);
-MAKE_CONSTR_ID(OpenMPDeclareTargetConstruct, D::OMPD_declare_target);
MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPRequiresConstruct, D::OMPD_requires);
@@ -97,7 +96,6 @@ struct DirectiveNameScope {
} else if constexpr (std::is_same_v<T, OpenMPDeclarativeAllocate> ||
std::is_same_v<T, OpenMPDeclarativeAssumes> ||
std::is_same_v<T, OpenMPDeclareReductionConstruct> ||
- std::is_same_v<T, OpenMPDeclareTargetConstruct> ||
std::is_same_v<T, OpenMPExecutableAllocate> ||
std::is_same_v<T, OpenMPRequiresConstruct>) {
return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id);
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index be30a95763208..e7593d9875097 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4961,10 +4961,16 @@ struct OmpDeclareTargetSpecifier {
std::variant<OmpDeclareTargetWithList, OmpDeclareTargetWithClause> u;
};
+// Ref: [4.5:110-113], [5.0:180-185], [5.1:210-216], [5.2:206-207],
+// [6.0:346-348]
+//
+// declare-target-directive -> // since 4.5
+// DECLARE_TARGET[(extended-list)] |
+// DECLARE_TARGET clause-list
struct OpenMPDeclareTargetConstruct {
- TUPLE_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct);
+ WRAPPER_CLASS_BOILERPLATE(
+ OpenMPDeclareTargetConstruct, OmpDirectiveSpecification);
CharBlock source;
- std::tuple<Verbatim, OmpDeclareTargetSpecifier> t;
};
// OMP v5.2: 5.8.8
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index d2e865b3e1d0c..1cb3335abbd06 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -761,19 +761,17 @@ static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr(
static void getDeclareTargetInfo(
lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
- const parser::OpenMPDeclareTargetConstruct &declareTargetConstruct,
+ const parser::OpenMPDeclareTargetConstruct &construct,
mlir::omp::DeclareTargetOperands &clauseOps,
llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &symbolAndClause) {
- const auto &spec =
- std::get<parser::OmpDeclareTargetSpecifier>(declareTargetConstruct.t);
- if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
- ObjectList objects{makeObjects(*objectList, semaCtx)};
+
+ if (!construct.v.Arguments().v.empty()) {
+ ObjectList objects{makeObjects(construct.v.Arguments(), semaCtx)};
// Case: declare target(func, var1, var2)
gatherFuncAndVarSyms(objects, mlir::omp::DeclareTargetCaptureClause::to,
symbolAndClause, /*automap=*/false);
- } else if (const auto *clauseList{
- parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
- List<Clause> clauses = makeClauses(*clauseList, semaCtx);
+ } else {
+ List<Clause> clauses = makeClauses(construct.v.Clauses(), semaCtx);
if (clauses.empty()) {
Fortran::lower::pft::FunctionLikeUnit *owningProc =
eval.getOwningProcedure();
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 0085576292ff5..bd080386c0aea 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1773,23 +1773,11 @@ TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
IsDirective(llvm::omp::Directive::OMPD_declare_reduction)) >=
Parser<OmpDirectiveSpecification>{})))
-// declare-target with list
-TYPE_PARSER(sourced(construct<OmpDeclareTargetWithList>(
- parenthesized(Parser<OmpObjectList>{}))))
-
-// declare-target with clause
-TYPE_PARSER(
- sourced(construct<OmpDeclareTargetWithClause>(Parser<OmpClauseList>{})))
-
-// declare-target-specifier
-TYPE_PARSER(
- construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithList>{}) ||
- construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithClause>{}))
-
// 2.10.6 Declare Target Construct
TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
- verbatim("DECLARE TARGET"_tok) || verbatim("DECLARE_TARGET"_tok),
- Parser<OmpDeclareTargetSpecifier>{})))
+ predicated(Parser<OmpDirectiveName>{},
+ IsDirective(llvm::omp::Directive::OMPD_declare_target)) >=
+ Parser<OmpDirectiveSpecification>{})))
static OmpMapperSpecifier ConstructOmpMapperSpecifier(
std::optional<Name> &&mapperName, TypeSpec &&typeSpec, Name &&varName) {
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index c9774dd137d2b..be166bcb743ba 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2582,8 +2582,8 @@ class UnparseVisitor {
}
void Unparse(const OpenMPDeclareTargetConstruct &x) {
BeginOpenMP();
- Word("!$OMP DECLARE TARGET ");
- Walk(std::get<parser::OmpDeclareTargetSpecifier>(x.t));
+ Word("!$OMP ");
+ Walk(x.v);
Put("\n");
EndOpenMP();
}
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index cf89d305e3cb2..05ff541657b1a 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -624,11 +624,6 @@ template <typename Checker> struct DirectiveSpellingVisitor {
checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_assumes);
return false;
}
- bool Pre(const parser::OpenMPDeclareTargetConstruct &x) {
- checker_(
- std::get<parser::Verbatim>(x.t).source, Directive::OMPD_declare_target);
- return false;
- }
bool Pre(const parser::OpenMPGroupprivate &x) {
checker_(x.v.DirName().source, Directive::OMPD_groupprivate);
return false;
@@ -1615,38 +1610,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
}
}
-void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithClause &x) {
- SetClauseSets(llvm::omp::Directive::OMPD_declare_target);
-}
-
-void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) {
- if (x.v.v.size() > 0) {
- const parser::OmpClause *enterClause =
- FindClause(llvm::omp::Clause::OMPC_enter);
- const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to);
- const parser::OmpClause *linkClause =
- FindClause(llvm::omp::Clause::OMPC_link);
- const parser::OmpClause *indirectClause =
- FindClause(llvm::omp::Clause::OMPC_indirect);
- if (!enterClause && !toClause && !linkClause) {
- context_.Say(x.source,
- "If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause"_err_en_US);
- }
- if (indirectClause && !enterClause) {
- context_.Say(x.source,
- "The INDIRECT clause cannot be used without the ENTER clause with the DECLARE TARGET directive."_err_en_US);
- }
- unsigned version{context_.langOptions().OpenMPVersion};
- if (toClause && version >= 52) {
- context_.Warn(common::UsageWarning::OpenMPUsage, toClause->source,
- "The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
- }
- if (indirectClause) {
- CheckAllowedClause(llvm::omp::Clause::OMPC_indirect);
- }
- }
-}
-
void OmpStructureChecker::Enter(const parser::OpenMPDeclareMapperConstruct &x) {
const parser::OmpDirectiveName &dirName{x.v.DirName()};
PushContextAndClauseSets(dirName.source, dirName.v);
@@ -1698,42 +1661,6 @@ void OmpStructureChecker::Leave(
dirContext_.pop_back();
}
-void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) {
- const auto &dir{std::get<parser::Verbatim>(x.t)};
- PushContext(dir.source, llvm::omp::Directive::OMPD_declare_target);
-}
-
-void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithList &x) {
- SymbolSourceMap symbols;
- GetSymbolsInObjectList(x.v, symbols);
- for (auto &[symbol, source] : symbols) {
- const GenericDetails *genericDetails = symbol->detailsIf<GenericDetails>();
- if (genericDetails) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be a generic name."_err_en_US,
- symbol->name());
- genericDetails->specific();
- }
- if (IsProcedurePointer(*symbol)) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be a procedure pointer."_err_en_US,
- symbol->name());
- }
- const SubprogramDetails *entryDetails =
- symbol->detailsIf<SubprogramDetails>();
- if (entryDetails && entryDetails->entryScope()) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be an entry name."_err_en_US,
- symbol->name());
- }
- if (IsStmtFunction(*symbol)) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be a statement function."_err_en_US,
- symbol->name());
- }
- }
-}
-
void OmpStructureChecker::CheckSymbolName(
const parser::CharBlock &source, const parser::OmpObject &object) {
common::visit(
@@ -1766,62 +1693,138 @@ void OmpStructureChecker::CheckSymbolNames(
}
}
+void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) {
+ const parser::OmpDirectiveName &dirName{x.v.DirName()};
+ PushContext(dirName.source, dirName.v);
+
+ // Check if arguments are extended-list-items.
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ const Symbol *symbol{GetArgumentSymbol(arg)};
+ if (!symbol) {
+ context_.Say(arg.source,
+ "An argument to the DECLARE TARGET directive should be an extended-list-item"_err_en_US);
+ continue;
+ }
+ const GenericDetails *genericDetails = symbol->detailsIf<GenericDetails>();
+ if (genericDetails) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be a generic name."_err_en_US,
+ symbol->name());
+ genericDetails->specific();
+ }
+ if (IsProcedurePointer(*symbol)) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be a procedure pointer."_err_en_US,
+ symbol->name());
+ }
+ const SubprogramDetails *entryDetails =
+ symbol->detailsIf<SubprogramDetails>();
+ if (entryDetails && entryDetails->entryScope()) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be an entry name."_err_en_US,
+ symbol->name());
+ }
+ if (IsStmtFunction(*symbol)) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be a statement function."_err_en_US,
+ symbol->name());
+ }
+ }
+
+ // Check if there are arguments or clauses, but not both.
+ if (!x.v.Clauses().v.empty()) {
+ if (!x.v.Arguments().v.empty()) {
+ context_.Say(x.source,
+ "DECLARE TARGET directive can have argument or clauses, but not both"_err_en_US);
+ }
+ SetClauseSets(llvm::omp::Directive::OMPD_declare_target);
+ }
+}
+
void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
- const auto &dir{std::get<parser::Verbatim>(x.t)};
- const auto &spec{std::get<parser::OmpDeclareTargetSpecifier>(x.t)};
+ const parser::OmpDirectiveName &dirName{x.v.DirName()};
+
// Handle both forms of DECLARE TARGET.
// - Extended list: It behaves as if there was an ENTER/TO clause with the
// list of objects as argument. It accepts no explicit clauses.
// - With clauses.
- if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
- deviceConstructFound_ = true;
- CheckSymbolNames(dir.source, *objectList);
- CheckVarIsNotPartOfAnotherVar(dir.source, *objectList);
- CheckThreadprivateOrDeclareTargetVar(*objectList);
- } else if (const auto *clauseList{
- parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
- bool toClauseFound{false}, deviceTypeClauseFound{false},
- enterClauseFound{false};
- for (const auto &clause : clauseList->v) {
- common::visit(
- common::visitors{
- [&](const parser::OmpClause::To &toClause) {
- toClauseFound = true;
- auto &objList{std::get<parser::OmpObjectList>(toClause.v.t)};
- CheckSymbolNames(dir.source, objList);
- CheckVarIsNotPartOfAnotherVar(dir.source, objList);
- CheckThreadprivateOrDeclareTargetVar(objList);
- },
- [&](const parser::OmpClause::Link &linkClause) {
- CheckSymbolNames(dir.source, linkClause.v);
- CheckVarIsNotPartOfAnotherVar(dir.source, linkClause.v);
- CheckThreadprivateOrDeclareTargetVar(linkClause.v);
- },
- [&](const parser::OmpClause::Enter &enterClause) {
- enterClauseFound = true;
- auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)};
- CheckSymbolNames(dir.source, objList);
- CheckVarIsNotPartOfAnotherVar(dir.source, objList);
- CheckThreadprivateOrDeclareTargetVar(objList);
- },
- [&](const parser::OmpClause::DeviceType &deviceTypeClause) {
- deviceTypeClauseFound = true;
- if (deviceTypeClause.v.v !=
- parser::OmpDeviceTypeClause::DeviceTypeDescription::Host) {
- // Function / subroutine explicitly marked as runnable by the
- // target device.
- deviceConstructFound_ = true;
- }
- },
- [&](const auto &) {},
- },
- clause.u);
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ if (auto *object{GetArgumentObject(arg)}) {
+ deviceConstructFound_ = true;
+ CheckSymbolName(dirName.source, *object);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, *object);
+ CheckThreadprivateOrDeclareTargetVar(*object);
+ }
+ }
- if ((toClauseFound || enterClauseFound) && !deviceTypeClauseFound) {
- deviceConstructFound_ = true;
- }
+ if (!x.v.Clauses().v.empty()) {
+ const parser::OmpClause *enterClause =
+ FindClause(llvm::omp::Clause::OMPC_enter);
+ const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to);
+ const parser::OmpClause *linkClause =
+ FindClause(llvm::omp::Clause::OMPC_link);
+ const parser::OmpClause *indirectClause =
+ FindClause(llvm::omp::Clause::OMPC_indirect);
+ if (!enterClause && !toClause && !linkClause) {
+ context_.Say(x.source,
+ "If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause"_err_en_US);
+ }
+ if (indirectClause && !enterClause) {
+ context_.Say(x.source,
+ "The INDIRECT clause cannot be used without the ENTER clause with the DECLARE TARGET directive."_err_en_US);
+ }
+ unsigned version{context_.langOptions().OpenMPVersion};
+ if (toClause && version >= 52) {
+ context_.Warn(common::UsageWarning::OpenMPUsage, toClause->source,
+ "The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
+ }
+ if (indirectClause) {
+ CheckAllowedClause(llvm::omp::Clause::OMPC_indirect);
}
}
+
+ bool toClauseFound{false}, deviceTypeClauseFound{false},
+ enterClauseFound{false};
+ for (const parser::OmpClause &clause : x.v.Clauses().v) {
+ common::visit(
+ common::visitors{
+ [&](const parser::OmpClause::To &toClause) {
+ toClauseFound = true;
+ auto &objList{std::get<parser::OmpObjectList>(toClause.v.t)};
+ CheckSymbolNames(dirName.source, objList);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
+ CheckThreadprivateOrDeclareTargetVar(objList);
+ },
+ [&](const parser::OmpClause::Link &linkClause) {
+ CheckSymbolNames(dirName.source, linkClause.v);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, linkClause.v);
+ CheckThreadprivateOrDeclareTargetVar(linkClause.v);
+ },
+ [&](const parser::OmpClause::Enter &enterClause) {
+ enterClauseFound = true;
+ auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)};
+ CheckSymbolNames(dirName.source, objList);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
+ CheckThreadprivateOrDeclareTargetVar(objList);
+ },
+ [&](const parser::OmpClause::DeviceType &deviceTypeClause) {
+ deviceTypeClauseFound = true;
+ if (deviceTypeClause.v.v !=
+ parser::OmpDeviceTypeClause::DeviceTypeDescription::Host) {
+ // Function / subroutine explicitly marked as runnable by the
+ // target device.
+ deviceConstructFound_ = true;
+ }
+ },
+ [&](const auto &) {},
+ },
+ clause.u);
+
+ if ((toClauseFound || enterClauseFound) && !deviceTypeClauseFound) {
+ deviceConstructFound_ = true;
+ }
+ }
+
dirContext_.pop_back();
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 176f6568814c5..193784555a887 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -113,9 +113,6 @@ class OmpStructureChecker
void Leave(const parser::OpenMPDeclareTargetConstruct &);
void Enter(const parser::OpenMPDepobjConstruct &);
void Leave(const parser::OpenMPDepobjConstruct &);
- void Enter(const parser::OmpDeclareTargetWithList &);
- void Enter(const parser::OmpDeclareTargetWithClause &);
- void Leave(const parser::OmpDeclareTargetWithClause &);
void Enter(const parser::OpenMPDispatchConstruct &);
void Leave(const parser::OpenMPDispatchConstruct &);
void Enter(const parser::OmpErrorDirective &);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 218e3e7266ca9..7ef211c8b428c 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2324,22 +2324,17 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPCriticalConstruct &x) {
bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareTargetConstruct &x) {
PushContext(x.source, llvm::omp::Directive::OMPD_declare_target);
- const auto &spec{std::get<parser::OmpDeclareTargetSpecifier>(x.t)};
- if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
- ResolveOmpObjectList(*objectList, Symbol::Flag::OmpDeclareTarget);
- } else if (const auto *clauseList{
- parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
- for (const auto &clause : clauseList->v) {
- if (const auto *toClause{std::get_if<parser::OmpClause::To>(&clause.u)}) {
- auto &objList{std::get<parser::OmpObjectList>(toClause->v.t)};
- ResolveOmpObjectList(objList, Symbol::Flag::OmpDeclareTarget);
- } else if (const auto *linkClause{
- std::get_if<parser::OmpClause::Link>(&clause.u)}) {
- ResolveOmpObjectList(linkClause->v, Symbol::Flag::OmpDeclareTarget);
- } else if (const auto *enterClause{
- std::get_if<parser::OmpClause::Enter>(&clause.u)}) {
- ResolveOmpObjectList(std::get<parser::OmpObjectList>(enterClause->v.t),
- Symbol::Flag::OmpDeclareTarget);
+
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ if (auto *object{omp::GetArgumentObject(arg)}) {
+ ResolveOmpObject(*object, Symbol::Flag::OmpDeclareTarget);
+ }
+ }
+
+ fo...
[truncated]
|
@llvm/pr-subscribers-flang-fir-hlfir Author: Krzysztof Parzyszek (kparzysz) ChangesPatch is 39.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/160573.diff 16 Files Affected:
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 4b8fe6a5b49f0..bf54f970a7d3a 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -41,7 +41,6 @@ struct ConstructId {
MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPDeclarativeAssumes, D::OMPD_assumes);
MAKE_CONSTR_ID(OpenMPDeclareReductionConstruct, D::OMPD_declare_reduction);
-MAKE_CONSTR_ID(OpenMPDeclareTargetConstruct, D::OMPD_declare_target);
MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPRequiresConstruct, D::OMPD_requires);
@@ -97,7 +96,6 @@ struct DirectiveNameScope {
} else if constexpr (std::is_same_v<T, OpenMPDeclarativeAllocate> ||
std::is_same_v<T, OpenMPDeclarativeAssumes> ||
std::is_same_v<T, OpenMPDeclareReductionConstruct> ||
- std::is_same_v<T, OpenMPDeclareTargetConstruct> ||
std::is_same_v<T, OpenMPExecutableAllocate> ||
std::is_same_v<T, OpenMPRequiresConstruct>) {
return MakeName(std::get<Verbatim>(x.t).source, ConstructId<T>::id);
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index be30a95763208..e7593d9875097 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4961,10 +4961,16 @@ struct OmpDeclareTargetSpecifier {
std::variant<OmpDeclareTargetWithList, OmpDeclareTargetWithClause> u;
};
+// Ref: [4.5:110-113], [5.0:180-185], [5.1:210-216], [5.2:206-207],
+// [6.0:346-348]
+//
+// declare-target-directive -> // since 4.5
+// DECLARE_TARGET[(extended-list)] |
+// DECLARE_TARGET clause-list
struct OpenMPDeclareTargetConstruct {
- TUPLE_CLASS_BOILERPLATE(OpenMPDeclareTargetConstruct);
+ WRAPPER_CLASS_BOILERPLATE(
+ OpenMPDeclareTargetConstruct, OmpDirectiveSpecification);
CharBlock source;
- std::tuple<Verbatim, OmpDeclareTargetSpecifier> t;
};
// OMP v5.2: 5.8.8
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index d2e865b3e1d0c..1cb3335abbd06 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -761,19 +761,17 @@ static void promoteNonCPtrUseDevicePtrArgsToUseDeviceAddr(
static void getDeclareTargetInfo(
lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
- const parser::OpenMPDeclareTargetConstruct &declareTargetConstruct,
+ const parser::OpenMPDeclareTargetConstruct &construct,
mlir::omp::DeclareTargetOperands &clauseOps,
llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &symbolAndClause) {
- const auto &spec =
- std::get<parser::OmpDeclareTargetSpecifier>(declareTargetConstruct.t);
- if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
- ObjectList objects{makeObjects(*objectList, semaCtx)};
+
+ if (!construct.v.Arguments().v.empty()) {
+ ObjectList objects{makeObjects(construct.v.Arguments(), semaCtx)};
// Case: declare target(func, var1, var2)
gatherFuncAndVarSyms(objects, mlir::omp::DeclareTargetCaptureClause::to,
symbolAndClause, /*automap=*/false);
- } else if (const auto *clauseList{
- parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
- List<Clause> clauses = makeClauses(*clauseList, semaCtx);
+ } else {
+ List<Clause> clauses = makeClauses(construct.v.Clauses(), semaCtx);
if (clauses.empty()) {
Fortran::lower::pft::FunctionLikeUnit *owningProc =
eval.getOwningProcedure();
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 0085576292ff5..bd080386c0aea 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1773,23 +1773,11 @@ TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
IsDirective(llvm::omp::Directive::OMPD_declare_reduction)) >=
Parser<OmpDirectiveSpecification>{})))
-// declare-target with list
-TYPE_PARSER(sourced(construct<OmpDeclareTargetWithList>(
- parenthesized(Parser<OmpObjectList>{}))))
-
-// declare-target with clause
-TYPE_PARSER(
- sourced(construct<OmpDeclareTargetWithClause>(Parser<OmpClauseList>{})))
-
-// declare-target-specifier
-TYPE_PARSER(
- construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithList>{}) ||
- construct<OmpDeclareTargetSpecifier>(Parser<OmpDeclareTargetWithClause>{}))
-
// 2.10.6 Declare Target Construct
TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>(
- verbatim("DECLARE TARGET"_tok) || verbatim("DECLARE_TARGET"_tok),
- Parser<OmpDeclareTargetSpecifier>{})))
+ predicated(Parser<OmpDirectiveName>{},
+ IsDirective(llvm::omp::Directive::OMPD_declare_target)) >=
+ Parser<OmpDirectiveSpecification>{})))
static OmpMapperSpecifier ConstructOmpMapperSpecifier(
std::optional<Name> &&mapperName, TypeSpec &&typeSpec, Name &&varName) {
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index c9774dd137d2b..be166bcb743ba 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2582,8 +2582,8 @@ class UnparseVisitor {
}
void Unparse(const OpenMPDeclareTargetConstruct &x) {
BeginOpenMP();
- Word("!$OMP DECLARE TARGET ");
- Walk(std::get<parser::OmpDeclareTargetSpecifier>(x.t));
+ Word("!$OMP ");
+ Walk(x.v);
Put("\n");
EndOpenMP();
}
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index cf89d305e3cb2..05ff541657b1a 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -624,11 +624,6 @@ template <typename Checker> struct DirectiveSpellingVisitor {
checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_assumes);
return false;
}
- bool Pre(const parser::OpenMPDeclareTargetConstruct &x) {
- checker_(
- std::get<parser::Verbatim>(x.t).source, Directive::OMPD_declare_target);
- return false;
- }
bool Pre(const parser::OpenMPGroupprivate &x) {
checker_(x.v.DirName().source, Directive::OMPD_groupprivate);
return false;
@@ -1615,38 +1610,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
}
}
-void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithClause &x) {
- SetClauseSets(llvm::omp::Directive::OMPD_declare_target);
-}
-
-void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) {
- if (x.v.v.size() > 0) {
- const parser::OmpClause *enterClause =
- FindClause(llvm::omp::Clause::OMPC_enter);
- const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to);
- const parser::OmpClause *linkClause =
- FindClause(llvm::omp::Clause::OMPC_link);
- const parser::OmpClause *indirectClause =
- FindClause(llvm::omp::Clause::OMPC_indirect);
- if (!enterClause && !toClause && !linkClause) {
- context_.Say(x.source,
- "If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause"_err_en_US);
- }
- if (indirectClause && !enterClause) {
- context_.Say(x.source,
- "The INDIRECT clause cannot be used without the ENTER clause with the DECLARE TARGET directive."_err_en_US);
- }
- unsigned version{context_.langOptions().OpenMPVersion};
- if (toClause && version >= 52) {
- context_.Warn(common::UsageWarning::OpenMPUsage, toClause->source,
- "The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
- }
- if (indirectClause) {
- CheckAllowedClause(llvm::omp::Clause::OMPC_indirect);
- }
- }
-}
-
void OmpStructureChecker::Enter(const parser::OpenMPDeclareMapperConstruct &x) {
const parser::OmpDirectiveName &dirName{x.v.DirName()};
PushContextAndClauseSets(dirName.source, dirName.v);
@@ -1698,42 +1661,6 @@ void OmpStructureChecker::Leave(
dirContext_.pop_back();
}
-void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) {
- const auto &dir{std::get<parser::Verbatim>(x.t)};
- PushContext(dir.source, llvm::omp::Directive::OMPD_declare_target);
-}
-
-void OmpStructureChecker::Enter(const parser::OmpDeclareTargetWithList &x) {
- SymbolSourceMap symbols;
- GetSymbolsInObjectList(x.v, symbols);
- for (auto &[symbol, source] : symbols) {
- const GenericDetails *genericDetails = symbol->detailsIf<GenericDetails>();
- if (genericDetails) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be a generic name."_err_en_US,
- symbol->name());
- genericDetails->specific();
- }
- if (IsProcedurePointer(*symbol)) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be a procedure pointer."_err_en_US,
- symbol->name());
- }
- const SubprogramDetails *entryDetails =
- symbol->detailsIf<SubprogramDetails>();
- if (entryDetails && entryDetails->entryScope()) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be an entry name."_err_en_US,
- symbol->name());
- }
- if (IsStmtFunction(*symbol)) {
- context_.Say(source,
- "The procedure '%s' in DECLARE TARGET construct cannot be a statement function."_err_en_US,
- symbol->name());
- }
- }
-}
-
void OmpStructureChecker::CheckSymbolName(
const parser::CharBlock &source, const parser::OmpObject &object) {
common::visit(
@@ -1766,62 +1693,138 @@ void OmpStructureChecker::CheckSymbolNames(
}
}
+void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) {
+ const parser::OmpDirectiveName &dirName{x.v.DirName()};
+ PushContext(dirName.source, dirName.v);
+
+ // Check if arguments are extended-list-items.
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ const Symbol *symbol{GetArgumentSymbol(arg)};
+ if (!symbol) {
+ context_.Say(arg.source,
+ "An argument to the DECLARE TARGET directive should be an extended-list-item"_err_en_US);
+ continue;
+ }
+ const GenericDetails *genericDetails = symbol->detailsIf<GenericDetails>();
+ if (genericDetails) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be a generic name."_err_en_US,
+ symbol->name());
+ genericDetails->specific();
+ }
+ if (IsProcedurePointer(*symbol)) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be a procedure pointer."_err_en_US,
+ symbol->name());
+ }
+ const SubprogramDetails *entryDetails =
+ symbol->detailsIf<SubprogramDetails>();
+ if (entryDetails && entryDetails->entryScope()) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be an entry name."_err_en_US,
+ symbol->name());
+ }
+ if (IsStmtFunction(*symbol)) {
+ context_.Say(arg.source,
+ "The procedure '%s' in DECLARE TARGET construct cannot be a statement function."_err_en_US,
+ symbol->name());
+ }
+ }
+
+ // Check if there are arguments or clauses, but not both.
+ if (!x.v.Clauses().v.empty()) {
+ if (!x.v.Arguments().v.empty()) {
+ context_.Say(x.source,
+ "DECLARE TARGET directive can have argument or clauses, but not both"_err_en_US);
+ }
+ SetClauseSets(llvm::omp::Directive::OMPD_declare_target);
+ }
+}
+
void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &x) {
- const auto &dir{std::get<parser::Verbatim>(x.t)};
- const auto &spec{std::get<parser::OmpDeclareTargetSpecifier>(x.t)};
+ const parser::OmpDirectiveName &dirName{x.v.DirName()};
+
// Handle both forms of DECLARE TARGET.
// - Extended list: It behaves as if there was an ENTER/TO clause with the
// list of objects as argument. It accepts no explicit clauses.
// - With clauses.
- if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
- deviceConstructFound_ = true;
- CheckSymbolNames(dir.source, *objectList);
- CheckVarIsNotPartOfAnotherVar(dir.source, *objectList);
- CheckThreadprivateOrDeclareTargetVar(*objectList);
- } else if (const auto *clauseList{
- parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
- bool toClauseFound{false}, deviceTypeClauseFound{false},
- enterClauseFound{false};
- for (const auto &clause : clauseList->v) {
- common::visit(
- common::visitors{
- [&](const parser::OmpClause::To &toClause) {
- toClauseFound = true;
- auto &objList{std::get<parser::OmpObjectList>(toClause.v.t)};
- CheckSymbolNames(dir.source, objList);
- CheckVarIsNotPartOfAnotherVar(dir.source, objList);
- CheckThreadprivateOrDeclareTargetVar(objList);
- },
- [&](const parser::OmpClause::Link &linkClause) {
- CheckSymbolNames(dir.source, linkClause.v);
- CheckVarIsNotPartOfAnotherVar(dir.source, linkClause.v);
- CheckThreadprivateOrDeclareTargetVar(linkClause.v);
- },
- [&](const parser::OmpClause::Enter &enterClause) {
- enterClauseFound = true;
- auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)};
- CheckSymbolNames(dir.source, objList);
- CheckVarIsNotPartOfAnotherVar(dir.source, objList);
- CheckThreadprivateOrDeclareTargetVar(objList);
- },
- [&](const parser::OmpClause::DeviceType &deviceTypeClause) {
- deviceTypeClauseFound = true;
- if (deviceTypeClause.v.v !=
- parser::OmpDeviceTypeClause::DeviceTypeDescription::Host) {
- // Function / subroutine explicitly marked as runnable by the
- // target device.
- deviceConstructFound_ = true;
- }
- },
- [&](const auto &) {},
- },
- clause.u);
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ if (auto *object{GetArgumentObject(arg)}) {
+ deviceConstructFound_ = true;
+ CheckSymbolName(dirName.source, *object);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, *object);
+ CheckThreadprivateOrDeclareTargetVar(*object);
+ }
+ }
- if ((toClauseFound || enterClauseFound) && !deviceTypeClauseFound) {
- deviceConstructFound_ = true;
- }
+ if (!x.v.Clauses().v.empty()) {
+ const parser::OmpClause *enterClause =
+ FindClause(llvm::omp::Clause::OMPC_enter);
+ const parser::OmpClause *toClause = FindClause(llvm::omp::Clause::OMPC_to);
+ const parser::OmpClause *linkClause =
+ FindClause(llvm::omp::Clause::OMPC_link);
+ const parser::OmpClause *indirectClause =
+ FindClause(llvm::omp::Clause::OMPC_indirect);
+ if (!enterClause && !toClause && !linkClause) {
+ context_.Say(x.source,
+ "If the DECLARE TARGET directive has a clause, it must contain at least one ENTER clause or LINK clause"_err_en_US);
+ }
+ if (indirectClause && !enterClause) {
+ context_.Say(x.source,
+ "The INDIRECT clause cannot be used without the ENTER clause with the DECLARE TARGET directive."_err_en_US);
+ }
+ unsigned version{context_.langOptions().OpenMPVersion};
+ if (toClause && version >= 52) {
+ context_.Warn(common::UsageWarning::OpenMPUsage, toClause->source,
+ "The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead."_warn_en_US);
+ }
+ if (indirectClause) {
+ CheckAllowedClause(llvm::omp::Clause::OMPC_indirect);
}
}
+
+ bool toClauseFound{false}, deviceTypeClauseFound{false},
+ enterClauseFound{false};
+ for (const parser::OmpClause &clause : x.v.Clauses().v) {
+ common::visit(
+ common::visitors{
+ [&](const parser::OmpClause::To &toClause) {
+ toClauseFound = true;
+ auto &objList{std::get<parser::OmpObjectList>(toClause.v.t)};
+ CheckSymbolNames(dirName.source, objList);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
+ CheckThreadprivateOrDeclareTargetVar(objList);
+ },
+ [&](const parser::OmpClause::Link &linkClause) {
+ CheckSymbolNames(dirName.source, linkClause.v);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, linkClause.v);
+ CheckThreadprivateOrDeclareTargetVar(linkClause.v);
+ },
+ [&](const parser::OmpClause::Enter &enterClause) {
+ enterClauseFound = true;
+ auto &objList{std::get<parser::OmpObjectList>(enterClause.v.t)};
+ CheckSymbolNames(dirName.source, objList);
+ CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
+ CheckThreadprivateOrDeclareTargetVar(objList);
+ },
+ [&](const parser::OmpClause::DeviceType &deviceTypeClause) {
+ deviceTypeClauseFound = true;
+ if (deviceTypeClause.v.v !=
+ parser::OmpDeviceTypeClause::DeviceTypeDescription::Host) {
+ // Function / subroutine explicitly marked as runnable by the
+ // target device.
+ deviceConstructFound_ = true;
+ }
+ },
+ [&](const auto &) {},
+ },
+ clause.u);
+
+ if ((toClauseFound || enterClauseFound) && !deviceTypeClauseFound) {
+ deviceConstructFound_ = true;
+ }
+ }
+
dirContext_.pop_back();
}
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 176f6568814c5..193784555a887 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -113,9 +113,6 @@ class OmpStructureChecker
void Leave(const parser::OpenMPDeclareTargetConstruct &);
void Enter(const parser::OpenMPDepobjConstruct &);
void Leave(const parser::OpenMPDepobjConstruct &);
- void Enter(const parser::OmpDeclareTargetWithList &);
- void Enter(const parser::OmpDeclareTargetWithClause &);
- void Leave(const parser::OmpDeclareTargetWithClause &);
void Enter(const parser::OpenMPDispatchConstruct &);
void Leave(const parser::OpenMPDispatchConstruct &);
void Enter(const parser::OmpErrorDirective &);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 218e3e7266ca9..7ef211c8b428c 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -2324,22 +2324,17 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPCriticalConstruct &x) {
bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareTargetConstruct &x) {
PushContext(x.source, llvm::omp::Directive::OMPD_declare_target);
- const auto &spec{std::get<parser::OmpDeclareTargetSpecifier>(x.t)};
- if (const auto *objectList{parser::Unwrap<parser::OmpObjectList>(spec.u)}) {
- ResolveOmpObjectList(*objectList, Symbol::Flag::OmpDeclareTarget);
- } else if (const auto *clauseList{
- parser::Unwrap<parser::OmpClauseList>(spec.u)}) {
- for (const auto &clause : clauseList->v) {
- if (const auto *toClause{std::get_if<parser::OmpClause::To>(&clause.u)}) {
- auto &objList{std::get<parser::OmpObjectList>(toClause->v.t)};
- ResolveOmpObjectList(objList, Symbol::Flag::OmpDeclareTarget);
- } else if (const auto *linkClause{
- std::get_if<parser::OmpClause::Link>(&clause.u)}) {
- ResolveOmpObjectList(linkClause->v, Symbol::Flag::OmpDeclareTarget);
- } else if (const auto *enterClause{
- std::get_if<parser::OmpClause::Enter>(&clause.u)}) {
- ResolveOmpObjectList(std::get<parser::OmpObjectList>(enterClause->v.t),
- Symbol::Flag::OmpDeclareTarget);
+
+ for (const parser::OmpArgument &arg : x.v.Arguments().v) {
+ if (auto *object{omp::GetArgumentObject(arg)}) {
+ ResolveOmpObject(*object, Symbol::Flag::OmpDeclareTarget);
+ }
+ }
+
+ fo...
[truncated]
|
eb12400
to
f5eb99f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but if possible wait for @TIFitis to double check the semantic check refactoring - I don't understand the finer points of these target things.
No description provided.