[flang-commits] [flang] [llvm] Adds Parser and Semantic Support for Interop Construct, and Init and Use Clauses. (PR #120584)
via flang-commits
flang-commits at lists.llvm.org
Thu Dec 19 06:27:21 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-parser
@llvm/pr-subscribers-flang-openmp
Author: None (swatheesh-mcw)
<details>
<summary>Changes</summary>
Adds Parser and Semantic Support for the below construct and clauses:
- Interop Construct
- Init Clause
- Use Clause
Note:
The other clauses supported by Interop Construct such as Destroy, Use, Depend and Device are added already.
---
Patch is 27.78 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/120584.diff
11 Files Affected:
- (modified) flang/examples/FeatureList/FeatureList.cpp (+9)
- (modified) flang/include/flang/Parser/dump-parse-tree.h (+9)
- (modified) flang/include/flang/Parser/parse-tree.h (+40-1)
- (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+7)
- (modified) flang/lib/Parser/openmp-parsers.cpp (+27-1)
- (modified) flang/lib/Parser/unparse.cpp (+19)
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+85)
- (modified) flang/lib/Semantics/check-omp-structure.h (+2)
- (added) flang/test/Parser/OpenMP/interop-construct.f90 (+204)
- (added) flang/test/Semantics/OpenMP/interop-construct.f90 (+30)
- (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+2)
``````````diff
diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index 3a689c335c81c0..ac70de588c7d9f 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -525,6 +525,14 @@ struct NodeVisitor {
READ_FEATURE(OmpScheduleClause)
READ_FEATURE(OmpScheduleClause::Kind)
READ_FEATURE(OmpScheduleClause::Modifier)
+ READ_FEATURE(InteropType)
+ READ_FEATURE(InteropType::Kind)
+ READ_FEATURE(InteropPreference)
+ READ_FEATURE(OmpInitClause)
+ READ_FEATURE(OmpInitClause::InteropModifier)
+ READ_FEATURE(OmpInitClause::InteropTypes)
+ READ_FEATURE(OmpInitClause::InteropVar)
+ READ_FEATURE(OmpUseClause)
READ_FEATURE(OmpDeviceModifier)
READ_FEATURE(OmpDeviceClause)
READ_FEATURE(OmpDeviceClause::Modifier)
@@ -545,6 +553,7 @@ struct NodeVisitor {
READ_FEATURE(OpenACCConstruct)
READ_FEATURE(OpenACCDeclarativeConstruct)
READ_FEATURE(OpenACCLoopConstruct)
+ READ_FEATURE(OpenMPInteropConstruct)
READ_FEATURE(OpenACCRoutineConstruct)
READ_FEATURE(OpenACCStandaloneDeclarativeConstruct)
READ_FEATURE(OpenACCStandaloneConstruct)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 7821d40a644a27..5020d481dff29f 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -620,6 +620,14 @@ class ParseTreeDumper {
NODE_ENUM(OmpDeviceModifier, Value)
NODE(parser, OmpDeviceTypeClause)
NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription)
+ NODE(parser, InteropType)
+ NODE_ENUM(InteropType, Kind)
+ NODE(parser, InteropPreference)
+ NODE(parser, OmpInitClause)
+ NODE(OmpInitClause, InteropModifier)
+ NODE(OmpInitClause, InteropTypes)
+ NODE(OmpInitClause, InteropVar)
+ NODE(parser, OmpUseClause)
NODE(parser, OmpUpdateClause)
NODE(parser, OmpChunkModifier)
NODE_ENUM(OmpChunkModifier, Value)
@@ -639,6 +647,7 @@ class ParseTreeDumper {
NODE(parser, OpenACCDeclarativeConstruct)
NODE(parser, OpenACCEndConstruct)
NODE(parser, OpenACCLoopConstruct)
+ NODE(parser, OpenMPInteropConstruct)
NODE(parser, OpenACCRoutineConstruct)
NODE(parser, OpenACCStandaloneDeclarativeConstruct)
NODE(parser, OpenACCStandaloneConstruct)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 2ef593b3e50daa..3a0f41a67b01b0 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4158,6 +4158,36 @@ struct OmpUpdateClause {
std::variant<OmpDependenceType, OmpTaskDependenceType> u;
};
+// REF: [5.1:217-220], [5.2:293-294]
+//
+// init-clause -> INIT ([interop-modifier,] [interop-type,]
+// interop-type: interop-var)
+// interop-modifier: prefer_type(preference-list)
+// interop-type: target, targetsync
+// There can be at most only two interop-type.
+struct InteropType {
+ ENUM_CLASS(Kind, Target, TargetSync)
+ WRAPPER_CLASS_BOILERPLATE(InteropType, Kind);
+};
+
+struct InteropPreference {
+ UNION_CLASS_BOILERPLATE(InteropPreference);
+ std::variant<CharLiteralConstant, ScalarIntConstantExpr> u;
+};
+
+struct OmpInitClause {
+ TUPLE_CLASS_BOILERPLATE(OmpInitClause);
+ WRAPPER_CLASS(InteropModifier, std::list<InteropPreference>);
+ WRAPPER_CLASS(InteropTypes, std::list<InteropType>);
+ WRAPPER_CLASS(InteropVar, OmpObject);
+ std::tuple<std::optional<InteropModifier>, InteropTypes, InteropVar> t;
+};
+
+// REF: [5.1:217-220], [5.2:294]
+//
+// 14.1.3 use-clause -> USE (interop-var)
+WRAPPER_CLASS(OmpUseClause, OmpObject);
+
// OpenMP Clauses
struct OmpClause {
UNION_CLASS_BOILERPLATE(OmpClause);
@@ -4528,6 +4558,15 @@ struct OmpSimpleStandaloneDirective {
CharBlock source;
};
+// Ref: [5.1:217-220], [5.2:291-292]
+//
+// interop -> INTEROP clause[ [ [,] clause]...]
+struct OpenMPInteropConstruct {
+ TUPLE_CLASS_BOILERPLATE(OpenMPInteropConstruct);
+ CharBlock source;
+ std::tuple<Verbatim, OmpClauseList> t;
+};
+
struct OpenMPSimpleStandaloneConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPSimpleStandaloneConstruct);
CharBlock source;
@@ -4539,7 +4578,7 @@ struct OpenMPStandaloneConstruct {
CharBlock source;
std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
OpenMPCancelConstruct, OpenMPCancellationPointConstruct,
- OpenMPDepobjConstruct>
+ OpenMPDepobjConstruct, OpenMPInteropConstruct>
u;
};
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index b07e89d201d198..b6328dda8441c9 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2752,6 +2752,13 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct");
}
+static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
+ semantics::SemanticsContext &semaCtx,
+ lower::pft::Evaluation &eval,
+ const parser::OpenMPInteropConstruct &interopConstruct) {
+ TODO(converter.getCurrentLocation(), "OpenMPInteropConstruct");
+}
+
static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 67385c03f66c80..ac9f7a45dbd77e 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -531,6 +531,22 @@ TYPE_PARSER(
// OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle)
TYPE_PARSER(construct<OmpDetachClause>(Parser<OmpObject>{}))
+// InteropTypes
+TYPE_PARSER(construct<InteropType>(
+ "TARGETSYNC" >> pure(InteropType::Kind::TargetSync) ||
+ "TARGET" >> pure(InteropType::Kind::Target)))
+
+// InteropPreference
+TYPE_PARSER(construct<InteropPreference>(
+ construct<InteropPreference>(charLiteralConstant) ||
+ construct<InteropPreference>(scalarIntConstantExpr)))
+
+// init clause
+TYPE_PARSER(construct<OmpInitClause>(
+ maybe(verbatim("PREFER_TYPE"_tok) >>
+ parenthesized(nonemptyList(Parser<InteropPreference>{})) / ","),
+ nonemptyList(Parser<InteropType>{}) / ":", Parser<OmpObject>{}))
+
// 2.8.1 ALIGNED (list: alignment)
TYPE_PARSER(construct<OmpAlignedClause>(Parser<OmpObjectList>{},
maybe(":" >> nonemptyList(Parser<OmpAlignedClause::Modifier>{}))))
@@ -644,6 +660,8 @@ TYPE_PARSER(
"IF" >> construct<OmpClause>(construct<OmpClause::If>(
parenthesized(Parser<OmpIfClause>{}))) ||
"INBRANCH" >> construct<OmpClause>(construct<OmpClause::Inbranch>()) ||
+ "INIT" >> construct<OmpClause>(construct<OmpClause::Init>(
+ parenthesized(Parser<OmpInitClause>{}))) ||
"INCLUSIVE" >> construct<OmpClause>(construct<OmpClause::Inclusive>(
parenthesized(Parser<OmpObjectList>{}))) ||
"IS_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::IsDevicePtr>(
@@ -718,6 +736,8 @@ TYPE_PARSER(
parenthesized(scalarIntExpr))) ||
"TO" >> construct<OmpClause>(construct<OmpClause::To>(
parenthesized(Parser<OmpToClause>{}))) ||
+ "USE" >> construct<OmpClause>(construct<OmpClause::Use>(
+ parenthesized(Parser<OmpObject>{}))) ||
"USE_DEVICE_PTR" >> construct<OmpClause>(construct<OmpClause::UseDevicePtr>(
parenthesized(Parser<OmpObjectList>{}))) ||
"USE_DEVICE_ADDR" >>
@@ -877,6 +897,10 @@ TYPE_PARSER(sourced(construct<OmpSimpleStandaloneDirective>(first(
TYPE_PARSER(sourced(construct<OpenMPSimpleStandaloneConstruct>(
Parser<OmpSimpleStandaloneDirective>{}, Parser<OmpClauseList>{})))
+// 14.1 Interop construct
+TYPE_PARSER(sourced(construct<OpenMPInteropConstruct>(
+ verbatim("INTEROP"_tok), sourced(Parser<OmpClauseList>{}))))
+
// Standalone Constructs
TYPE_PARSER(
sourced(construct<OpenMPStandaloneConstruct>(
@@ -885,7 +909,9 @@ TYPE_PARSER(
construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
construct<OpenMPStandaloneConstruct>(
Parser<OpenMPCancellationPointConstruct>{}) ||
- construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{})) /
+ construct<OpenMPStandaloneConstruct>(Parser<OpenMPDepobjConstruct>{}) ||
+ construct<OpenMPStandaloneConstruct>(
+ Parser<OpenMPInteropConstruct>{})) /
endOfLine)
// Directives enclosing structured-block
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 0a6af7435b4a22..00957c6c424019 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2097,6 +2097,15 @@ class UnparseVisitor {
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
Walk(std::get<OmpObjectList>(x.t));
}
+ void Unparse(const OmpInitClause::InteropTypes &x) { Walk(x.v, ","); }
+ void Unparse(const OmpInitClause::InteropModifier &x) { Walk(x.v, ","); }
+ void Unparse(const OmpInitClause &x) {
+ Walk("PREFER_TYPE(",
+ std::get<std::optional<OmpInitClause::InteropModifier>>(x.t), "),");
+ Walk(std::get<OmpInitClause::InteropTypes>(x.t));
+ Put(": ");
+ Walk(std::get<OmpInitClause::InteropVar>(x.t));
+ }
void Unparse(const OmpMapClause &x) {
using Modifier = OmpMapClause::Modifier;
Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
@@ -2638,6 +2647,15 @@ class UnparseVisitor {
Put(")");
Walk(std::get<std::optional<OmpReductionInitializerClause>>(x.t));
}
+
+ void Unparse(const OpenMPInteropConstruct &x) {
+ BeginOpenMP();
+ Word("!$OMP INTEROP");
+ Walk(std::get<OmpClauseList>(x.t));
+ Put("\n");
+ EndOpenMP();
+ }
+
bool Pre(const OpenMPDeclarativeConstruct &x) {
BeginOpenMP();
Word("!$OMP ");
@@ -2923,6 +2941,7 @@ class UnparseVisitor {
OmpDeviceTypeClause, DeviceTypeDescription) // OMP device_type
WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier
WALK_NESTED_ENUM(OmpExpectation, Value) // OMP motion-expectation
+ WALK_NESTED_ENUM(InteropType, Kind) // OMP InteropVar
WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type
WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering
WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 95b962f5daf57c..68a041fe6e9eeb 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -4801,6 +4801,91 @@ void OmpStructureChecker::Leave(const parser::DoConstruct &x) {
Base::Leave(x);
}
+void OmpStructureChecker::Enter(const parser::OpenMPInteropConstruct &x) {
+ bool isDependClauseOccured{false};
+ int targetCount{0}, targetSyncCount{0};
+ const auto &dir{std::get<parser::Verbatim>(x.t)};
+ std::list<std::string> ObjectNameList;
+ PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_interop);
+ const auto &clauseList{std::get<parser::OmpClauseList>(x.t)};
+ for (const auto &clause : clauseList.v) {
+ common::visit(
+ common::visitors{
+ [&](const parser::OmpClause::Init &InitClause) {
+ const auto &InteropTypeList{
+ std::get<parser::OmpInitClause::InteropTypes>(
+ InitClause.v.t)};
+ for (auto &InteropTypeVal : InteropTypeList.v) {
+ if (*(parser::Unwrap<parser::InteropType::Kind>(
+ InteropTypeVal)) ==
+ parser::InteropType::Kind::TargetSync) {
+ ++targetSyncCount;
+ } else {
+ ++targetCount;
+ }
+ if (targetCount > 1 || targetSyncCount > 1) {
+ context_.Say(GetContext().directiveSource,
+ "Each interop-type may be specified at most once."_err_en_US);
+ }
+ }
+ const auto &InteropVar{parser::Unwrap<parser::OmpObject>(
+ std::get<parser::OmpInitClause::InteropVar>(InitClause.v.t))};
+ const auto *name{parser::Unwrap<parser::Name>(InteropVar)};
+ const auto ObjectName{name->ToString()};
+ if (ObjectNameList.end() !=
+ std::find(ObjectNameList.begin(), ObjectNameList.end(),
+ ObjectName)) {
+ context_.Say(GetContext().directiveSource,
+ "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US);
+ } else {
+ ObjectNameList.push_back(ObjectName);
+ }
+ },
+ [&](const parser::OmpClause::Depend &DependClause) {
+ isDependClauseOccured = true;
+ },
+ [&](const parser::OmpClause::Destroy &DestroyClause) {
+ const auto &InteropVar{
+ parser::Unwrap<parser::OmpObject>(DestroyClause.v)};
+ const auto *name{parser::Unwrap<parser::Name>(InteropVar)};
+ const auto ObjectName{name->ToString()};
+ if (ObjectNameList.end() !=
+ std::find(ObjectNameList.begin(), ObjectNameList.end(),
+ ObjectName)) {
+ context_.Say(GetContext().directiveSource,
+ "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US);
+ } else {
+ ObjectNameList.push_back(ObjectName);
+ }
+ },
+ [&](const parser::OmpClause::Use &UseClause) {
+ const auto &InteropVar{
+ parser::Unwrap<parser::OmpObject>(UseClause.v)};
+ const auto *name{parser::Unwrap<parser::Name>(InteropVar)};
+ const auto ObjectName{name->ToString()};
+ if (ObjectNameList.end() !=
+ std::find(ObjectNameList.begin(), ObjectNameList.end(),
+ ObjectName)) {
+ context_.Say(GetContext().directiveSource,
+ "Each interop-var may be specified for at most one action-clause of each interop construct."_err_en_US);
+ } else {
+ ObjectNameList.push_back(ObjectName);
+ }
+ },
+ [&](const auto &) {},
+ },
+ clause.u);
+ }
+ if (isDependClauseOccured && !targetSyncCount) {
+ context_.Say(GetContext().directiveSource,
+ "A depend clause can only appear on the directive if the interop-type includes targetsync"_err_en_US);
+ }
+}
+
+void OmpStructureChecker::Leave(const parser::OpenMPInteropConstruct &) {
+ dirContext_.pop_back();
+}
+
void OmpStructureChecker::CheckAllowedRequiresClause(llvmOmpClause clause) {
CheckAllowedClause(clause);
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 346a7bed9138f0..7b3d9fa3d736b8 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -73,6 +73,8 @@ class OmpStructureChecker
void Enter(const parser::OpenMPConstruct &);
void Leave(const parser::OpenMPConstruct &);
+ void Enter(const parser::OpenMPInteropConstruct &);
+ void Leave(const parser::OpenMPInteropConstruct &);
void Enter(const parser::OpenMPLoopConstruct &);
void Leave(const parser::OpenMPLoopConstruct &);
void Enter(const parser::OmpEndLoopDirective &);
diff --git a/flang/test/Parser/OpenMP/interop-construct.f90 b/flang/test/Parser/OpenMP/interop-construct.f90
new file mode 100644
index 00000000000000..9fd2b3d63d5c5d
--- /dev/null
+++ b/flang/test/Parser/OpenMP/interop-construct.f90
@@ -0,0 +1,204 @@
+! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s
+! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s
+
+subroutine test_interop_01()
+ !$omp interop device(1)
+ print *,'pass'
+end subroutine test_interop_01
+
+!UNPARSE: SUBROUTINE test_interop_01
+!UNPARSE: !$OMP INTEROP DEVICE(1_4)
+!UNPARSE: PRINT *, "pass"
+!UNPARSE: END SUBROUTINE test_interop_01
+
+!PARSE-TREE: | SubroutineStmt
+!PARSE-TREE: | | Name = 'test_interop_01'
+!PARSE-TREE: | SpecificationPart
+!PARSE-TREE: | | ImplicitPart ->
+!PARSE-TREE: | ExecutionPart -> Block
+!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct
+!PARSE-TREE: | | | Verbatim
+!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Device -> OmpDeviceClause
+!PARSE-TREE: | | | | Scalar -> Integer -> Expr -> LiteralConstant -> IntLiteralConstant = '1'
+!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt
+!PARSE-TREE: | | | Format -> Star
+!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant
+!PARSE-TREE: | | | | string = 'pass'
+!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_01'
+
+subroutine test_interop_02()
+ use omp_lib
+ integer(omp_interop_kind) :: obj1, obj2, obj3
+ !$omp interop init(targetsync: obj) use(obj1) destroy(obj3)
+ print *,'pass'
+end subroutine test_interop_02
+
+!UNPARSE: SUBROUTINE test_interop_02
+!UNPARSE: USE :: omp_lib
+!UNPARSE: INTEGER(KIND=8_4) obj1, obj2, obj3
+!UNPARSE: !$OMP INTEROP INIT(TARGETSYNC: obj) USE(obj1) DESTROY(obj3)
+!UNPARSE: PRINT *, "pass"
+!UNPARSE: END SUBROUTINE test_interop_02
+
+!PARSE-TREE: | SubroutineStmt
+!PARSE-TREE: | | Name = 'test_interop_02'
+!PARSE-TREE: | SpecificationPart
+!PARSE-TREE: | | UseStmt
+!PARSE-TREE: | | | Name = 'omp_lib'
+!PARSE-TREE: | | ImplicitPart ->
+!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt
+!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind'
+!PARSE-TREE: | | | EntityDecl
+!PARSE-TREE: | | | | Name = 'obj1'
+!PARSE-TREE: | | | EntityDecl
+!PARSE-TREE: | | | | Name = 'obj2'
+!PARSE-TREE: | | | EntityDecl
+!PARSE-TREE: | | | | Name = 'obj3'
+!PARSE-TREE: | ExecutionPart -> Block
+!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct
+!PARSE-TREE: | | | Verbatim
+!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Init -> OmpInitClause
+!PARSE-TREE: | | | | InteropTypes -> InteropType -> Kind = TargetSync
+!PARSE-TREE: | | | | InteropVar -> OmpObject -> Designator -> DataRef -> Name = 'obj'
+!PARSE-TREE: | | | OmpClause -> Use -> OmpUseClause -> OmpObject -> Designator -> DataRef -> Name = 'obj1'
+!PARSE-TREE: | | | OmpClause -> Destroy -> OmpDestroyClause -> OmpObject -> Designator -> DataRef -> Name = 'obj3'
+!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> PrintStmt
+!PARSE-TREE: | | | Format -> Star
+!PARSE-TREE: | | | OutputItem -> Expr -> LiteralConstant -> CharLiteralConstant
+!PARSE-TREE: | | | | string = 'pass'
+!PARSE-TREE: | EndSubroutineStmt -> Name = 'test_interop_02'
+
+subroutine test_interop_03()
+ use omp_lib
+ Integer(omp_interop_kind) :: obj
+ !$omp interop init(targetsync: obj) depend(inout: obj)
+ print *,'pass'
+end subroutine test_interop_03
+
+!UNPARSE: SUBROUTINE test_interop_03
+!UNPARSE: USE :: omp_lib
+!UNPARSE: INTEGER(KIND=8_4) obj
+!UNPARSE: !$OMP INTEROP INIT(TARGETSYNC: obj) DEPEND(INOUT: obj)
+!UNPARSE: PRINT *, "pass"
+!UNPARSE: END SUBROUTINE test_interop_03
+
+!PARSE-TREE: | SubroutineStmt
+!PARSE-TREE: | | Name = 'test_interop_03'
+!PARSE-TREE: | SpecificationPart
+!PARSE-TREE: | | UseStmt
+!PARSE-TREE: | | | Name = 'omp_lib'
+!PARSE-TREE: | | ImplicitPart ->
+!PARSE-TREE: | | DeclarationConstruct -> SpecificationConstruct -> TypeDeclarationStmt
+!PARSE-TREE: | | | DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr -> Designator -> DataRef -> Name = 'omp_interop_kind'
+!PARSE-TREE: | | | EntityDecl
+!PARSE-TREE: | | | | Name = 'obj'
+!PARSE-TREE: | ExecutionPart -> Block
+!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPStandaloneConstruct -> OpenMPInteropConstruct
+!...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/120584
More information about the flang-commits
mailing list