[flang-commits] [flang] [flang][OpenMP] Use 'present-modifier' instead of 'expectation' in 5.1 (PR #214083)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Wed Aug 5 05:51:10 PDT 2026
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/214083
>From 3b924056bc1cfcc45d161a90053d7d79eb2b34c9 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Tue, 4 Aug 2026 15:56:59 -0500
Subject: [PATCH 1/3] [flang][OpenMP] Use 'present-modifier' instead of
'expectation' in 5.1
The 5.1 spec lists PRESENT as an alternative in a 'motion-modifier'.
The other alternatives are mapper and iterator. These already exist
as separate modifiers, so 'motion-modifier' would best be expressed
as a modifier group. While modifier groups are not implemented yet,
borrow 'present-modifier' from the 6.0 spec.
The 'expectation' modifier only existed in 5.2, it was replaced by
'present-modifier' in 6.0.
---
flang/include/flang/Parser/parse-tree.h | 48 ++++++++-----
flang/lib/Lower/OpenMP/Clauses.cpp | 72 ++++++++++++-------
flang/lib/Parser/openmp-parsers.cpp | 30 +++++---
flang/lib/Semantics/openmp-modifiers.cpp | 9 ++-
.../test/Semantics/OpenMP/from-clause-v45.f90 | 8 +--
.../test/Semantics/OpenMP/from-clause-v51.f90 | 2 +-
flang/test/Semantics/OpenMP/to-clause-v45.f90 | 8 +--
flang/test/Semantics/OpenMP/to-clause-v51.f90 | 2 +-
8 files changed, 117 insertions(+), 62 deletions(-)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index d647879c0dc92..6a21d5d8c79d7 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4292,14 +4292,16 @@ struct OmpPrescriptiveness {
WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value);
};
-// Ref: [4.5:216-219], [5.0:315-324], [5.1:347-355], [5.2:150-158],
-// [6.0:279-288]
+// Ref: [5.1:205-210], [6.0:279-288]
//
// present-modifier ->
-// PRESENT // since 5.1
+// PRESENT // since 5.1, until 5.1
+// // since 6.0
//
-// Until 5.2, it was a part of map-type-modifier. Since 6.0 the
-// map-type-modifier has been split into individual modifiers.
+// In 5.1 it was a part of "motion-modifier" (on FROM and TO clauses), which
+// should really be modeled as a modifier-group. In 5.2 it was replaced by
+// "expectation". It was restored in 6.0 when map-type-modifier was broken up
+// into individual modifiers.
struct OmpPresentModifier {
ENUM_CLASS(Value, Present)
WRAPPER_CLASS_BOILERPLATE(OmpPresentModifier, Value);
@@ -4711,17 +4713,24 @@ struct OmpFailClause {
WRAPPER_CLASS_BOILERPLATE(OmpFailClause, MemoryOrder);
};
-// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
+// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168],
+// [6.0:298-299]
//
// from-clause ->
-// FROM(locator-list) |
-// FROM(mapper-modifier: locator-list) | // since 5.0
-// FROM(motion-modifier[,] ...: locator-list) // since 5.1
+// FROM(locator-list) | // since 4.5
+// FROM(modifier[,] ...: locator-list) | // since 5.0
+// modifier ->
+// mapper | // since 5.2
+// motion-modifier | // since 5.1, until 5.1
+// expectation | mapper | iterator // since 5.2, until 5.2
+// present-modifier | mapper | iterator | // since 6.0
+// directive-name-modifier // since 6.0
// motion-modifier ->
// PRESENT | mapper-modifier | iterator-modifier
struct OmpFromClause {
TUPLE_CLASS_BOILERPLATE(OmpFromClause);
- MODIFIER_BOILERPLATE(OmpExpectation, OmpIterator, OmpMapper);
+ MODIFIER_BOILERPLATE(
+ OmpExpectation, OmpPresentModifier, OmpIterator, OmpMapper);
std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
};
@@ -5070,18 +5079,25 @@ struct OmpThreadsetClause {
};
// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
+// [6.0:297-298]
//
// to-clause (in DECLARE TARGET) ->
-// TO(extended-list) | // until 5.1
+// TO(extended-list) | // since 4.5, until 5.1
// to-clause (in TARGET UPDATE) ->
-// TO(locator-list) |
-// TO(mapper-modifier: locator-list) | // since 5.0
-// TO(motion-modifier[,] ...: locator-list) // since 5.1
-// motion-modifier ->
+// TO(locator-list) | // since 4.5
+// TO(modifier[,] ...: locator-list) | // since 5.0
+// modifier ->
+// mapper | // since 5.2
+// motion-modifier | // since 5.1, until 5.1
+// expectation | mapper | iterator // since 5.2, until 5.2
+// present-modifier | mapper | iterator | // since 6.0
+// directive-name-modifier // since 6.0
+// motion-modifier ->
// PRESENT | mapper-modifier | iterator-modifier
struct OmpToClause {
TUPLE_CLASS_BOILERPLATE(OmpToClause);
- MODIFIER_BOILERPLATE(OmpExpectation, OmpIterator, OmpMapper);
+ MODIFIER_BOILERPLATE(
+ OmpExpectation, OmpPresentModifier, OmpIterator, OmpMapper);
std::tuple<MODIFIERS(), OmpObjectList, /*CommaSeparated=*/bool> t;
};
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 1b9ce1401118e..a7912ecf6a57b 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -970,11 +970,17 @@ Firstprivate make(const parser::OmpClause::Firstprivate &inp,
// Flush: empty
-From make(const parser::OmpClause::From &inp,
- semantics::SemanticsContext &semaCtx) {
+From make(
+ const parser::OmpClause::From &inp, semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpFromClause
CLAUSET_ENUM_CONVERT( //
- convert, parser::OmpExpectation::Value, From::Expectation,
+ convertExp, parser::OmpExpectation::Value, From::Expectation,
+ // clang-format off
+ MS(Present, Present)
+ // clang-format on
+ );
+ CLAUSET_ENUM_CONVERT( //
+ convertPre, parser::OmpPresentModifier::Value, From::Expectation,
// clang-format off
MS(Present, Present)
// clang-format on
@@ -982,26 +988,32 @@ From make(const parser::OmpClause::From &inp,
auto &mods = semantics::OmpGetModifiers(inp.v);
auto *t0 = semantics::OmpGetUniqueModifier<parser::OmpExpectation>(mods);
- auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods);
- auto *t2 = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods);
- auto &t3 = std::get<parser::OmpObjectList>(inp.v.t);
+ auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpPresentModifier>(mods);
+ auto *t2 = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods);
+ auto *t3 = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods);
+ auto &t4 = std::get<parser::OmpObjectList>(inp.v.t);
+
+ std::optional<From::Expectation> maybeExp = //
+ t0 ? maybeApplyToV(convertExp, t0)
+ : t1 ? maybeApplyToV(convertPre, t1)
+ : std::optional<From::Expectation>{};
auto mappers = [&]() -> std::optional<List<Mapper>> {
- if (t1)
- return List<Mapper>{Mapper{makeObject(t1->v, semaCtx)}};
+ if (t2)
+ return List<Mapper>{Mapper{makeObject(t2->v, semaCtx)}};
return std::nullopt;
}();
auto iterator = [&]() -> std::optional<Iterator> {
- if (t2)
- return makeIterator(*t2, semaCtx);
+ if (t3)
+ return makeIterator(*t3, semaCtx);
return std::nullopt;
}();
- return From{{/*Expectation=*/maybeApplyToV(convert, t0),
- /*Mappers=*/std::move(mappers),
- /*Iterator=*/std::move(iterator),
- /*LocatorList=*/makeObjects(t3, semaCtx)}};
+ return From{{/*Expectation=*/maybeExp,
+ /*Mappers=*/std::move(mappers),
+ /*Iterator=*/std::move(iterator),
+ /*LocatorList=*/makeObjects(t4, semaCtx)}};
}
// Full: empty
@@ -1694,7 +1706,13 @@ To make(const parser::OmpClause::To &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpToClause
CLAUSET_ENUM_CONVERT( //
- convert, parser::OmpExpectation::Value, To::Expectation,
+ convertExp, parser::OmpExpectation::Value, To::Expectation,
+ // clang-format off
+ MS(Present, Present)
+ // clang-format on
+ );
+ CLAUSET_ENUM_CONVERT( //
+ convertPre, parser::OmpPresentModifier::Value, From::Expectation,
// clang-format off
MS(Present, Present)
// clang-format on
@@ -1702,26 +1720,32 @@ To make(const parser::OmpClause::To &inp,
auto &mods = semantics::OmpGetModifiers(inp.v);
auto *t0 = semantics::OmpGetUniqueModifier<parser::OmpExpectation>(mods);
- auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods);
- auto *t2 = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods);
- auto &t3 = std::get<parser::OmpObjectList>(inp.v.t);
+ auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpPresentModifier>(mods);
+ auto *t2 = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods);
+ auto *t3 = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods);
+ auto &t4 = std::get<parser::OmpObjectList>(inp.v.t);
+
+ std::optional<From::Expectation> maybeExp = //
+ t0 ? maybeApplyToV(convertExp, t0)
+ : t1 ? maybeApplyToV(convertPre, t1)
+ : std::optional<From::Expectation>{};
auto mappers = [&]() -> std::optional<List<Mapper>> {
- if (t1)
- return List<Mapper>{Mapper{makeObject(t1->v, semaCtx)}};
+ if (t2)
+ return List<Mapper>{Mapper{makeObject(t2->v, semaCtx)}};
return std::nullopt;
}();
auto iterator = [&]() -> std::optional<Iterator> {
- if (t2)
- return makeIterator(*t2, semaCtx);
+ if (t3)
+ return makeIterator(*t3, semaCtx);
return std::nullopt;
}();
- return To{{/*Expectation=*/maybeApplyToV(convert, t0),
+ return To{{/*Expectation=*/maybeExp,
/*Mappers=*/{std::move(mappers)},
/*Iterator=*/std::move(iterator),
- /*LocatorList=*/makeObjects(t3, semaCtx)}};
+ /*LocatorList=*/makeObjects(t4, semaCtx)}};
}
UnifiedAddress make(const parser::OmpClause::UnifiedAddress &inp,
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index ad74cb84aa8bf..7c4e49a673bb0 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1088,10 +1088,27 @@ TYPE_PARSER(
TYPE_PARSER(
sourced(construct<OmpEnterClause::Modifier>(Parser<OmpAutomapModifier>{})))
-TYPE_PARSER(sourced(construct<OmpFromClause::Modifier>(
- sourced(construct<OmpFromClause::Modifier>(Parser<OmpExpectation>{}) ||
- construct<OmpFromClause::Modifier>(Parser<OmpMapper>{}) ||
- construct<OmpFromClause::Modifier>(Parser<OmpIterator>{})))))
+template <typename MotionClause> struct OmpMotionClauseModifierParser {
+ using resultType = typename MotionClause::Modifier;
+
+ std::optional<resultType> Parse(ParseState &state) const {
+ unsigned version{state.userState()->langOptions().OpenMPVersion};
+ if (version == 52) {
+ auto expect{sourced(construct<resultType>(Parser<OmpExpectation>{}))};
+ if (auto &&result{attempt(expect).Parse(state)}) {
+ return std::move(result);
+ }
+ }
+ auto parser{sourced( //
+ construct<resultType>(Parser<OmpPresentModifier>{}) ||
+ construct<resultType>(Parser<OmpMapper>{}) ||
+ construct<resultType>(Parser<OmpIterator>{}))};
+ return parser.Parse(state);
+ }
+};
+
+TYPE_PARSER(OmpMotionClauseModifierParser<OmpFromClause>{})
+TYPE_PARSER(OmpMotionClauseModifierParser<OmpToClause>{})
TYPE_PARSER(sourced(
construct<OmpGrainsizeClause::Modifier>(Parser<OmpPrescriptiveness>{})))
@@ -1176,11 +1193,6 @@ TYPE_PARSER(sourced(construct<OmpTaskReductionClause::Modifier>(
TYPE_PARSER(sourced(
construct<OmpThreadLimitClause::Modifier>(Parser<OmpDimsModifier>{})))
-TYPE_PARSER(sourced(construct<OmpToClause::Modifier>(
- sourced(construct<OmpToClause::Modifier>(Parser<OmpExpectation>{}) ||
- construct<OmpToClause::Modifier>(Parser<OmpMapper>{}) ||
- construct<OmpToClause::Modifier>(Parser<OmpIterator>{})))))
-
TYPE_PARSER(sourced(construct<OmpWhenClause::Modifier>( //
Parser<OmpContextSelector>{})))
diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp
index 972788aff1247..293136d3649ad 100644
--- a/flang/lib/Semantics/openmp-modifiers.cpp
+++ b/flang/lib/Semantics/openmp-modifiers.cpp
@@ -361,11 +361,12 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpExpectation>() {
/*name=*/"expectation",
/*props=*/
{
- {51, {OmpProperty::Unique}},
+ {52, {OmpProperty::Unique}},
},
/*clauses=*/
{
- {51, {Clause::OMPC_from, Clause::OMPC_to}},
+ {52, {Clause::OMPC_from, Clause::OMPC_to}},
+ {60, {}},
},
};
return desc;
@@ -629,7 +630,9 @@ const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpPresentModifier>() {
},
/*clauses=*/
{
- {51, {Clause::OMPC_map}},
+ {51, {Clause::OMPC_from, Clause::OMPC_to}},
+ {52, {}},
+ {60, {Clause::OMPC_from, Clause::OMPC_map, Clause::OMPC_to}},
},
};
return desc;
diff --git a/flang/test/Semantics/OpenMP/from-clause-v45.f90 b/flang/test/Semantics/OpenMP/from-clause-v45.f90
index 654af4b7dd9b7..284511acfdd59 100644
--- a/flang/test/Semantics/OpenMP/from-clause-v45.f90
+++ b/flang/test/Semantics/OpenMP/from-clause-v45.f90
@@ -14,16 +14,16 @@ subroutine f01(x)
subroutine f02(x)
integer :: x(10)
-!WARNING: 'expectation' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
+!WARNING: 'present-modifier' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
!WARNING: 'iterator' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
!$omp target update from(present, iterator(i = 1:5): x(i))
end
subroutine f03(x)
integer :: x(10)
-!WARNING: 'expectation' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
-!WARNING: 'expectation' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
-!ERROR: 'expectation' modifier cannot occur multiple times
+!WARNING: 'present-modifier' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
+!WARNING: 'present-modifier' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
+!ERROR: 'present-modifier' modifier cannot occur multiple times
!$omp target update from(present, present: x)
end
diff --git a/flang/test/Semantics/OpenMP/from-clause-v51.f90 b/flang/test/Semantics/OpenMP/from-clause-v51.f90
index 8771f519fec03..60252a8a1745c 100644
--- a/flang/test/Semantics/OpenMP/from-clause-v51.f90
+++ b/flang/test/Semantics/OpenMP/from-clause-v51.f90
@@ -8,7 +8,7 @@ subroutine f01(x)
subroutine f03(x)
integer :: x(10)
-!ERROR: 'expectation' modifier cannot occur multiple times
+!ERROR: 'present-modifier' modifier cannot occur multiple times
!$omp target update from(present, present: x)
end
diff --git a/flang/test/Semantics/OpenMP/to-clause-v45.f90 b/flang/test/Semantics/OpenMP/to-clause-v45.f90
index 7e56817e1ff7c..2fff681d621b1 100644
--- a/flang/test/Semantics/OpenMP/to-clause-v45.f90
+++ b/flang/test/Semantics/OpenMP/to-clause-v45.f90
@@ -14,16 +14,16 @@ subroutine f01(x)
subroutine f02(x)
integer :: x(10)
-!WARNING: 'expectation' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
+!WARNING: 'present-modifier' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
!WARNING: 'iterator' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
!$omp target update to(present, iterator(i = 1:5): x(i))
end
subroutine f03(x)
integer :: x(10)
-!WARNING: 'expectation' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
-!WARNING: 'expectation' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
-!ERROR: 'expectation' modifier cannot occur multiple times
+!WARNING: 'present-modifier' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
+!WARNING: 'present-modifier' modifier is not supported in OpenMP v4.5, try -fopenmp-version=51
+!ERROR: 'present-modifier' modifier cannot occur multiple times
!$omp target update to(present, present: x)
end
diff --git a/flang/test/Semantics/OpenMP/to-clause-v51.f90 b/flang/test/Semantics/OpenMP/to-clause-v51.f90
index 0db292a22238b..15e742c1ece22 100644
--- a/flang/test/Semantics/OpenMP/to-clause-v51.f90
+++ b/flang/test/Semantics/OpenMP/to-clause-v51.f90
@@ -8,7 +8,7 @@ subroutine f01(x)
subroutine f03(x)
integer :: x(10)
-!ERROR: 'expectation' modifier cannot occur multiple times
+!ERROR: 'present-modifier' modifier cannot occur multiple times
!$omp target update to(present, present: x)
end
>From 99fabb8ecc18980e465488bb6d10c330daad32af Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Tue, 4 Aug 2026 17:05:19 -0500
Subject: [PATCH 2/3] format
---
flang/lib/Lower/OpenMP/Clauses.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index a7912ecf6a57b..383b1274d148f 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -970,8 +970,8 @@ Firstprivate make(const parser::OmpClause::Firstprivate &inp,
// Flush: empty
-From make(
- const parser::OmpClause::From &inp, semantics::SemanticsContext &semaCtx) {
+From make(const parser::OmpClause::From &inp,
+ semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpFromClause
CLAUSET_ENUM_CONVERT( //
convertExp, parser::OmpExpectation::Value, From::Expectation,
@@ -1011,9 +1011,9 @@ From make(
}();
return From{{/*Expectation=*/maybeExp,
- /*Mappers=*/std::move(mappers),
- /*Iterator=*/std::move(iterator),
- /*LocatorList=*/makeObjects(t4, semaCtx)}};
+ /*Mappers=*/std::move(mappers),
+ /*Iterator=*/std::move(iterator),
+ /*LocatorList=*/makeObjects(t4, semaCtx)}};
}
// Full: empty
>From 63190015c23e1ba2b6bc9305750e728d04739835 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Wed, 5 Aug 2026 07:50:34 -0500
Subject: [PATCH 3/3] Fix copy/paste error: From -> To
---
flang/lib/Lower/OpenMP/Clauses.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 383b1274d148f..0d315c218770a 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -1712,7 +1712,7 @@ To make(const parser::OmpClause::To &inp,
// clang-format on
);
CLAUSET_ENUM_CONVERT( //
- convertPre, parser::OmpPresentModifier::Value, From::Expectation,
+ convertPre, parser::OmpPresentModifier::Value, To::Expectation,
// clang-format off
MS(Present, Present)
// clang-format on
@@ -1725,10 +1725,10 @@ To make(const parser::OmpClause::To &inp,
auto *t3 = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods);
auto &t4 = std::get<parser::OmpObjectList>(inp.v.t);
- std::optional<From::Expectation> maybeExp = //
+ std::optional<To::Expectation> maybeExp = //
t0 ? maybeApplyToV(convertExp, t0)
: t1 ? maybeApplyToV(convertPre, t1)
- : std::optional<From::Expectation>{};
+ : std::optional<To::Expectation>{};
auto mappers = [&]() -> std::optional<List<Mapper>> {
if (t2)
More information about the flang-commits
mailing list