llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-flang-openmp Author: Krzysztof Parzyszek (kparzysz) <details> <summary>Changes</summary> Implement parsing and symbol resolution for directives that take arguments. There are a few, and most of them take objects. Special handling is needed for two that take more specialized arguments: DECLARE MAPPER and DECLARE REDUCTION. This only affects directives in METADIRECTIVE's WHEN and OTHERWISE clauses. Parsing and semantic checks of other cases is unaffected. --- Patch is 37.25 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/124278.diff 9 Files Affected: - (modified) flang/examples/FeatureList/FeatureList.cpp (-1) - (modified) flang/include/flang/Parser/dump-parse-tree.h (+7-2) - (modified) flang/include/flang/Parser/parse-tree.h (+97-45) - (modified) flang/lib/Parser/openmp-parsers.cpp (+45-23) - (modified) flang/lib/Parser/unparse.cpp (+25-15) - (modified) flang/lib/Semantics/check-omp-structure.cpp (+1-1) - (modified) flang/lib/Semantics/resolve-names.cpp (+98-32) - (modified) flang/test/Parser/OpenMP/declare-mapper-unparse.f90 (+2-2) - (added) flang/test/Parser/OpenMP/metadirective-dirspec.f90 (+242) ``````````diff diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index 3a689c335c81c0..e35f120d8661ea 100644 --- a/flang/examples/FeatureList/FeatureList.cpp +++ b/flang/examples/FeatureList/FeatureList.cpp @@ -514,7 +514,6 @@ struct NodeVisitor { READ_FEATURE(OmpReductionClause) READ_FEATURE(OmpInReductionClause) READ_FEATURE(OmpReductionCombiner) - READ_FEATURE(OmpReductionCombiner::FunctionCombiner) READ_FEATURE(OmpReductionInitializerClause) READ_FEATURE(OmpReductionIdentifier) READ_FEATURE(OmpAllocateClause) diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 1323fd695d4439..ce518c7c3edea0 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -476,6 +476,12 @@ class ParseTreeDumper { NODE(parser, NullInit) NODE(parser, ObjectDecl) NODE(parser, OldParameterStmt) + NODE(parser, OmpTypeSpecifier) + NODE(parser, OmpTypeNameList) + NODE(parser, OmpLocator) + NODE(parser, OmpLocatorList) + NODE(parser, OmpReductionSpecifier) + NODE(parser, OmpArgument) NODE(parser, OmpMetadirectiveDirective) NODE(parser, OmpMatchClause) NODE(parser, OmpOtherwiseClause) @@ -541,7 +547,7 @@ class ParseTreeDumper { NODE(parser, OmpDeclareTargetSpecifier) NODE(parser, OmpDeclareTargetWithClause) NODE(parser, OmpDeclareTargetWithList) - NODE(parser, OmpDeclareMapperSpecifier) + NODE(parser, OmpMapperSpecifier) NODE(parser, OmpDefaultClause) NODE_ENUM(OmpDefaultClause, DataSharingAttribute) NODE(parser, OmpVariableCategory) @@ -624,7 +630,6 @@ class ParseTreeDumper { NODE(parser, OmpReductionCombiner) NODE(parser, OmpTaskReductionClause) NODE(OmpTaskReductionClause, Modifier) - NODE(OmpReductionCombiner, FunctionCombiner) NODE(parser, OmpReductionInitializerClause) NODE(parser, OmpReductionIdentifier) NODE(parser, OmpAllocateClause) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 2e27b6ea7eafa1..993c1338f7235b 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3454,15 +3454,7 @@ WRAPPER_CLASS(PauseStmt, std::optional<StopCode>); // --- Common definitions struct OmpClause; -struct OmpClauseList; - -struct OmpDirectiveSpecification { - TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification); - std::tuple<llvm::omp::Directive, - std::optional<common::Indirection<OmpClauseList>>> - t; - CharBlock source; -}; +struct OmpDirectiveSpecification; // 2.1 Directives or clauses may accept a list or extended-list. // A list item is a variable, array section or common block name (enclosed @@ -3475,15 +3467,76 @@ struct OmpObject { WRAPPER_CLASS(OmpObjectList, std::list<OmpObject>); -#define MODIFIER_BOILERPLATE(...) \ - struct Modifier { \ - using Variant = std::variant<__VA_ARGS__>; \ - UNION_CLASS_BOILERPLATE(Modifier); \ - CharBlock source; \ - Variant u; \ - } +// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124] +// +// reduction-identifier -> +// base-language-identifier | // since 4.5 +// - | // 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<DefinedOperator, ProcedureDesignator> u; +}; -#define MODIFIERS() std::optional<std::list<Modifier>> +// Ref: [4.5:222:6], [5.0:305:27], [5.1:337:19], [5.2:126:3-4], [6.0:240:27-28] +// +// combiner-expression -> // since 4.5 +// assignment-statement | +// function-reference +struct OmpReductionCombiner { + UNION_CLASS_BOILERPLATE(OmpReductionCombiner); + std::variant<AssignmentStmt, FunctionReference> u; +}; + +inline namespace arguments { +struct OmpTypeSpecifier { + UNION_CLASS_BOILERPLATE(OmpTypeSpecifier); + std::variant<TypeSpec, DeclarationTypeSpec> u; +}; + +WRAPPER_CLASS(OmpTypeNameList, std::list<OmpTypeSpecifier>); + +struct OmpLocator { + UNION_CLASS_BOILERPLATE(OmpLocator); + std::variant<OmpObject, FunctionReference> u; +}; + +WRAPPER_CLASS(OmpLocatorList, std::list<OmpLocator>); + +// Ref: [5.0:326:10-16], [5.1:359:5-11], [5.2:163:2-7], [6.0:293:16-21] +// +// mapper-specifier -> +// [mapper-identifier :] type :: var | // since 5.0 +// DEFAULT type :: var +struct OmpMapperSpecifier { + // Absent mapper-identifier is equivalent to DEFAULT. + TUPLE_CLASS_BOILERPLATE(OmpMapperSpecifier); + std::tuple<std::optional<Name>, TypeSpec, Name> t; +}; + +// Ref: [4.5:222:1-5], [5.0:305:20-27], [5.1:337:11-19], [5.2:139:18-23], +// [6.0:260:16-20] +// +// reduction-specifier -> +// reduction-identifier : typename-list +// : combiner-expression // since 4.5, until 5.2 +// reduction-identifier : typename-list // since 6.0 +struct OmpReductionSpecifier { + TUPLE_CLASS_BOILERPLATE(OmpReductionSpecifier); + std::tuple<OmpReductionIdentifier, OmpTypeNameList, + std::optional<OmpReductionCombiner>> + t; +}; + +struct OmpArgument { + CharBlock source; + UNION_CLASS_BOILERPLATE(OmpArgument); + std::variant<OmpLocator, // {variable, extended, locator}-list-item + OmpMapperSpecifier, OmpReductionSpecifier> + u; +}; +} // namespace arguments inline namespace traits { // trait-property-name -> @@ -3617,6 +3670,16 @@ struct OmpContextSelectorSpecification { // Modifier }; } // namespace traits +#define MODIFIER_BOILERPLATE(...) \ + struct Modifier { \ + using Variant = std::variant<__VA_ARGS__>; \ + UNION_CLASS_BOILERPLATE(Modifier); \ + CharBlock source; \ + Variant u; \ + } + +#define MODIFIERS() std::optional<std::list<Modifier>> + inline namespace modifier { // For uniformity, in all keyword modifiers the name of the type defined // by ENUM_CLASS is "Value", e.g. @@ -3829,18 +3892,6 @@ struct OmpPrescriptiveness { WRAPPER_CLASS_BOILERPLATE(OmpPrescriptiveness, Value); }; -// Ref: [4.5:201-207], [5.0:293-299], [5.1:325-331], [5.2:124] -// -// reduction-identifier -> -// base-language-identifier | // since 4.5 -// - | // 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<DefinedOperator, ProcedureDesignator> u; -}; - // Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137] // // reduction-modifier -> @@ -3983,7 +4034,9 @@ struct OmpBindClause { struct OmpDefaultClause { ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None) UNION_CLASS_BOILERPLATE(OmpDefaultClause); - std::variant<DataSharingAttribute, OmpDirectiveSpecification> u; + std::variant<DataSharingAttribute, + common::Indirection<OmpDirectiveSpecification>> + u; }; // Ref: [4.5:103-107], [5.0:324-325], [5.1:357-358], [5.2:161-162] @@ -4248,8 +4301,8 @@ struct OmpOrderClause { // otherwise-clause -> // OTHERWISE ([directive-specification])] // since 5.2 struct OmpOtherwiseClause { - WRAPPER_CLASS_BOILERPLATE( - OmpOtherwiseClause, std::optional<OmpDirectiveSpecification>); + WRAPPER_CLASS_BOILERPLATE(OmpOtherwiseClause, + std::optional<common::Indirection<OmpDirectiveSpecification>>); }; // Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:229-230] @@ -4345,7 +4398,9 @@ struct OmpUpdateClause { struct OmpWhenClause { TUPLE_CLASS_BOILERPLATE(OmpWhenClause); MODIFIER_BOILERPLATE(OmpContextSelector); - std::tuple<MODIFIERS(), std::optional<OmpDirectiveSpecification>> t; + std::tuple<MODIFIERS(), + std::optional<common::Indirection<OmpDirectiveSpecification>>> + t; }; // OpenMP Clauses @@ -4372,6 +4427,14 @@ struct OmpClauseList { // --- Directives and constructs +struct OmpDirectiveSpecification { + CharBlock source; + TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification); + std::tuple<llvm::omp::Directive, std::optional<std::list<OmpArgument>>, + std::optional<OmpClauseList>> + t; +}; + struct OmpMetadirectiveDirective { TUPLE_CLASS_BOILERPLATE(OmpMetadirectiveDirective); std::tuple<OmpClauseList> t; @@ -4472,27 +4535,16 @@ struct OpenMPDeclareTargetConstruct { std::tuple<Verbatim, OmpDeclareTargetSpecifier> t; }; -struct OmpDeclareMapperSpecifier { - TUPLE_CLASS_BOILERPLATE(OmpDeclareMapperSpecifier); - std::tuple<std::optional<Name>, TypeSpec, Name> t; -}; - // OMP v5.2: 5.8.8 // declare-mapper -> DECLARE MAPPER ([mapper-name :] type :: var) map-clauses struct OpenMPDeclareMapperConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPDeclareMapperConstruct); CharBlock source; - std::tuple<Verbatim, OmpDeclareMapperSpecifier, OmpClauseList> t; + std::tuple<Verbatim, OmpMapperSpecifier, OmpClauseList> t; }; // 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list // : combiner) [initializer-clause] -struct OmpReductionCombiner { - UNION_CLASS_BOILERPLATE(OmpReductionCombiner); - WRAPPER_CLASS(FunctionCombiner, Call); - std::variant<AssignmentStmt, FunctionCombiner> u; -}; - WRAPPER_CLASS(OmpReductionInitializerClause, Expr); struct OpenMPDeclareReductionConstruct { diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index f5387dcf4b3c3d..e73e0ac2c85ff9 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -68,6 +68,8 @@ void OmpDirectiveNameParser::initTokens(NameWithId *table) const { [](auto &a, auto &b) { return a.first.size() > b.first.size(); }); } +// --- Modifier helpers ----------------------------------------------- + template <typename Clause, typename Separator> struct ModifierList { constexpr ModifierList(Separator sep) : sep_(sep) {} constexpr ModifierList(const ModifierList &) = default; @@ -118,10 +120,8 @@ struct SpecificModifierParser { } }; -// OpenMP Clauses +// --- Iterator helpers ----------------------------------------------- -// [5.0] 2.1.6 iterator-specifier -> type-declaration-stmt = subscript-triple | -// identifier = subscript-triple // [5.0:47:17-18] In an iterator-specifier, if the iterator-type is not // specified then the type of that iterator is default integer. // [5.0:49:14] The iterator-type must be an integer type. @@ -153,8 +153,30 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) { makeEntityList(std::move(names))); } -TYPE_PARSER(sourced(construct<OmpDirectiveSpecification>( - OmpDirectiveNameParser{}, maybe(indirect(Parser<OmpClauseList>{}))))) +// --- Parsers for arguments ------------------------------------------ + +// At the moment these are only directive arguments. This is needed for +// parsing directive-specification. + +TYPE_PARSER( // + construct<OmpLocator>(Parser<OmpObject>{}) || + construct<OmpLocator>(Parser<FunctionReference>{})) + +TYPE_PARSER(sourced( // + construct<OmpArgument>(Parser<OmpMapperSpecifier>{}) || + construct<OmpArgument>(Parser<OmpReductionSpecifier>{}) || + construct<OmpArgument>(Parser<OmpLocator>{}))) + +TYPE_PARSER(construct<OmpLocatorList>(nonemptyList(Parser<OmpLocator>{}))) + +TYPE_PARSER( // + construct<OmpTypeSpecifier>(Parser<TypeSpec>{}) || + construct<OmpTypeSpecifier>(Parser<DeclarationTypeSpec>{})) + +TYPE_PARSER(construct<OmpReductionSpecifier>( // + Parser<OmpReductionIdentifier>{}, + ":"_tok >> nonemptyList(Parser<OmpTypeSpecifier>{}), + maybe(":"_tok >> Parser<OmpReductionCombiner>{}))) // --- Parsers for context traits ------------------------------------- @@ -213,15 +235,11 @@ static constexpr auto propertyListParser(PropParser... pp) { // the entire list in each of the alternative property parsers. Otherwise, // the name parser could stop after "foo" in "(foo, bar(1))", without // allowing the next parser to give the list a try. - auto listOf{[](auto parser) { // - return nonemptySeparated(parser, ","); - }}; - using P = OmpTraitProperty; return maybe("(" >> // construct<OmpTraitSelector::Properties>( maybe(Parser<OmpTraitScore>{} / ":"), - (attempt(listOf(sourced(construct<P>(pp))) / ")") || ...))); + (attempt(nonemptyList(sourced(construct<P>(pp))) / ")") || ...))); } // Parser for OmpTraitSelector @@ -309,7 +327,7 @@ TYPE_PARSER(sourced(construct<OmpTraitSetSelector>( // TYPE_PARSER(sourced(construct<OmpContextSelectorSpecification>( nonemptySeparated(Parser<OmpTraitSetSelector>{}, ",")))) -// Parser<OmpContextSelector> == Parser<traits::OmpContextSelectorSpecification> +// Note: OmpContextSelector is a type alias. // --- Parsers for clause modifiers ----------------------------------- @@ -543,7 +561,7 @@ TYPE_PARSER(construct<OmpDefaultClause::DataSharingAttribute>( TYPE_PARSER(construct<OmpDefaultClause>( construct<OmpDefaultClause>( Parser<OmpDefaultClause::DataSharingAttribute>{}) || - construct<OmpDefaultClause>(Parser<OmpDirectiveSpecification>{}))) + construct<OmpDefaultClause>(indirect(Parser<OmpDirectiveSpecification>{})))) // 2.5 PROC_BIND (MASTER | CLOSE | PRIMARY | SPREAD) TYPE_PARSER(construct<OmpProcBindClause>( @@ -713,11 +731,11 @@ TYPE_PARSER(construct<OmpMatchClause>( Parser<traits::OmpContextSelectorSpecification>{})) TYPE_PARSER(construct<OmpOtherwiseClause>( - maybe(sourced(Parser<OmpDirectiveSpecification>{})))) + maybe(indirect(sourced(Parser<OmpDirectiveSpecification>{}))))) TYPE_PARSER(construct<OmpWhenClause>( maybe(nonemptyList(Parser<OmpWhenClause::Modifier>{}) / ":"), - maybe(sourced(Parser<OmpDirectiveSpecification>{})))) + maybe(indirect(sourced(Parser<OmpDirectiveSpecification>{}))))) // OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression) TYPE_PARSER(construct<OmpGrainsizeClause>( @@ -929,6 +947,13 @@ TYPE_PARSER(construct<OmpObjectList>(nonemptyList(Parser<OmpObject>{}))) TYPE_PARSER(sourced(construct<OmpErrorDirective>( verbatim("ERROR"_tok), Parser<OmpClauseList>{}))) +// --- Parsers for directives and constructs -------------------------- + +TYPE_PARSER(sourced(construct<OmpDirectiveSpecification>( // + OmpDirectiveNameParser{}, + maybe(parenthesized(nonemptyList(Parser<OmpArgument>{}))), + maybe(Parser<OmpClauseList>{})))) + TYPE_PARSER(sourced(construct<OmpNothingDirective>("NOTHING" >> ok))) TYPE_PARSER(sourced(construct<OpenMPUtilityConstruct>( @@ -1141,20 +1166,17 @@ TYPE_PARSER( TYPE_PARSER(sourced(construct<OpenMPDeclareTargetConstruct>( verbatim("DECLARE TARGET"_tok), Parser<OmpDeclareTargetSpecifier>{}))) -// declare-mapper-specifier -TYPE_PARSER(construct<OmpDeclareMapperSpecifier>( +// mapper-specifier +TYPE_PARSER(construct<OmpMapperSpecifier>( maybe(name / ":" / !":"_tok), typeSpec / "::", name)) // OpenMP 5.2: 5.8.8 Declare Mapper Construct -TYPE_PARSER(sourced(construct<OpenMPDeclareMapperConstruct>( - verbatim("DECLARE MAPPER"_tok), - "(" >> Parser<OmpDeclareMapperSpecifier>{} / ")", Parser<OmpClauseList>{}))) +TYPE_PARSER(sourced( + construct<OpenMPDeclareMapperConstruct>(verbatim("DECLARE MAPPER"_tok), + parenthesized(Parser<OmpMapperSpecifier>{}), Parser<OmpClauseList>{}))) TYPE_PARSER(construct<OmpReductionCombiner>(Parser<AssignmentStmt>{}) || - construct<OmpReductionCombiner>( - construct<OmpReductionCombiner::FunctionCombiner>( - construct<Call>(Parser<ProcedureDesignator>{}, - parenthesized(optionalList(actualArgSpec)))))) + construct<OmpReductionCombiner>(Parser<FunctionReference>{})) // 2.17.7 atomic -> ATOMIC [clause [,]] atomic-clause [[,] clause] | // ATOMIC [clause] diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 7d3b03e5bc27e7..bc1c472f276ea1 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2067,12 +2067,33 @@ class UnparseVisitor { } // OpenMP Clauses & Directives + void Unparse(const OmpTypeNameList &x) { // + Walk(x.v, ","); + } + void Unparse(const OmpMapperSpecifier &x) { + Walk(std::get<std::optional<Name>>(x.t), ":"); + Walk(std::get<TypeSpec>(x.t)); + Put("::"); + Walk(std::get<Name>(x.t)); + } + void Unparse(const OmpReductionSpecifier &x) { + Walk(std::get<OmpReductionIdentifier>(x.t)); + Put(":"); + Walk(std::get<OmpTypeNameList>(x.t)); + Walk(":", std::get<std::optional<OmpReductionCombiner>>(x.t)); + } void Unparse(const llvm::omp::Directive &x) { Word(llvm::omp::getOpenMPDirectiveName(x).str()); } void Unparse(const OmpDirectiveSpecification &x) { + using ArgList = std::list<parser::OmpArgument>; Walk(std::get<llvm::omp::Directive>(x.t)); - Walk(std::get<std::optional<common::Indirection<OmpClauseList>>>(x.t)); + if (auto &args{std::get<std::optional<ArgList>>(x.t)}) { + Put("("); + Walk(*args); + Put(")"); + } + Walk(std::get<std::optional<OmpClauseList>>(x.t)); } void Unparse(const OmpTraitScore &x) { Word("SCORE("); @@ -2297,8 +2318,9 @@ class UnparseVisitor { } void Unparse(const OmpWhenClause &x) { using Modifier = OmpWhenClause::Modifier; + using Directive = common::Indirection<OmpDirectiveSpecification>; Walk(std::get<std::optional<std::list<Modifier>>>(x.t), ": "); - Walk(std::get<std::optional<OmpDirectiveSpecification>>(x.t)); + Walk(std::get<std::optional<Directive>>(x.t)); } #define GEN_FLANG_CLAUSE_UNPARSE #include "llvm/Frontend/OpenMP/OMP.inc" @@ -2660,18 +2682,6 @@ class UnparseVisitor { Walk(x.v); Put(")"); } - void Unparse(const OmpReductionCombiner::FunctionCombiner &x) { - const auto &pd = std::get<ProcedureDesignator>(x.v.t); - const auto &args = std::get<std::list<ActualArgSpec>>(x.v.t); - Walk(pd); - if (args.empty()) { - if (std::holds_alternative<ProcComponentRef>(pd.u)) { - Put("()"); - } - } else { - Walk("(", args, ", ", ")"); - } - } void Unparse(const OpenMPDeclareReductionConstruct &x) { BeginOpenMP(); Word("!$OMP DECLARE REDUCTION "); @@ -2687,7 +2697,7 @@ class UnparseVisitor { void Unparse(const OpenMPDeclareMapperConstruct &z) { BeginOpenMP(); Word("!$OMP DECLARE MAPPER ("); - const auto &spec{std::get<OmpDeclareMapperSpecifier>(z.t)}; + const auto &spec{std::get<OmpMapperSpecifier>(z.t)}; if (auto mapname{std::get<std::optional<Name>>(spec.t)}) { Walk(mapname); Put(":"); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 94886d6b9dfdc9..bde97e0b87e565 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1606,7 +1606,7 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclareMapperConstruct &x) { const auto &dir{std::get<parser::Verbatim>(x.t)}; PushContextAndClauseSets( dir.source, llvm::omp::Directive::OMPD_declare_mapper); - const auto &spec{std::get<parser::OmpDeclareMapperSpecifier>(x.t)}; + const auto &spec{std::get<parser::OmpMapperSpecifier>(x.t)}; const auto &type = std::get<parser::TypeSpec>(spec.t); if (!std::get_if<parser::DerivedTypeSpec>(&type.u)) { context_.Say(dir.source, "Type is not a derived type"_err_en_US); diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index f3c2a5bf094d04..82bfaa1385fbba 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1471,7 +1471,12 @@ class OmpVisitor : public virtual DeclarationVisitor { return true; } - bool Pre(const parser::OpenMPDeclareMapperConstruct &); + bool Pre(const parser::OpenMPDeclareMapperConstruct &x) { + AddOmpSourceRange(x.source); + ProcessMapperSpecifier(std::get<parser::OmpMapperSpecifier>(x.t), + std::get<parser::OmpClauseList>(x.t)); + return false; + } bool Pre(const parser::OmpMapClause &); @@ -1573,6 +1578,21 @@ class OmpVisitor : public virtual Declara... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/124278 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits