[flang-commits] [flang] [llvm] [flang][OpenMP] Fix crash on standalone ordered with depend(source|sink:) (PR #200193)
Carlos Seo via flang-commits
flang-commits at lists.llvm.org
Thu May 28 11:52:28 PDT 2026
https://github.com/ceseo updated https://github.com/llvm/llvm-project/pull/200193
>From b8c306bd1916189cfa99286d1aa0f8da1f0a8730 Mon Sep 17 00:00:00 2001
From: Carlos Seo <carlos.seo at linaro.org>
Date: Wed, 27 May 2026 22:11:11 -0300
Subject: [PATCH] [flang][OpenMP] Fix crash on standalone ordered with
depend(source|sink:)
A standalone ordered construct using the (pre-5.2) depend(source) /
depend(sink:) spelling crashed flang with an assertion failure in
buildConstructQueue ("Construct decomposition failed"), or emitted a
TODO when assertions were disabled.
These dependence types are valid on ordered since OpenMP 4.5 (and only
deprecated in 5.2 in favor of the dedicated doacross clause), but flang
was rewriting them into the internal OMPC_doacross clause. Construct
decomposition only permits doacross on ordered from OpenMP 5.2
(matching the doacross keyword in the directive-clause table), so
decomposition produced an empty output and tripped the assertion at every
OpenMP version below 5.2 (including the default 3.1).
Fix the representation: extend DependT with an optional iteration
vector (mirroring DoacrossT::Vector), so that the depend(source|sink:)
spelling can keep its surface identity as a depend clause. The
directive-clause table already allows OMPC_depend on ordered at all
versions, so decomposition succeeds naturally and no special-case is
needed in lowering. The doacross clause representation is preserved for
the 5.2+ keyword form.
Fixes #198972
---
flang/lib/Lower/OpenMP/Clauses.cpp | 25 +++++++++++++++++--
.../test/Lower/OpenMP/Todo/ordered-depend.f90 | 20 +++++++++++++++
llvm/include/llvm/Frontend/OpenMP/ClauseT.h | 8 +++++-
3 files changed, 50 insertions(+), 3 deletions(-)
create mode 100644 flang/test/Lower/OpenMP/Todo/ordered-depend.f90
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 10fd906db931b..03852dc9e7d74 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -730,9 +730,24 @@ Depend makeDepend(const parser::OmpDependClause::TaskDep &inp,
m0 ? makeIterator(*m0, semaCtx) : std::optional<Iterator>{};
return Depend{{/*DependenceType=*/makeDepType(*m1),
/*Iterator=*/std::move(maybeIter),
+ /*Vector=*/std::nullopt,
/*LocatorList=*/makeObjects(t1, semaCtx)}};
}
+// depend(source) / depend(sink: vec) on ordered (4.5..5.1 spelling, deprecated
+// in 5.2 in favor of the dedicated doacross clause). Internally modelled as a
+// Depend with the optional iteration Vector populated and an empty
+// LocatorList, mirroring the shape of Doacross.
+Depend makeDependDoacross(const parser::OmpDoacross &doa,
+ semantics::SemanticsContext &semaCtx) {
+ Doacross doacross = makeDoacross(doa, semaCtx);
+ return Depend{
+ {/*DependenceType=*/std::get<Doacross::DependenceType>(doacross.t),
+ /*Iterator=*/std::nullopt,
+ /*Vector=*/std::get<Doacross::Vector>(std::move(doacross.t)),
+ /*LocatorList=*/{}}};
+}
+
// Depobj: empty
Depth make(const parser::OmpClause::Depth &inp,
@@ -1733,8 +1748,14 @@ Clause makeClause(const parser::OmpClause &cls,
return makeClause(llvm::omp::Clause::OMPC_depend,
clause::makeDepend(*dep, semaCtx), cls.source);
} else if (auto *doa = std::get_if<parser::OmpDoacross>(&s.v.u)) {
- return makeClause(llvm::omp::Clause::OMPC_doacross,
- clause::makeDoacross(*doa, semaCtx),
+ // depend(source) / depend(sink:) on ordered is the
+ // 4.5 - 5.1 spelling of what 5.2 renamed to the doacross
+ // clause. Represent it as OMPC_depend (the surface clause is
+ // depend) rather than rewriting to OMPC_doacross, otherwise
+ // construct decomposition rejects the clause at OpenMP < 5.2
+ // even though the construct itself is valid since 4.5.
+ return makeClause(llvm::omp::Clause::OMPC_depend,
+ clause::makeDependDoacross(*doa, semaCtx),
cls.source);
} else {
llvm_unreachable("Unexpected alternative");
diff --git a/flang/test/Lower/OpenMP/Todo/ordered-depend.f90 b/flang/test/Lower/OpenMP/Todo/ordered-depend.f90
new file mode 100644
index 0000000000000..9706d2be0c665
--- /dev/null
+++ b/flang/test/Lower/OpenMP/Todo/ordered-depend.f90
@@ -0,0 +1,20 @@
+!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -o - %s 2>&1 | FileCheck %s
+
+! Issue #198972: a standalone ordered construct using the (pre-5.2)
+! depend(source) / depend(sink:) spelling must reach the "not yet
+! implemented" path instead of crashing during construct decomposition. The
+! depend(source|sink:) spelling is represented internally as a doacross
+! clause, which decomposition only accepts from OpenMP 5.2, while the construct
+! itself is valid (using this spelling) since OpenMP 4.5.
+
+!CHECK: not yet implemented: OMPD_ordered
+subroutine f00
+ integer :: i
+ !$omp do ordered(1)
+ do i = 1, 10
+ !$omp ordered depend(source)
+ !$omp ordered depend(sink: i - 1)
+ end do
+ !$omp end do
+end
+
diff --git a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
index 3f4502bf73a47..b2f809e9b51ee 100644
--- a/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
+++ b/llvm/include/llvm/Frontend/OpenMP/ClauseT.h
@@ -533,10 +533,16 @@ struct DependT {
using Iterator = type::IteratorT<T, I, E>;
using LocatorList = ObjectListT<I, E>;
using DependenceType = tomp::type::DependenceType;
+ // For the (pre-5.2) doacross spelling of the depend clause on the
+ // ordered directive: depend(source) / depend(sink: vec). Empty Vector
+ // means omp_cur_iteration, matching DoacrossT::Vector. When Vector has a
+ // value, LocatorList must be empty and the dependence type must be Source or
+ // Sink.
+ using Vector = ListT<type::LoopIterationT<I, E>>;
using TupleTrait = std::true_type;
// Empty LocatorList means "omp_all_memory".
- std::tuple<DependenceType, OPT(Iterator), LocatorList> t;
+ std::tuple<DependenceType, OPT(Iterator), OPT(Vector), LocatorList> t;
};
// [tr14:212-213]
More information about the flang-commits
mailing list