[flang-commits] [flang] [flang][OpenMP] Diagnose task reduction array sections and elements (PR #215997)

via flang-commits flang-commits at lists.llvm.org
Mon Sep 7 21:13:31 PDT 2026


================
@@ -183,6 +181,146 @@ static bool hasPrivatizedArrayElementReduction(
   return false;
 }
 
+static bool
+hasPartialArrayReductionObject(llvm::ArrayRef<Object> reductionObjects,
+                               semantics::SemanticsContext &semaCtx) {
+  for (const Object &object : reductionObjects) {
+    if (!object.ref() || isWholeArraySection(object, semaCtx))
+      continue;
+    if (evaluate::IsArraySection(*object.ref()))
+      return true;
+  }
+  return false;
+}
+
+static void
+checkTaskModifierPartialArrayReduction(mlir::Location loc,
+                                       semantics::SemanticsContext &semaCtx,
+                                       const List<Clause> &clauses) {
+  bool found = false;
+  ClauseFinder::findRepeatableClause<clause::Reduction>(
+      clauses,
+      [&](const clause::Reduction &reductionClause, const parser::CharBlock &) {
+        if (found)
+          return;
+
+        using ReductionModifier = clause::Reduction::ReductionModifier;
+        const auto &modifier =
+            std::get<std::optional<ReductionModifier>>(reductionClause.t);
+        if (!modifier || *modifier != ReductionModifier::Task)
+          return;
+
+        const ObjectList &objects = std::get<ObjectList>(reductionClause.t);
+        found = hasPartialArrayReductionObject(objects, semaCtx);
+      });
+  if (found)
+    TODO(loc, "REDUCTION with TASK modifier of a partial array section");
+}
+
+static bool isArrayElementReductionObject(const Object &object) {
+  return object.ref() && object.ref()->Rank() == 0 &&
+         evaluate::IsArrayElement(*object.ref(), /*intoSubstring=*/false);
+}
+
+static bool
+hasArrayElementReductionObject(llvm::ArrayRef<Object> reductionObjects) {
+  return llvm::any_of(reductionObjects, isArrayElementReductionObject);
+}
+
+static bool isUserDefinedReductionOperator(
+    const clause::ReductionOperator &reductionOperator, const Object &object,
+    lower::AbstractConverter &converter, semantics::SemanticsContext &semaCtx) {
+  const semantics::Symbol *objectSymbol = object.sym();
+  const semantics::DeclTypeSpec *objectType =
+      objectSymbol ? objectSymbol->GetUltimate().GetType() : nullptr;
+  if (!objectType)
+    return false;
+
+  return common::visit(
+      common::visitors{
+          [&](const clause::DefinedOperator &definedOperator) {
+            return common::visit(
+                common::visitors{
+                    [&](const clause::DefinedOperator::IntrinsicOperator &op) {
+                      using IntrinsicOperator =
+                          clause::DefinedOperator::IntrinsicOperator;
+                      switch (op) {
+                      case IntrinsicOperator::Add:
+                      case IntrinsicOperator::Multiply:
+                      case IntrinsicOperator::AND:
+                      case IntrinsicOperator::OR:
+                      case IntrinsicOperator::EQV:
+                      case IntrinsicOperator::NEQV:
+                        break;
+                      default:
+                        return false;
+                      }
+
+                      parser::CharBlock mangledName =
+                          semantics::omp::MangledIntrinsicOperatorReductionName(
+                              ReductionProcessor::toParserIntrinsicOperator(op),
+                              semaCtx);
+                      return semantics::omp::FindUserReductionSymbol(
+                                 converter.getCurrentScope(), mangledName,
+                                 objectType) != nullptr;
+                    },
+                    [&](const clause::DefinedOperator::DefinedOpName &op) {
+                      const semantics::Symbol *operatorSymbol = op.v.sym();
+                      return operatorSymbol &&
+                             semantics::omp::FindOperatorUserReductionSymbol(
+                                 converter.getCurrentScope(), *operatorSymbol,
+                                 objectType);
+                    },
+                },
+                definedOperator.u);
+          },
+          [&](const clause::ProcedureDesignator &procedureDesignator) {
+            const semantics::Symbol *symbol = procedureDesignator.v.sym();
+            return (symbol &&
+                    symbol->GetUltimate()
+                        .detailsIf<semantics::UserReductionDetails>()) ||
+                   ReductionProcessor::findUserDefinedReductionForIntrinsic(
+                       converter.getCurrentScope(), procedureDesignator,
+                       objectType) != nullptr;
+          },
+      },
+      reductionOperator.u);
+}
+
+template <typename ReductionClause>
+static bool
+hasUserDefinedArrayElementReduction(const List<Clause> &clauses,
+                                    lower::AbstractConverter &converter,
+                                    semantics::SemanticsContext &semaCtx) {
+  bool found = false;
+  ClauseFinder::findRepeatableClause<ReductionClause>(
+      clauses,
+      [&](const ReductionClause &reductionClause, const parser::CharBlock &) {
+        if (found)
+          return;
+
+        const auto &reductionOperators =
+            std::get<clause::ReductionOperatorList>(reductionClause.t);
+        assert(reductionOperators.size() == 1 &&
+               "expected one reduction operator");
+        const ObjectList &objects = std::get<ObjectList>(reductionClause.t);
+        found = llvm::any_of(objects, [&](const Object &object) {
+          return isArrayElementReductionObject(object) &&
+                 isUserDefinedReductionOperator(reductionOperators.front(),
+                                                object, converter, semaCtx);
+        });
+      });
+  return found;
+}
+
+static void checkUserDefinedArrayElementReduction(
+    mlir::Location loc, lower::AbstractConverter &converter,
+    semantics::SemanticsContext &semaCtx, const List<Clause> &clauses) {
+  if (hasUserDefinedArrayElementReduction<clause::Reduction>(clauses, converter,
----------------
MattPD wrote:

Confirmed fixed.

https://github.com/llvm/llvm-project/pull/215997


More information about the flang-commits mailing list