Skip to content
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

Revert "Revert "[flang][openmp] Adds Parser and Semantic Support for Interop Construct, and Init and Use Clauses."" #132343

Conversation

swatheesh-mcw
Copy link
Contributor

Reverts #132005

@llvmbot llvmbot added flang Flang issues not falling into any other category flang:fir-hlfir flang:openmp flang:semantics flang:parser clang:openmp OpenMP related changes to Clang labels Mar 21, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 21, 2025

@llvm/pr-subscribers-flang-parser
@llvm/pr-subscribers-flang-fir-hlfir

@llvm/pr-subscribers-flang-semantics

Author: None (swatheesh-mcw)

Changes

Reverts llvm/llvm-project#132005


Patch is 32.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132343.diff

14 Files Affected:

  • (modified) flang/examples/FeatureList/FeatureList.cpp (+8)
  • (modified) flang/include/flang/Parser/dump-parse-tree.h (+8)
  • (modified) flang/include/flang/Parser/parse-tree.h (+56-1)
  • (modified) flang/include/flang/Semantics/openmp-modifiers.h (+2)
  • (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+10)
  • (modified) flang/lib/Parser/openmp-parsers.cpp (+32-1)
  • (modified) flang/lib/Parser/unparse.cpp (+34)
  • (modified) flang/lib/Semantics/check-omp-structure.cpp (+82)
  • (modified) flang/lib/Semantics/check-omp-structure.h (+2)
  • (modified) flang/lib/Semantics/openmp-modifiers.cpp (+32)
  • (added) flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 (+9)
  • (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 --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index 25485bbb8ff4d..94fdfa3e4dea9 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -522,6 +522,13 @@ struct NodeVisitor {
   READ_FEATURE(OmpScheduleClause)
   READ_FEATURE(OmpScheduleClause::Kind)
   READ_FEATURE(OmpScheduleClause::Modifier)
+  READ_FEATURE(OmpInteropRuntimeIdentifier)
+  READ_FEATURE(OmpInteropPreference)
+  READ_FEATURE(OmpInteropType)
+  READ_FEATURE(OmpInteropType::Value)
+  READ_FEATURE(OmpInitClause)
+  READ_FEATURE(OmpInitClause::Modifier)
+  READ_FEATURE(OmpUseClause)
   READ_FEATURE(OmpDeviceModifier)
   READ_FEATURE(OmpDeviceClause)
   READ_FEATURE(OmpDeviceClause::Modifier)
@@ -541,6 +548,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 9bff2dab974ec..41ad15794ad15 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -657,6 +657,13 @@ class ParseTreeDumper {
   NODE_ENUM(OmpDeviceModifier, Value)
   NODE(parser, OmpDeviceTypeClause)
   NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription)
+  NODE(parser, OmpInteropRuntimeIdentifier)
+  NODE(parser, OmpInteropPreference)
+  NODE(parser, OmpInteropType)
+  NODE_ENUM(OmpInteropType, Value)
+  NODE(parser, OmpInitClause)
+  NODE(OmpInitClause, Modifier)
+  NODE(parser, OmpUseClause)
   NODE(parser, OmpUpdateClause)
   NODE(parser, OmpChunkModifier)
   NODE_ENUM(OmpChunkModifier, Value)
@@ -675,6 +682,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 029c3de354b66..76cd3380e203c 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3829,6 +3829,33 @@ struct OmpExpectation {
   WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value);
 };
 
+// REF: [5.1:217-220], [5.2:293-294]
+//
+// OmpInteropRuntimeIdentifier ->                   // since 5.2
+// CharLiteralConstant || ScalarIntConstantExpr
+struct OmpInteropRuntimeIdentifier {
+  UNION_CLASS_BOILERPLATE(OmpInteropRuntimeIdentifier);
+  std::variant<CharLiteralConstant, ScalarIntConstantExpr> u;
+};
+
+// REF: [5.1:217-220], [5.2:293-294]
+//
+// OmpInteropPreference ->                          // since 5.2
+// ([OmpRuntimeIdentifier, ...])
+struct OmpInteropPreference {
+  WRAPPER_CLASS_BOILERPLATE(
+      OmpInteropPreference, std::list<OmpInteropRuntimeIdentifier>);
+};
+
+// REF: [5.1:217-220], [5.2:293-294]
+//
+// InteropType -> target || targetsync              // since 5.2
+// There can be at most only two interop-type.
+struct OmpInteropType {
+  ENUM_CLASS(Value, Target, TargetSync)
+  WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value);
+};
+
 // Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
 //
 // iterator-modifier ->
@@ -4486,6 +4513,25 @@ struct OmpWhenClause {
       t;
 };
 
+// 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
+// interop-var: Ompobject
+// There can be at most only two interop-type.
+struct OmpInitClause {
+  TUPLE_CLASS_BOILERPLATE(OmpInitClause);
+  MODIFIER_BOILERPLATE(OmpInteropPreference, OmpInteropType);
+  std::tuple<MODIFIERS(), OmpObject> 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);
@@ -4935,6 +4981,15 @@ struct OpenMPFlushConstruct {
   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 {
   WRAPPER_CLASS_BOILERPLATE(
       OpenMPSimpleStandaloneConstruct, OmpDirectiveSpecification);
@@ -4946,7 +5001,7 @@ struct OpenMPStandaloneConstruct {
   CharBlock source;
   std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
       OpenMPCancelConstruct, OpenMPCancellationPointConstruct,
-      OpenMPDepobjConstruct, OmpMetadirectiveDirective>
+      OpenMPDepobjConstruct, OmpMetadirectiveDirective, OpenMPInteropConstruct>
       u;
 };
 
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
index 7cdbf65adebe1..4fbd80f989e72 100644
--- a/flang/include/flang/Semantics/openmp-modifiers.h
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -77,6 +77,8 @@ DECLARE_DESCRIPTOR(parser::OmpDependenceType);
 DECLARE_DESCRIPTOR(parser::OmpDeviceModifier);
 DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier);
 DECLARE_DESCRIPTOR(parser::OmpExpectation);
+DECLARE_DESCRIPTOR(parser::OmpInteropPreference);
+DECLARE_DESCRIPTOR(parser::OmpInteropType);
 DECLARE_DESCRIPTOR(parser::OmpIterator);
 DECLARE_DESCRIPTOR(parser::OmpLastprivateModifier);
 DECLARE_DESCRIPTOR(parser::OmpLinearModifier);
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index b8ef18860e9b4..1304f06ed28cf 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -424,6 +424,9 @@ extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) {
                     },
                     [](const parser::OpenMPDepobjConstruct &c) {
                       return llvm::omp::OMPD_depobj;
+                    },
+                    [](const parser::OpenMPInteropConstruct &c) {
+                      return llvm::omp::OMPD_interop;
                     }},
                 c.u);
           },
@@ -3363,6 +3366,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 f76a136655478..601cd72c79bf5 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -425,6 +425,17 @@ TYPE_PARSER(construct<OmpDeviceModifier>(
 TYPE_PARSER(construct<OmpExpectation>( //
     "PRESENT" >> pure(OmpExpectation::Value::Present)))
 
+TYPE_PARSER(construct<OmpInteropRuntimeIdentifier>(
+    construct<OmpInteropRuntimeIdentifier>(charLiteralConstant) ||
+    construct<OmpInteropRuntimeIdentifier>(scalarIntConstantExpr)))
+
+TYPE_PARSER(construct<OmpInteropPreference>(verbatim("PREFER_TYPE"_tok) >>
+    parenthesized(nonemptyList(Parser<OmpInteropRuntimeIdentifier>{}))))
+
+TYPE_PARSER(construct<OmpInteropType>(
+    "TARGETSYNC" >> pure(OmpInteropType::Value::TargetSync) ||
+    "TARGET" >> pure(OmpInteropType::Value::Target)))
+
 TYPE_PARSER(construct<OmpIteratorSpecifier>(
     // Using Parser<TypeDeclarationStmt> or Parser<EntityDecl> has the problem
     // that they will attempt to treat what follows the '=' as initialization.
@@ -552,6 +563,11 @@ TYPE_PARSER(sourced(
 
 TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
 
+TYPE_PARSER(sourced(
+    construct<OmpInitClause::Modifier>(
+        construct<OmpInitClause::Modifier>(Parser<OmpInteropPreference>{})) ||
+    construct<OmpInitClause::Modifier>(Parser<OmpInteropType>{})))
+
 TYPE_PARSER(sourced(construct<OmpInReductionClause::Modifier>(
     Parser<OmpReductionIdentifier>{})))
 
@@ -788,6 +804,11 @@ TYPE_PARSER(
 // OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle)
 TYPE_PARSER(construct<OmpDetachClause>(Parser<OmpObject>{}))
 
+// init clause
+TYPE_PARSER(construct<OmpInitClause>(
+    maybe(nonemptyList(Parser<OmpInitClause::Modifier>{}) / ":"),
+    Parser<OmpObject>{}))
+
 // 2.8.1 ALIGNED (list: alignment)
 TYPE_PARSER(construct<OmpAlignedClause>(Parser<OmpObjectList>{},
     maybe(":" >> nonemptyList(Parser<OmpAlignedClause::Modifier>{}))))
@@ -927,6 +948,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>{}))) ||
     "INITIALIZER" >> construct<OmpClause>(construct<OmpClause::Initializer>(
@@ -1016,6 +1039,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" >>
@@ -1251,6 +1276,10 @@ TYPE_PARSER(sourced( //
             IsDirective(llvm::omp::Directive::OMPD_depobj)) >=
         Parser<OmpDirectiveSpecification>{})))
 
+// OMP 5.2 14.1 Interop construct
+TYPE_PARSER(sourced(construct<OpenMPInteropConstruct>(
+    verbatim("INTEROP"_tok), sourced(Parser<OmpClauseList>{}))))
+
 // Standalone Constructs
 TYPE_PARSER(
     sourced( //
@@ -1263,7 +1292,9 @@ TYPE_PARSER(
         construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
         construct<OpenMPStandaloneConstruct>(
             Parser<OmpMetadirectiveDirective>{}) ||
-        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 8cdbf8ed2a672..1674c45ac3096 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2180,6 +2180,30 @@ class UnparseVisitor {
     Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
     Walk(std::get<OmpObjectList>(x.t));
   }
+  void Unparse(const OmpInteropPreference &x) { Walk(x.v, ","); }
+  void Unparse(const OmpInitClause &x) {
+    using Modifier = OmpInitClause::Modifier;
+    auto &modifiers{std::get<std::optional<std::list<Modifier>>>(x.t)};
+    bool isTypeStart{true};
+    for (const Modifier &m : *modifiers) {
+      if (auto *interopPreferenceMod{
+              std::get_if<parser::OmpInteropPreference>(&m.u)}) {
+        Put("PREFER_TYPE(");
+        Walk(*interopPreferenceMod);
+        Put("),");
+      } else if (auto *interopTypeMod{
+                     std::get_if<parser::OmpInteropType>(&m.u)}) {
+        if (isTypeStart) {
+          isTypeStart = false;
+        } else {
+          Put(",");
+        }
+        Walk(*interopTypeMod);
+      }
+    }
+    Put(": ");
+    Walk(std::get<OmpObject>(x.t));
+  }
   void Unparse(const OmpMapClause &x) {
     using Modifier = OmpMapClause::Modifier;
     Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
@@ -2710,6 +2734,15 @@ class UnparseVisitor {
     Put("\n");
     EndOpenMP();
   }
+
+  void Unparse(const OpenMPInteropConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP INTEROP");
+    Walk(std::get<OmpClauseList>(x.t));
+    Put("\n");
+    EndOpenMP();
+  }
+
   void Unparse(const OpenMPDeclarativeAssumes &x) {
     BeginOpenMP();
     Word("!$OMP ASSUMES ");
@@ -3004,6 +3037,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(OmpInteropType, Value) // OMP InteropType
   WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering
   WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier
   WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 6bddd629d607e..1e2ae6300114c 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -5720,6 +5720,88 @@ 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::set<const Symbol *> objectSymbolList;
+  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) {
+              if (OmpVerifyModifiers(initClause.v, llvm::omp::OMPC_init,
+                      GetContext().directiveSource, context_)) {
+
+                auto &modifiers{OmpGetModifiers(initClause.v)};
+                auto &&interopTypeModifier{
+                    OmpGetRepeatableModifier<parser::OmpInteropType>(
+                        modifiers)};
+                for (const auto &it : interopTypeModifier) {
+                  if (it->v == parser::OmpInteropType::Value::TargetSync) {
+                    ++targetSyncCount;
+                  } else {
+                    ++targetCount;
+                  }
+                }
+              }
+              const auto &interopVar{parser::Unwrap<parser::OmpObject>(
+                  std::get<parser::OmpObject>(initClause.v.t))};
+              const auto *name{parser::Unwrap<parser::Name>(interopVar)};
+              const auto *objectSymbol{name->symbol};
+              if (llvm::is_contained(objectSymbolList, objectSymbol)) {
+                context_.Say(GetContext().directiveSource,
+                    "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
+              } else {
+                objectSymbolList.insert(objectSymbol);
+              }
+            },
+            [&](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 *objectSymbol{name->symbol};
+              if (llvm::is_contained(objectSymbolList, objectSymbol)) {
+                context_.Say(GetContext().directiveSource,
+                    "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
+              } else {
+                objectSymbolList.insert(objectSymbol);
+              }
+            },
+            [&](const parser::OmpClause::Use &useClause) {
+              const auto &interopVar{
+                  parser::Unwrap<parser::OmpObject>(useClause.v)};
+              const auto *name{parser::Unwrap<parser::Name>(interopVar)};
+              const auto *objectSymbol{name->symbol};
+              if (llvm::is_contained(objectSymbolList, objectSymbol)) {
+                context_.Say(GetContext().directiveSource,
+                    "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
+              } else {
+                objectSymbolList.insert(objectSymbol);
+              }
+            },
+            [&](const auto &) {},
+        },
+        clause.u);
+  }
+  if (targetCount > 1 || targetSyncCount > 1) {
+    context_.Say(GetContext().directiveSource,
+        "Each interop-type may be specified at most once."_err_en_US);
+  }
+  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 d802afeefe72f..a8869561cf5ea 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::OpenMPDeclarativeConstruct &);
   void Leave(const parser::OpenMPDeclarativeConstruct &);
 
diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
index 73ad7751ee517..c84e832ee52a1 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -240,6 +240,38 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpExpectation>() {
   return desc;
 }
 
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropPreference>() {
+  static const OmpModifierDescriptor desc{
+      /*name=*/"interop-preference",
+      /*props=*/
+      {
+          {52, {OmpProperty::Unique}},
+      },
+      /*clauses=*/
+      {
+          {52, {Clause::OMPC_init}},
+      },
+  };
+  return desc;
+}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropType>() {
+  static const OmpModifierDescriptor desc{
+      /*name=*/"interop-type",
+      /*props=*/
+      {
+          {52, {OmpProperty::Required}},
+      },
+      /*clauses=*/
+      {
+          {52, {Clause::OMPC_init}},
+      },
+  };
+  return desc;
+}
+
 template <>
 const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpIterator>() {
   static const OmpModifierDescriptor desc{
diff --git a/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 b/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90
new file mode 100644
index 0000000000000..f7920c09464ed
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90
@@ -0,0 +1,9 @@
+! REQUIRES: openmp_runtime
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s
+
+! CHECK: not yet implemented: OpenMPInteropConstruct
+program interop_test
+  use omp_lib
+  integer(omp_interop_kind) :: obj
+  !$omp interop init(targetsync,target: obj)
+end program interop_test
diff --git a/flang/test/Parser/OpenMP/interop-construct.f90 b/flang/test/Parser/OpenMP/interop-construct.f90
new file mode 100644
index 0000000000000..a1781d559b46d
--- /dev/null
+++ b/flang/test/Parser/OpenMP/interop-construct.f90
@@ -0,0 +1,204 @@
+! REQUIRES: openmp_runtime
+! RUN: %flang_fc1 -fdebug-unparse -fopenmp-version...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Mar 21, 2025

@llvm/pr-subscribers-flang-openmp

Author: None (swatheesh-mcw)

Changes

Reverts llvm/llvm-project#132005


Patch is 32.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/132343.diff

14 Files Affected:

  • (modified) flang/examples/FeatureList/FeatureList.cpp (+8)
  • (modified) flang/include/flang/Parser/dump-parse-tree.h (+8)
  • (modified) flang/include/flang/Parser/parse-tree.h (+56-1)
  • (modified) flang/include/flang/Semantics/openmp-modifiers.h (+2)
  • (modified) flang/lib/Lower/OpenMP/OpenMP.cpp (+10)
  • (modified) flang/lib/Parser/openmp-parsers.cpp (+32-1)
  • (modified) flang/lib/Parser/unparse.cpp (+34)
  • (modified) flang/lib/Semantics/check-omp-structure.cpp (+82)
  • (modified) flang/lib/Semantics/check-omp-structure.h (+2)
  • (modified) flang/lib/Semantics/openmp-modifiers.cpp (+32)
  • (added) flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 (+9)
  • (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 --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index 25485bbb8ff4d..94fdfa3e4dea9 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -522,6 +522,13 @@ struct NodeVisitor {
   READ_FEATURE(OmpScheduleClause)
   READ_FEATURE(OmpScheduleClause::Kind)
   READ_FEATURE(OmpScheduleClause::Modifier)
+  READ_FEATURE(OmpInteropRuntimeIdentifier)
+  READ_FEATURE(OmpInteropPreference)
+  READ_FEATURE(OmpInteropType)
+  READ_FEATURE(OmpInteropType::Value)
+  READ_FEATURE(OmpInitClause)
+  READ_FEATURE(OmpInitClause::Modifier)
+  READ_FEATURE(OmpUseClause)
   READ_FEATURE(OmpDeviceModifier)
   READ_FEATURE(OmpDeviceClause)
   READ_FEATURE(OmpDeviceClause::Modifier)
@@ -541,6 +548,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 9bff2dab974ec..41ad15794ad15 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -657,6 +657,13 @@ class ParseTreeDumper {
   NODE_ENUM(OmpDeviceModifier, Value)
   NODE(parser, OmpDeviceTypeClause)
   NODE_ENUM(OmpDeviceTypeClause, DeviceTypeDescription)
+  NODE(parser, OmpInteropRuntimeIdentifier)
+  NODE(parser, OmpInteropPreference)
+  NODE(parser, OmpInteropType)
+  NODE_ENUM(OmpInteropType, Value)
+  NODE(parser, OmpInitClause)
+  NODE(OmpInitClause, Modifier)
+  NODE(parser, OmpUseClause)
   NODE(parser, OmpUpdateClause)
   NODE(parser, OmpChunkModifier)
   NODE_ENUM(OmpChunkModifier, Value)
@@ -675,6 +682,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 029c3de354b66..76cd3380e203c 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3829,6 +3829,33 @@ struct OmpExpectation {
   WRAPPER_CLASS_BOILERPLATE(OmpExpectation, Value);
 };
 
+// REF: [5.1:217-220], [5.2:293-294]
+//
+// OmpInteropRuntimeIdentifier ->                   // since 5.2
+// CharLiteralConstant || ScalarIntConstantExpr
+struct OmpInteropRuntimeIdentifier {
+  UNION_CLASS_BOILERPLATE(OmpInteropRuntimeIdentifier);
+  std::variant<CharLiteralConstant, ScalarIntConstantExpr> u;
+};
+
+// REF: [5.1:217-220], [5.2:293-294]
+//
+// OmpInteropPreference ->                          // since 5.2
+// ([OmpRuntimeIdentifier, ...])
+struct OmpInteropPreference {
+  WRAPPER_CLASS_BOILERPLATE(
+      OmpInteropPreference, std::list<OmpInteropRuntimeIdentifier>);
+};
+
+// REF: [5.1:217-220], [5.2:293-294]
+//
+// InteropType -> target || targetsync              // since 5.2
+// There can be at most only two interop-type.
+struct OmpInteropType {
+  ENUM_CLASS(Value, Target, TargetSync)
+  WRAPPER_CLASS_BOILERPLATE(OmpInteropType, Value);
+};
+
 // Ref: [5.0:47-49], [5.1:49-51], [5.2:67-69]
 //
 // iterator-modifier ->
@@ -4486,6 +4513,25 @@ struct OmpWhenClause {
       t;
 };
 
+// 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
+// interop-var: Ompobject
+// There can be at most only two interop-type.
+struct OmpInitClause {
+  TUPLE_CLASS_BOILERPLATE(OmpInitClause);
+  MODIFIER_BOILERPLATE(OmpInteropPreference, OmpInteropType);
+  std::tuple<MODIFIERS(), OmpObject> 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);
@@ -4935,6 +4981,15 @@ struct OpenMPFlushConstruct {
   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 {
   WRAPPER_CLASS_BOILERPLATE(
       OpenMPSimpleStandaloneConstruct, OmpDirectiveSpecification);
@@ -4946,7 +5001,7 @@ struct OpenMPStandaloneConstruct {
   CharBlock source;
   std::variant<OpenMPSimpleStandaloneConstruct, OpenMPFlushConstruct,
       OpenMPCancelConstruct, OpenMPCancellationPointConstruct,
-      OpenMPDepobjConstruct, OmpMetadirectiveDirective>
+      OpenMPDepobjConstruct, OmpMetadirectiveDirective, OpenMPInteropConstruct>
       u;
 };
 
diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h
index 7cdbf65adebe1..4fbd80f989e72 100644
--- a/flang/include/flang/Semantics/openmp-modifiers.h
+++ b/flang/include/flang/Semantics/openmp-modifiers.h
@@ -77,6 +77,8 @@ DECLARE_DESCRIPTOR(parser::OmpDependenceType);
 DECLARE_DESCRIPTOR(parser::OmpDeviceModifier);
 DECLARE_DESCRIPTOR(parser::OmpDirectiveNameModifier);
 DECLARE_DESCRIPTOR(parser::OmpExpectation);
+DECLARE_DESCRIPTOR(parser::OmpInteropPreference);
+DECLARE_DESCRIPTOR(parser::OmpInteropType);
 DECLARE_DESCRIPTOR(parser::OmpIterator);
 DECLARE_DESCRIPTOR(parser::OmpLastprivateModifier);
 DECLARE_DESCRIPTOR(parser::OmpLinearModifier);
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index b8ef18860e9b4..1304f06ed28cf 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -424,6 +424,9 @@ extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) {
                     },
                     [](const parser::OpenMPDepobjConstruct &c) {
                       return llvm::omp::OMPD_depobj;
+                    },
+                    [](const parser::OpenMPInteropConstruct &c) {
+                      return llvm::omp::OMPD_interop;
                     }},
                 c.u);
           },
@@ -3363,6 +3366,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 f76a136655478..601cd72c79bf5 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -425,6 +425,17 @@ TYPE_PARSER(construct<OmpDeviceModifier>(
 TYPE_PARSER(construct<OmpExpectation>( //
     "PRESENT" >> pure(OmpExpectation::Value::Present)))
 
+TYPE_PARSER(construct<OmpInteropRuntimeIdentifier>(
+    construct<OmpInteropRuntimeIdentifier>(charLiteralConstant) ||
+    construct<OmpInteropRuntimeIdentifier>(scalarIntConstantExpr)))
+
+TYPE_PARSER(construct<OmpInteropPreference>(verbatim("PREFER_TYPE"_tok) >>
+    parenthesized(nonemptyList(Parser<OmpInteropRuntimeIdentifier>{}))))
+
+TYPE_PARSER(construct<OmpInteropType>(
+    "TARGETSYNC" >> pure(OmpInteropType::Value::TargetSync) ||
+    "TARGET" >> pure(OmpInteropType::Value::Target)))
+
 TYPE_PARSER(construct<OmpIteratorSpecifier>(
     // Using Parser<TypeDeclarationStmt> or Parser<EntityDecl> has the problem
     // that they will attempt to treat what follows the '=' as initialization.
@@ -552,6 +563,11 @@ TYPE_PARSER(sourced(
 
 TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
 
+TYPE_PARSER(sourced(
+    construct<OmpInitClause::Modifier>(
+        construct<OmpInitClause::Modifier>(Parser<OmpInteropPreference>{})) ||
+    construct<OmpInitClause::Modifier>(Parser<OmpInteropType>{})))
+
 TYPE_PARSER(sourced(construct<OmpInReductionClause::Modifier>(
     Parser<OmpReductionIdentifier>{})))
 
@@ -788,6 +804,11 @@ TYPE_PARSER(
 // OpenMPv5.2 12.5.2 detach-clause -> DETACH (event-handle)
 TYPE_PARSER(construct<OmpDetachClause>(Parser<OmpObject>{}))
 
+// init clause
+TYPE_PARSER(construct<OmpInitClause>(
+    maybe(nonemptyList(Parser<OmpInitClause::Modifier>{}) / ":"),
+    Parser<OmpObject>{}))
+
 // 2.8.1 ALIGNED (list: alignment)
 TYPE_PARSER(construct<OmpAlignedClause>(Parser<OmpObjectList>{},
     maybe(":" >> nonemptyList(Parser<OmpAlignedClause::Modifier>{}))))
@@ -927,6 +948,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>{}))) ||
     "INITIALIZER" >> construct<OmpClause>(construct<OmpClause::Initializer>(
@@ -1016,6 +1039,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" >>
@@ -1251,6 +1276,10 @@ TYPE_PARSER(sourced( //
             IsDirective(llvm::omp::Directive::OMPD_depobj)) >=
         Parser<OmpDirectiveSpecification>{})))
 
+// OMP 5.2 14.1 Interop construct
+TYPE_PARSER(sourced(construct<OpenMPInteropConstruct>(
+    verbatim("INTEROP"_tok), sourced(Parser<OmpClauseList>{}))))
+
 // Standalone Constructs
 TYPE_PARSER(
     sourced( //
@@ -1263,7 +1292,9 @@ TYPE_PARSER(
         construct<OpenMPStandaloneConstruct>(Parser<OpenMPCancelConstruct>{}) ||
         construct<OpenMPStandaloneConstruct>(
             Parser<OmpMetadirectiveDirective>{}) ||
-        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 8cdbf8ed2a672..1674c45ac3096 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2180,6 +2180,30 @@ class UnparseVisitor {
     Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
     Walk(std::get<OmpObjectList>(x.t));
   }
+  void Unparse(const OmpInteropPreference &x) { Walk(x.v, ","); }
+  void Unparse(const OmpInitClause &x) {
+    using Modifier = OmpInitClause::Modifier;
+    auto &modifiers{std::get<std::optional<std::list<Modifier>>>(x.t)};
+    bool isTypeStart{true};
+    for (const Modifier &m : *modifiers) {
+      if (auto *interopPreferenceMod{
+              std::get_if<parser::OmpInteropPreference>(&m.u)}) {
+        Put("PREFER_TYPE(");
+        Walk(*interopPreferenceMod);
+        Put("),");
+      } else if (auto *interopTypeMod{
+                     std::get_if<parser::OmpInteropType>(&m.u)}) {
+        if (isTypeStart) {
+          isTypeStart = false;
+        } else {
+          Put(",");
+        }
+        Walk(*interopTypeMod);
+      }
+    }
+    Put(": ");
+    Walk(std::get<OmpObject>(x.t));
+  }
   void Unparse(const OmpMapClause &x) {
     using Modifier = OmpMapClause::Modifier;
     Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
@@ -2710,6 +2734,15 @@ class UnparseVisitor {
     Put("\n");
     EndOpenMP();
   }
+
+  void Unparse(const OpenMPInteropConstruct &x) {
+    BeginOpenMP();
+    Word("!$OMP INTEROP");
+    Walk(std::get<OmpClauseList>(x.t));
+    Put("\n");
+    EndOpenMP();
+  }
+
   void Unparse(const OpenMPDeclarativeAssumes &x) {
     BeginOpenMP();
     Word("!$OMP ASSUMES ");
@@ -3004,6 +3037,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(OmpInteropType, Value) // OMP InteropType
   WALK_NESTED_ENUM(OmpOrderClause, Ordering) // OMP ordering
   WALK_NESTED_ENUM(OmpOrderModifier, Value) // OMP order-modifier
   WALK_NESTED_ENUM(OmpPrescriptiveness, Value) // OMP prescriptiveness
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 6bddd629d607e..1e2ae6300114c 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -5720,6 +5720,88 @@ 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::set<const Symbol *> objectSymbolList;
+  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) {
+              if (OmpVerifyModifiers(initClause.v, llvm::omp::OMPC_init,
+                      GetContext().directiveSource, context_)) {
+
+                auto &modifiers{OmpGetModifiers(initClause.v)};
+                auto &&interopTypeModifier{
+                    OmpGetRepeatableModifier<parser::OmpInteropType>(
+                        modifiers)};
+                for (const auto &it : interopTypeModifier) {
+                  if (it->v == parser::OmpInteropType::Value::TargetSync) {
+                    ++targetSyncCount;
+                  } else {
+                    ++targetCount;
+                  }
+                }
+              }
+              const auto &interopVar{parser::Unwrap<parser::OmpObject>(
+                  std::get<parser::OmpObject>(initClause.v.t))};
+              const auto *name{parser::Unwrap<parser::Name>(interopVar)};
+              const auto *objectSymbol{name->symbol};
+              if (llvm::is_contained(objectSymbolList, objectSymbol)) {
+                context_.Say(GetContext().directiveSource,
+                    "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
+              } else {
+                objectSymbolList.insert(objectSymbol);
+              }
+            },
+            [&](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 *objectSymbol{name->symbol};
+              if (llvm::is_contained(objectSymbolList, objectSymbol)) {
+                context_.Say(GetContext().directiveSource,
+                    "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
+              } else {
+                objectSymbolList.insert(objectSymbol);
+              }
+            },
+            [&](const parser::OmpClause::Use &useClause) {
+              const auto &interopVar{
+                  parser::Unwrap<parser::OmpObject>(useClause.v)};
+              const auto *name{parser::Unwrap<parser::Name>(interopVar)};
+              const auto *objectSymbol{name->symbol};
+              if (llvm::is_contained(objectSymbolList, objectSymbol)) {
+                context_.Say(GetContext().directiveSource,
+                    "Each interop-var may be specified for at most one action-clause of each INTEROP construct."_err_en_US);
+              } else {
+                objectSymbolList.insert(objectSymbol);
+              }
+            },
+            [&](const auto &) {},
+        },
+        clause.u);
+  }
+  if (targetCount > 1 || targetSyncCount > 1) {
+    context_.Say(GetContext().directiveSource,
+        "Each interop-type may be specified at most once."_err_en_US);
+  }
+  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 d802afeefe72f..a8869561cf5ea 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::OpenMPDeclarativeConstruct &);
   void Leave(const parser::OpenMPDeclarativeConstruct &);
 
diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
index 73ad7751ee517..c84e832ee52a1 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -240,6 +240,38 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpExpectation>() {
   return desc;
 }
 
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropPreference>() {
+  static const OmpModifierDescriptor desc{
+      /*name=*/"interop-preference",
+      /*props=*/
+      {
+          {52, {OmpProperty::Unique}},
+      },
+      /*clauses=*/
+      {
+          {52, {Clause::OMPC_init}},
+      },
+  };
+  return desc;
+}
+
+template <>
+const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropType>() {
+  static const OmpModifierDescriptor desc{
+      /*name=*/"interop-type",
+      /*props=*/
+      {
+          {52, {OmpProperty::Required}},
+      },
+      /*clauses=*/
+      {
+          {52, {Clause::OMPC_init}},
+      },
+  };
+  return desc;
+}
+
 template <>
 const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpIterator>() {
   static const OmpModifierDescriptor desc{
diff --git a/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90 b/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90
new file mode 100644
index 0000000000000..f7920c09464ed
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/inteorp-construct.f90
@@ -0,0 +1,9 @@
+! REQUIRES: openmp_runtime
+! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=52 -o - %s 2>&1 | FileCheck %s
+
+! CHECK: not yet implemented: OpenMPInteropConstruct
+program interop_test
+  use omp_lib
+  integer(omp_interop_kind) :: obj
+  !$omp interop init(targetsync,target: obj)
+end program interop_test
diff --git a/flang/test/Parser/OpenMP/interop-construct.f90 b/flang/test/Parser/OpenMP/interop-construct.f90
new file mode 100644
index 0000000000000..a1781d559b46d
--- /dev/null
+++ b/flang/test/Parser/OpenMP/interop-construct.f90
@@ -0,0 +1,204 @@
+! REQUIRES: openmp_runtime
+! RUN: %flang_fc1 -fdebug-unparse -fopenmp-version...
[truncated]

@kiranchandramohan
Copy link
Contributor

@swatheesh-mcw Can you reproduce the CI failure locally? Can you have a look to find out why the CI is failing?

@swatheesh-mcw
Copy link
Contributor Author

Sure @kiranchandramohan!

@kiranchandramohan kiranchandramohan requested review from kparzysz and kiranchandramohan and removed request for kparzysz March 25, 2025 09:37
@swatheesh-mcw
Copy link
Contributor Author

Hi @kiranchandramohan, the build is working fine locally. I don't see any failures.

But checking the logs with the CI, I could see the following:


�_bk;t=1742826592286��[31mFAILED: �[0mtools/flang/examples/FlangOmpReport/CMakeFiles/flangOmpReport.dir/FlangOmpReportVisitor.cpp.o 

�_bk;t=1742826592286�CCACHE_CPP2=yes CCACHE_HASHDIR=yes /usr/bin/ccache /usr/bin/clang++ -DFLANG_INCLUDE_TESTS=1 -DFLANG_LITTLE_ENDIAN=1 -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/build/tools/flang/examples/FlangOmpReport -I/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/examples/FlangOmpReport -I/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/include -I/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/build/tools/flang/include -I/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/build/include -I/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/llvm/include -isystem /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/../mlir/include -isystem /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/build/tools/mlir/include -isystem /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/build/tools/clang/include -isystem /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/llvm/../clang/include -gmlt -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wno-deprecated-copy -Wno-string-conversion -Wno-ctad-maybe-unsupported -Wno-unused-command-line-argument -Wstring-conversion           -Wcovered-switch-default -Wno-nested-anon-types -O3 -DNDEBUG -fPIC  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -std=c++17 -MD -MT tools/flang/examples/FlangOmpReport/CMakeFiles/flangOmpReport.dir/FlangOmpReportVisitor.cpp.o -MF tools/flang/examples/FlangOmpReport/CMakeFiles/flangOmpReport.dir/FlangOmpReportVisitor.cpp.o.d -o tools/flang/examples/FlangOmpReport/CMakeFiles/flangOmpReport.dir/FlangOmpReportVisitor.cpp.o -c /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp

�_bk;t=1742826592286��[1m/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp:137:56: �[0m�[0;1;31merror: �[0m�[1mno member named 'v' in 'Fortran::parser::OpenMPInteropConstruct'�[0m

�_bk;t=1742826592286�                          std::get<OmpDirectiveName>(d.v.t).source};

�_bk;t=1742826592286��[0;1;32m                                                     ~ ^

�_bk;t=1742826592286��[0m�[1m/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/include/flang/Common/visit.h:52:7: �[0m�[0;1;30mnote: �[0min instantiation of function template specialization 'Fortran::parser::OpenMPCounterVisitor::getName(const OpenMPConstruct &)::(anonymous class)::operator()(const OpenMPStandaloneConstruct &)::(anonymous class)::operator()<const Fortran::parser::OpenMPInteropConstruct &>' requested here�[0m

�_bk;t=1742826592286�      VISIT_CASE_N(6)

�_bk;t=1742826592286��[0;1;32m      ^

�_bk;t=1742826592286��[0m�[1m/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/include/flang/Common/visit.h:40:14: �[0m�[0;1;30mnote: �[0mexpanded from macro 'VISIT_CASE_N'�[0m

�_bk;t=1742826592286�      return visitor(std::get<(LOW + N)>(std::forward<VARIANT>(u))...); \

�_bk;t=1742826592286��[0;1;32m             ^

�_bk;t=1742826592286��[0m�[1m/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/include/flang/Common/visit.h:78:12: �[0m�[0;1;30mnote: �[0min instantiation of function template specialization 'Fortran::common::log2visit::Log2VisitHelper<0UL, 6UL, std::basic_string<char>, Fortran::common::visitors<(lambda at /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp:132:21), (lambda at /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp:135:21)>, const std::variant<Fortran::parser::OpenMPSimpleStandaloneConstruct, Fortran::parser::OpenMPFlushConstruct, Fortran::parser::OpenMPCancelConstruct, Fortran::parser::OpenMPCancellationPointConstruct, Fortran::parser::OpenMPDepobjConstruct, Fortran::parser::OmpMetadirectiveDirective, Fortran::parser::OpenMPInteropConstruct> &>' requested here�[0m

�_bk;t=1742826592286�    return Log2VisitHelper<0, high, Result>(std::forward<VISITOR>(visitor),

�_bk;t=1742826592286��[0;1;32m           ^

�_bk;t=1742826592286��[0m�[1m/var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp:130:28: �[0m�[0;1;30mnote: �[0min instantiation of function template specialization 'Fortran::common::log2visit::visit<Fortran::common::visitors<(lambda at /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp:132:21), (lambda at /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-5b8n6-1/llvm-project/github-pull-requests/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp:135:21)>, const std::variant<Fortran::parser::OpenMPSimpleStandaloneConstruct, Fortran::parser::OpenMPFlushConstruct, Fortran::parser::OpenMPCancelConstruct, Fortran::parser::OpenMPCancellationPointConstruct, Fortran::parser::OpenMPDepobjConstruct, Fortran::parser::OmpMetadirectiveDirective, Fortran::parser::OpenMPInteropConstruct> &>' requested here�[0m

�_bk;t=1742826592286�            return common::visit(

�_bk;t=1742826592286��[0;1;32m                           ^

�_bk;t=1742826592286��[0m1 error generated.

�_bk;t=1742826592286�```

@kiranchandramohan
Copy link
Contributor

Thanks. Hope you can fix the issue in FlangOmpReportVisitor.cpp.
If you build flang/llvm with -DLLVM_BUILD_EXAMPLES=ON you might be able to reproduce on your machine.

@kparzysz
Copy link
Contributor

Thanks. Hope you can fix the issue in FlangOmpReportVisitor.cpp. If you build flang/llvm with -DLLVM_BUILD_EXAMPLES=ON you might be able to reproduce on your machine.

The examples can be built even without that flag, but you need to specify the targets manually, i.e.

make flangFeatureList
make flangOmpReport
make flangPrintFunctionNames

@swatheesh-mcw swatheesh-mcw force-pushed the revert-132005-revert-120584-swatheesh-interop-latest branch from aaaf865 to 8efec33 Compare March 28, 2025 09:36
@swatheesh-mcw
Copy link
Contributor Author

Hi @kiranchandramohan, I have refactored the code and modified the test case. Please let me know if any changes are required. Thanks!

@kiranchandramohan
Copy link
Contributor

Have you added %openmp_flags to the following three tests?

Lower/OpenMP/Todo/inteorp-construct.f90
Parser/OpenMP/interop-construct.f90
Semantics/OpenMP/interop-construct.f90

@swatheesh-mcw
Copy link
Contributor Author

swatheesh-mcw commented Mar 28, 2025

I have added %openmp_flags on Lower/OpenMP/Todo/inteorp-construct.f90.

Parser/OpenMP/interop-construct.f90 and Semantics/OpenMP/interop-construct.f90 already has -fopenmp as a parameter in the command. But if you want me to add %openmp_flags instead of -fopenmp, happy to do so!

Thanks!

@kiranchandramohan
Copy link
Contributor

I have added %openmp_flags on Lower/OpenMP/Todo/inteorp-construct.f90.

Parser/OpenMP/interop-construct.f90 and Semantics/OpenMP/interop-construct.f90 already has -fopenmp as a parameter in the command. But if you want me to add %openmp_flags instead of -fopenmp, happy to do so!

Thanks!

-fopenmp is not sufficient. %openmp_flags expands to the following:

# Determine if OpenMP runtime was built (enable OpenMP tests via REQUIRES in test file)
if config.have_openmp_rtl:
    config.available_features.add("openmp_runtime")
    # For the enabled OpenMP tests, add a substitution that is needed in the tests to find
    # the omp_lib.{h,mod} files, depending on whether the OpenMP runtime was built as a
    # project or runtime.
    if config.openmp_module_dir:
        config.substitutions.append(
            ("%openmp_flags", f"-fopenmp -J {config.openmp_module_dir}")
        )
    else:
        config.substitutions.append(("%openmp_flags", "-fopenmp"))

@swatheesh-mcw
Copy link
Contributor Author

I have added %openmp_flags on Lower/OpenMP/Todo/inteorp-construct.f90.
Parser/OpenMP/interop-construct.f90 and Semantics/OpenMP/interop-construct.f90 already has -fopenmp as a parameter in the command. But if you want me to add %openmp_flags instead of -fopenmp, happy to do so!
Thanks!

-fopenmp is not sufficient. %openmp_flags expands to the following:

# Determine if OpenMP runtime was built (enable OpenMP tests via REQUIRES in test file)
if config.have_openmp_rtl:
    config.available_features.add("openmp_runtime")
    # For the enabled OpenMP tests, add a substitution that is needed in the tests to find
    # the omp_lib.{h,mod} files, depending on whether the OpenMP runtime was built as a
    # project or runtime.
    if config.openmp_module_dir:
        config.substitutions.append(
            ("%openmp_flags", f"-fopenmp -J {config.openmp_module_dir}")
        )
    else:
        config.substitutions.append(("%openmp_flags", "-fopenmp"))

Great! I will add the flag then. Thanks!

Copy link
Contributor

@kiranchandramohan kiranchandramohan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG. Thanks for the updates.

@kiranchandramohan kiranchandramohan merged commit fe30cf1 into llvm:main Mar 28, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:openmp OpenMP related changes to Clang flang:fir-hlfir flang:openmp flang:parser flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants