[llvm-branch-commits] [flang] [flang][OpenMP] Use OmpDirectiveSpecification in DECLARE_TARGET (PR #160573)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Sep 24 10:51:39 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-openmp
Author: Krzysztof Parzyszek (kparzysz)
<details>
<summary>Changes</summary>
---
Patch is 39.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/160573.diff
16 Files Affected:
- (modified) flang/include/flang/Parser/openmp-utils.h (-2)
- (modified) flang/include/flang/Parser/parse-tree.h (+8-2)
- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+6-8)
- (modified) flang/lib/Parser/openmp-parsers.cpp (+3-15)
- (modified) flang/lib/Parser/unparse.cpp (+2-2)
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+124-121)
- (modified) flang/lib/Semantics/check-omp-structure.h (-3)
- (modified) flang/lib/Semantics/resolve-directives.cpp (+11-16)
- (modified) flang/lib/Semantics/resolve-names.cpp (+34-43)
- (modified) flang/test/Parser/OpenMP/declare-target-indirect-tree.f90 (+16-12)
- (modified) flang/test/Parser/OpenMP/declare-target-to-clause.f90 (+8-6)
- (modified) flang/test/Parser/OpenMP/declare_target-device_type.f90 (+93-15)
- (modified) flang/test/Parser/OpenMP/enter-automap-modifier.f90 (+7-4)
- (modified) flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 (+5-4)
- (modified) flang/test/Semantics/OpenMP/blank-common-block.f90 (+1)
- (modified) flang/test/Semantics/OpenMP/declare-target-function-name-with-symbols.f90 (+1-1)
``````````diff
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]
``````````
</details>
https://github.com/llvm/llvm-project/pull/160573
More information about the llvm-branch-commits
mailing list