[flang-commits] [flang] 3488652 - [flang][OpenMP] Implement better GetOmpObjectList, NFC (#195171)

via flang-commits flang-commits at lists.llvm.org
Fri May 1 05:56:34 PDT 2026


Author: Krzysztof Parzyszek
Date: 2026-05-01T07:56:30-05:00
New Revision: 3488652381157488ea6a30854242506d986c67b1

URL: https://github.com/llvm/llvm-project/commit/3488652381157488ea6a30854242506d986c67b1
DIFF: https://github.com/llvm/llvm-project/commit/3488652381157488ea6a30854242506d986c67b1.diff

LOG: [flang][OpenMP] Implement better GetOmpObjectList, NFC (#195171)

The current implementation lists all clauses that contain an
OmpObjectList, together with the means of extracting it. For a clause
that is not listed, it returns nullptr.

The new implementation traverses an AST node until it finds an
OmpObjectList, and when one isn't found, returns nullptr. This is
actually simpler and is independent of any changes to the AST.

Added: 
    

Modified: 
    flang/include/flang/Parser/openmp-utils.h
    flang/lib/Parser/openmp-utils.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 1952c4297f828..b86f5fcdadcfb 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -132,88 +132,44 @@ const OpenMPLoopConstruct *GetOmpLoop(const ExecutionPartConstruct &x);
 const DoConstruct *GetDoConstruct(const ExecutionPartConstruct &x);
 
 namespace detail {
-// Clauses with flangClass = "OmpObjectList".
-using MemberObjectListClauses =
-    std::tuple<OmpClause::Copyin, OmpClause::Copyprivate, OmpClause::Exclusive,
-        OmpClause::Firstprivate, OmpClause::HasDeviceAddr, OmpClause::Inclusive,
-        OmpClause::IsDevicePtr, OmpClause::Link, OmpClause::Private,
-        OmpClause::Shared, OmpClause::UseDeviceAddr, OmpClause::UseDevicePtr>;
-
-// Clauses with flangClass = "OmpSomeClause", and OmpObjectList a
-// member of tuple OmpSomeClause::t.
-using TupleObjectListClauses = std::tuple<OmpClause::AdjustArgs,
-    OmpClause::Affinity, OmpClause::Aligned, OmpClause::Allocate,
-    OmpClause::Enter, OmpClause::From, OmpClause::InReduction,
-    OmpClause::Lastprivate, OmpClause::Linear, OmpClause::Map,
-    OmpClause::Reduction, OmpClause::TaskReduction, OmpClause::To>;
-
-// Does U have WrapperTrait (i.e. has a member 'v'), and if so, is T the
-// type of v?
-template <typename T, typename U, bool IsWrapper> struct WrappedInType {
-  static constexpr bool value{false};
-};
-
-template <typename T, typename U> struct WrappedInType<T, U, true> {
-  static constexpr bool value{std::is_same_v<T, decltype(U::v)>};
-};
-
-// Same as WrappedInType, but with a list of types Us. Satisfied if any
-// type U in Us satisfies WrappedInType<T, U>.
-template <typename...> struct WrappedInTypes;
-
-template <typename T> struct WrappedInTypes<T> {
-  static constexpr bool value{false};
-};
+struct OmpObjectListScope {
+  template <typename T> static const OmpObjectList *Get(const T &x) {
+    if constexpr (std::is_same_v<OmpObjectList, T>) {
+      return &x;
+    } else if constexpr (WrapperTrait<T>) {
+      return Get(x.v);
+    } else if constexpr (UnionTrait<T>) {
+      return std::visit([](auto &&s) { return Get(s); }, x.u);
+    } else if constexpr (TupleTrait<T>) {
+      return GetFromTuple(
+          x.t, std::make_index_sequence<std::tuple_size_v<decltype(x.t)>>{});
+    } else if constexpr (ConstraintTrait<T>) {
+      return Get(x.thing);
+    } else {
+      return nullptr;
+    }
+  }
 
-template <typename T, typename U, typename... Us>
-struct WrappedInTypes<T, U, Us...> {
-  static constexpr bool value{WrappedInType<T, U, WrapperTrait<U>>::value ||
-      WrappedInTypes<T, Us...>::value};
-};
+  template <typename T>
+  static const OmpObjectList *Get(const common::Indirection<T> &x) {
+    return Get(x.value());
+  }
 
-// Same as WrappedInTypes, but takes type list in a form of a tuple or
-// a variant.
-template <typename...> struct WrappedInTupleOrVariant {
-  static constexpr bool value{false};
-};
-template <typename T, typename... Us>
-struct WrappedInTupleOrVariant<T, std::tuple<Us...>> {
-  static constexpr bool value{WrappedInTypes<T, Us...>::value};
-};
-template <typename T, typename... Us>
-struct WrappedInTupleOrVariant<T, std::variant<Us...>> {
-  static constexpr bool value{WrappedInTypes<T, Us...>::value};
+  template <typename... Ts, size_t... Is>
+  static const OmpObjectList *GetFromTuple(
+      const std::tuple<Ts...> &t, std::index_sequence<Is...>) {
+    const OmpObjectList *objects{nullptr};
+    ((objects = objects ? objects : Get(std::get<Is>(t))), ...);
+    return objects;
+  }
 };
-template <typename T, typename U>
-constexpr bool WrappedInTupleOrVariantV{WrappedInTupleOrVariant<T, U>::value};
 } // namespace detail
 
 template <typename T> const OmpObjectList *GetOmpObjectList(const T &clause) {
-  using namespace detail;
   static_assert(std::is_class_v<T>, "Unexpected argument type");
-
-  if constexpr (common::HasMember<T, decltype(OmpClause::u)>) {
-    if constexpr (common::HasMember<T, MemberObjectListClauses>) {
-      return &clause.v;
-    } else if constexpr (common::HasMember<T, TupleObjectListClauses>) {
-      return &std::get<OmpObjectList>(clause.v.t);
-    } else {
-      return nullptr;
-    }
-  } else if constexpr (WrappedInTupleOrVariantV<T, TupleObjectListClauses>) {
-    return &std::get<OmpObjectList>(clause.t);
-  } else if constexpr (WrappedInTupleOrVariantV<T, decltype(OmpClause::u)>) {
-    return nullptr;
-  } else {
-    // The condition should be type-dependent, but it should always be false.
-    static_assert(sizeof(T) < 0 && "Unexpected argument type");
-  }
+  return detail::OmpObjectListScope::Get(clause);
 }
 
-const OmpObjectList *GetOmpObjectList(const OmpClause &clause);
-const OmpObjectList *GetOmpObjectList(const OmpClause::Depend &clause);
-const OmpObjectList *GetOmpObjectList(const OmpDependClause::TaskDep &x);
-
 template <typename T>
 const T *GetFirstArgument(const OmpDirectiveSpecification &spec) {
   for (const OmpArgument &arg : spec.Arguments().v) {

diff  --git a/flang/lib/Parser/openmp-utils.cpp b/flang/lib/Parser/openmp-utils.cpp
index b1824d13b2dab..74277eb9e0ac8 100644
--- a/flang/lib/Parser/openmp-utils.cpp
+++ b/flang/lib/Parser/openmp-utils.cpp
@@ -152,23 +152,6 @@ const DoConstruct *GetDoConstruct(const ExecutionPartConstruct &x) {
   return nullptr;
 }
 
-const OmpObjectList *GetOmpObjectList(const OmpClause &clause) {
-  return common::visit([](auto &&s) { return GetOmpObjectList(s); }, clause.u);
-}
-
-const OmpObjectList *GetOmpObjectList(const OmpClause::Depend &clause) {
-  return common::visit(
-      common::visitors{
-          [](const OmpDoacross &) -> const OmpObjectList * { return nullptr; },
-          [](const OmpDependClause::TaskDep &x) { return GetOmpObjectList(x); },
-      },
-      clause.v.u);
-}
-
-const OmpObjectList *GetOmpObjectList(const OmpDependClause::TaskDep &x) {
-  return &std::get<OmpObjectList>(x.t);
-}
-
 const OmpClause *FindClause(
     const OmpDirectiveSpecification &spec, llvm::omp::Clause clauseId) {
   for (auto &clause : spec.Clauses().v) {


        


More information about the flang-commits mailing list