[flang-commits] [flang] [flang][OpenMP] Remove over-broad global scan for declare reduction symbols (PR #200329)
via flang-commits
flang-commits at lists.llvm.org
Thu May 28 22:36:16 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Matt (MattPD)
<details>
<summary>Changes</summary>
`CheckSymbolSupportsType` walked all module scopes in the global scope to
find reduction declarations. This incorrectly matched reductions from
modules that were never `USE`'d by the current scope, or reductions that
were excluded via `USE...ONLY`.
Now that #<!-- -->200328 added `GetUltimate()` resolution, `FindSymbol` correctly
resolves USE-associated reductions through their `UseDetails` chains. The
global scan workaround is no longer needed.
Depends on #<!-- -->200328.
Fixes https://github.com/llvm/llvm-project/issues/200300
Assisted-by: Claude Opus 4.6.
---
Full diff: https://github.com/llvm/llvm-project/pull/200329.diff
3 Files Affected:
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+5-22)
- (added) flang/test/Semantics/OpenMP/declare-reduction-overbroad-lookup.f90 (+32)
- (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..96c4e84bd8963 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,29 +3948,12 @@ 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);
}
}
- // Look through module scopes in the global scope.
- // This covers reductions declared in a module and used via USE association.
- const SemanticsContext &semCtx{scope.context()};
- Scope &global = const_cast<SemanticsContext &>(semCtx).globalScope();
- for (const Scope &child : global.children()) {
- if (child.kind() == Scope::Kind::Module) {
- if (const auto *symbol{child.FindSymbol(name)}) {
- // Skip PRIVATE reductions that aren't visible in the current scope.
- if (symbol->attrs().test(Attr::PRIVATE)) {
- continue;
- }
- if (const auto *reductionDetails{
- symbol->detailsIf<UserReductionDetails>()}) {
- return reductionDetails->SupportsType(type);
- }
- }
- }
- }
return false;
}
@@ -4063,7 +4046,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-overbroad-lookup.f90 b/flang/test/Semantics/OpenMP/declare-reduction-overbroad-lookup.f90
new file mode 100644
index 0000000000000..1db247b4eaff5
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/declare-reduction-overbroad-lookup.f90
@@ -0,0 +1,32 @@
+! RUN: not %flang_fc1 -fopenmp -fopenmp-version=52 %s 2>&1 | FileCheck %s
+
+! Test that a declare reduction from a module that was not USE'd (or only
+! partially USE'd) is not incorrectly found during type checking.
+! Related: https://github.com/llvm/llvm-project/issues/200300
+
+module m_with_reduction
+ type :: t
+ integer :: val = 0
+ end type
+ !$omp declare reduction(+:t:omp_out%val=omp_out%val+omp_in%val) &
+ !$omp initializer(omp_priv=t(0))
+end module
+
+! proxy re-exports only the type, not the reduction
+module m_proxy
+ use m_with_reduction, only: t
+end module
+
+program test_overbroad_lookup
+ use m_proxy
+ type(t) :: x
+ integer :: i
+ x = t(0)
+ !CHECK: error: The type of 'x' is incompatible with the reduction operator.
+ !$omp parallel do reduction(+:x)
+ do i = 1, 10
+ x%val = x%val + 1
+ end do
+ !$omp end parallel do
+ print *, x%val
+end program
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/200329
More information about the flang-commits
mailing list