From d7303ba83c92abbd6e8b849dbed8239345054269 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Fri, 19 Sep 2025 13:15:30 -0500 Subject: [PATCH 01/10] [flang][OpenMP] Simplify handling of UserReductionDetails a bit Instead of having a variant with specific AST nodes that can contain a reduction specifier, simply store the OpenMPDeclarativeConstruct. It is used to emit the source code directive when generating a module file, and unparsing the top-level AST node will work just fine. --- flang/include/flang/Semantics/symbol.h | 11 +++++------ flang/lib/Parser/unparse.cpp | 7 ++----- flang/lib/Semantics/mod-file.cpp | 15 ++------------- flang/lib/Semantics/resolve-names.cpp | 20 +++++++++----------- 4 files changed, 18 insertions(+), 35 deletions(-) diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index 774fc9873f7bc..e90e9c617805d 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -30,8 +30,7 @@ class raw_ostream; } namespace Fortran::parser { struct Expr; -struct OpenMPDeclareReductionConstruct; -struct OmpMetadirectiveDirective; +struct OpenMPDeclarativeConstruct; } namespace Fortran::semantics { @@ -736,9 +735,7 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &, const GenericDetails &); class UserReductionDetails { public: using TypeVector = std::vector; - using DeclInfo = std::variant; - using DeclVector = std::vector; + using DeclVector = std::vector; UserReductionDetails() = default; @@ -756,7 +753,9 @@ class UserReductionDetails { return false; } - void AddDecl(const DeclInfo &decl) { declList_.emplace_back(decl); } + void AddDecl(const parser::OpenMPDeclarativeConstruct *decl) { + declList_.emplace_back(decl); + } const DeclVector &GetDeclList() const { return declList_; } private: diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 9d73bcafa0e15..2db60c9a78b0f 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -3082,11 +3082,8 @@ template void Unparse(llvm::raw_ostream &, const Expr &, const common::LangOptions &, Encoding, bool, bool, preStatementType *, AnalyzedObjectsAsFortran *); -template void Unparse( - llvm::raw_ostream &, const parser::OpenMPDeclareReductionConstruct &, +template void Unparse( + llvm::raw_ostream &, const parser::OpenMPDeclarativeConstruct &, const common::LangOptions &, Encoding, bool, bool, preStatementType *, AnalyzedObjectsAsFortran *); -template void Unparse(llvm::raw_ostream &, - const parser::OmpMetadirectiveDirective &, const common::LangOptions &, - Encoding, bool, bool, preStatementType *, AnalyzedObjectsAsFortran *); } // namespace Fortran::parser diff --git a/flang/lib/Semantics/mod-file.cpp b/flang/lib/Semantics/mod-file.cpp index 82c8536902eb2..8074c94b41e1a 100644 --- a/flang/lib/Semantics/mod-file.cpp +++ b/flang/lib/Semantics/mod-file.cpp @@ -1056,19 +1056,8 @@ void ModFileWriter::PutUserReduction( // The module content for a OpenMP Declare Reduction is the OpenMP // declaration. There may be multiple declarations. // Decls are pointers, so do not use a reference. - for (const auto decl : details.GetDeclList()) { - common::visit( // - common::visitors{// - [&](const parser::OpenMPDeclareReductionConstruct *d) { - Unparse(os, *d, context_.langOptions()); - }, - [&](const parser::OmpMetadirectiveDirective *m) { - Unparse(os, *m, context_.langOptions()); - }, - [&](const auto &) { - DIE("Unknown OpenMP DECLARE REDUCTION content"); - }}, - decl); + for (const auto *decl : details.GetDeclList()) { + Unparse(os, *decl, context_.langOptions()); } } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index cdd8d6ff2f60e..69b8a45e6ceaa 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1480,12 +1480,10 @@ class OmpVisitor : public virtual DeclarationVisitor { static bool NeedsScope(const parser::OmpClause &); bool Pre(const parser::OmpMetadirectiveDirective &x) { // - metaDirective_ = &x; ++metaLevel_; return true; } void Post(const parser::OmpMetadirectiveDirective &) { // - metaDirective_ = nullptr; --metaLevel_; } @@ -1583,7 +1581,8 @@ class OmpVisitor : public virtual DeclarationVisitor { AddOmpSourceRange(x.source); ProcessReductionSpecifier( std::get>(x.t).value(), - std::get>(x.t), x); + std::get>(x.t), + declaratives_.back()); return false; } bool Pre(const parser::OmpMapClause &); @@ -1684,9 +1683,11 @@ class OmpVisitor : public virtual DeclarationVisitor { // can implicitly declare variables instead of only using the // ones already declared in the Fortran sources. SkipImplicitTyping(true); + declaratives_.push_back(&x); return true; } void Post(const parser::OpenMPDeclarativeConstruct &) { + declaratives_.pop_back(); SkipImplicitTyping(false); messageHandler().set_currStmtSource(std::nullopt); } @@ -1728,15 +1729,14 @@ class OmpVisitor : public virtual DeclarationVisitor { private: void ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec, const parser::OmpClauseList &clauses); - template void ProcessReductionSpecifier(const parser::OmpReductionSpecifier &spec, const std::optional &clauses, - const T &wholeConstruct); + const parser::OpenMPDeclarativeConstruct *wholeConstruct); void ResolveCriticalName(const parser::OmpArgument &arg); int metaLevel_{0}; - const parser::OmpMetadirectiveDirective *metaDirective_{nullptr}; + std::vector declaratives_; }; bool OmpVisitor::NeedsScope(const parser::OmpBlockConstruct &x) { @@ -1861,11 +1861,10 @@ std::string MangleDefinedOperator(const parser::CharBlock &name) { return "op" + name.ToString(); } -template void OmpVisitor::ProcessReductionSpecifier( const parser::OmpReductionSpecifier &spec, const std::optional &clauses, - const T &wholeOmpConstruct) { + const parser::OpenMPDeclarativeConstruct *construct) { const parser::Name *name{nullptr}; parser::CharBlock mangledName; UserReductionDetails reductionDetailsTemp; @@ -1952,7 +1951,7 @@ void OmpVisitor::ProcessReductionSpecifier( PopScope(); } - reductionDetails->AddDecl(&wholeOmpConstruct); + reductionDetails->AddDecl(construct); if (!symbol) { symbol = &MakeSymbol(mangledName, Attrs{}, std::move(*reductionDetails)); @@ -2017,8 +2016,7 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) { if (maybeArgs && maybeClauses) { const parser::OmpArgument &first{maybeArgs->v.front()}; if (auto *spec{std::get_if(&first.u)}) { - CHECK(metaDirective_); - ProcessReductionSpecifier(*spec, maybeClauses, *metaDirective_); + ProcessReductionSpecifier(*spec, maybeClauses, declaratives_.back()); } } break; From 0fa862b9382c8e5b774bf103c7c3c7fb04bc6268 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Sat, 20 Sep 2025 12:11:18 -0500 Subject: [PATCH 02/10] [flang][OpenMP] Stop tracking metadirective level in name resolution This was checked in the visitor for OmpDirectiveSpecification, and is not necessary anymore: the early exit (in case of not being inside of a METADIRECTIVE) performs the same actions as the code that was skipped, except it does so through a different sequence of function calls. The net result ends up being the same in either case. The processing of the mapper and reduction specifiers inside of OmpDirectiveSpecification is necesary for the declare directives on WHEN/OTHERWISE clauses, so it's the early exit that needs to be removed. In fact, when the DECLARE_MAPPER/REDUCTION use OmpDirectiveSpecification, this processing will automatically take over the handling of the contained specifiers. --- flang/lib/Semantics/resolve-names.cpp | 46 +++++++++------------------ 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 69b8a45e6ceaa..13edb118a3286 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1479,14 +1479,6 @@ class OmpVisitor : public virtual DeclarationVisitor { static bool NeedsScope(const parser::OmpBlockConstruct &); static bool NeedsScope(const parser::OmpClause &); - bool Pre(const parser::OmpMetadirectiveDirective &x) { // - ++metaLevel_; - return true; - } - void Post(const parser::OmpMetadirectiveDirective &) { // - --metaLevel_; - } - bool Pre(const parser::OpenMPRequiresConstruct &x) { AddOmpSourceRange(x.source); return true; @@ -1579,10 +1571,11 @@ class OmpVisitor : public virtual DeclarationVisitor { bool Pre(const parser::OpenMPDeclareReductionConstruct &x) { AddOmpSourceRange(x.source); + parser::OmpClauseList empty(std::list{}); + auto &maybeClauses{std::get>(x.t)}; ProcessReductionSpecifier( std::get>(x.t).value(), - std::get>(x.t), - declaratives_.back()); + maybeClauses ? *maybeClauses : empty, declaratives_.back()); return false; } bool Pre(const parser::OmpMapClause &); @@ -1730,12 +1723,11 @@ class OmpVisitor : public virtual DeclarationVisitor { void ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec, const parser::OmpClauseList &clauses); void ProcessReductionSpecifier(const parser::OmpReductionSpecifier &spec, - const std::optional &clauses, + const parser::OmpClauseList &clauses, const parser::OpenMPDeclarativeConstruct *wholeConstruct); void ResolveCriticalName(const parser::OmpArgument &arg); - int metaLevel_{0}; std::vector declaratives_; }; @@ -1863,7 +1855,7 @@ std::string MangleDefinedOperator(const parser::CharBlock &name) { void OmpVisitor::ProcessReductionSpecifier( const parser::OmpReductionSpecifier &spec, - const std::optional &clauses, + const parser::OmpClauseList &clauses, const parser::OpenMPDeclarativeConstruct *construct) { const parser::Name *name{nullptr}; parser::CharBlock mangledName; @@ -1991,39 +1983,31 @@ void OmpVisitor::ResolveCriticalName(const parser::OmpArgument &arg) { bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) { AddOmpSourceRange(x.source); - if (metaLevel_ == 0) { - // Not in METADIRECTIVE. - return true; - } - // If OmpDirectiveSpecification (which contains clauses) is a part of - // METADIRECTIVE, some semantic checks may not be applicable. - // Disable the semantic analysis for it in such cases to allow the compiler - // to parse METADIRECTIVE without flagging errors. - auto &maybeArgs{std::get>(x.t)}; - auto &maybeClauses{std::get>(x.t)}; + const parser::OmpArgumentList &args{x.Arguments()}; + const parser::OmpClauseList &clauses{x.Clauses()}; switch (x.DirId()) { case llvm::omp::Directive::OMPD_declare_mapper: - if (maybeArgs && maybeClauses) { - const parser::OmpArgument &first{maybeArgs->v.front()}; + if (!args.v.empty()) { + const parser::OmpArgument &first{args.v.front()}; if (auto *spec{std::get_if(&first.u)}) { - ProcessMapperSpecifier(*spec, *maybeClauses); + ProcessMapperSpecifier(*spec, clauses); } } break; case llvm::omp::Directive::OMPD_declare_reduction: - if (maybeArgs && maybeClauses) { - const parser::OmpArgument &first{maybeArgs->v.front()}; + if (!args.v.empty()) { + const parser::OmpArgument &first{args.v.front()}; if (auto *spec{std::get_if(&first.u)}) { - ProcessReductionSpecifier(*spec, maybeClauses, declaratives_.back()); + ProcessReductionSpecifier(*spec, clauses, declaratives_.back()); } } break; default: // Default processing. - Walk(maybeArgs); - Walk(maybeClauses); + Walk(args); + Walk(clauses); break; } return false; From e0ae3e5dd4817329f0e104e0ea7fd883754f442f Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Sat, 20 Sep 2025 09:58:43 -0500 Subject: [PATCH 03/10] [flang][OpenMP] Resolve all components of OmpDirectiveSpecification Fully resolve all arguments and clauses in OmpDirectiveSpecification instead of just looking for special cases. Delegate resolution from nodes that inherit from ODS to use the ODS resolution. --- flang/lib/Semantics/resolve-names.cpp | 129 +++++++++++++------------- 1 file changed, 62 insertions(+), 67 deletions(-) diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 13edb118a3286..5dd0e1fd5072e 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1486,34 +1486,16 @@ class OmpVisitor : public virtual DeclarationVisitor { bool Pre(const parser::OmpBlockConstruct &); void Post(const parser::OmpBlockConstruct &); bool Pre(const parser::OmpBeginDirective &x) { - AddOmpSourceRange(x.source); - // Manually resolve names in CRITICAL directives. This is because these - // names do not denote Fortran objects, and the CRITICAL directive causes - // them to be "auto-declared", i.e. inserted into the global scope. - // More specifically, they are not expected to have explicit declarations, - // and if they do the behavior is unspeficied. - if (x.DirName().v == llvm::omp::Directive::OMPD_critical) { - for (const parser::OmpArgument &arg : x.Arguments().v) { - ResolveCriticalName(arg); - } - } - return true; + return Pre(static_cast(x)); } - void Post(const parser::OmpBeginDirective &) { - messageHandler().set_currStmtSource(std::nullopt); + void Post(const parser::OmpBeginDirective &x) { + Post(static_cast(x)); } bool Pre(const parser::OmpEndDirective &x) { - AddOmpSourceRange(x.source); - // Manually resolve names in CRITICAL directives. - if (x.DirName().v == llvm::omp::Directive::OMPD_critical) { - for (const parser::OmpArgument &arg : x.Arguments().v) { - ResolveCriticalName(arg); - } - } - return true; + return Pre(static_cast(x)); } - void Post(const parser::OmpEndDirective &) { - messageHandler().set_currStmtSource(std::nullopt); + void Post(const parser::OmpEndDirective &x) { + Post(static_cast(x)); } bool Pre(const parser::OpenMPLoopConstruct &) { @@ -1522,8 +1504,16 @@ class OmpVisitor : public virtual DeclarationVisitor { } void Post(const parser::OpenMPLoopConstruct &) { PopScope(); } bool Pre(const parser::OmpBeginLoopDirective &x) { - AddOmpSourceRange(x.source); - return true; + return Pre(static_cast(x)); + } + void Post(const parser::OmpBeginLoopDirective &x) { + Post(static_cast(x)); + } + bool Pre(const parser::OmpEndLoopDirective &x) { + return Pre(static_cast(x)); + } + void Post(const parser::OmpEndLoopDirective &x) { + Post(static_cast(x)); } bool Pre(const parser::OpenMPDeclareMapperConstruct &x) { @@ -1580,35 +1570,22 @@ class OmpVisitor : public virtual DeclarationVisitor { } bool Pre(const parser::OmpMapClause &); - void Post(const parser::OmpBeginLoopDirective &) { - messageHandler().set_currStmtSource(std::nullopt); - } - bool Pre(const parser::OmpEndLoopDirective &x) { - AddOmpSourceRange(x.source); - return true; - } - void Post(const parser::OmpEndLoopDirective &) { - messageHandler().set_currStmtSource(std::nullopt); - } - bool Pre(const parser::OpenMPSectionsConstruct &) { PushScope(Scope::Kind::OtherConstruct, nullptr); return true; } void Post(const parser::OpenMPSectionsConstruct &) { PopScope(); } bool Pre(const parser::OmpBeginSectionsDirective &x) { - AddOmpSourceRange(x.source); - return true; + return Pre(static_cast(x)); } - void Post(const parser::OmpBeginSectionsDirective &) { - messageHandler().set_currStmtSource(std::nullopt); + void Post(const parser::OmpBeginSectionsDirective &x) { + Post(static_cast(x)); } bool Pre(const parser::OmpEndSectionsDirective &x) { - AddOmpSourceRange(x.source); - return true; + return Pre(static_cast(x)); } - void Post(const parser::OmpEndSectionsDirective &) { - messageHandler().set_currStmtSource(std::nullopt); + void Post(const parser::OmpEndSectionsDirective &x) { + Post(static_cast(x)); } bool Pre(const parser::OpenMPThreadprivate &) { SkipImplicitTyping(true); @@ -1710,6 +1687,9 @@ class OmpVisitor : public virtual DeclarationVisitor { } } bool Pre(const parser::OmpDirectiveSpecification &x); + void Post(const parser::OmpDirectiveSpecification &) { + messageHandler().set_currStmtSource(std::nullopt); + } bool Pre(const parser::OmpTypeSpecifier &x) { BeginDeclTypeSpec(); @@ -1719,6 +1699,16 @@ class OmpVisitor : public virtual DeclarationVisitor { EndDeclTypeSpec(); } + bool Pre(const parser::OpenMPConstruct &x) { + // Indicate that the current directive is not a declarative one. + declaratives_.push_back(nullptr); + return true; + } + void Post(const parser::OpenMPConstruct &) { + // Pop the null pointer. + declaratives_.pop_back(); + } + private: void ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec, const parser::OmpClauseList &clauses); @@ -1987,29 +1977,34 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) { const parser::OmpArgumentList &args{x.Arguments()}; const parser::OmpClauseList &clauses{x.Clauses()}; - switch (x.DirId()) { - case llvm::omp::Directive::OMPD_declare_mapper: - if (!args.v.empty()) { - const parser::OmpArgument &first{args.v.front()}; - if (auto *spec{std::get_if(&first.u)}) { - ProcessMapperSpecifier(*spec, clauses); - } - } - break; - case llvm::omp::Directive::OMPD_declare_reduction: - if (!args.v.empty()) { - const parser::OmpArgument &first{args.v.front()}; - if (auto *spec{std::get_if(&first.u)}) { - ProcessReductionSpecifier(*spec, clauses, declaratives_.back()); - } - } - break; - default: - // Default processing. - Walk(args); - Walk(clauses); - break; + for (const parser::OmpArgument &arg : args.v) { + common::visit( // + common::visitors{ + [&](const parser::OmpMapperSpecifier &spec) { + ProcessMapperSpecifier(spec, clauses); + }, + [&](const parser::OmpReductionSpecifier &spec) { + ProcessReductionSpecifier(spec, clauses, declaratives_.back()); + }, + [&](const parser::OmpLocator &locator) { + // Manually resolve names in CRITICAL directives. This is because + // these names do not denote Fortran objects, and the CRITICAL + // directive causes them to be "auto-declared", i.e. inserted into + // the global scope. More specifically, they are not expected to + // have explicit declarations, and if they do the behavior is + // unspeficied. + if (x.DirId() == llvm::omp::Directive::OMPD_critical) { + ResolveCriticalName(arg); + } else { + Walk(locator); + } + }, + }, + arg.u); } + + Walk(clauses); + return false; } From aa085d70f7e6e7d22e1810787dcfd4accb20a638 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Sat, 20 Sep 2025 16:13:07 -0500 Subject: [PATCH 04/10] format --- flang/lib/Parser/unparse.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 2db60c9a78b0f..b06a8c1fa4374 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -3082,8 +3082,7 @@ template void Unparse(llvm::raw_ostream &, const Expr &, const common::LangOptions &, Encoding, bool, bool, preStatementType *, AnalyzedObjectsAsFortran *); -template void Unparse( - llvm::raw_ostream &, const parser::OpenMPDeclarativeConstruct &, - const common::LangOptions &, Encoding, bool, bool, preStatementType *, - AnalyzedObjectsAsFortran *); +template void Unparse(llvm::raw_ostream &, + const parser::OpenMPDeclarativeConstruct &, const common::LangOptions &, + Encoding, bool, bool, preStatementType *, AnalyzedObjectsAsFortran *); } // namespace Fortran::parser From bc7d5988383d6404b786013f05fe890a92bcf06c Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 22 Sep 2025 13:05:06 -0500 Subject: [PATCH 05/10] Don't walk clauses twice --- flang/lib/Semantics/resolve-names.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 5dd0e1fd5072e..358bec20f243c 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1976,15 +1976,18 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) { const parser::OmpArgumentList &args{x.Arguments()}; const parser::OmpClauseList &clauses{x.Clauses()}; + bool visitClauses{true}; for (const parser::OmpArgument &arg : args.v) { common::visit( // common::visitors{ [&](const parser::OmpMapperSpecifier &spec) { ProcessMapperSpecifier(spec, clauses); + visitClauses = false; }, [&](const parser::OmpReductionSpecifier &spec) { ProcessReductionSpecifier(spec, clauses, declaratives_.back()); + visitClauses = false; }, [&](const parser::OmpLocator &locator) { // Manually resolve names in CRITICAL directives. This is because @@ -2003,7 +2006,9 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) { arg.u); } - Walk(clauses); + if (visitClauses) { + Walk(clauses); + } return false; } From db95ffd7044e5155c7a5ec2a0022a928ee261a55 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Fri, 19 Sep 2025 08:52:08 -0500 Subject: [PATCH 06/10] [flang][OpenMP] Use OmpDirectiveSpecification in DECLARE_MAPPER --- flang/include/flang/Parser/openmp-utils.h | 2 -- flang/include/flang/Parser/parse-tree.h | 4 +-- flang/lib/Lower/OpenMP/OpenMP.cpp | 20 ++++++------ flang/lib/Parser/openmp-parsers.cpp | 5 +-- flang/lib/Parser/unparse.cpp | 17 ++-------- flang/lib/Semantics/check-omp-structure.cpp | 31 ++++++++++++------- flang/lib/Semantics/resolve-directives.cpp | 3 +- flang/lib/Semantics/resolve-names.cpp | 5 ++- .../Parser/OpenMP/declare-mapper-unparse.f90 | 4 +-- .../OpenMP/openmp6-directive-spellings.f90 | 9 +++--- .../Semantics/OpenMP/declare-mapper04.f90 | 18 +++++++++++ 11 files changed, 66 insertions(+), 52 deletions(-) create mode 100644 flang/test/Semantics/OpenMP/declare-mapper04.f90 diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h index 98e849eef9bbc..19e23e4d9f62b 100644 --- a/flang/include/flang/Parser/openmp-utils.h +++ b/flang/include/flang/Parser/openmp-utils.h @@ -43,7 +43,6 @@ MAKE_CONSTR_ID(OmpErrorDirective, D::OMPD_error); MAKE_CONSTR_ID(OmpMetadirectiveDirective, D::OMPD_metadirective); MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate); MAKE_CONSTR_ID(OpenMPDeclarativeAssumes, D::OMPD_assumes); -MAKE_CONSTR_ID(OpenMPDeclareMapperConstruct, D::OMPD_declare_mapper); MAKE_CONSTR_ID(OpenMPDeclareReductionConstruct, D::OMPD_declare_reduction); MAKE_CONSTR_ID(OpenMPDeclareSimdConstruct, D::OMPD_declare_simd); MAKE_CONSTR_ID(OpenMPDeclareTargetConstruct, D::OMPD_declare_target); @@ -105,7 +104,6 @@ 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 || std::is_same_v || diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index bd0debe297916..73f8fbdbbb467 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4951,9 +4951,9 @@ struct OpenMPDeclareTargetConstruct { // OMP v5.2: 5.8.8 // declare-mapper -> DECLARE MAPPER ([mapper-name :] type :: var) map-clauses struct OpenMPDeclareMapperConstruct { - TUPLE_CLASS_BOILERPLATE(OpenMPDeclareMapperConstruct); + WRAPPER_CLASS_BOILERPLATE( + OpenMPDeclareMapperConstruct, OmpDirectiveSpecification); CharBlock source; - std::tuple t; }; // ref: 5.2: Section 5.5.11 139-141 diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 5681be664d450..c549485565bad 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -3444,15 +3444,17 @@ 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::OpenMPDeclareMapperConstruct &declareMapperConstruct) { - mlir::Location loc = converter.genLocation(declareMapperConstruct.source); + const parser::OpenMPDeclareMapperConstruct &construct) { + mlir::Location loc = converter.genLocation(construct.source); fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); + const parser::OmpArgumentList &args = construct.v.Arguments(); + assert(args.v.size() == 1 && "Expecting single argument"); lower::StatementContext stmtCtx; - const auto &spec = - std::get(declareMapperConstruct.t); - const auto &mapperName{std::get(spec.t)}; - const auto &varType{std::get(spec.t)}; - const auto &varName{std::get(spec.t)}; + const auto *spec = std::get_if(&args.v.front().u); + assert(spec && "Expecting mapper specifier"); + const auto &mapperName{std::get(spec->t)}; + const auto &varType{std::get(spec->t)}; + const auto &varName{std::get(spec->t)}; assert(varType.declTypeSpec->category() == semantics::DeclTypeSpec::Category::TypeDerived && "Expected derived type"); @@ -3476,9 +3478,7 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, // Populate the declareMapper region with the map information. mlir::omp::DeclareMapperInfoOperands clauseOps; - const auto *clauseList{ - parser::Unwrap(declareMapperConstruct.t)}; - List clauses = makeClauses(*clauseList, semaCtx); + List clauses = makeClauses(construct.v.Clauses(), semaCtx); ClauseProcessor cp(converter, semaCtx, clauses); cp.processMap(loc, stmtCtx, clauseOps); mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseOps.mapVars); diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 8ab9905123135..dc638ca9d00fe 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -1756,8 +1756,9 @@ TYPE_PARSER(applyFunction(ConstructOmpMapperSpecifier, // OpenMP 5.2: 5.8.8 Declare Mapper Construct TYPE_PARSER(sourced(construct( - verbatim("DECLARE MAPPER"_tok) || verbatim("DECLARE_MAPPER"_tok), - parenthesized(Parser{}), Parser{}))) + predicated(Parser{}, + IsDirective(llvm::omp::Directive::OMPD_declare_mapper)) >= + Parser{}))) TYPE_PARSER(construct(Parser{}) || construct(Parser{})) diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index b06a8c1fa4374..01b0e32a1164e 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2547,21 +2547,10 @@ class UnparseVisitor { Put("\n"); EndOpenMP(); } - void Unparse(const OpenMPDeclareMapperConstruct &z) { + void Unparse(const OpenMPDeclareMapperConstruct &x) { BeginOpenMP(); - Word("!$OMP DECLARE MAPPER ("); - const auto &spec{std::get(z.t)}; - const auto &mapperName{std::get(spec.t)}; - if (mapperName.find(llvm::omp::OmpDefaultMapperName) == std::string::npos) { - Walk(mapperName); - Put(":"); - } - Walk(std::get(spec.t)); - Put("::"); - Walk(std::get(spec.t)); - Put(")"); - - Walk(std::get(z.t)); + Word("!$OMP "); + Walk(x.v); Put("\n"); EndOpenMP(); } diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index c39daef6b0ea9..17954b5826586 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -629,11 +629,6 @@ template struct DirectiveSpellingVisitor { checker_(std::get(x.t).source, Directive::OMPD_assumes); return false; } - bool Pre(const parser::OpenMPDeclareMapperConstruct &x) { - checker_( - std::get(x.t).source, Directive::OMPD_declare_mapper); - return false; - } bool Pre(const parser::OpenMPDeclareReductionConstruct &x) { checker_(std::get(x.t).source, Directive::OMPD_declare_reduction); @@ -1595,13 +1590,25 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetWithClause &x) { } void OmpStructureChecker::Enter(const parser::OpenMPDeclareMapperConstruct &x) { - const auto &dir{std::get(x.t)}; - PushContextAndClauseSets( - dir.source, llvm::omp::Directive::OMPD_declare_mapper); - const auto &spec{std::get(x.t)}; - const auto &type = std::get(spec.t); - if (!std::get_if(&type.u)) { - context_.Say(dir.source, "Type is not a derived type"_err_en_US); + const parser::OmpDirectiveName &dirName{x.v.DirName()}; + PushContextAndClauseSets(dirName.source, dirName.v); + + const parser::OmpArgumentList &args{x.v.Arguments()}; + if (args.v.size() != 1) { + context_.Say(args.source, + "DECLARE_MAPPER directive should have a single argument"_err_en_US); + return; + } + + const parser::OmpArgument &arg{args.v.front()}; + if (auto *spec{std::get_if(&arg.u)}) { + const auto &type = std::get(spec->t); + if (!std::get_if(&type.u)) { + context_.Say(arg.source, "Type is not a derived type"_err_en_US); + } + } else { + context_.Say(arg.source, + "The argument to the DECLARE_MAPPER directive should be a mapper-specifier"_err_en_US); } } diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 2d1bec9968593..48cd0e54a155a 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -2331,7 +2331,8 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareTargetConstruct &x) { } bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclareMapperConstruct &x) { - PushContext(x.source, llvm::omp::Directive::OMPD_declare_mapper); + const parser::OmpDirectiveName &dirName{x.v.DirName()}; + PushContext(dirName.source, dirName.v); return true; } diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 358bec20f243c..b6d2ba7c4344d 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1518,9 +1518,7 @@ class OmpVisitor : public virtual DeclarationVisitor { bool Pre(const parser::OpenMPDeclareMapperConstruct &x) { AddOmpSourceRange(x.source); - ProcessMapperSpecifier(std::get(x.t), - std::get(x.t)); - return false; + return true; } bool Pre(const parser::OpenMPDeclareSimdConstruct &x) { @@ -1686,6 +1684,7 @@ class OmpVisitor : public virtual DeclarationVisitor { PopScope(); } } + bool Pre(const parser::OmpMapperSpecifier &x) { return false; } bool Pre(const parser::OmpDirectiveSpecification &x); void Post(const parser::OmpDirectiveSpecification &) { messageHandler().set_currStmtSource(std::nullopt); diff --git a/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 b/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 index 30d75d02736f3..b53bf5ce10557 100644 --- a/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 +++ b/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 @@ -9,7 +9,7 @@ program main end type ty -!CHECK: !$OMP DECLARE MAPPER (mymapper:ty::mapped) MAP(mapped,mapped%x) +!CHECK: !$OMP DECLARE MAPPER(mymapper:ty::mapped) MAP(mapped,mapped%x) !$omp declare mapper(mymapper : ty :: mapped) map(mapped, mapped%x) !PARSE-TREE: OpenMPDeclareMapperConstruct @@ -24,7 +24,7 @@ program main !PARSE-TREE: DataRef -> Name = 'mapped' !PARSE-TREE: Name = 'x' -!CHECK: !$OMP DECLARE MAPPER (ty::mapped) MAP(mapped,mapped%x) +!CHECK: !$OMP DECLARE MAPPER(ty::mapped) MAP(mapped,mapped%x) !$omp declare mapper(ty :: mapped) map(mapped, mapped%x) !PARSE-TREE: OpenMPDeclareMapperConstruct diff --git a/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 b/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 index c2498c878f559..47237de2d5aff 100644 --- a/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 +++ b/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 @@ -51,12 +51,12 @@ subroutine f01 !UNPARSE: TYPE :: t !UNPARSE: INTEGER :: x !UNPARSE: END TYPE -!UNPARSE: !$OMP DECLARE MAPPER (t::v) MAP(v%x) +!UNPARSE: !$OMP DECLARE_MAPPER(t::v) MAP(v%x) !UNPARSE: END SUBROUTINE -!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareMapperConstruct -!PARSE-TREE: | Verbatim -!PARSE-TREE: | OmpMapperSpecifier +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareMapperConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare mapper +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpMapperSpecifier !PARSE-TREE: | | string = 't.omp.default.mapper' !PARSE-TREE: | | TypeSpec -> DerivedTypeSpec !PARSE-TREE: | | | Name = 't' @@ -66,6 +66,7 @@ subroutine f01 !PARSE-TREE: | | | DataRef -> Name = 'v' !PARSE-TREE: | | | Name = 'x' !PARSE-TREE: | | bool = 'true' +!PARSE-TREE: | Flags = None subroutine f02 type :: t diff --git a/flang/test/Semantics/OpenMP/declare-mapper04.f90 b/flang/test/Semantics/OpenMP/declare-mapper04.f90 new file mode 100644 index 0000000000000..2f45e230c3513 --- /dev/null +++ b/flang/test/Semantics/OpenMP/declare-mapper04.f90 @@ -0,0 +1,18 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=60 + +type :: t1 + integer :: y +end type + +type :: t2 + integer :: y +end type + +!ERROR: DECLARE_MAPPER directive should have a single argument +!$omp declare mapper(m1:t1::x, m2:t2::x) map(x, x%y) + +integer :: x(10) +!ERROR: The argument to the DECLARE_MAPPER directive should be a mapper-specifier +!$omp declare mapper(x) map(to: x) + +end From 7e3d8a74746878c864ba7821089a6dd28b053824 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 22 Sep 2025 13:36:17 -0500 Subject: [PATCH 07/10] format --- flang/lib/Lower/OpenMP/OpenMP.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index c549485565bad..d2e865b3e1d0c 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -3441,10 +3441,10 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct"); } -static void -genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, - semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, - const parser::OpenMPDeclareMapperConstruct &construct) { +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPDeclareMapperConstruct &construct) { mlir::Location loc = converter.genLocation(construct.source); fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); const parser::OmpArgumentList &args = construct.v.Arguments(); From 3947c8326f562db035cbcb964d533c9077e552f9 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 22 Sep 2025 14:49:15 -0500 Subject: [PATCH 08/10] Abort when walk reaches OmpMapperSpecifier If it happens, it's a bug to be fixed. --- flang/lib/Semantics/resolve-names.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index b6d2ba7c4344d..69ca86ec65242 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1684,7 +1684,11 @@ class OmpVisitor : public virtual DeclarationVisitor { PopScope(); } } - bool Pre(const parser::OmpMapperSpecifier &x) { return false; } + bool Pre(const parser::OmpMapperSpecifier &x) { + // OmpMapperSpecifier is handled explicitly, and the Walk infrastructure + // should not reach the point where it calls this function. + llvm_unreachable("This function should not be reached by 'Walk'"); + } bool Pre(const parser::OmpDirectiveSpecification &x); void Post(const parser::OmpDirectiveSpecification &) { messageHandler().set_currStmtSource(std::nullopt); From 7fe518ccc679cc1ed97a5ca8a0da9c2da5a60177 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 22 Sep 2025 14:58:08 -0500 Subject: [PATCH 09/10] Better wording --- flang/lib/Semantics/resolve-names.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 69ca86ec65242..86ada0f8cdc85 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1685,9 +1685,9 @@ class OmpVisitor : public virtual DeclarationVisitor { } } bool Pre(const parser::OmpMapperSpecifier &x) { - // OmpMapperSpecifier is handled explicitly, and the Walk infrastructure - // should not reach the point where it calls this function. - llvm_unreachable("This function should not be reached by 'Walk'"); + // OmpMapperSpecifier is handled explicitly, and the AST traversal + // should not reach a point where it calls this function. + llvm_unreachable("This function should not be reached by AST traversal"); } bool Pre(const parser::OmpDirectiveSpecification &x); void Post(const parser::OmpDirectiveSpecification &) { From d04b0664a612b1060897834160395cfe2a3ca492 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Mon, 22 Sep 2025 14:42:16 -0500 Subject: [PATCH 10/10] [flang][OpenMP] Use OmpDirectiveSpecification in DECLARE_REDUCTION --- flang/include/flang/Parser/parse-tree.h | 6 +- flang/lib/Parser/openmp-parsers.cpp | 6 +- flang/lib/Parser/unparse.cpp | 7 +- flang/lib/Semantics/check-omp-structure.cpp | 23 ++- flang/lib/Semantics/resolve-names.cpp | 22 ++- .../Parser/OpenMP/declare-reduction-multi.f90 | 158 ++++++++++-------- .../OpenMP/declare-reduction-operator.f90 | 38 +++-- ...declare-reduction-unparse-with-symbols.f90 | 2 +- .../OpenMP/declare-reduction-unparse.f90 | 51 ++++-- .../OpenMP/openmp6-directive-spellings.f90 | 9 +- .../OpenMP/declare-reduction-modfile.f90 | 12 +- 11 files changed, 188 insertions(+), 146 deletions(-) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 73f8fbdbbb467..2063eccf8b7f4 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4960,11 +4960,9 @@ struct OpenMPDeclareMapperConstruct { // 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list // : combiner) [initializer-clause] struct OpenMPDeclareReductionConstruct { - TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct); + WRAPPER_CLASS_BOILERPLATE( + OpenMPDeclareReductionConstruct, OmpDirectiveSpecification); CharBlock source; - std::tuple, - std::optional> - t; }; // 2.8.2 declare-simd -> DECLARE SIMD [(proc-name)] [declare-simd-clause[ [,] diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index dc638ca9d00fe..57b812665073a 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -1708,9 +1708,9 @@ TYPE_PARSER(sourced(construct( // 2.16 Declare Reduction Construct TYPE_PARSER(sourced(construct( - verbatim("DECLARE REDUCTION"_tok) || verbatim("DECLARE_REDUCTION"_tok), - "(" >> indirect(Parser{}) / ")", - maybe(Parser{})))) + predicated(Parser{}, + IsDirective(llvm::omp::Directive::OMPD_declare_reduction)) >= + Parser{}))) // declare-target with list TYPE_PARSER(sourced(construct( diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 01b0e32a1164e..750f1258be2fc 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2495,11 +2495,8 @@ class UnparseVisitor { } void Unparse(const OpenMPDeclareReductionConstruct &x) { BeginOpenMP(); - Word("!$OMP DECLARE REDUCTION "); - Put("("); - Walk(std::get>(x.t)); - Put(")"); - Walk(std::get>(x.t)); + Word("!$OMP "); + Walk(x.v); Put("\n"); EndOpenMP(); } diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 17954b5826586..bff5c2498344a 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -629,11 +629,6 @@ template struct DirectiveSpellingVisitor { checker_(std::get(x.t).source, Directive::OMPD_assumes); return false; } - bool Pre(const parser::OpenMPDeclareReductionConstruct &x) { - checker_(std::get(x.t).source, - Directive::OMPD_declare_reduction); - return false; - } bool Pre(const parser::OpenMPDeclareSimdConstruct &x) { checker_( std::get(x.t).source, Directive::OMPD_declare_simd); @@ -1618,9 +1613,21 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareMapperConstruct &) { void OmpStructureChecker::Enter( const parser::OpenMPDeclareReductionConstruct &x) { - const auto &dir{std::get(x.t)}; - PushContextAndClauseSets( - dir.source, llvm::omp::Directive::OMPD_declare_reduction); + const parser::OmpDirectiveName &dirName{x.v.DirName()}; + PushContextAndClauseSets(dirName.source, dirName.v); + + const parser::OmpArgumentList &args{x.v.Arguments()}; + if (args.v.size() != 1) { + context_.Say(args.source, + "DECLARE_REDUCTION directive should have a single argument"_err_en_US); + return; + } + + const parser::OmpArgument &arg{args.v.front()}; + if (!std::holds_alternative(arg.u)) { + context_.Say(arg.source, + "The argument to the DECLARE_REDUCTION directive should be a reduction-specifier"_err_en_US); + } } void OmpStructureChecker::Leave( diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 86ada0f8cdc85..3b6140429f9ed 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1559,12 +1559,7 @@ class OmpVisitor : public virtual DeclarationVisitor { bool Pre(const parser::OpenMPDeclareReductionConstruct &x) { AddOmpSourceRange(x.source); - parser::OmpClauseList empty(std::list{}); - auto &maybeClauses{std::get>(x.t)}; - ProcessReductionSpecifier( - std::get>(x.t).value(), - maybeClauses ? *maybeClauses : empty, declaratives_.back()); - return false; + return true; } bool Pre(const parser::OmpMapClause &); @@ -1689,6 +1684,11 @@ class OmpVisitor : public virtual DeclarationVisitor { // should not reach a point where it calls this function. llvm_unreachable("This function should not be reached by AST traversal"); } + bool Pre(const parser::OmpReductionSpecifier &x) { + // OmpReductionSpecifier is handled explicitly, and the AST traversal + // should not reach a point where it calls this function. + llvm_unreachable("This function should not be reached by AST traversal"); + } bool Pre(const parser::OmpDirectiveSpecification &x); void Post(const parser::OmpDirectiveSpecification &) { messageHandler().set_currStmtSource(std::nullopt); @@ -1716,8 +1716,7 @@ class OmpVisitor : public virtual DeclarationVisitor { void ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec, const parser::OmpClauseList &clauses); void ProcessReductionSpecifier(const parser::OmpReductionSpecifier &spec, - const parser::OmpClauseList &clauses, - const parser::OpenMPDeclarativeConstruct *wholeConstruct); + const parser::OmpClauseList &clauses); void ResolveCriticalName(const parser::OmpArgument &arg); @@ -1848,8 +1847,7 @@ std::string MangleDefinedOperator(const parser::CharBlock &name) { void OmpVisitor::ProcessReductionSpecifier( const parser::OmpReductionSpecifier &spec, - const parser::OmpClauseList &clauses, - const parser::OpenMPDeclarativeConstruct *construct) { + const parser::OmpClauseList &clauses) { const parser::Name *name{nullptr}; parser::CharBlock mangledName; UserReductionDetails reductionDetailsTemp; @@ -1936,7 +1934,7 @@ void OmpVisitor::ProcessReductionSpecifier( PopScope(); } - reductionDetails->AddDecl(construct); + reductionDetails->AddDecl(declaratives_.back()); if (!symbol) { symbol = &MakeSymbol(mangledName, Attrs{}, std::move(*reductionDetails)); @@ -1989,7 +1987,7 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) { visitClauses = false; }, [&](const parser::OmpReductionSpecifier &spec) { - ProcessReductionSpecifier(spec, clauses, declaratives_.back()); + ProcessReductionSpecifier(spec, clauses); visitClauses = false; }, [&](const parser::OmpLocator &locator) { diff --git a/flang/test/Parser/OpenMP/declare-reduction-multi.f90 b/flang/test/Parser/OpenMP/declare-reduction-multi.f90 index 693e69d8896be..19266aca9db03 100644 --- a/flang/test/Parser/OpenMP/declare-reduction-multi.f90 +++ b/flang/test/Parser/OpenMP/declare-reduction-multi.f90 @@ -26,111 +26,127 @@ program omp_examples type(tt) :: values(n), sum, prod, big, small !$omp declare reduction(+:tt:omp_out%r = omp_out%r + omp_in%r) initializer(omp_priv%r = 0) -!CHECK: !$OMP DECLARE REDUCTION (+:tt: omp_out%r=omp_out%r+omp_in%r +!CHECK: !$OMP DECLARE REDUCTION(+:tt: omp_out%r=omp_out%r+omp_in%r !CHECK-NEXT: ) INITIALIZER(omp_priv%r=0_4) -!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -!PARSE-TREE: Verbatim -!PARSE-TREE: OmpReductionSpecifier -!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add -!PARSE-TREE: OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec -!PARSE-TREE-NEXT: Name = 'tt' -!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=omp_out%r+omp_in%r' -!PARSE-TREE: OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=0._4 + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier +!PARSE-TREE: | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add +!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec +!PARSE-TREE: | | | Name = 'tt' +!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=omp_out%r+omp_in%r' +!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=0._4' + !$omp declare reduction(*:tt:omp_out%r = omp_out%r * omp_in%r) initializer(omp_priv%r = 1) -!CHECK-NEXT: !$OMP DECLARE REDUCTION (*:tt: omp_out%r=omp_out%r*omp_in%r +!CHECK-NEXT: !$OMP DECLARE REDUCTION(*:tt: omp_out%r=omp_out%r*omp_in%r !CHECK-NEXT: ) INITIALIZER(omp_priv%r=1_4) -!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -!PARSE-TREE: Verbatim -!PARSE-TREE: OmpReductionSpecifier -!PARSE-TREE: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply -!PARSE-TREE: OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec -!PARSE-TREE-NEXT: Name = 'tt' -!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=omp_out%r*omp_in%r' -!PARSE-TREE: OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=1._4' + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier +!PARSE-TREE: | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply +!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec +!PARSE-TREE: | | | Name = 'tt' +!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=omp_out%r*omp_in%r' +!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=1._4' + !$omp declare reduction(max:tt:omp_out = mymax(omp_out, omp_in)) initializer(omp_priv%r = 0) -!CHECK-NEXT: !$OMP DECLARE REDUCTION (max:tt: omp_out=mymax(omp_out,omp_in) +!CHECK-NEXT: !$OMP DECLARE REDUCTION(max:tt: omp_out=mymax(omp_out,omp_in) !CHECK-NEXT: ) INITIALIZER(omp_priv%r=0_4) -!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -!PARSE-TREE: Verbatim -!PARSE-TREE: OmpReductionSpecifier -!PARSE-TREE: OmpReductionIdentifier -> ProcedureDesignator -> Name = 'max' -!PARSE-TREE: OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec -!PARSE-TREE: Name = 'tt' -!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out=mymax(omp_out,omp_in)' -!PARSE-TREE: OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=0._4' + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier +!PARSE-TREE: | | OmpReductionIdentifier -> ProcedureDesignator -> Name = 'max' +!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec +!PARSE-TREE: | | | Name = 'tt' +!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out=mymax(omp_out,omp_in)' +!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=0._4' + !$omp declare reduction(min:tt:omp_out%r = min(omp_out%r, omp_in%r)) initializer(omp_priv%r = 1) -!CHECK-NEXT: !$OMP DECLARE REDUCTION (min:tt: omp_out%r=min(omp_out%r,omp_in%r) +!CHECK-NEXT: !$OMP DECLARE REDUCTION(min:tt: omp_out%r=min(omp_out%r,omp_in%r) !CHECK-NEXT: ) INITIALIZER(omp_priv%r=1_4) -!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -!PARSE-TREE: Verbatim -!PARSE-TREE: OmpReductionSpecifier -!PARSE-TREE: OmpReductionIdentifier -> ProcedureDesignator -> Name = 'min' -!PARSE-TREE: OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec -!PARSE-TREE: Name = 'tt' -!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=min(omp_out%r,omp_in%r)' -!PARSE-TREE: OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=1._4' + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier +!PARSE-TREE: | | OmpReductionIdentifier -> ProcedureDesignator -> Name = 'min' +!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec +!PARSE-TREE: | | | Name = 'tt' +!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=min(omp_out%r,omp_in%r)' +!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=1._4' + call random_number(values%r) sum%r = 0 !$omp parallel do reduction(+:sum) -!CHECK: !$OMP PARALLEL DO REDUCTION(+: sum) +!CHECK: !$OMP PARALLEL DO REDUCTION(+: sum) + !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct -!PARSE-TREE: OmpBeginLoopDirective -!PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = parallel do -!PARSE-TREE: OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause -!PARSE-TREE: Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add -!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'sum -!PARSE-TREE: Flags = None -!PARSE-TREE: DoConstruct +!PARSE-TREE: | OmpBeginLoopDirective +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = parallel do +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause +!PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add +!PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'sum' +!PARSE-TREE: | | Flags = None +!PARSE-TREE: | DoConstruct + do i = 1, n sum%r = sum%r + values(i)%r end do prod%r = 1 !$omp parallel do reduction(*:prod) -!CHECK: !$OMP PARALLEL DO REDUCTION(*: prod) -!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct -!PARSE-TREE: OmpBeginLoopDirective -!PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = parallel do -!PARSE-TREE: OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause -!PARSE-TREE: Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply -!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'prod' -!PARSE-TREE: Flags = None -!PARSE-TREE: DoConstruct +!CHECK: !$OMP PARALLEL DO REDUCTION(*: prod) + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!PARSE-TREE: | OmpBeginLoopDirective +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = parallel do +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause +!PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply +!PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'prod' +!PARSE-TREE: | | Flags = None +!PARSE-TREE: | DoConstruct + do i = 1, n prod%r = prod%r * (values(i)%r+0.6) end do big%r = 0 !$omp parallel do reduction(max:big) -!CHECK: $OMP PARALLEL DO REDUCTION(max: big) +!CHECK: $OMP PARALLEL DO REDUCTION(max: big) + !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct -!PARSE-TREE: OmpBeginLoopDirective -!PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = parallel do -!PARSE-TREE: OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause -!PARSE-TREE: Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'max' -!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'big' -!PARSE-TREE: Flags = None -!PARSE-TREE: DoConstruct +!PARSE-TREE: | OmpBeginLoopDirective +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = parallel do +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause +!PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'max' +!PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'big' +!PARSE-TREE: | | Flags = None +!PARSE-TREE: | DoConstruct + do i = 1, n big = mymax(values(i), big) end do small%r = 1 !$omp parallel do reduction(min:small) -!CHECK: !$OMP PARALLEL DO REDUCTION(min: small) -!CHECK-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct -!CHECK-TREE: OmpBeginLoopDirective -!CHECK-TREE: OmpDirectiveName -> llvm::omp::Directive = parallel do -!CHECK-TREE: OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause -!CHECK-TREE: Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'min' -!CHECK-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'small' -!PARSE-TREE: Flags = None -!CHECK-TREE: DoConstruct +!CHECK: !$OMP PARALLEL DO REDUCTION(min: small) + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct +!PARSE-TREE: | OmpBeginLoopDirective +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = parallel do +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause +!PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'min' +!PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'small' +!PARSE-TREE: | | Flags = None +!PARSE-TREE: | DoConstruct + do i = 1, n small%r = min(values(i)%r, small%r) end do - + print *, values%r print *, "sum=", sum%r print *, "prod=", prod%r diff --git a/flang/test/Parser/OpenMP/declare-reduction-operator.f90 b/flang/test/Parser/OpenMP/declare-reduction-operator.f90 index 7bfb78115b10d..c41daa596d2d0 100644 --- a/flang/test/Parser/OpenMP/declare-reduction-operator.f90 +++ b/flang/test/Parser/OpenMP/declare-reduction-operator.f90 @@ -16,27 +16,33 @@ subroutine reduce_1 ( n, tts ) type(tt) :: tts(n) type(tt2) :: tts2(n) -!CHECK: !$OMP DECLARE REDUCTION (+:tt: omp_out=tt(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y) +!CHECK: !$OMP DECLARE REDUCTION(+:tt: omp_out=tt(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y) !CHECK: ) INITIALIZER(omp_priv=tt(x=0_4,y=0_4)) -!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -!PARSE-TREE: Verbatim -!PARSE-TREE: OmpReductionSpecifier -!PARSE-TREE: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add -!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out=tt(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y)' -!PARSE-TREE: OmpInitializerClause -> AssignmentStmt = 'omp_priv=tt(x=0_4,y=0_4)' - + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier +!PARSE-TREE: | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add +!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec +!PARSE-TREE: | | | Name = 'tt' +!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out=tt(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y)' +!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv=tt(x=0_4,y=0_4)' + !$omp declare reduction(+ : tt : omp_out = tt(omp_out%x - omp_in%x , omp_out%y - omp_in%y)) initializer(omp_priv = tt(0,0)) -!CHECK: !$OMP DECLARE REDUCTION (+:tt2: omp_out=tt2(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y) +!CHECK: !$OMP DECLARE REDUCTION(+:tt2: omp_out=tt2(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y) !CHECK: ) INITIALIZER(omp_priv=tt2(x=0._8,y=0._8) -!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -!PARSE-TREE: Verbatim -!PARSE-TREE: OmpReductionSpecifier -!PARSE-TREE: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add -!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out=tt2(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y)' -!PARSE-TREE: OmpInitializerClause -> AssignmentStmt = 'omp_priv=tt2(x=0._8,y=0._8)' - + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier +!PARSE-TREE: | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add +!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec +!PARSE-TREE: | | | Name = 'tt2' +!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out=tt2(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y)' +!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv=tt2(x=0._8,y=0._8)' + !$omp declare reduction(+ :tt2 : omp_out = tt2(omp_out%x - omp_in%x , omp_out%y - omp_in%y)) initializer(omp_priv = tt2(0,0)) type(tt) :: diffp = tt( 0, 0 ) diff --git a/flang/test/Parser/OpenMP/declare-reduction-unparse-with-symbols.f90 b/flang/test/Parser/OpenMP/declare-reduction-unparse-with-symbols.f90 index fbcd5b62821a3..131a816057d5a 100644 --- a/flang/test/Parser/OpenMP/declare-reduction-unparse-with-symbols.f90 +++ b/flang/test/Parser/OpenMP/declare-reduction-unparse-with-symbols.f90 @@ -8,6 +8,6 @@ subroutine f00 !CHECK: !DEF: /f00 (Subroutine) Subprogram !CHECK: subroutine f00 -!CHECK: !$omp declare reduction (fred:integer,real:omp_out = omp_in+omp_out) +!CHECK: !$omp declare reduction(fred:integer,real:omp_out = omp_in+omp_out) !CHECK: end subroutine diff --git a/flang/test/Parser/OpenMP/declare-reduction-unparse.f90 b/flang/test/Parser/OpenMP/declare-reduction-unparse.f90 index 0ed693e5821d6..7607b3d20b52d 100644 --- a/flang/test/Parser/OpenMP/declare-reduction-unparse.f90 +++ b/flang/test/Parser/OpenMP/declare-reduction-unparse.f90 @@ -18,21 +18,38 @@ subroutine initme(x,n) integer x,n end subroutine initme end interface -!CHECK: !$OMP DECLARE REDUCTION (red_add:INTEGER(KIND=4_4): omp_out=omp_out+omp_in -!CHECK: ) INITIALIZER(initme(omp_priv, 0_4)) !$omp declare reduction(red_add:integer(4):omp_out=omp_out+omp_in) initializer(initme(omp_priv,0)) -!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out=omp_out+omp_in' -!PARSE-TREE: OmpInitializerClause -> OmpInitializerProc -!PARSE-TREE-NEXT: ProcedureDesignator -> Name = 'initme' +!CHECK: !$OMP DECLARE REDUCTION(red_add:INTEGER(KIND=4_4): omp_out=omp_out+omp_in +!CHECK: ) INITIALIZER(initme(omp_priv, 0_4)) + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier +!PARSE-TREE: | | OmpReductionIdentifier -> ProcedureDesignator -> Name = 'red_add' +!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> KindSelector -> Scalar -> Integer -> Constant -> Expr = '4_4' +!PARSE-TREE: | | | LiteralConstant -> IntLiteralConstant = '4' +!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out=omp_out+omp_in' +!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> OmpInitializerProc +!PARSE-TREE: | | ProcedureDesignator -> Name = 'initme' + res=init !$omp simd reduction(red_add:res) !CHECK: !$OMP SIMD REDUCTION(red_add: res) + +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt = 'res=init' +!PARSE-TREE: | Variable = 'res' +!PARSE-TREE: | | Designator -> DataRef -> Name = 'res' +!PARSE-TREE: | Expr = 'init' +!PARSE-TREE: | | Designator -> DataRef -> Name = 'init' !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct -!PARSE-TREE: OmpBeginLoopDirective -!PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = simd -!PARSE-TREE: OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause -!PARSE-TREE: Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'red_add +!PARSE-TREE: | OmpBeginLoopDirective +!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = simd +!PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause +!PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'red_add' +!PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'res' +!PARSE-TREE: | | Flags = None +!PARSE-TREE: | DoConstruct + do i=1,n res=res+x(i) enddo @@ -43,7 +60,7 @@ end function func !CHECK-LABEL: program main program main integer :: my_var -!CHECK: !$OMP DECLARE REDUCTION (my_add_red:INTEGER: omp_out=omp_out+omp_in +!CHECK: !$OMP DECLARE REDUCTION(my_add_red:INTEGER: omp_out=omp_out+omp_in !CHECK-NEXT: ) INITIALIZER(omp_priv=0_4) !$omp declare reduction (my_add_red : integer : omp_out = omp_out + omp_in) initializer (omp_priv=0) @@ -54,8 +71,10 @@ program main print *, "sum of thread numbers is ", my_var end program main -!PARSE-TREE: OpenMPDeclareReductionConstruct -!PARSE-TREE: OmpReductionIdentifier -> ProcedureDesignator -> Name = 'my_add_red' -!PARSE-TREE: DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out=omp_out+omp_in' -!PARSE-TREE: OmpInitializerClause -> AssignmentStmt = 'omp_priv=0_4' +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier +!PARSE-TREE: | | OmpReductionIdentifier -> ProcedureDesignator -> Name = 'my_add_red' +!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> DeclarationTypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out=omp_out+omp_in' +!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv=0_4' diff --git a/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 b/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 index 47237de2d5aff..c4d9f6ef4618c 100644 --- a/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 +++ b/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 @@ -79,13 +79,13 @@ subroutine f02 !UNPARSE: TYPE :: t !UNPARSE: INTEGER :: x !UNPARSE: END TYPE -!UNPARSE: !$OMP DECLARE REDUCTION (+:t: omp_out%x=omp_out%x+omp_in%x +!UNPARSE: !$OMP DECLARE_REDUCTION(+:t: omp_out%x=omp_out%x+omp_in%x !UNPARSE: ) !UNPARSE: END SUBROUTINE -!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -!PARSE-TREE: | Verbatim -!PARSE-TREE: | OmpReductionSpecifier +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier !PARSE-TREE: | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add !PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec !PARSE-TREE: | | | Name = 't' @@ -105,6 +105,7 @@ subroutine f02 !PARSE-TREE: | | | | | | | DataRef -> Name = 'omp_in' !PARSE-TREE: | | | | | | | Name = 'x' !PARSE-TREE: | OmpClauseList -> +!PARSE-TREE: | Flags = None subroutine f03 !$omp declare_simd diff --git a/flang/test/Semantics/OpenMP/declare-reduction-modfile.f90 b/flang/test/Semantics/OpenMP/declare-reduction-modfile.f90 index f80eb1097e18a..2fb2cd7c4b89d 100644 --- a/flang/test/Semantics/OpenMP/declare-reduction-modfile.f90 +++ b/flang/test/Semantics/OpenMP/declare-reduction-modfile.f90 @@ -6,13 +6,13 @@ !type::t1 !integer(4)::val !endtype -!!$OMP DECLARE REDUCTION (*:t1:omp_out = omp_out*omp_in) INITIALIZER(omp_priv=t& -!!$OMP&1(1)) +!!$OMP DECLARE REDUCTION(*:t1:omp_out = omp_out*omp_in) INITIALIZER(omp_priv=t1& +!!$OMP&(1)) !!$OMP METADIRECTIVE OTHERWISE(DECLARE REDUCTION(+:INTEGER)) -!!$OMP DECLARE REDUCTION (.fluffy.:t1:omp_out = omp_out.fluffy.omp_in) INITIALI& -!!$OMP&ZER(omp_priv=t1(0)) -!!$OMP DECLARE REDUCTION (.mul.:t1:omp_out = omp_out.mul.omp_in) INITIALIZER(om& -!!$OMP&p_priv=t1(1)) +!!$OMP DECLARE REDUCTION(.fluffy.:t1:omp_out = omp_out.fluffy.omp_in) INITIALIZ& +!!$OMP&ER(omp_priv=t1(0)) +!!$OMP DECLARE REDUCTION(.mul.:t1:omp_out = omp_out.mul.omp_in) INITIALIZER(omp& +!!$OMP&_priv=t1(1)) !interface operator(.mul.) !procedure::mul !end interface