[llvm-branch-commits] [flang] [llvm] [flang][OpenMP] Semantic checks for IN_REDUCTION and TASK_REDUCTION (PR #118841)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Dec 5 09:38:15 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-openmp
@llvm/pr-subscribers-flang-fir-hlfir
Author: Krzysztof Parzyszek (kparzysz)
<details>
<summary>Changes</summary>
Update parsing of these two clauses and add semantic checks for them. Simplify some code in IsReductionAllowedForType and CheckReductionOperator.
---
Patch is 36.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/118841.diff
16 Files Affected:
- (modified) flang/include/flang/Parser/dump-parse-tree.h (+3)
- (modified) flang/include/flang/Parser/parse-tree.h (+16-3)
- (modified) flang/lib/Lower/OpenMP/Clauses.cpp (+16-12)
- (modified) flang/lib/Parser/openmp-parsers.cpp (+15-4)
- (modified) flang/lib/Parser/unparse.cpp (+8-3)
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+151-151)
- (modified) flang/lib/Semantics/check-omp-structure.h (+6-5)
- (modified) flang/test/Parser/OpenMP/in-reduction-clause.f90 (+6-6)
- (modified) flang/test/Parser/OpenMP/reduction-modifier.f90 (+1-1)
- (added) flang/test/Parser/OpenMP/task-reduction-clause.f90 (+23)
- (modified) flang/test/Preprocessing/directive-contin-with-pp.F90 (+3-3)
- (added) flang/test/Semantics/OpenMP/in-reduction.f90 (+44)
- (modified) flang/test/Semantics/OpenMP/symbol08.f90 (+3-2)
- (added) flang/test/Semantics/OpenMP/task-reduction.f90 (+44)
- (modified) flang/test/Semantics/OpenMP/taskgroup01.f90 (+2)
- (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+1-1)
``````````diff
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index c6f35a07d81ea5..b87bc5b60cafe9 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -592,7 +592,10 @@ class ParseTreeDumper {
NODE(parser, OmpReductionClause)
NODE(OmpReductionClause, Modifier)
NODE(parser, OmpInReductionClause)
+ NODE(OmpInReductionClause, Modifier)
NODE(parser, OmpReductionCombiner)
+ NODE(parser, OmpTaskReductionClause)
+ NODE(OmpTaskReductionClause, Modifier)
NODE(OmpReductionCombiner, FunctionCombiner)
NODE(parser, OmpReductionInitializerClause)
NODE(parser, OmpReductionIdentifier)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 8160b095f06dd9..e2530cea3652a2 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3951,11 +3951,14 @@ struct OmpIfClause {
std::tuple<MODIFIERS(), ScalarLogicalExpr> t;
};
-// OMP 5.0 2.19.5.6 in_reduction-clause -> IN_REDUCTION (reduction-identifier:
-// variable-name-list)
+// Ref: [5.0:170-176], [5.1:197-205], [5.2:138-139]
+//
+// in-reduction-clause ->
+// IN_REDUCTION(reduction-identifier: list) // since 5.0
struct OmpInReductionClause {
TUPLE_CLASS_BOILERPLATE(OmpInReductionClause);
- std::tuple<OmpReductionIdentifier, OmpObjectList> t;
+ MODIFIER_BOILERPLATE(OmpReductionIdentifier);
+ std::tuple<MODIFIERS(), OmpObjectList> t;
};
// Ref: [4.5:199-201], [5.0:288-290], [5.1:321-322], [5.2:115-117]
@@ -4070,6 +4073,16 @@ struct OmpScheduleClause {
std::tuple<MODIFIERS(), Kind, std::optional<ScalarIntExpr>> t;
};
+// Ref: [5.0:232-234], [5.1:264-266], [5.2:137]
+//
+// task-reduction-clause ->
+// TASK_REDUCTION(reduction-identifier: list) // since 5.0
+struct OmpTaskReductionClause {
+ TUPLE_CLASS_BOILERPLATE(OmpTaskReductionClause);
+ MODIFIER_BOILERPLATE(OmpReductionIdentifier);
+ std::tuple<MODIFIERS(), OmpObjectList> t;
+};
+
// Ref: [4.5:107-109], [5.0:176-180], [5.1:205-210], [5.2:167-168]
//
// to-clause (in DECLARE TARGET) ->
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index 10c31963ec493a..a0dc1be0afc5c0 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -859,10 +859,14 @@ Init make(const parser::OmpClause::Init &inp,
InReduction make(const parser::OmpClause::InReduction &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpInReductionClause
- auto &t0 = std::get<parser::OmpReductionIdentifier>(inp.v.t);
+ auto &mods = semantics::OmpGetModifiers(inp.v);
+ auto *m0 =
+ semantics::OmpGetUniqueModifier<parser::OmpReductionIdentifier>(mods);
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
+ assert(m0 && "OmpReductionIdentifier is required");
+
return InReduction{
- {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)},
+ {/*ReductionIdentifiers=*/{makeReductionOperator(*m0, semaCtx)},
/*List=*/makeObjects(t1, semaCtx)}};
}
@@ -1155,17 +1159,17 @@ Reduction make(const parser::OmpClause::Reduction &inp,
);
auto &mods = semantics::OmpGetModifiers(inp.v);
- auto *t0 =
+ auto *m0 =
semantics::OmpGetUniqueModifier<parser::OmpReductionModifier>(mods);
- auto *t1 =
+ auto *m1 =
semantics::OmpGetUniqueModifier<parser::OmpReductionIdentifier>(mods);
- auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
- assert(t1 && "OmpReductionIdentifier is required");
+ auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
+ assert(m1 && "OmpReductionIdentifier is required");
return Reduction{
- {/*ReductionModifier=*/maybeApplyToV(convert, t0),
- /*ReductionIdentifiers=*/{makeReductionOperator(*t1, semaCtx)},
- /*List=*/makeObjects(t2, semaCtx)}};
+ {/*ReductionModifier=*/maybeApplyToV(convert, m0),
+ /*ReductionIdentifiers=*/{makeReductionOperator(*m1, semaCtx)},
+ /*List=*/makeObjects(t1, semaCtx)}};
}
// Relaxed: empty
@@ -1259,13 +1263,13 @@ TaskReduction make(const parser::OmpClause::TaskReduction &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpReductionClause
auto &mods = semantics::OmpGetModifiers(inp.v);
- auto *t0 =
+ auto *m0 =
semantics::OmpGetUniqueModifier<parser::OmpReductionIdentifier>(mods);
auto &t1 = std::get<parser::OmpObjectList>(inp.v.t);
- assert(t0 && "OmpReductionIdentifier is required");
+ assert(m0 && "OmpReductionIdentifier is required");
return TaskReduction{
- {/*ReductionIdentifiers=*/{makeReductionOperator(*t0, semaCtx)},
+ {/*ReductionIdentifiers=*/{makeReductionOperator(*m0, semaCtx)},
/*List=*/makeObjects(t1, semaCtx)}};
}
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 86d475c1a15422..cff372658a996e 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -282,6 +282,9 @@ TYPE_PARSER(sourced(
TYPE_PARSER(sourced(construct<OmpIfClause::Modifier>(OmpDirectiveNameParser{})))
+TYPE_PARSER(sourced(construct<OmpInReductionClause::Modifier>(
+ Parser<OmpReductionIdentifier>{})))
+
TYPE_PARSER(sourced(construct<OmpLastprivateClause::Modifier>(
Parser<OmpLastprivateModifier>{})))
@@ -306,6 +309,9 @@ TYPE_PARSER(sourced(construct<OmpScheduleClause::Modifier>(sourced(
construct<OmpScheduleClause::Modifier>(Parser<OmpChunkModifier>{}) ||
construct<OmpScheduleClause::Modifier>(Parser<OmpOrderingModifier>{})))))
+TYPE_PARSER(sourced(construct<OmpTaskReductionClause::Modifier>(
+ Parser<OmpReductionIdentifier>{})))
+
TYPE_PARSER(sourced(construct<OmpToClause::Modifier>(
sourced(construct<OmpToClause::Modifier>(Parser<OmpExpectation>{}) ||
construct<OmpToClause::Modifier>(Parser<OmpMapper>{}) ||
@@ -407,7 +413,12 @@ TYPE_PARSER(construct<OmpReductionClause>(
// OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list)
TYPE_PARSER(construct<OmpInReductionClause>(
- Parser<OmpReductionIdentifier>{} / ":", Parser<OmpObjectList>{}))
+ maybe(nonemptyList(Parser<OmpInReductionClause::Modifier>{}) / ":"),
+ Parser<OmpObjectList>{}))
+
+TYPE_PARSER(construct<OmpTaskReductionClause>(
+ maybe(nonemptyList(Parser<OmpTaskReductionClause::Modifier>{}) / ":"),
+ Parser<OmpObjectList>{}))
// OMP 5.0 2.11.4 allocate-clause -> ALLOCATE ([allocator:] variable-name-list)
// OMP 5.2 2.13.4 allocate-clause -> ALLOCATE ([allocate-modifier
@@ -609,15 +620,15 @@ TYPE_PARSER(
parenthesized(Parser<OmpObjectList>{}))) ||
"PROC_BIND" >> construct<OmpClause>(construct<OmpClause::ProcBind>(
parenthesized(Parser<OmpProcBindClause>{}))) ||
- "REDUCTION" >> construct<OmpClause>(construct<OmpClause::Reduction>(
- parenthesized(Parser<OmpReductionClause>{}))) ||
+ "REDUCTION"_id >> construct<OmpClause>(construct<OmpClause::Reduction>(
+ parenthesized(Parser<OmpReductionClause>{}))) ||
"IN_REDUCTION" >> construct<OmpClause>(construct<OmpClause::InReduction>(
parenthesized(Parser<OmpInReductionClause>{}))) ||
"DETACH" >> construct<OmpClause>(construct<OmpClause::Detach>(
parenthesized(Parser<OmpDetachClause>{}))) ||
"TASK_REDUCTION" >>
construct<OmpClause>(construct<OmpClause::TaskReduction>(
- parenthesized(Parser<OmpReductionClause>{}))) ||
+ parenthesized(Parser<OmpTaskReductionClause>{}))) ||
"RELAXED" >> construct<OmpClause>(construct<OmpClause::Relaxed>()) ||
"RELEASE" >> construct<OmpClause>(construct<OmpClause::Release>()) ||
"REVERSE_OFFLOAD" >>
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 4782cc1f2d7d7d..f8c4069e65f304 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2143,13 +2143,18 @@ class UnparseVisitor {
}
void Unparse(const OmpReductionClause &x) {
using Modifier = OmpReductionClause::Modifier;
- Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ":");
+ Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
Walk(std::get<OmpObjectList>(x.t));
}
void Unparse(const OmpDetachClause &x) { Walk(x.v); }
void Unparse(const OmpInReductionClause &x) {
- Walk(std::get<OmpReductionIdentifier>(x.t));
- Put(":");
+ using Modifier = OmpInReductionClause::Modifier;
+ Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
+ Walk(std::get<OmpObjectList>(x.t));
+ }
+ void Unparse(const OmpTaskReductionClause &x) {
+ using Modifier = OmpTaskReductionClause::Modifier;
+ Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": ");
Walk(std::get<OmpObjectList>(x.t));
}
void Unparse(const OmpAllocateClause &x) {
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 0d43bc907907a7..cb14d6032d345c 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -2821,7 +2821,6 @@ CHECK_SIMPLE_CLAUSE(Grainsize, OMPC_grainsize)
CHECK_SIMPLE_CLAUSE(Hint, OMPC_hint)
CHECK_SIMPLE_CLAUSE(Holds, OMPC_holds)
CHECK_SIMPLE_CLAUSE(Inclusive, OMPC_inclusive)
-CHECK_SIMPLE_CLAUSE(InReduction, OMPC_in_reduction)
CHECK_SIMPLE_CLAUSE(Match, OMPC_match)
CHECK_SIMPLE_CLAUSE(Nontemporal, OMPC_nontemporal)
CHECK_SIMPLE_CLAUSE(NumTasks, OMPC_num_tasks)
@@ -2846,7 +2845,6 @@ CHECK_SIMPLE_CLAUSE(SeqCst, OMPC_seq_cst)
CHECK_SIMPLE_CLAUSE(Simd, OMPC_simd)
CHECK_SIMPLE_CLAUSE(Sizes, OMPC_sizes)
CHECK_SIMPLE_CLAUSE(Permutation, OMPC_permutation)
-CHECK_SIMPLE_CLAUSE(TaskReduction, OMPC_task_reduction)
CHECK_SIMPLE_CLAUSE(Uniform, OMPC_uniform)
CHECK_SIMPLE_CLAUSE(Unknown, OMPC_unknown)
CHECK_SIMPLE_CLAUSE(Untied, OMPC_untied)
@@ -2915,14 +2913,17 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_reduction,
GetContext().clauseSource, context_)) {
- if (CheckReductionOperators(x)) {
- CheckReductionTypeList(x);
- }
auto &modifiers{OmpGetModifiers(x.v)};
+ const auto *ident{
+ OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
+ assert(ident && "reduction-identifier is a required modifier");
+ if (CheckReductionOperator(*ident, OmpGetModifierSource(modifiers, ident),
+ llvm::omp::OMPC_reduction)) {
+ CheckReductionObjectTypes(objects, *ident);
+ }
using ReductionModifier = parser::OmpReductionModifier;
- if (auto *maybeModifier{
- OmpGetUniqueModifier<ReductionModifier>(modifiers)}) {
- CheckReductionModifier(*maybeModifier);
+ if (auto *modifier{OmpGetUniqueModifier<ReductionModifier>(modifiers)}) {
+ CheckReductionModifier(*modifier);
}
}
CheckReductionObjects(objects, llvm::omp::Clause::OMPC_reduction);
@@ -2934,70 +2935,88 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
}
}
-bool OmpStructureChecker::CheckReductionOperators(
- const parser::OmpClause::Reduction &x) {
- bool ok = false;
- auto &modifiers{OmpGetModifiers(x.v)};
- if (const auto *ident{
- OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)}) {
-
- auto visitOperator{[&](const parser::DefinedOperator &dOpr) {
- if (const auto *intrinsicOp{
- std::get_if<parser::DefinedOperator::IntrinsicOperator>(
- &dOpr.u)}) {
- ok = CheckIntrinsicOperator(*intrinsicOp);
- } else {
- context_.Say(GetContext().clauseSource,
- "Invalid reduction operator in REDUCTION clause."_err_en_US,
- ContextDirectiveAsFortran());
- }
- }};
+void OmpStructureChecker::Enter(const parser::OmpClause::InReduction &x) {
+ CheckAllowedClause(llvm::omp::Clause::OMPC_in_reduction);
+ auto &objects{std::get<parser::OmpObjectList>(x.v.t)};
- auto visitDesignator{[&](const parser::ProcedureDesignator &procD) {
- const parser::Name *name{std::get_if<parser::Name>(&procD.u)};
- if (name && name->symbol) {
- const SourceName &realName{name->symbol->GetUltimate().name()};
- if (realName == "max" || realName == "min" || realName == "iand" ||
- realName == "ior" || realName == "ieor") {
- ok = true;
- }
- }
- if (!ok) {
+ if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_in_reduction,
+ GetContext().clauseSource, context_)) {
+ auto &modifiers{OmpGetModifiers(x.v)};
+ const auto *ident{
+ OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
+ assert(ident && "reduction-identifier is a required modifier");
+ if (CheckReductionOperator(*ident, OmpGetModifierSource(modifiers, ident),
+ llvm::omp::OMPC_in_reduction)) {
+ CheckReductionObjectTypes(objects, *ident);
+ }
+ }
+ CheckReductionObjects(objects, llvm::omp::Clause::OMPC_in_reduction);
+}
+
+void OmpStructureChecker::Enter(const parser::OmpClause::TaskReduction &x) {
+ CheckAllowedClause(llvm::omp::Clause::OMPC_task_reduction);
+ auto &objects{std::get<parser::OmpObjectList>(x.v.t)};
+
+ if (OmpVerifyModifiers(x.v, llvm::omp::OMPC_task_reduction,
+ GetContext().clauseSource, context_)) {
+ auto &modifiers{OmpGetModifiers(x.v)};
+ const auto *ident{
+ OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
+ assert(ident && "reduction-identifier is a required modifier");
+ if (CheckReductionOperator(*ident, OmpGetModifierSource(modifiers, ident),
+ llvm::omp::OMPC_task_reduction)) {
+ CheckReductionObjectTypes(objects, *ident);
+ }
+ }
+ CheckReductionObjects(objects, llvm::omp::Clause::OMPC_task_reduction);
+}
+
+bool OmpStructureChecker::CheckReductionOperator(
+ const parser::OmpReductionIdentifier &ident, parser::CharBlock source,
+ llvm::omp::Clause clauseId) {
+ auto visitOperator{[&](const parser::DefinedOperator &dOpr) {
+ if (const auto *intrinsicOp{
+ std::get_if<parser::DefinedOperator::IntrinsicOperator>(&dOpr.u)}) {
+ switch (*intrinsicOp) {
+ case parser::DefinedOperator::IntrinsicOperator::Add:
+ case parser::DefinedOperator::IntrinsicOperator::Multiply:
+ case parser::DefinedOperator::IntrinsicOperator::AND:
+ case parser::DefinedOperator::IntrinsicOperator::OR:
+ case parser::DefinedOperator::IntrinsicOperator::EQV:
+ case parser::DefinedOperator::IntrinsicOperator::NEQV:
+ return true;
+ case parser::DefinedOperator::IntrinsicOperator::Subtract:
context_.Say(GetContext().clauseSource,
- "Invalid reduction identifier in REDUCTION "
- "clause."_err_en_US,
+ "The minus reduction operator is deprecated since OpenMP 5.2 and is not supported in the REDUCTION clause."_err_en_US,
ContextDirectiveAsFortran());
+ return false;
+ default:
+ break;
}
- }};
- common::visit(common::visitors{visitOperator, visitDesignator}, ident->u);
- }
-
- return ok;
-}
+ }
+ context_.Say(source, "Invalid reduction operator in %s clause."_err_en_US,
+ parser::ToUpperCaseLetters(getClauseName(clauseId).str()));
+ return false;
+ }};
-bool OmpStructureChecker::CheckIntrinsicOperator(
- const parser::DefinedOperator::IntrinsicOperator &op) {
+ auto visitDesignator{[&](const parser::ProcedureDesignator &procD) {
+ const parser::Name *name{std::get_if<parser::Name>(&procD.u)};
+ bool valid{false};
+ if (name && name->symbol) {
+ const SourceName &realName{name->symbol->GetUltimate().name()};
+ valid =
+ llvm::is_contained({"max", "min", "iand", "ior", "ieor"}, realName);
+ }
+ if (!valid) {
+ context_.Say(source,
+ "Invalid reduction identifier in %s clause."_err_en_US,
+ parser::ToUpperCaseLetters(getClauseName(clauseId).str()));
+ }
+ return valid;
+ }};
- switch (op) {
- case parser::DefinedOperator::IntrinsicOperator::Add:
- case parser::DefinedOperator::IntrinsicOperator::Multiply:
- case parser::DefinedOperator::IntrinsicOperator::AND:
- case parser::DefinedOperator::IntrinsicOperator::OR:
- case parser::DefinedOperator::IntrinsicOperator::EQV:
- case parser::DefinedOperator::IntrinsicOperator::NEQV:
- return true;
- case parser::DefinedOperator::IntrinsicOperator::Subtract:
- context_.Say(GetContext().clauseSource,
- "The minus reduction operator is deprecated since OpenMP 5.2 and is "
- "not supported in the REDUCTION clause."_err_en_US,
- ContextDirectiveAsFortran());
- break;
- default:
- context_.Say(GetContext().clauseSource,
- "Invalid reduction operator in REDUCTION clause."_err_en_US,
- ContextDirectiveAsFortran());
- }
- return false;
+ return common::visit(
+ common::visitors{visitOperator, visitDesignator}, ident.u);
}
/// Check restrictions on objects that are common to all reduction clauses.
@@ -3011,7 +3030,7 @@ void OmpStructureChecker::CheckReductionObjects(
for (const parser::OmpObject &object : objects.v) {
CheckIfContiguous(object);
}
- CheckReductionArraySection(objects);
+ CheckReductionArraySection(objects, clauseId);
// An object must be definable.
CheckDefinableObjects(symbols, clauseId);
// Procedure pointers are not allowed.
@@ -3064,100 +3083,82 @@ void OmpStructureChecker::CheckReductionObjects(
}
static bool IsReductionAllowedForType(
- const parser::OmpClause::Reduction &x, const DeclTypeSpec &type) {
- auto &modifiers{OmpGetModifiers(x.v)};
- const auto *definedOp{
- OmpGetUniqueModifier<parser::OmpReductionIdentifier>(modifiers)};
- if (!definedOp) {
- return false;
- }
- // TODO: user defined reduction operators. Just allow everything for now.
- bool ok{true};
-
- auto IsLogical{[](const DeclTypeSpec &type) -> bool {
+ const parser::OmpReductionIdentifier &ident, const DeclTypeSpec &type) {
+ auto isLogical{[](const DeclTypeSpec &type) -> bool {
return type.category() == DeclTypeSpec::Logical;
}};
- auto IsCharacter{[](const DeclTypeSpec &type) -> bool {
+ auto isCharacter{[](const DeclTypeSpec &type) -> bool {
return type.category() == DeclTypeSpec::Character;
}};
- common::visit(
- common::visitors{
- [&](const parser::DefinedOperator &dOpr) {
- if (const auto *intrinsicOp{
- std::get_if<parser::DefinedOperator::IntrinsicOperator>(
- &dOpr.u)}) {
- // 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
- // .LT., .LE., .GT., .GE. are handled as procedure designators
- // below.
- switch (*intrinsicOp) {
- case parser::DefinedOperator::IntrinsicOperator::Multiply:
- [[fallthrough]];
- case parser::DefinedOperator::IntrinsicOperator::Add:
- [[fallthrough]];
- case parser::DefinedOperator::IntrinsicOperator::Subtract:
- ok = type.IsNumeric(TypeCategory::Integer) ||
- type.IsNumeric(TypeCategory::Real) ||
- type.IsNumeric(TypeCategory::Complex);
- break;
-
- case parser::DefinedOperator::IntrinsicOperator::AND:
- [[fallthrough]];
- case parser::DefinedOperator::IntrinsicOperator::OR:
- [[fallthrough]];
- case parser::DefinedOperator::IntrinsicOperator::EQV:
- [[fallthrough]];
- case parser::DefinedOperator::IntrinsicOperator::NEQV:
- ok = IsLogical(type);
- break;
+ auto checkOperator{[&](const parser::DefinedOperator &dOpr) {
+ if (const auto *intrinsicOp{
+ std::get_if<parser::DefinedOperator::IntrinsicOperator>(&dOpr.u)}) {
+ // 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
+ // .LT., .LE., .GT., .GE. are handled as procedure designators
+ // below.
+...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/118841
More information about the llvm-branch-commits
mailing list