diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp index 3a689c335c81c..e35f120d8661e 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 87bb65fa5c466..3e4e909cdec9a 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -477,6 +477,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) @@ -542,7 +548,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) @@ -625,7 +631,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 df166ddc24b05..d7b1ae9893c03 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3457,15 +3457,7 @@ WRAPPER_CLASS(PauseStmt, std::optional); // --- Common definitions struct OmpClause; -struct OmpClauseList; - -struct OmpDirectiveSpecification { - TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification); - std::tuple>> - 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 @@ -3478,15 +3470,76 @@ struct OmpObject { WRAPPER_CLASS(OmpObjectList, std::list); -#define MODIFIER_BOILERPLATE(...) \ - struct Modifier { \ - using Variant = std::variant<__VA_ARGS__>; \ - UNION_CLASS_BOILERPLATE(Modifier); \ - CharBlock source; \ - Variant u; \ - } +// 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 u; +}; -#define MODIFIERS() std::optional> +// 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 u; +}; + +inline namespace arguments { +struct OmpTypeSpecifier { + UNION_CLASS_BOILERPLATE(OmpTypeSpecifier); + std::variant u; +}; + +WRAPPER_CLASS(OmpTypeNameList, std::list); + +struct OmpLocator { + UNION_CLASS_BOILERPLATE(OmpLocator); + std::variant u; +}; + +WRAPPER_CLASS(OmpLocatorList, std::list); + +// 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, 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> + t; +}; + +struct OmpArgument { + CharBlock source; + UNION_CLASS_BOILERPLATE(OmpArgument); + std::variant + u; +}; +} // namespace arguments inline namespace traits { // trait-property-name -> @@ -3620,6 +3673,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> + inline namespace modifier { // For uniformity, in all keyword modifiers the name of the type defined // by ENUM_CLASS is "Value", e.g. @@ -3832,18 +3895,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 u; -}; - // Ref: [5.0:300-302], [5.1:332-334], [5.2:134-137] // // reduction-modifier -> @@ -3986,7 +4037,9 @@ struct OmpBindClause { struct OmpDefaultClause { ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None) UNION_CLASS_BOILERPLATE(OmpDefaultClause); - std::variant u; + std::variant> + u; }; // Ref: [4.5:103-107], [5.0:324-325], [5.1:357-358], [5.2:161-162] @@ -4251,8 +4304,8 @@ struct OmpOrderClause { // otherwise-clause -> // OTHERWISE ([directive-specification])] // since 5.2 struct OmpOtherwiseClause { - WRAPPER_CLASS_BOILERPLATE( - OmpOtherwiseClause, std::optional); + WRAPPER_CLASS_BOILERPLATE(OmpOtherwiseClause, + std::optional>); }; // Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:229-230] @@ -4348,7 +4401,9 @@ struct OmpUpdateClause { struct OmpWhenClause { TUPLE_CLASS_BOILERPLATE(OmpWhenClause); MODIFIER_BOILERPLATE(OmpContextSelector); - std::tuple> t; + std::tuple>> + t; }; // OpenMP Clauses @@ -4375,6 +4430,14 @@ struct OmpClauseList { // --- Directives and constructs +struct OmpDirectiveSpecification { + CharBlock source; + TUPLE_CLASS_BOILERPLATE(OmpDirectiveSpecification); + std::tuple>, + std::optional> + t; +}; + struct OmpMetadirectiveDirective { TUPLE_CLASS_BOILERPLATE(OmpMetadirectiveDirective); std::tuple t; @@ -4475,27 +4538,16 @@ struct OpenMPDeclareTargetConstruct { std::tuple t; }; -struct OmpDeclareMapperSpecifier { - TUPLE_CLASS_BOILERPLATE(OmpDeclareMapperSpecifier); - std::tuple, 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 t; + std::tuple 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 u; -}; - WRAPPER_CLASS(OmpReductionInitializerClause, Expr); struct OpenMPDeclareReductionConstruct { diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index b72e83958a488..2b6c77c08cc58 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 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 &&names) { makeEntityList(std::move(names))); } -TYPE_PARSER(sourced(construct( - OmpDirectiveNameParser{}, maybe(indirect(Parser{}))))) +// --- Parsers for arguments ------------------------------------------ + +// At the moment these are only directive arguments. This is needed for +// parsing directive-specification. + +TYPE_PARSER( // + construct(Parser{}) || + construct(Parser{})) + +TYPE_PARSER(sourced( // + construct(Parser{}) || + construct(Parser{}) || + construct(Parser{}))) + +TYPE_PARSER(construct(nonemptyList(Parser{}))) + +TYPE_PARSER( // + construct(Parser{}) || + construct(Parser{})) + +TYPE_PARSER(construct( // + Parser{}, + ":"_tok >> nonemptyList(Parser{}), + maybe(":"_tok >> Parser{}))) // --- 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( maybe(Parser{} / ":"), - (attempt(listOf(sourced(construct

(pp))) / ")") || ...))); + (attempt(nonemptyList(sourced(construct

(pp))) / ")") || ...))); } // Parser for OmpTraitSelector @@ -309,7 +327,7 @@ TYPE_PARSER(sourced(construct( // TYPE_PARSER(sourced(construct( nonemptySeparated(Parser{}, ",")))) -// Parser == Parser +// Note: OmpContextSelector is a type alias. // --- Parsers for clause modifiers ----------------------------------- @@ -543,7 +561,7 @@ TYPE_PARSER(construct( TYPE_PARSER(construct( construct( Parser{}) || - construct(Parser{}))) + construct(indirect(Parser{})))) // 2.5 PROC_BIND (MASTER | CLOSE | PRIMARY | SPREAD) TYPE_PARSER(construct( @@ -713,11 +731,11 @@ TYPE_PARSER(construct( Parser{})) TYPE_PARSER(construct( - maybe(sourced(Parser{})))) + maybe(indirect(sourced(Parser{}))))) TYPE_PARSER(construct( maybe(nonemptyList(Parser{}) / ":"), - maybe(sourced(Parser{})))) + maybe(indirect(sourced(Parser{}))))) // OMP 5.2 12.6.1 grainsize([ prescriptiveness :] scalar-integer-expression) TYPE_PARSER(construct( @@ -933,6 +951,13 @@ TYPE_PARSER(construct(nonemptyList(Parser{}))) TYPE_PARSER(sourced(construct( verbatim("ERROR"_tok), Parser{}))) +// --- Parsers for directives and constructs -------------------------- + +TYPE_PARSER(sourced(construct( // + OmpDirectiveNameParser{}, + maybe(parenthesized(nonemptyList(Parser{}))), + maybe(Parser{})))) + TYPE_PARSER(sourced(construct("NOTHING" >> ok))) TYPE_PARSER(sourced(construct( @@ -1145,20 +1170,17 @@ TYPE_PARSER( TYPE_PARSER(sourced(construct( verbatim("DECLARE TARGET"_tok), Parser{}))) -// declare-mapper-specifier -TYPE_PARSER(construct( +// mapper-specifier +TYPE_PARSER(construct( maybe(name / ":" / !":"_tok), typeSpec / "::", name)) // OpenMP 5.2: 5.8.8 Declare Mapper Construct -TYPE_PARSER(sourced(construct( - verbatim("DECLARE MAPPER"_tok), - "(" >> Parser{} / ")", Parser{}))) +TYPE_PARSER(sourced( + construct(verbatim("DECLARE MAPPER"_tok), + parenthesized(Parser{}), Parser{}))) TYPE_PARSER(construct(Parser{}) || - construct( - construct( - construct(Parser{}, - parenthesized(optionalList(actualArgSpec)))))) + construct(Parser{})) // 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 813dd652e1e9f..243f586b3ca4f 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2071,12 +2071,33 @@ class UnparseVisitor { } // OpenMP Clauses & Directives + void Unparse(const OmpTypeNameList &x) { // + Walk(x.v, ","); + } + void Unparse(const OmpMapperSpecifier &x) { + Walk(std::get>(x.t), ":"); + Walk(std::get(x.t)); + Put("::"); + Walk(std::get(x.t)); + } + void Unparse(const OmpReductionSpecifier &x) { + Walk(std::get(x.t)); + Put(":"); + Walk(std::get(x.t)); + Walk(":", std::get>(x.t)); + } void Unparse(const llvm::omp::Directive &x) { Word(llvm::omp::getOpenMPDirectiveName(x).str()); } void Unparse(const OmpDirectiveSpecification &x) { + using ArgList = std::list; Walk(std::get(x.t)); - Walk(std::get>>(x.t)); + if (auto &args{std::get>(x.t)}) { + Put("("); + Walk(*args); + Put(")"); + } + Walk(std::get>(x.t)); } void Unparse(const OmpTraitScore &x) { Word("SCORE("); @@ -2301,8 +2322,9 @@ class UnparseVisitor { } void Unparse(const OmpWhenClause &x) { using Modifier = OmpWhenClause::Modifier; + using Directive = common::Indirection; Walk(std::get>>(x.t), ": "); - Walk(std::get>(x.t)); + Walk(std::get>(x.t)); } #define GEN_FLANG_CLAUSE_UNPARSE #include "llvm/Frontend/OpenMP/OMP.inc" @@ -2664,18 +2686,6 @@ class UnparseVisitor { Walk(x.v); Put(")"); } - void Unparse(const OmpReductionCombiner::FunctionCombiner &x) { - const auto &pd = std::get(x.v.t); - const auto &args = std::get>(x.v.t); - Walk(pd); - if (args.empty()) { - if (std::holds_alternative(pd.u)) { - Put("()"); - } - } else { - Walk("(", args, ", ", ")"); - } - } void Unparse(const OpenMPDeclareReductionConstruct &x) { BeginOpenMP(); Word("!$OMP DECLARE REDUCTION "); @@ -2691,7 +2701,7 @@ class UnparseVisitor { void Unparse(const OpenMPDeclareMapperConstruct &z) { BeginOpenMP(); Word("!$OMP DECLARE MAPPER ("); - const auto &spec{std::get(z.t)}; + const auto &spec{std::get(z.t)}; if (auto mapname{std::get>(spec.t)}) { Walk(mapname); Put(":"); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 70d4427df7aa3..6306251ca15dd 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1640,7 +1640,7 @@ 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 &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); diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index c4562727f09b3..87314124afae6 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1474,7 +1474,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(x.t), + std::get(x.t)); + return false; + } bool Pre(const parser::OmpMapClause &); @@ -1616,6 +1621,21 @@ class OmpVisitor : public virtual DeclarationVisitor { PopScope(); } } + bool Pre(const parser::OmpDirectiveSpecification &x); + + bool Pre(const parser::OmpTypeSpecifier &x) { + BeginDeclTypeSpec(); + return true; + } + void Post(const parser::OmpTypeSpecifier &x) { // + EndDeclTypeSpec(); + } + +private: + void ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec, + const parser::OmpClauseList &clauses); + void ProcessReductionSpecifier(const parser::OmpReductionSpecifier &spec, + const parser::OmpClauseList &clauses); }; bool OmpVisitor::NeedsScope(const parser::OpenMPBlockConstruct &x) { @@ -1655,37 +1675,6 @@ void OmpVisitor::Post(const parser::OpenMPBlockConstruct &x) { } } -// This "manually" walks the tree of the construct, because we need -// to resolve the type before the map clauses are processed - when -// just following the natural flow, the map clauses gets processed before -// the type has been fully processed. -bool OmpVisitor::Pre(const parser::OpenMPDeclareMapperConstruct &x) { - AddOmpSourceRange(x.source); - BeginDeclTypeSpec(); - const auto &spec{std::get(x.t)}; - Symbol *mapperSym{nullptr}; - if (const auto &mapperName{std::get>(spec.t)}) { - mapperSym = - &MakeSymbol(*mapperName, MiscDetails{MiscDetails::Kind::ConstructName}); - mapperName->symbol = mapperSym; - } else { - const parser::CharBlock defaultName{"default", 7}; - mapperSym = &MakeSymbol( - defaultName, Attrs{}, MiscDetails{MiscDetails::Kind::ConstructName}); - } - - PushScope(Scope::Kind::OtherConstruct, nullptr); - Walk(std::get(spec.t)); - const auto &varName{std::get(spec.t)}; - DeclareObjectEntity(varName); - - Walk(std::get(x.t)); - - EndDeclTypeSpec(); - PopScope(); - return false; -} - bool OmpVisitor::Pre(const parser::OmpMapClause &x) { auto &mods{OmpGetModifiers(x)}; if (auto *mapper{OmpGetUniqueModifier(mods)}) { @@ -1713,6 +1702,83 @@ bool OmpVisitor::Pre(const parser::OmpMapClause &x) { return true; } +void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec, + const parser::OmpClauseList &clauses) { + // This "manually" walks the tree of the construct, because we need + // to resolve the type before the map clauses are processed - when + // just following the natural flow, the map clauses gets processed before + // the type has been fully processed. + BeginDeclTypeSpec(); + if (auto &mapperName{std::get>(spec.t)}) { + mapperName->symbol = + &MakeSymbol(*mapperName, MiscDetails{MiscDetails::Kind::ConstructName}); + } else { + const parser::CharBlock defaultName{"default", 7}; + MakeSymbol( + defaultName, Attrs{}, MiscDetails{MiscDetails::Kind::ConstructName}); + } + + PushScope(Scope::Kind::OtherConstruct, nullptr); + Walk(std::get(spec.t)); + auto &varName{std::get(spec.t)}; + DeclareObjectEntity(varName); + + Walk(clauses); + EndDeclTypeSpec(); + PopScope(); +} + +void OmpVisitor::ProcessReductionSpecifier( + const parser::OmpReductionSpecifier &spec, + const parser::OmpClauseList &clauses) { + // Creating a new scope in case the combiner expression (or clauses) use + // reerved identifiers, like "omp_in". This is a temporary solution until + // we deal with these in a more thorough way. + PushScope(Scope::Kind::OtherConstruct, nullptr); + Walk(std::get(spec.t)); + Walk(std::get(spec.t)); + Walk(std::get>(spec.t)); + Walk(clauses); + PopScope(); +} + +bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) { + // OmpDirectiveSpecification is only used in METADIRECTIVE at the moment. + // Since it contains directives and clauses, some semantic checks may + // not be applicable. + // Disable the semantic analysis for it for now to allow the compiler to + // parse METADIRECTIVE without flagging errors. + AddOmpSourceRange(x.source); + auto dirId{std::get(x.t)}; + auto &maybeArgs{std::get>>(x.t)}; + auto &maybeClauses{std::get>(x.t)}; + + switch (dirId) { + case llvm::omp::Directive::OMPD_declare_mapper: + if (maybeArgs && maybeClauses) { + const parser::OmpArgument &first{maybeArgs->front()}; + if (auto *spec{std::get_if(&first.u)}) { + ProcessMapperSpecifier(*spec, *maybeClauses); + } + } + break; + case llvm::omp::Directive::OMPD_declare_reduction: + if (maybeArgs && maybeClauses) { + const parser::OmpArgument &first{maybeArgs->front()}; + if (auto *spec{std::get_if(&first.u)}) { + ProcessReductionSpecifier(*spec, *maybeClauses); + } + } + break; + default: + // Default processing. + Walk(maybeArgs); + Walk(maybeClauses); + break; + } + return false; +} + // Walk the parse tree and resolve names to symbols. class ResolveNamesVisitor : public virtual ScopeHandler, public ModuleVisitor, diff --git a/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 b/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 index 5ba147d20955e..407bfd29153fa 100644 --- a/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 +++ b/flang/test/Parser/OpenMP/declare-mapper-unparse.f90 @@ -13,7 +13,7 @@ program main !$omp declare mapper(mymapper : ty :: mapped) map(mapped, mapped%x) !PARSE-TREE: OpenMPDeclareMapperConstruct -!PARSE-TREE: OmpDeclareMapperSpecifier +!PARSE-TREE: OmpMapperSpecifier !PARSE-TREE: Name = 'mymapper' !PARSE-TREE: TypeSpec -> DerivedTypeSpec !PARSE-TREE: Name = 'ty' @@ -28,7 +28,7 @@ program main !$omp declare mapper(ty :: mapped) map(mapped, mapped%x) !PARSE-TREE: OpenMPDeclareMapperConstruct -!PARSE-TREE: OmpDeclareMapperSpecifier +!PARSE-TREE: OmpMapperSpecifier !PARSE-TREE: TypeSpec -> DerivedTypeSpec !PARSE-TREE: Name = 'ty' !PARSE-TREE: Name = 'mapped' diff --git a/flang/test/Parser/OpenMP/metadirective-dirspec.f90 b/flang/test/Parser/OpenMP/metadirective-dirspec.f90 new file mode 100644 index 0000000000000..73520c41fe77d --- /dev/null +++ b/flang/test/Parser/OpenMP/metadirective-dirspec.f90 @@ -0,0 +1,242 @@ +!RUN: %flang_fc1 -fdebug-unparse -fopenmp -fopenmp-version=52 %s | FileCheck --ignore-case --check-prefix="UNPARSE" %s +!RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp -fopenmp-version=52 %s | FileCheck --check-prefix="PARSE-TREE" %s + +!Directive specification where directives have arguments + +subroutine f00(x) + integer :: x(10) + !$omp metadirective when(user={condition(.true.)}: & + !$omp & allocate(x)) +end + +!UNPARSE: SUBROUTINE f00 (x) +!UNPARSE: INTEGER x(10_4) +!UNPARSE: !$OMP METADIRECTIVE WHEN(USER={CONDITION(.true._4)}: ALLOCATE(x)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpMetadirectiveDirective +!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause +!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector +!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = User +!PARSE-TREE: | | | OmpTraitSelector +!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Condition +!PARSE-TREE: | | | | Properties +!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4' +!PARSE-TREE: | | | | | | LiteralConstant -> LogicalLiteralConstant +!PARSE-TREE: | | | | | | | bool = 'true' +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | llvm::omp::Directive = allocate +!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | | OmpClauseList -> + +subroutine f01(x) + integer :: x + !$omp metadirective when(user={condition(.true.)}: & + !$omp & critical(x)) +end + +!UNPARSE: SUBROUTINE f01 (x) +!UNPARSE: INTEGER x +!UNPARSE: !$OMP METADIRECTIVE WHEN(USER={CONDITION(.true._4)}: CRITICAL(x)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpMetadirectiveDirective +!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause +!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector +!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = User +!PARSE-TREE: | | | OmpTraitSelector +!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Condition +!PARSE-TREE: | | | | Properties +!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4' +!PARSE-TREE: | | | | | | LiteralConstant -> LogicalLiteralConstant +!PARSE-TREE: | | | | | | | bool = 'true' +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | llvm::omp::Directive = critical +!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | | OmpClauseList -> + +subroutine f02 + !$omp metadirective when(user={condition(.true.)}: & + !$omp & declare mapper(mymapper : integer :: v) map(tofrom: v)) +end + +!UNPARSE: SUBROUTINE f02 +!UNPARSE: !$OMP METADIRECTIVE WHEN(USER={CONDITION(.true._4)}: DECLARE MAPPER(mymapper:INTEGER:& +!UNPARSE: !$OMP&:v) MAP(TOFROM: v)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpMetadirectiveDirective +!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause +!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector +!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = User +!PARSE-TREE: | | | OmpTraitSelector +!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Condition +!PARSE-TREE: | | | | Properties +!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4' +!PARSE-TREE: | | | | | | LiteralConstant -> LogicalLiteralConstant +!PARSE-TREE: | | | | | | | bool = 'true' +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | llvm::omp::Directive = declare mapper +!PARSE-TREE: | | | OmpArgument -> OmpMapperSpecifier +!PARSE-TREE: | | | | Name = 'mymapper' +!PARSE-TREE: | | | | TypeSpec -> IntrinsicTypeSpec -> IntegerTypeSpec -> +!PARSE-TREE: | | | | Name = 'v' +!PARSE-TREE: | | | OmpClauseList -> OmpClause -> Map -> OmpMapClause +!PARSE-TREE: | | | | Modifier -> OmpMapType -> Value = Tofrom +!PARSE-TREE: | | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'v' +!PARSE-TREE: | | | | bool = 'true' +!PARSE-TREE: ImplicitPart -> + +subroutine f03 + type :: tt1 + integer :: x + endtype + type :: tt2 + real :: a + endtype + !$omp metadirective when(user={condition(.true.)}: & + !$omp & declare reduction(+ : tt1, tt2 : omp_out = omp_in + omp_out)) +end + +!UNPARSE: SUBROUTINE f03 +!UNPARSE: TYPE :: tt1 +!UNPARSE: INTEGER :: x +!UNPARSE: END TYPE +!UNPARSE: TYPE :: tt2 +!UNPARSE: REAL :: a +!UNPARSE: END TYPE +!UNPARSE: !$OMP METADIRECTIVE WHEN(USER={CONDITION(.true._4)}: DECLARE REDUCTION(+:tt1,tt2: omp_out=omp_in+omp_out +!UNPARSE: )) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpMetadirectiveDirective +!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause +!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector +!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = User +!PARSE-TREE: | | | OmpTraitSelector +!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Condition +!PARSE-TREE: | | | | Properties +!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4' +!PARSE-TREE: | | | | | | LiteralConstant -> LogicalLiteralConstant +!PARSE-TREE: | | | | | | | bool = 'true' +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | llvm::omp::Directive = declare reduction +!PARSE-TREE: | | | OmpArgument -> OmpReductionSpecifier +!PARSE-TREE: | | | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add +!PARSE-TREE: | | | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec +!PARSE-TREE: | | | | | Name = 'tt1' +!PARSE-TREE: | | | | OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec +!PARSE-TREE: | | | | | Name = 'tt2' +!PARSE-TREE: | | | | OmpReductionCombiner -> AssignmentStmt = 'omp_out=omp_in+omp_out' +!PARSE-TREE: | | | | | Variable = 'omp_out' +!PARSE-TREE: | | | | | | Designator -> DataRef -> Name = 'omp_out' +!PARSE-TREE: | | | | | Expr = 'omp_in+omp_out' +!PARSE-TREE: | | | | | | Add +!PARSE-TREE: | | | | | | | Expr = 'omp_in' +!PARSE-TREE: | | | | | | | | Designator -> DataRef -> Name = 'omp_in' +!PARSE-TREE: | | | | | | | Expr = 'omp_out' +!PARSE-TREE: | | | | | | | | Designator -> DataRef -> Name = 'omp_out' +!PARSE-TREE: | | | OmpClauseList -> + +subroutine f04 + !$omp metadirective when(user={condition(.true.)}: & + !$omp & declare simd(f04)) +end + +!UNPARSE: SUBROUTINE f04 +!UNPARSE: !$OMP METADIRECTIVE WHEN(USER={CONDITION(.true._4)}: DECLARE SIMD(f04)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpMetadirectiveDirective +!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause +!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector +!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = User +!PARSE-TREE: | | | OmpTraitSelector +!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Condition +!PARSE-TREE: | | | | Properties +!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4' +!PARSE-TREE: | | | | | | LiteralConstant -> LogicalLiteralConstant +!PARSE-TREE: | | | | | | | bool = 'true' +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | llvm::omp::Directive = declare simd +!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f04' +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: ImplicitPart -> + +subroutine f05 + !$omp metadirective when(user={condition(.true.)}: & + !$omp & declare target(f05)) +end + +!UNPARSE: SUBROUTINE f05 +!UNPARSE: !$OMP METADIRECTIVE WHEN(USER={CONDITION(.true._4)}: DECLARE TARGET(f05)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpMetadirectiveDirective +!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause +!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector +!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = User +!PARSE-TREE: | | | OmpTraitSelector +!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Condition +!PARSE-TREE: | | | | Properties +!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4' +!PARSE-TREE: | | | | | | LiteralConstant -> LogicalLiteralConstant +!PARSE-TREE: | | | | | | | bool = 'true' +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | llvm::omp::Directive = declare target +!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f05' +!PARSE-TREE: | | | OmpClauseList -> +!PARSE-TREE: ImplicitPart -> + +subroutine f06(x, y) + integer :: x, y + !$omp metadirective when(user={condition(.true.)}: & + !$omp & flush(x, y)) +end + +!UNPARSE: SUBROUTINE f06 (x, y) +!UNPARSE: INTEGER x, y +!UNPARSE: !$OMP METADIRECTIVE WHEN(USER={CONDITION(.true._4)}: FLUSH(x, y)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpMetadirectiveDirective +!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause +!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector +!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = User +!PARSE-TREE: | | | OmpTraitSelector +!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Condition +!PARSE-TREE: | | | | Properties +!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4' +!PARSE-TREE: | | | | | | LiteralConstant -> LogicalLiteralConstant +!PARSE-TREE: | | | | | | | bool = 'true' +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | llvm::omp::Directive = flush +!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'x' +!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'y' +!PARSE-TREE: | | | OmpClauseList -> + +subroutine f07 + integer :: t + !$omp metadirective when(user={condition(.true.)}: & + !$omp & threadprivate(t)) +end + +!UNPARSE: SUBROUTINE f07 +!UNPARSE: INTEGER t +!UNPARSE: !$OMP METADIRECTIVE WHEN(USER={CONDITION(.true._4)}: THREADPRIVATE(t)) +!UNPARSE: END SUBROUTINE + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpMetadirectiveDirective +!PARSE-TREE: | OmpClauseList -> OmpClause -> When -> OmpWhenClause +!PARSE-TREE: | | Modifier -> OmpContextSelectorSpecification -> OmpTraitSetSelector +!PARSE-TREE: | | | OmpTraitSetSelectorName -> Value = User +!PARSE-TREE: | | | OmpTraitSelector +!PARSE-TREE: | | | | OmpTraitSelectorName -> Value = Condition +!PARSE-TREE: | | | | Properties +!PARSE-TREE: | | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4' +!PARSE-TREE: | | | | | | LiteralConstant -> LogicalLiteralConstant +!PARSE-TREE: | | | | | | | bool = 'true' +!PARSE-TREE: | | OmpDirectiveSpecification +!PARSE-TREE: | | | llvm::omp::Directive = threadprivate +!PARSE-TREE: | | | OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 't' +!PARSE-TREE: | | | OmpClauseList ->