diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp index 5c64870b74be..cc058bf28329 100644 --- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp +++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp @@ -101,22 +101,8 @@ std::string OpenMPCounterVisitor::getName(const OmpWrapperType &w) { return getName(*std::get(w)); } std::string OpenMPCounterVisitor::getName(const OpenMPDeclarativeConstruct &c) { - return std::visit( // - Fortran::common::visitors{ - [&](const OpenMPUtilityConstruct &o) -> std::string { - const CharBlock &source{o.source}; - return normalize_construct_name(source.ToString()); - }, - [&](const OmpMetadirectiveDirective &o) -> std::string { - const CharBlock &source{o.source}; - return normalize_construct_name(source.ToString()); - }, - [&](const auto &o) -> std::string { - const CharBlock &source{std::get(o.t).source}; - return normalize_construct_name(source.ToString()); - }, - }, - c.u); + return normalize_construct_name( + omp::GetOmpDirectiveName(c).source.ToString()); } std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) { return normalize_construct_name( diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index a4380e19cdba..57421da4fa93 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -733,6 +733,7 @@ public: NODE(parser, OpenMPLoopConstruct) NODE(parser, OpenMPExecutableAllocate) NODE(parser, OpenMPAllocatorsConstruct) + NODE(parser, OpenMPGroupprivate) NODE(parser, OpenMPRequiresConstruct) NODE(parser, OpenMPSimpleStandaloneConstruct) NODE(parser, OpenMPStandaloneConstruct) diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h index fa0f7656cd5d..5cae305c55a3 100644 --- a/flang/include/flang/Parser/openmp-utils.h +++ b/flang/include/flang/Parser/openmp-utils.h @@ -95,7 +95,8 @@ struct DirectiveNameScope { std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v) { + std::is_same_v || + std::is_same_v) { return x.v.DirName(); } else { return GetOmpDirectiveName(x.v); diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index e9045b4f772e..1d1a4a163084 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4955,6 +4955,15 @@ struct OpenMPDeclareSimdConstruct { std::tuple, OmpClauseList> t; }; +// ref: [6.0:301-303] +// +// groupprivate-directive -> +// GROUPPRIVATE (variable-list-item...) // since 6.0 +struct OpenMPGroupprivate { + WRAPPER_CLASS_BOILERPLATE(OpenMPGroupprivate, OmpDirectiveSpecification); + CharBlock source; +}; + // 2.4 requires -> REQUIRES requires-clause[ [ [,] requires-clause]...] struct OpenMPRequiresConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPRequiresConstruct); @@ -4982,8 +4991,9 @@ struct OpenMPDeclarativeConstruct { std::variant + OmpDeclareVariantDirective, OpenMPGroupprivate, OpenMPThreadprivate, + OpenMPRequiresConstruct, OpenMPUtilityConstruct, + OmpMetadirectiveDirective> u; }; diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index fef64ccc1501..ec2ec37e623f 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -3593,6 +3593,13 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, } } +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPGroupprivate &directive) { + TODO(converter.getCurrentLocation(), "GROUPPRIVATE"); +} + static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index d83635952740..56cee4ab38e9 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -1790,6 +1790,12 @@ TYPE_PARSER(sourced(construct( verbatim("DECLARE SIMD"_tok) || verbatim("DECLARE_SIMD"_tok), maybe(parenthesized(name)), Parser{}))) +TYPE_PARSER(sourced( // + construct( + predicated(OmpDirectiveNameParser{}, + IsDirective(llvm::omp::Directive::OMPD_groupprivate)) >= + Parser{}))) + // 2.4 Requires construct TYPE_PARSER(sourced(construct( verbatim("REQUIRES"_tok), Parser{}))) @@ -1825,6 +1831,8 @@ TYPE_PARSER( Parser{}) || construct( Parser{}) || + construct( + Parser{}) || construct( Parser{}) || construct( diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index f3b82975a837..09dcfe60a46b 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2721,6 +2721,13 @@ public: void Unparse(const OpenMPDispatchConstruct &x) { // Unparse(static_cast(x)); } + void Unparse(const OpenMPGroupprivate &x) { + BeginOpenMP(); + Word("!$OMP "); + Walk(x.v); + Put("\n"); + EndOpenMP(); + } void Unparse(const OpenMPRequiresConstruct &y) { BeginOpenMP(); Word("!$OMP REQUIRES "); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 1be3c41b9bcc..9b1733796ddc 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -571,6 +571,10 @@ template struct DirectiveSpellingVisitor { Directive::OMPD_declare_variant); return false; } + bool Pre(const parser::OpenMPGroupprivate &x) { + checker_(x.v.DirName().source, Directive::OMPD_groupprivate); + return false; + } bool Pre(const parser::OpenMPThreadprivate &x) { checker_( std::get(x.t).source, Directive::OMPD_threadprivate); @@ -1175,6 +1179,15 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar( } } +void OmpStructureChecker::Enter(const parser::OpenMPGroupprivate &x) { + PushContextAndClauseSets( + x.v.DirName().source, llvm::omp::Directive::OMPD_groupprivate); +} + +void OmpStructureChecker::Leave(const parser::OpenMPGroupprivate &x) { + dirContext_.pop_back(); +} + void OmpStructureChecker::Enter(const parser::OpenMPThreadprivate &c) { const auto &dir{std::get(c.t)}; PushContextAndClauseSets( diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index abf76e604b7a..b548a455ee07 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -126,6 +126,8 @@ public: void Leave(const parser::OpenMPAllocatorsConstruct &); void Enter(const parser::OpenMPRequiresConstruct &); void Leave(const parser::OpenMPRequiresConstruct &); + void Enter(const parser::OpenMPGroupprivate &); + void Leave(const parser::OpenMPGroupprivate &); void Enter(const parser::OpenMPThreadprivate &); void Leave(const parser::OpenMPThreadprivate &); diff --git a/flang/test/Lower/OpenMP/Todo/groupprivate.f90 b/flang/test/Lower/OpenMP/Todo/groupprivate.f90 new file mode 100644 index 000000000000..9ad9b9382760 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/groupprivate.f90 @@ -0,0 +1,9 @@ +!RUN: %not_todo_cmd %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 -o - %s 2>&1 | FileCheck %s + +!CHECK: not yet implemented: GROUPPRIVATE + +module m +implicit none +integer :: x +!$omp groupprivate(x) +end module diff --git a/flang/test/Parser/OpenMP/groupprivate.f90 b/flang/test/Parser/OpenMP/groupprivate.f90 new file mode 100644 index 000000000000..8bd840147a2d --- /dev/null +++ b/flang/test/Parser/OpenMP/groupprivate.f90 @@ -0,0 +1,30 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=60 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=60 %s | FileCheck --check-prefix="PARSE-TREE" %s + +module m +implicit none + +integer :: x, y(10), z +!$omp groupprivate(x, y) device_type(nohost) +!$omp groupprivate(z) + +end module + +!UNPARSE: MODULE m +!UNPARSE: IMPLICIT NONE +!UNPARSE: INTEGER x, y(10_4), z +!UNPARSE: !$OMP GROUPPRIVATE(x, y) DEVICE_TYPE(NOHOST) +!UNPARSE: !$OMP GROUPPRIVATE(z) +!UNPARSE: END MODULE + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPGroupprivate -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = groupprivate +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'y' +!PARSE-TREE: | OmpClauseList -> OmpClause -> DeviceType -> OmpDeviceTypeClause -> DeviceTypeDescription = Nohost +!PARSE-TREE: | Flags = None +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPGroupprivate -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = groupprivate +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'z' +!PARSE-TREE: | OmpClauseList -> +!PARSE-TREE: | Flags = None