diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index fe7fee97bc78e..753ecb918a9cc 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -468,7 +468,7 @@ struct NodeVisitor { READ_FEATURE(OmpDefaultClause::Type) READ_FEATURE(OmpDefaultmapClause) READ_FEATURE(OmpDefaultmapClause::ImplicitBehavior) - READ_FEATURE(OmpDefaultmapClause::VariableCategory) + READ_FEATURE(OmpVariableCategory::Value) READ_FEATURE(OmpDependClause) READ_FEATURE(OmpDependClause::TaskDep) READ_FEATURE(OmpDoacross::Sink) diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp index c184fdafb5c33..a9ff163f8243c 100644 --- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp +++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp @@ -208,10 +208,9 @@ void OpenMPCounterVisitor::Post( "implicit_behavior=" + std::string{OmpDefaultmapClause::EnumToString(c)} + ";"; } -void OpenMPCounterVisitor::Post( - const OmpDefaultmapClause::VariableCategory &c) { +void OpenMPCounterVisitor::Post(const OmpVariableCategory::Value &c) { clauseDetails += - "variable_category=" + std::string{OmpDefaultmapClause::EnumToString(c)} + + "variable_category=" + std::string{OmpVariableCategory::EnumToString(c)} + ";"; } void OpenMPCounterVisitor::Post(const OmpScheduleModifierType::ModType &c) { diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h index 6c2d194a88e69..83bd3644577e1 100644 --- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h +++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.h @@ -69,7 +69,7 @@ struct OpenMPCounterVisitor { void Post(const OmpProcBindClause::Type &c); void Post(const OmpDefaultClause::Type &c); void Post(const OmpDefaultmapClause::ImplicitBehavior &c); - void Post(const OmpDefaultmapClause::VariableCategory &c); + void Post(const OmpVariableCategory::Value &c); void Post(const OmpDeviceTypeClause::Type &c); void Post(const OmpScheduleModifierType::ModType &c); void Post(const OmpLinearModifier::Value &c); diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 63fddc424182b..e9c149758c149 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -509,9 +509,11 @@ class ParseTreeDumper { NODE(parser, OmpDeclareMapperSpecifier) NODE(parser, OmpDefaultClause) NODE_ENUM(OmpDefaultClause, Type) + NODE(parser, OmpVariableCategory) + NODE_ENUM(OmpVariableCategory, Value) NODE(parser, OmpDefaultmapClause) NODE_ENUM(OmpDefaultmapClause, ImplicitBehavior) - NODE_ENUM(OmpDefaultmapClause, VariableCategory) + NODE(OmpDefaultmapClause, Modifier) NODE(parser, OmpDependenceType) NODE_ENUM(OmpDependenceType, Value) NODE(parser, OmpTaskDependenceType) @@ -568,8 +570,10 @@ class ParseTreeDumper { NODE_ENUM(OmpBindClause, Type) NODE(parser, OmpProcBindClause) NODE_ENUM(OmpProcBindClause, Type) - NODE_ENUM(OmpReductionClause, ReductionModifier) + NODE(parser, OmpReductionModifier) + NODE_ENUM(OmpReductionModifier, Value) NODE(parser, OmpReductionClause) + NODE(OmpReductionClause, Modifier) NODE(parser, OmpInReductionClause) NODE(parser, OmpReductionCombiner) NODE(OmpReductionCombiner, FunctionCombiner) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 22b7f9acd1af5..32ebaa7fbffca 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3440,6 +3440,16 @@ struct OmpObject { WRAPPER_CLASS(OmpObjectList, std::list); +#define MODIFIER_BOILERPLATE(...) \ + struct Modifier { \ + using Variant = std::variant<__VA_ARGS__>; \ + UNION_CLASS_BOILERPLATE(Modifier); \ + CharBlock source; \ + Variant u; \ + } + +#define MODIFIERS() std::optional> + inline namespace modifier { // For uniformity, in all keyword modifiers the name of the type defined // by ENUM_CLASS is "Value", e.g. @@ -3505,12 +3515,20 @@ struct OmpLinearModifier { // - | // since 4.5, until 5.2 // + | * | .AND. | .OR. | .EQV. | .NEQV. | // since 4.5 // MIN | MAX | IAND | IOR | IEOR // since 4.5 -// struct OmpReductionIdentifier { UNION_CLASS_BOILERPLATE(OmpReductionIdentifier); std::variant u; }; +// Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137] +// +// reduction-modifier -> +// DEFAULT | INSCAN | TASK // since 5.0 +struct OmpReductionModifier { + ENUM_CLASS(Value, Default, Inscan, Task); + WRAPPER_CLASS_BOILERPLATE(OmpReductionModifier, Value); +}; + // Ref: [4.5:169-170], [5.0:254-256], [5.1:287-289], [5.2:321] // // task-dependence-type -> // "dependence-type" in 5.1 and before @@ -3521,6 +3539,17 @@ struct OmpTaskDependenceType { ENUM_CLASS(Value, In, Out, Inout, Inoutset, Mutexinoutset, Depobj) WRAPPER_CLASS_BOILERPLATE(OmpTaskDependenceType, Value); }; + +// Ref: [4.5:229-230], [5.0:324-325], [5.1:357-358], [5.2:161-162] +// +// variable-category -> +// SCALAR | // since 4.5 +// AGGREGATE | ALLOCATABLE | POINTER | // since 5.0 +// ALL // since 5.2 +struct OmpVariableCategory { + ENUM_CLASS(Value, Aggregate, All, Allocatable, Pointer, Scalar) + WRAPPER_CLASS_BOILERPLATE(OmpVariableCategory, Value); +}; } // namespace modifier // --- Clauses @@ -3578,8 +3607,8 @@ struct OmpDefaultmapClause { TUPLE_CLASS_BOILERPLATE(OmpDefaultmapClause); ENUM_CLASS( ImplicitBehavior, Alloc, To, From, Tofrom, Firstprivate, None, Default) - ENUM_CLASS(VariableCategory, All, Scalar, Aggregate, Allocatable, Pointer) - std::tuple> t; + MODIFIER_BOILERPLATE(OmpVariableCategory); + std::tuple t; }; // 2.13.9 iteration-offset -> +/- non-negative-constant @@ -3775,14 +3804,16 @@ struct OmpProcBindClause { WRAPPER_CLASS_BOILERPLATE(OmpProcBindClause, Type); }; -// 2.15.3.6 reduction-clause -> REDUCTION (reduction-identifier: -// variable-name-list) +// Ref: [4.5:201-207], [5.0:300-302], [5.1:332-334], [5.2:134-137] +// +// reduction-clause -> +// REDUCTION(reduction-identifier: list) | // since 4.5 +// REDUCTION([reduction-modifier,] +// reduction-identifier: list) // since 5.0 struct OmpReductionClause { TUPLE_CLASS_BOILERPLATE(OmpReductionClause); - ENUM_CLASS(ReductionModifier, Inscan, Task, Default) - std::tuple, OmpReductionIdentifier, - OmpObjectList> - t; + MODIFIER_BOILERPLATE(OmpReductionModifier, OmpReductionIdentifier); + std::tuple t; }; // 2.7.1 sched-modifier -> MONOTONIC | NONMONOTONIC | SIMD diff --git a/flang/include/flang/Semantics/openmp-modifiers.h b/flang/include/flang/Semantics/openmp-modifiers.h index 6be582761ed68..28fec7314cd8b 100644 --- a/flang/include/flang/Semantics/openmp-modifiers.h +++ b/flang/include/flang/Semantics/openmp-modifiers.h @@ -70,7 +70,11 @@ const OmpModifierDescriptor &OmpGetDescriptor(); template <> const OmpModifierDescriptor &OmpGetDescriptor(); template <> +const OmpModifierDescriptor &OmpGetDescriptor(); +template <> const OmpModifierDescriptor &OmpGetDescriptor(); +template <> +const OmpModifierDescriptor &OmpGetDescriptor(); // Explanation of terminology: // diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp index eddc742d4c095..4f9e7a7c1d78c 100644 --- a/flang/lib/Lower/OpenMP/Clauses.cpp +++ b/flang/lib/Lower/OpenMP/Clauses.cpp @@ -13,6 +13,7 @@ #include "flang/Optimizer/Builder/Todo.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" +#include "flang/Semantics/openmp-modifiers.h" #include "flang/Semantics/symbol.h" #include "llvm/Frontend/OpenMP/OMPConstants.h" @@ -572,7 +573,8 @@ Defaultmap make(const parser::OmpClause::Defaultmap &inp, ); CLAUSET_ENUM_CONVERT( // - convert2, wrapped::VariableCategory, Defaultmap::VariableCategory, + convert2, parser::OmpVariableCategory::Value, + Defaultmap::VariableCategory, // clang-format off MS(Aggregate, Aggregate) MS(All, All) @@ -582,10 +584,11 @@ Defaultmap make(const parser::OmpClause::Defaultmap &inp, // clang-format on ); + auto &mods{semantics::OmpGetModifiers(inp.v)}; auto &t0 = std::get(inp.v.t); - auto &t1 = std::get>(inp.v.t); + auto *t1 = semantics::OmpGetUniqueModifier(mods); - auto category = t1 ? convert2(*t1) : Defaultmap::VariableCategory::All; + auto category = t1 ? convert2(t1->v) : Defaultmap::VariableCategory::All; return Defaultmap{{/*ImplicitBehavior=*/convert1(t0), /*VariableCategory=*/category}}; } @@ -1178,10 +1181,9 @@ ProcBind make(const parser::OmpClause::ProcBind &inp, Reduction make(const parser::OmpClause::Reduction &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpReductionClause - using wrapped = parser::OmpReductionClause; - CLAUSET_ENUM_CONVERT( // - convert, wrapped::ReductionModifier, Reduction::ReductionModifier, + convert, parser::OmpReductionModifier::Value, + Reduction::ReductionModifier, // clang-format off MS(Inscan, Inscan) MS(Task, Task) @@ -1189,16 +1191,17 @@ Reduction make(const parser::OmpClause::Reduction &inp, // clang-format on ); - auto &t0 = - std::get>( - inp.v.t); - auto &t1 = std::get(inp.v.t); + auto &mods = semantics::OmpGetModifiers(inp.v); + auto *t0 = + semantics::OmpGetUniqueModifier(mods); + auto *t1 = + semantics::OmpGetUniqueModifier(mods); auto &t2 = std::get(inp.v.t); return Reduction{ {/*ReductionModifier=*/t0 - ? std::make_optional(convert(*t0)) + ? std::make_optional(convert(t0->v)) : std::nullopt, - /*ReductionIdentifiers=*/{makeReductionOperator(t1, semaCtx)}, + /*ReductionIdentifiers=*/{makeReductionOperator(*t1, semaCtx)}, /*List=*/makeObjects(t2, semaCtx)}}; } @@ -1319,10 +1322,12 @@ Permutation make(const parser::OmpClause::Permutation &inp, TaskReduction make(const parser::OmpClause::TaskReduction &inp, semantics::SemanticsContext &semaCtx) { // inp.v -> parser::OmpReductionClause - auto &t0 = std::get(inp.v.t); + auto &mods = semantics::OmpGetModifiers(inp.v); + auto *t0 = + semantics::OmpGetUniqueModifier(mods); auto &t1 = std::get(inp.v.t); return TaskReduction{ - {/*ReductionIdentifiers=*/{makeReductionOperator(t0, semaCtx)}, + {/*ReductionIdentifiers=*/{makeReductionOperator(*t0, semaCtx)}, /*List=*/makeObjects(t1, semaCtx)}}; } diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 630acf9a6b256..a1d368d73ab83 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -228,6 +228,11 @@ TYPE_PARSER(construct( // TYPE_PARSER(construct(Parser{}) || construct(Parser{})) +TYPE_PARSER(construct( + "INSCAN" >> pure(OmpReductionModifier::Value::Inscan) || + "TASK" >> pure(OmpReductionModifier::Value::Task) || + "DEFAULT" >> pure(OmpReductionModifier::Value::Default))) + TYPE_PARSER(construct( "DEPOBJ" >> pure(OmpTaskDependenceType::Value::Depobj) || "IN"_id >> pure(OmpTaskDependenceType::Value::In) || @@ -236,6 +241,22 @@ TYPE_PARSER(construct( "MUTEXINOUTSET" >> pure(OmpTaskDependenceType::Value::Mutexinoutset) || "OUT" >> pure(OmpTaskDependenceType::Value::Out))) +// This could be auto-generated. +TYPE_PARSER(sourced(construct(sourced( + construct(Parser{}) || + construct( + Parser{}))))) + +TYPE_PARSER(construct( + "AGGREGATE" >> pure(OmpVariableCategory::Value::Aggregate) || + "ALL"_id >> pure(OmpVariableCategory::Value::All) || + "ALLOCATABLE" >> pure(OmpVariableCategory::Value::Allocatable) || + "POINTER" >> pure(OmpVariableCategory::Value::Pointer) || + "SCALAR" >> pure(OmpVariableCategory::Value::Scalar))) + +TYPE_PARSER(sourced( + construct(Parser{}))) + // --- Parsers for clauses -------------------------------------------- // [5.0] 2.10.1 affinity([aff-modifier:] locator-list) @@ -313,16 +334,7 @@ TYPE_PARSER(construct( pure(OmpDefaultmapClause::ImplicitBehavior::Firstprivate) || "NONE" >> pure(OmpDefaultmapClause::ImplicitBehavior::None) || "DEFAULT" >> pure(OmpDefaultmapClause::ImplicitBehavior::Default)), - maybe(":" >> - construct( - "ALL"_id >> pure(OmpDefaultmapClause::VariableCategory::All) || - "SCALAR" >> pure(OmpDefaultmapClause::VariableCategory::Scalar) || - "AGGREGATE" >> - pure(OmpDefaultmapClause::VariableCategory::Aggregate) || - "ALLOCATABLE" >> - pure(OmpDefaultmapClause::VariableCategory::Allocatable) || - "POINTER" >> - pure(OmpDefaultmapClause::VariableCategory::Pointer))))) + maybe(":" >> nonemptyList(Parser{})))) // 2.7.1 SCHEDULE ([modifier1 [, modifier2]:]kind[, chunk_size]) // Modifier -> MONITONIC | NONMONOTONIC | SIMD @@ -379,12 +391,8 @@ TYPE_PARSER(construct( scalarLogicalExpr)) TYPE_PARSER(construct( - maybe( - ("INSCAN" >> pure(OmpReductionClause::ReductionModifier::Inscan) || - "TASK" >> pure(OmpReductionClause::ReductionModifier::Task) || - "DEFAULT" >> pure(OmpReductionClause::ReductionModifier::Default)) / - ","), - Parser{} / ":", Parser{})) + maybe(nonemptyList(Parser{}) / ":"), + Parser{})) // OMP 5.0 2.19.5.6 IN_REDUCTION (reduction-identifier: variable-name-list) TYPE_PARSER(construct( diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 4d6aaceb69c18..72123ae0d318d 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2189,10 +2189,8 @@ class UnparseVisitor { Walk(":", x.step); } void Unparse(const OmpReductionClause &x) { - Walk(std::get>(x.t), - ","); - Walk(std::get(x.t)); - Put(":"); + using Modifier = OmpReductionClause::Modifier; + Walk(std::get>>(x.t), ":"); Walk(std::get(x.t)); } void Unparse(const OmpDetachClause &x) { Walk(x.v); } @@ -2256,9 +2254,9 @@ class UnparseVisitor { Walk(std::get(x.t)); } void Unparse(const OmpDefaultmapClause &x) { + using Modifier = OmpDefaultmapClause::Modifier; Walk(std::get(x.t)); - Walk(":", - std::get>(x.t)); + Walk(":", std::get>>(x.t)); } void Unparse(const OmpToClause &x) { auto &expect{ @@ -2906,7 +2904,7 @@ class UnparseVisitor { WALK_NESTED_ENUM(OmpProcBindClause, Type) // OMP PROC_BIND WALK_NESTED_ENUM(OmpDefaultClause, Type) // OMP DEFAULT WALK_NESTED_ENUM(OmpDefaultmapClause, ImplicitBehavior) // OMP DEFAULTMAP - WALK_NESTED_ENUM(OmpDefaultmapClause, VariableCategory) // OMP DEFAULTMAP + WALK_NESTED_ENUM(OmpVariableCategory, Value) // OMP variable-category WALK_NESTED_ENUM( OmpLastprivateClause, LastprivateModifier) // OMP lastprivate-modifier WALK_NESTED_ENUM(OmpScheduleModifierType, ModType) // OMP schedule-modifier @@ -2915,8 +2913,7 @@ class UnparseVisitor { WALK_NESTED_ENUM(OmpScheduleClause, ScheduleType) // OMP schedule-type WALK_NESTED_ENUM(OmpDeviceClause, DeviceModifier) // OMP device modifier WALK_NESTED_ENUM(OmpDeviceTypeClause, Type) // OMP DEVICE_TYPE - WALK_NESTED_ENUM( - OmpReductionClause, ReductionModifier) // OMP reduction-modifier + WALK_NESTED_ENUM(OmpReductionModifier, Value) // OMP reduction-modifier WALK_NESTED_ENUM(OmpFromClause, Expectation) // OMP motion-expectation WALK_NESTED_ENUM(OmpIfClause, DirectiveNameModifier) // OMP directive-modifier WALK_NESTED_ENUM(OmpCancelType, Type) // OMP cancel-type diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 9cac652216fcf..079d0fd17bfac 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -11,6 +11,7 @@ #include "flang/Evaluate/check-expression.h" #include "flang/Parser/parse-tree.h" #include "flang/Semantics/expression.h" +#include "flang/Semantics/openmp-modifiers.h" #include "flang/Semantics/tools.h" #include @@ -195,7 +196,7 @@ bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) { if (!llvm::omp::isAllowedClauseForDirective(dir, clause, version)) { unsigned allowedInVersion{[&] { - for (unsigned v : {45, 50, 51, 52, 60}) { + for (unsigned v : llvm::omp::getOpenMPVersions()) { if (v <= version) { continue; } @@ -979,12 +980,14 @@ void OmpStructureChecker::Leave(const parser::OpenMPLoopConstruct &x) { // constructs inside LOOP may add the relevant information. Scan reduction is // supported only in loop constructs, so same checks are not applicable to // other directives. + using ReductionModifier = parser::OmpReductionModifier; for (const auto &clause : clauseList.v) { if (const auto *reductionClause{ std::get_if(&clause.u)}) { - const auto &maybeModifier{ - std::get>(reductionClause->v.t)}; - if (maybeModifier && *maybeModifier == ReductionModifier::Inscan) { + auto &modifiers{OmpGetModifiers(reductionClause->v)}; + auto *maybeModifier{OmpGetUniqueModifier(modifiers)}; + if (maybeModifier && + maybeModifier->v == ReductionModifier::Value::Inscan) { const auto &objectList{ std::get(reductionClause->v.t)}; auto checkReductionSymbolInScan = [&](const parser::Name *name) { @@ -2850,20 +2853,27 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Destroy &x) { void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) { CheckAllowedClause(llvm::omp::Clause::OMPC_reduction); - if (CheckReductionOperators(x)) { - CheckReductionTypeList(x); - } - if (const auto &maybeModifier{ - std::get>(x.v.t)}) { - const ReductionModifier modifier{*maybeModifier}; - CheckReductionModifier(modifier); + if (OmpVerifyModifiers(x.v, GetContext().clauseSource, context_)) { + if (CheckReductionOperators(x)) { + CheckReductionTypeList(x); + } + auto &modifiers{OmpGetModifiers(x.v)}; + using ReductionModifier = parser::OmpReductionModifier; + if (auto *maybeModifier{ + OmpGetUniqueModifier(modifiers)}) { + CheckReductionModifier(*maybeModifier); + } } } bool OmpStructureChecker::CheckReductionOperators( const parser::OmpClause::Reduction &x) { - - const auto &definedOp{std::get(x.v.t)}; + auto &modifiers{OmpGetModifiers(x.v)}; + const auto *definedOp{ + OmpGetUniqueModifier(modifiers)}; + if (!definedOp) { + return false; + } bool ok = false; common::visit( common::visitors{ @@ -2896,7 +2906,7 @@ bool OmpStructureChecker::CheckReductionOperators( } }, }, - definedOp.u); + definedOp->u); return ok; } @@ -2928,7 +2938,12 @@ bool OmpStructureChecker::CheckIntrinsicOperator( static bool IsReductionAllowedForType( const parser::OmpClause::Reduction &x, const DeclTypeSpec &type) { - const auto &definedOp{std::get(x.v.t)}; + auto &modifiers{OmpGetModifiers(x.v)}; + const auto *definedOp{ + OmpGetUniqueModifier(modifiers)}; + if (!definedOp) { + return false; + } // TODO: user defined reduction operators. Just allow everything for now. bool ok{true}; @@ -3002,7 +3017,7 @@ static bool IsReductionAllowedForType( } }, }, - definedOp.u); + definedOp->u); return ok; } @@ -3035,8 +3050,9 @@ void OmpStructureChecker::CheckReductionTypeList( } void OmpStructureChecker::CheckReductionModifier( - const ReductionModifier &modifier) { - if (modifier == ReductionModifier::Default) { + const parser::OmpReductionModifier &modifier) { + using ReductionModifier = parser::OmpReductionModifier; + if (modifier.v == ReductionModifier::Value::Default) { // The default one is always ok. return; } @@ -3049,7 +3065,7 @@ void OmpStructureChecker::CheckReductionModifier( context_.Say(GetContext().clauseSource, "REDUCTION modifier on LOOP directive must be DEFAULT"_err_en_US); } - if (modifier == ReductionModifier::Task) { + if (modifier.v == ReductionModifier::Value::Task) { // "Task" is only allowed on worksharing or "parallel" directive. static llvm::omp::Directive worksharing[]{ llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_scope, @@ -3065,7 +3081,7 @@ void OmpStructureChecker::CheckReductionModifier( "Modifier 'TASK' on REDUCTION clause is only allowed with " "PARALLEL or worksharing directive"_err_en_US); } - } else if (modifier == ReductionModifier::Inscan) { + } else if (modifier.v == ReductionModifier::Value::Inscan) { // "Inscan" is only allowed on worksharing-loop, worksharing-loop simd, // or "simd" directive. // The worksharing-loop directives are OMPD_do and OMPD_for. Only the @@ -3382,28 +3398,27 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) { ThisVersion(version), TryVersion(50)); } } - using VariableCategory = parser::OmpDefaultmapClause::VariableCategory; - auto maybeCategory{std::get>(x.v.t)}; - if (!maybeCategory) { - if (version <= 45) { - context_.Say(GetContext().clauseSource, - "The DEFAULTMAP clause requires a variable-category SCALAR in %s, %s"_warn_en_US, - ThisVersion(version), TryVersion(50)); - } - } else { - VariableCategory category{*maybeCategory}; + if (!OmpVerifyModifiers(x.v, GetContext().clauseSource, context_)) { + // If modifier verification fails, return early. + return; + } + auto &modifiers{OmpGetModifiers(x.v)}; + auto *maybeCategory{ + OmpGetUniqueModifier(modifiers)}; + if (maybeCategory) { + using VariableCategory = parser::OmpVariableCategory; + VariableCategory::Value category{maybeCategory->v}; unsigned tryVersion{0}; - if (version <= 45 && category != VariableCategory::Scalar) { + if (version <= 45 && category != VariableCategory::Value::Scalar) { tryVersion = 50; } - if (version < 52 && category == VariableCategory::All) { + if (version < 52 && category == VariableCategory::Value::All) { tryVersion = 52; } if (tryVersion) { context_.Say(GetContext().clauseSource, "%s is not allowed in %s, %s"_warn_en_US, - parser::ToUpperCaseLetters( - parser::OmpDefaultmapClause::EnumToString(category)), + parser::ToUpperCaseLetters(VariableCategory::EnumToString(category)), ThisVersion(version), TryVersion(tryVersion)); } } diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index df21ebac0f6d7..af61215ecc403 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -70,7 +70,6 @@ class OmpStructureChecker ) { } using llvmOmpClause = const llvm::omp::Clause; - using ReductionModifier = parser::OmpReductionClause::ReductionModifier; void Enter(const parser::OpenMPConstruct &); void Leave(const parser::OpenMPConstruct &); @@ -227,7 +226,7 @@ class OmpStructureChecker bool CheckIntrinsicOperator( const parser::DefinedOperator::IntrinsicOperator &); void CheckReductionTypeList(const parser::OmpClause::Reduction &); - void CheckReductionModifier(const ReductionModifier &); + void CheckReductionModifier(const parser::OmpReductionModifier &); void CheckMasterNesting(const parser::OpenMPBlockConstruct &x); void ChecksOnOrderedAsBlock(); void CheckBarrierNesting(const parser::OpenMPSimpleStandaloneConstruct &x); diff --git a/flang/lib/Semantics/openmp-modifiers.cpp b/flang/lib/Semantics/openmp-modifiers.cpp index 70ca988cddce5..a425eec76a36d 100644 --- a/flang/lib/Semantics/openmp-modifiers.cpp +++ b/flang/lib/Semantics/openmp-modifiers.cpp @@ -128,6 +128,22 @@ OmpGetDescriptor() { return desc; } +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"reduction-modifier", + /*props=*/ + { + {45, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {45, {Clause::OMPC_reduction}}, + }, + }; + return desc; +} + template <> const OmpModifierDescriptor &OmpGetDescriptor() { static const OmpModifierDescriptor desc{ @@ -143,4 +159,21 @@ const OmpModifierDescriptor &OmpGetDescriptor() { }; return desc; } + +template <> +const OmpModifierDescriptor &OmpGetDescriptor() { + static const OmpModifierDescriptor desc{ + /*name=*/"variable-category", + /*props=*/ + { + {45, {OmpProperty::Required, OmpProperty::Unique}}, + {50, {OmpProperty::Unique}}, + }, + /*clauses=*/ + { + {45, {Clause::OMPC_defaultmap}}, + }, + }; + return desc; +} } // namespace Fortran::semantics diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 80e238f3476ac..c75808a8963b3 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -19,6 +19,7 @@ #include "flang/Parser/parse-tree.h" #include "flang/Parser/tools.h" #include "flang/Semantics/expression.h" +#include "flang/Semantics/openmp-modifiers.h" #include "flang/Semantics/symbol.h" #include "flang/Semantics/tools.h" #include @@ -518,8 +519,14 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { } bool Pre(const parser::OmpClause::Reduction &x) { - const parser::OmpReductionIdentifier &opr{ - std::get(x.v.t)}; + const auto &objList{std::get(x.v.t)}; + ResolveOmpObjectList(objList, Symbol::Flag::OmpReduction); + + auto &modifiers{OmpGetModifiers(x.v)}; + if (!modifiers) { + return false; + } + auto createDummyProcSymbol = [&](const parser::Name *name) { // If name resolution failed, create a dummy symbol const auto namePair{ @@ -530,30 +537,35 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { } name->symbol = &newSymbol; }; - if (const auto *procD{parser::Unwrap(opr.u)}) { - if (const auto *name{parser::Unwrap(procD->u)}) { - if (!name->symbol) { - if (!ResolveName(name)) { - createDummyProcSymbol(name); + + for (auto &mod : *modifiers) { + if (!std::holds_alternative(mod.u)) { + continue; + } + auto &opr{std::get(mod.u)}; + if (auto *procD{parser::Unwrap(opr.u)}) { + if (auto *name{parser::Unwrap(procD->u)}) { + if (!name->symbol) { + if (!ResolveName(name)) { + createDummyProcSymbol(name); + } } } - } - if (const auto *procRef{ - parser::Unwrap(procD->u)}) { - if (!procRef->v.thing.component.symbol) { - if (!ResolveName(&procRef->v.thing.component)) { - createDummyProcSymbol(&procRef->v.thing.component); + if (auto *procRef{parser::Unwrap(procD->u)}) { + if (!procRef->v.thing.component.symbol) { + if (!ResolveName(&procRef->v.thing.component)) { + createDummyProcSymbol(&procRef->v.thing.component); + } } } } } - const auto &objList{std::get(x.v.t)}; - ResolveOmpObjectList(objList, Symbol::Flag::OmpReduction); - using ReductionModifier = parser::OmpReductionClause::ReductionModifier; - const auto &maybeModifier{ - std::get>(x.v.t)}; - if (maybeModifier && *maybeModifier == ReductionModifier::Inscan) { - ResolveOmpObjectList(objList, Symbol::Flag::OmpInScanReduction); + using ReductionModifier = parser::OmpReductionModifier; + if (auto *maybeModifier{ + OmpGetUniqueModifier(modifiers)}) { + if (maybeModifier->v == ReductionModifier::Value::Inscan) { + ResolveOmpObjectList(objList, Symbol::Flag::OmpInScanReduction); + } } return false; } diff --git a/flang/test/Parser/OpenMP/defaultmap-clause.f90 b/flang/test/Parser/OpenMP/defaultmap-clause.f90 index 6f018ffe8561c..dc036aedcd003 100644 --- a/flang/test/Parser/OpenMP/defaultmap-clause.f90 +++ b/flang/test/Parser/OpenMP/defaultmap-clause.f90 @@ -31,7 +31,7 @@ subroutine f01 !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: | | ImplicitBehavior = Firstprivate -!PARSE-TREE: | | VariableCategory = Aggregate +!PARSE-TREE: | | Modifier -> OmpVariableCategory -> Value = Aggregate subroutine f02 !$omp target defaultmap(alloc: all) @@ -47,7 +47,7 @@ subroutine f02 !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: | | ImplicitBehavior = Alloc -!PARSE-TREE: | | VariableCategory = All +!PARSE-TREE: | | Modifier -> OmpVariableCategory -> Value = All ! Both "all" and "allocatable" are valid, and "all" is a prefix of ! "allocatable". Make sure we parse this correctly. @@ -65,7 +65,7 @@ subroutine f03 !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: | | ImplicitBehavior = Alloc -!PARSE-TREE: | | VariableCategory = Allocatable +!PARSE-TREE: | | Modifier -> OmpVariableCategory -> Value = Allocatable subroutine f04 !$omp target defaultmap(tofrom: scalar) @@ -81,4 +81,4 @@ subroutine f04 !PARSE-TREE: | OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: | OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: | | ImplicitBehavior = Tofrom -!PARSE-TREE: | | VariableCategory = Scalar +!PARSE-TREE: | | Modifier -> OmpVariableCategory -> Value = Scalar diff --git a/flang/test/Parser/OpenMP/defaultmap-unparse.f90 b/flang/test/Parser/OpenMP/defaultmap-unparse.f90 index e7333b02bc8f6..bbbb6fc938326 100644 --- a/flang/test/Parser/OpenMP/defaultmap-unparse.f90 +++ b/flang/test/Parser/OpenMP/defaultmap-unparse.f90 @@ -38,7 +38,7 @@ program main !PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = Tofrom -!PARSE-TREE: VariableCategory = Scalar +!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar !CHECK: !$omp target defaultmap(alloc:scalar) !$omp target defaultmap(alloc:scalar) @@ -50,7 +50,7 @@ program main !PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = Alloc -!PARSE-TREE: VariableCategory = Scalar +!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar !CHECK: !$omp target defaultmap(none) !$omp target defaultmap(none) @@ -73,7 +73,7 @@ program main !PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = None -!PARSE-TREE: VariableCategory = Scalar +!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar !CHECK: !$omp target defaultmap(to:scalar) !$omp target defaultmap(to:scalar) @@ -85,7 +85,7 @@ program main !PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = To -!PARSE-TREE: VariableCategory = Scalar +!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar !CHECK: !$omp target defaultmap(firstprivate:scalar) !$omp target defaultmap(firstprivate:scalar) @@ -97,7 +97,7 @@ program main !PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = Firstprivate -!PARSE-TREE: VariableCategory = Scalar +!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Scalar !CHECK: !$omp target defaultmap(tofrom:aggregate) !$omp target defaultmap(tofrom:aggregate) @@ -112,7 +112,7 @@ program main !PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = Tofrom -!PARSE-TREE: VariableCategory = Aggregate +!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Aggregate !CHECK: !$omp target defaultmap(tofrom:allocatable) !$omp target defaultmap(tofrom:allocatable) @@ -124,7 +124,7 @@ program main !PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = Tofrom -!PARSE-TREE: VariableCategory = Allocatable +!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Allocatable !CHECK: !$omp target defaultmap(default:pointer) !$omp target defaultmap(default:pointer) @@ -138,7 +138,7 @@ program main !PARSE-TREE: OmpBlockDirective -> llvm::omp::Directive = target !PARSE-TREE: OmpClauseList -> OmpClause -> Defaultmap -> OmpDefaultmapClause !PARSE-TREE: ImplicitBehavior = Default -!PARSE-TREE: VariableCategory = Pointer +!PARSE-TREE: Modifier -> OmpVariableCategory -> Value = Pointer end program main !CHECK-LABEL: end program main diff --git a/flang/test/Parser/OpenMP/reduction-modifier.f90 b/flang/test/Parser/OpenMP/reduction-modifier.f90 index 4bba23bcf0611..64cd452e839e7 100644 --- a/flang/test/Parser/OpenMP/reduction-modifier.f90 +++ b/flang/test/Parser/OpenMP/reduction-modifier.f90 @@ -4,13 +4,13 @@ subroutine foo() integer :: i, j j = 0 -! CHECK: !$OMP DO REDUCTION(TASK,*:j) +! CHECK: !$OMP DO REDUCTION(TASK, *:j) ! PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct ! PARSE-TREE: | | | OmpBeginLoopDirective ! PARSE-TREE: | | | | OmpLoopDirective -> llvm::omp::Directive = do ! PARSE-TREE: | | | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause -! PARSE-TREE: | | | | | ReductionModifier = Task -! PARSE-TREE: | | | | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply +! PARSE-TREE: | | | | | Modifier -> OmpReductionModifier -> Value = Task +! PARSE-TREE: | | | | | Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply ! PARSE-TREE: | | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'j !$omp do reduction (task, *: j) do i = 1, 10 diff --git a/flang/test/Semantics/OpenMP/combined-constructs.f90 b/flang/test/Semantics/OpenMP/combined-constructs.f90 index 38b0d090e441d..25893a47860f4 100644 --- a/flang/test/Semantics/OpenMP/combined-constructs.f90 +++ b/flang/test/Semantics/OpenMP/combined-constructs.f90 @@ -33,7 +33,7 @@ program main enddo !$omp end target parallel - !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 + !ERROR: A variable-category modifier is required !$omp target parallel defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -80,7 +80,7 @@ program main enddo !$omp end target parallel do - !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 + !ERROR: A variable-category modifier is required !$omp target parallel do defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -140,7 +140,7 @@ program main enddo !$omp end target teams - !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 + !ERROR: A variable-category modifier is required !$omp target teams defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -240,7 +240,7 @@ program main enddo !$omp end target teams distribute - !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 + !ERROR: A variable-category modifier is required !$omp target teams distribute defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -333,7 +333,7 @@ program main enddo !$omp end target teams distribute parallel do - !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 + !ERROR: A variable-category modifier is required !$omp target teams distribute parallel do defaultmap(tofrom) do i = 1, N a(i) = 3.14 @@ -433,7 +433,7 @@ program main enddo !$omp end target teams distribute parallel do simd - !ERROR: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v1.1, try -fopenmp-version=50 + !ERROR: A variable-category modifier is required !$omp target teams distribute parallel do simd defaultmap(tofrom) do i = 1, N a(i) = 3.14 diff --git a/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 b/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 index a30d90ddce029..9cb91a71c5535 100644 --- a/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 +++ b/flang/test/Semantics/OpenMP/defaultmap-clause-v45.f90 @@ -1,7 +1,7 @@ !RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45 -Werror subroutine f00 -!WARNING: The DEFAULTMAP clause requires a variable-category SCALAR in OpenMP v4.5, try -fopenmp-version=50 +!WARNING: A variable-category modifier is required !$omp target defaultmap(tofrom) !$omp end target end