[flang-commits] [flang] [flang][OpenMP] Fix USE-associated declare reduction symbol resolution (PR #200328)
via flang-commits
flang-commits at lists.llvm.org
Thu May 28 22:07:57 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-openmp
Author: Matt (MattPD)
<details>
<summary>Changes</summary>
When a declare reduction is accessed via USE association, the symbol in
the consuming scope has `UseDetails` rather than `UserReductionDetails`.
Calling `detailsIf<UserReductionDetails>()` directly on such a symbol
returns nullptr. This causes two distinct failure modes:
1. **Operator/identifier validation** (`CheckReductionOperator`): named
reductions and defined operators are rejected with "Invalid reduction
identifier" or "Invalid reduction operator".
2. **Type validation** (`CheckSymbolSupportsType`, `IsReductionAllowedForType`):
the type compatibility check cannot find `UserReductionDetails` for the
reduction, producing "The type of 'x' is incompatible with the
reduction operator".
This bug has existed since `UserReductionDetails` was introduced (June
2025). Only intrinsic operator reductions (like `+`) worked via USE,
because they bypass the operator validation check and their type checking
was handled by a global module scan workaround (added Feb 2026).
**Fix:** Add `GetUltimate()` at 4 locations in `check-omp-structure.cpp` to resolve
through `UseDetails` chains before checking for `UserReductionDetails`:
two in `CheckReductionOperator` (validation paths 1 and 2 above), one in
`CheckSymbolSupportsType`, and one in `IsReductionAllowedForType`.
Fixes https://github.com/llvm/llvm-project/issues/184932
---
Full diff: https://github.com/llvm/llvm-project/pull/200328.diff
2 Files Affected:
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+5-4)
- (added) flang/test/Semantics/OpenMP/declare-reduction-use-assoc-named.f90 (+82)
``````````diff
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index ff41f49d88b32..c450c3fbfeb43 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -3847,7 +3847,7 @@ bool OmpStructureChecker::CheckReductionOperator(
std::string mangled{MangleDefinedOperator(definedOp->v.symbol->name())};
const Scope &scope{definedOp->v.symbol->owner()};
if (const Symbol *symbol{scope.FindSymbol(mangled)}) {
- if (symbol->detailsIf<UserReductionDetails>()) {
+ if (symbol->GetUltimate().detailsIf<UserReductionDetails>()) {
return true;
}
}
@@ -3865,7 +3865,7 @@ bool OmpStructureChecker::CheckReductionOperator(
valid =
llvm::is_contained({"max", "min", "iand", "ior", "ieor"}, realName);
if (!valid) {
- valid = name->symbol->detailsIf<UserReductionDetails>();
+ valid = name->symbol->GetUltimate().detailsIf<UserReductionDetails>();
}
}
if (!valid) {
@@ -3948,8 +3948,9 @@ void OmpStructureChecker::CheckReductionObjects(
static bool CheckSymbolSupportsType(const Scope &scope,
const parser::CharBlock &name, const DeclTypeSpec &type) {
if (const auto *symbol{scope.FindSymbol(name)}) {
+ const auto &ultimate{symbol->GetUltimate()};
if (const auto *reductionDetails{
- symbol->detailsIf<UserReductionDetails>()}) {
+ ultimate.detailsIf<UserReductionDetails>()}) {
return reductionDetails->SupportsType(type);
}
}
@@ -4063,7 +4064,7 @@ static bool IsReductionAllowedForType(
// if the symbol has UserReductionDetails, and if so, the type is
// supported.
if (const auto *reductionDetails{
- name->symbol->detailsIf<UserReductionDetails>()}) {
+ name->symbol->GetUltimate().detailsIf<UserReductionDetails>()}) {
return reductionDetails->SupportsType(type);
}
diff --git a/flang/test/Semantics/OpenMP/declare-reduction-use-assoc-named.f90 b/flang/test/Semantics/OpenMP/declare-reduction-use-assoc-named.f90
new file mode 100644
index 0000000000000..2b7b3864bdef2
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/declare-reduction-use-assoc-named.f90
@@ -0,0 +1,82 @@
+! RUN: %flang_fc1 -fopenmp -fopenmp-version=52 -fsyntax-only %s
+! RUN: %flang_fc1 -fopenmp -fopenmp-version=52 -fdebug-dump-symbols %s 2>&1 | FileCheck %s
+
+! Test that USE-associated named reductions and user-defined operator
+! reductions are correctly resolved through UseDetails.
+
+module m_named_reduction
+ type :: t
+ integer :: val = 0
+ end type
+ !$omp declare reduction(myred:t:omp_out%val=omp_out%val+omp_in%val) &
+ !$omp initializer(omp_priv=t(0))
+end module
+
+module m_defined_op_reduction
+ type :: dt
+ real :: x = 0.0
+ end type
+ interface operator(.combine.)
+ module procedure combine_fn
+ end interface
+ !$omp declare reduction(.combine.:dt:omp_out%x=omp_out%x+omp_in%x) &
+ !$omp initializer(omp_priv=dt(0.0))
+contains
+ type(dt) function combine_fn(a, b)
+ type(dt), intent(in) :: a, b
+ combine_fn%x = a%x + b%x
+ end function
+end module
+
+program test_use_assoc_reductions
+ use m_named_reduction
+ use m_defined_op_reduction
+ type(t) :: x
+ type(dt) :: y
+ integer :: i
+ x = t(0)
+ y = dt(0.0)
+ ! Both should compile without error: reductions are accessible via USE.
+ !$omp parallel do reduction(myred:x)
+ do i = 1, 10
+ x%val = x%val + 1
+ end do
+ !$omp end parallel do
+ !$omp parallel do reduction(.combine.:y)
+ do i = 1, 10
+ y%x = y%x + 1.0
+ end do
+ !$omp end parallel do
+ print *, x%val, y%x
+end program
+
+! Test defined operator with external interface via USE (issue #184932 pattern).
+! Uses !$omp parallel (not parallel do) to cover that variant.
+module m_external_op
+ type :: ty
+ integer :: ii
+ end type
+ interface operator(.x.)
+ function h(a, b)
+ import :: ty
+ type(ty), intent(in) :: a, b
+ end function
+ end interface
+ !$omp declare reduction(.x.:ty:omp_out=ty(1)) initializer(omp_priv=ty(0))
+end module
+
+subroutine test_external_op_reduction
+ use m_external_op
+ type(ty) :: v
+ v = ty(0)
+ !$omp parallel reduction(.x.:v)
+ v = ty(1)
+ !$omp end parallel
+end subroutine
+
+!CHECK: Module scope: m_named_reduction
+!CHECK: myred, PUBLIC: UserReductionDetails TYPE(t)
+!CHECK: Module scope: m_defined_op_reduction
+!CHECK: op.combine., PUBLIC: UserReductionDetails TYPE(dt)
+!CHECK: Module scope: m_external_op
+!CHECK: op.x., PUBLIC: UserReductionDetails TYPE(ty)
``````````
</details>
https://github.com/llvm/llvm-project/pull/200328
More information about the flang-commits
mailing list