[flang-commits] [flang] [flang][OpenMP] Catch assumed-rank/size variables for privatization a… (PR #152764)

via flang-commits flang-commits at lists.llvm.org
Fri Aug 8 10:17:03 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics

@llvm/pr-subscribers-flang-openmp

Author: Tom Eccles (tblah)

<details>
<summary>Changes</summary>

…nd reduction

Fixes #<!-- -->152312

Assumed size is valid for privatization and simple examples generate sensible looking HLFIR.

---
Full diff: https://github.com/llvm/llvm-project/pull/152764.diff


4 Files Affected:

- (modified) flang/lib/Lower/Support/PrivateReductionUtils.cpp (+2) 
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+19-5) 
- (added) flang/test/Lower/OpenMP/Todo/assumed-rank-privatization.f90 (+9) 
- (added) flang/test/Semantics/OpenMP/reduction-assumed.f90 (+53) 


``````````diff
diff --git a/flang/lib/Lower/Support/PrivateReductionUtils.cpp b/flang/lib/Lower/Support/PrivateReductionUtils.cpp
index fff060b79c9fe..1b09801c607c6 100644
--- a/flang/lib/Lower/Support/PrivateReductionUtils.cpp
+++ b/flang/lib/Lower/Support/PrivateReductionUtils.cpp
@@ -616,6 +616,8 @@ void PopulateInitAndCleanupRegionsHelper::populateByRefInitAndCleanupRegions() {
     assert(sym && "Symbol information is required to privatize derived types");
     assert(!scalarInitValue && "ScalarInitvalue is unused for privatization");
   }
+  if (hlfir::Entity{moldArg}.isAssumedRank())
+    TODO(loc, "Privatization of assumed rank variable");
   mlir::Type valTy = fir::unwrapRefType(argType);
 
   if (fir::isa_trivial(valTy)) {
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index cbe6b2c68bf05..bf126bbb0d8c1 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2891,7 +2891,8 @@ static bool CheckSymbolSupportsType(const Scope &scope,
 
 static bool IsReductionAllowedForType(
     const parser::OmpReductionIdentifier &ident, const DeclTypeSpec &type,
-    const Scope &scope, SemanticsContext &context) {
+    bool cannotBeBuiltinReduction, const Scope &scope,
+    SemanticsContext &context) {
   auto isLogical{[](const DeclTypeSpec &type) -> bool {
     return type.category() == DeclTypeSpec::Logical;
   }};
@@ -2902,6 +2903,10 @@ static bool IsReductionAllowedForType(
   auto checkOperator{[&](const parser::DefinedOperator &dOpr) {
     if (const auto *intrinsicOp{
             std::get_if<parser::DefinedOperator::IntrinsicOperator>(&dOpr.u)}) {
+      if (cannotBeBuiltinReduction) {
+        return false;
+      }
+
       // OMP5.2: The type [...] of a list item that appears in a
       // reduction clause must be valid for the combiner expression
       // See F2023: Table 10.2
@@ -2953,7 +2958,8 @@ static bool IsReductionAllowedForType(
         // IAND: arguments must be integers: F2023 16.9.100
         // IEOR: arguments must be integers: F2023 16.9.106
         // IOR: arguments must be integers: F2023 16.9.111
-        if (type.IsNumeric(TypeCategory::Integer)) {
+        if (type.IsNumeric(TypeCategory::Integer) &&
+            !cannotBeBuiltinReduction) {
           return true;
         }
       } else if (realName == "max" || realName == "min") {
@@ -2961,8 +2967,9 @@ static bool IsReductionAllowedForType(
         // F2023 16.9.135
         // MIN: arguments must be integer, real, or character:
         // F2023 16.9.141
-        if (type.IsNumeric(TypeCategory::Integer) ||
-            type.IsNumeric(TypeCategory::Real) || isCharacter(type)) {
+        if ((type.IsNumeric(TypeCategory::Integer) ||
+                type.IsNumeric(TypeCategory::Real) || isCharacter(type)) &&
+            !cannotBeBuiltinReduction) {
           return true;
         }
       }
@@ -2995,9 +3002,16 @@ void OmpStructureChecker::CheckReductionObjectTypes(
   GetSymbolsInObjectList(objects, symbols);
 
   for (auto &[symbol, source] : symbols) {
+    // Built in reductions require types which can be used in their initializer
+    // and combiner expressions. For example, for +:
+    // r = 0; r = r + r2
+    // But it might be valid to use these with DECLARE REDUCTION.
+    // Assumed size is already caught elsewhere.
+    bool cannotBeBuiltinReduction{evaluate::IsAssumedRank(*symbol)};
     if (auto *type{symbol->GetType()}) {
       const auto &scope{context_.FindScope(symbol->name())};
-      if (!IsReductionAllowedForType(ident, *type, scope, context_)) {
+      if (!IsReductionAllowedForType(
+              ident, *type, cannotBeBuiltinReduction, scope, context_)) {
         context_.Say(source,
             "The type of '%s' is incompatible with the reduction operator."_err_en_US,
             symbol->name());
diff --git a/flang/test/Lower/OpenMP/Todo/assumed-rank-privatization.f90 b/flang/test/Lower/OpenMP/Todo/assumed-rank-privatization.f90
new file mode 100644
index 0000000000000..e57833a1013b6
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/assumed-rank-privatization.f90
@@ -0,0 +1,9 @@
+! RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
+
+! CHECK: not yet implemented: Privatization of assumed rank variable
+subroutine assumedPriv(a)
+  integer :: a(..)
+
+  !$omp parallel private(a)
+  !$omp end parallel
+end
diff --git a/flang/test/Semantics/OpenMP/reduction-assumed.f90 b/flang/test/Semantics/OpenMP/reduction-assumed.f90
new file mode 100644
index 0000000000000..0bc8cd318a74d
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/reduction-assumed.f90
@@ -0,0 +1,53 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp
+
+! Types for built in reductions must have types which are valid for the
+! initialization and combiner expressions in the spec. This implies assumed
+! rank and assumed size cannot be used.
+
+subroutine assumedRank1(a)
+  integer :: a(..)
+
+  ! ERROR: The type of 'a' is incompatible with the reduction operator.
+  !$omp parallel reduction(+:a)
+  !$omp end parallel
+end
+
+subroutine assumedRank2(a)
+  integer :: a(..)
+
+  ! ERROR: The type of 'a' is incompatible with the reduction operator.
+  !$omp parallel reduction(min:a)
+  !$omp end parallel
+end
+
+subroutine assumedRank3(a)
+  integer :: a(..)
+
+  ! ERROR: The type of 'a' is incompatible with the reduction operator.
+  !$omp parallel reduction(iand:a)
+  !$omp end parallel
+end
+
+subroutine assumedSize1(a)
+  integer :: a(*)
+
+  ! ERROR: Whole assumed-size array 'a' may not appear here without subscripts
+  !$omp parallel reduction(+:a)
+  !$omp end parallel
+end
+
+subroutine assumedSize2(a)
+  integer :: a(*)
+
+  ! ERROR: Whole assumed-size array 'a' may not appear here without subscripts
+  !$omp parallel reduction(max:a)
+  !$omp end parallel
+end
+
+subroutine assumedSize3(a)
+  integer :: a(*)
+
+  ! ERROR: Whole assumed-size array 'a' may not appear here without subscripts
+  !$omp parallel reduction(ior:a)
+  !$omp end parallel
+end

``````````

</details>


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


More information about the flang-commits mailing list