diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index b2341226c7688..7540d38baa584 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -522,6 +522,7 @@ class ParseTreeDumper { NODE(parser, OmpAtomicDefaultMemOrderClause) NODE(parser, OmpAutomapModifier) NODE_ENUM(OmpAutomapModifier, Value) + NODE(parser, OmpBaseVariantNames) NODE(parser, OmpBeginDirective) NODE(parser, OmpBeginLoopDirective) NODE(parser, OmpBeginSectionsDirective) diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h index 34eb6ac3436bc..64be9714f6cc2 100644 --- a/flang/include/flang/Parser/openmp-utils.h +++ b/flang/include/flang/Parser/openmp-utils.h @@ -38,7 +38,6 @@ struct ConstructId { static constexpr llvm::omp::Directive id{Id}; \ } -MAKE_CONSTR_ID(OmpDeclareVariantDirective, D::OMPD_declare_variant); MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate); MAKE_CONSTR_ID(OpenMPDeclarativeAssumes, D::OMPD_assumes); MAKE_CONSTR_ID(OpenMPDeclareReductionConstruct, D::OMPD_declare_reduction); @@ -92,8 +91,7 @@ struct DirectiveNameScope { } else if constexpr (TupleTrait) { if constexpr (std::is_base_of_v) { return std::get(x.t).DirName(); - } else if constexpr (std::is_same_v || - std::is_same_v || + } else if constexpr (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 39dbeb5e7cfbe..de65088c01eae 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3555,6 +3555,18 @@ struct OmpLocator { WRAPPER_CLASS(OmpLocatorList, std::list); +// Ref: [4.5:58-60], [5.0:58-60], [5.1:63-68], [5.2:197-198], [6.0:334-336] +// +// Argument to DECLARE VARIANT with the base-name present. (When only +// variant-name is present, it is a simple OmpObject). +// +// base-name-variant-name -> // since 4.5 +// base-name : variant-name +struct OmpBaseVariantNames { + TUPLE_CLASS_BOILERPLATE(OmpBaseVariantNames); + std::tuple t; +}; + // Ref: [5.0:326:10-16], [5.1:359:5-11], [5.2:163:2-7], [6.0:293:16-21] // // mapper-specifier -> @@ -3584,6 +3596,7 @@ struct OmpArgument { CharBlock source; UNION_CLASS_BOILERPLATE(OmpArgument); std::variant u; }; @@ -4920,10 +4933,14 @@ struct OpenMPSectionsConstruct { t; }; +// Ref: [4.5:58-60], [5.0:58-60], [5.1:63-68], [5.2:197-198], [6.0:334-336] +// +// declare-variant-directive -> +// DECLARE_VARIANT([base-name:]variant-name) // since 4.5 struct OmpDeclareVariantDirective { - TUPLE_CLASS_BOILERPLATE(OmpDeclareVariantDirective); + WRAPPER_CLASS_BOILERPLATE( + OmpDeclareVariantDirective, OmpDirectiveSpecification); CharBlock source; - std::tuple, Name, OmpClauseList> t; }; // 2.10.6 declare-target -> DECLARE TARGET (extended-list) | diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index 30bc02ce851db..6ec6eb4038933 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -315,15 +315,56 @@ TYPE_PARSER( // construct(Parser{}) || construct(Parser{})) -TYPE_PARSER(sourced( // - construct(Parser{}) || - construct(Parser{}) || - construct(Parser{}))) +TYPE_PARSER(construct( + Parser{} / ":", Parser{})) + +// Make the parsing of OmpArgument directive-sensitive. The issue is that +// name1:name2 can match either OmpBaseVariantNames or OmpReductionSpecifier. +// In the former case, "name2" is a name of a function, in the latter, of a +// type. To resolve the conflict we need information provided by name +// resolution, but by that time we can't modify the AST anymore, and the +// name resolution may have implicitly declared a symbol, or issued a message. +template +struct OmpArgumentParser { + using resultType = OmpArgument; + + std::optional Parse(ParseState &state) const { + constexpr auto parser{sourced(first( // + construct(Parser{}), + // By default, prefer OmpReductionSpecifier over OmpBaseVariantNames. + construct(Parser{}), + construct(Parser{})))}; + return parser.Parse(state); + } +}; + +template <> +struct OmpArgumentParser { + using resultType = OmpArgument; + + std::optional Parse(ParseState &state) const { + constexpr auto parser{sourced(first( // + construct(Parser{}), + // In DECLARE_VARIANT parse OmpBaseVariantNames instead of + // OmpReductionSpecifier. + construct(Parser{}), + construct(Parser{})))}; + return parser.Parse(state); + } +}; TYPE_PARSER(construct(nonemptyList(Parser{}))) -TYPE_PARSER(sourced( // - construct(nonemptyList(Parser{})))) +template +struct OmpArgumentListParser { + using resultType = OmpArgumentList; + + std::optional Parse(ParseState &state) const { + return sourced( + construct(nonemptyList(OmpArgumentParser{}))) + .Parse(state); + } +}; TYPE_PARSER( // construct(Parser{}) || @@ -1312,12 +1353,23 @@ TYPE_PARSER( applyFunction(makeFlushFromOldSyntax, verbatim("FLUSH"_tok) / !lookAhead("("_tok), maybe(Parser{}), - maybe(parenthesized(Parser{})), + maybe(parenthesized( + OmpArgumentListParser{})), pure(OmpDirectiveSpecification::Flags::DeprecatedSyntax)))) || + // Parse DECLARE_VARIANT individually, because the "[base:]variant" + // argument will conflict with DECLARE_REDUCTION's "ident:types...". + predicated(Parser{}, + IsDirective(llvm::omp::Directive::OMPD_declare_variant)) >= + sourced(construct( + sourced(OmpDirectiveNameParser{}), + maybe(parenthesized(OmpArgumentListParser< + llvm::omp::Directive::OMPD_declare_variant>{})), + maybe(Parser{}), + pure(OmpDirectiveSpecification::Flags::None))) || // Parse the standard syntax: directive [(arguments)] [clauses] sourced(construct( // sourced(OmpDirectiveNameParser{}), - maybe(parenthesized(Parser{})), + maybe(parenthesized(OmpArgumentListParser<>{})), maybe(Parser{}), pure(OmpDirectiveSpecification::Flags::None)))) @@ -1711,8 +1763,9 @@ TYPE_PARSER(construct( // OpenMP 5.2: 7.5.4 Declare Variant directive TYPE_PARSER(sourced(construct( - verbatim("DECLARE VARIANT"_tok) || verbatim("DECLARE_VARIANT"_tok), - "(" >> maybe(name / ":"), name / ")", Parser{}))) + predicated(Parser{}, + IsDirective(llvm::omp::Directive::OMPD_declare_variant)) >= + Parser{}))) // 2.16 Declare Reduction Construct TYPE_PARSER(sourced(construct( diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 3455b535ccb51..fc81cfb7a3818 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2089,6 +2089,11 @@ class UnparseVisitor { // OpenMP Clauses & Directives void Unparse(const OmpArgumentList &x) { Walk(x.v, ", "); } + void Unparse(const OmpBaseVariantNames &x) { + Walk(std::get<0>(x.t)); // OmpObject + Put(":"); + Walk(std::get<1>(x.t)); // OmpObject + } void Unparse(const OmpTypeNameList &x) { // Walk(x.v, ","); } @@ -2534,12 +2539,8 @@ class UnparseVisitor { } void Unparse(const OmpDeclareVariantDirective &x) { BeginOpenMP(); - Word("!$OMP DECLARE VARIANT "); - Put("("); - Walk(std::get>(x.t), ":"); - 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 e9bd34d449461..9c624750f0e77 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -634,11 +634,6 @@ template struct DirectiveSpellingVisitor { std::get(x.t).source, Directive::OMPD_declare_target); return false; } - bool Pre(const parser::OmpDeclareVariantDirective &x) { - checker_(std::get(x.t).source, - Directive::OMPD_declare_variant); - return false; - } bool Pre(const parser::OpenMPGroupprivate &x) { checker_(x.v.DirName().source, Directive::OMPD_groupprivate); return false; @@ -1370,9 +1365,50 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &) { } void OmpStructureChecker::Enter(const parser::OmpDeclareVariantDirective &x) { - const auto &dir{std::get(x.t)}; - PushContextAndClauseSets( - dir.source, llvm::omp::Directive::OMPD_declare_variant); + 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_VARIANT directive should have a single argument"_err_en_US); + return; + } + + auto InvalidArgument{[&](parser::CharBlock source) { + context_.Say(source, + "The argument to the DECLARE_VARIANT directive should be [base-name:]variant-name"_err_en_US); + }}; + + auto CheckSymbol{[&](const Symbol *sym, parser::CharBlock source) { + if (sym) { + if (!IsProcedure(*sym) && !IsFunction(*sym)) { + auto &msg{context_.Say(source, + "The name '%s' should refer to a procedure"_err_en_US, + sym->name())}; + if (sym->test(Symbol::Flag::Implicit)) { + msg.Attach(source, "The name '%s' has been implicitly declared"_en_US, + sym->name()); + } + } + } else { + InvalidArgument(source); + } + }}; + + const parser::OmpArgument &arg{args.v.front()}; + common::visit( // + common::visitors{ + [&](const parser::OmpBaseVariantNames &y) { + CheckSymbol(GetObjectSymbol(std::get<0>(y.t)), arg.source); + CheckSymbol(GetObjectSymbol(std::get<1>(y.t)), arg.source); + }, + [&](const parser::OmpLocator &y) { + CheckSymbol(GetArgumentSymbol(arg), arg.source); + }, + [&](auto &&y) { InvalidArgument(arg.source); }, + }, + arg.u); } void OmpStructureChecker::Leave(const parser::OmpDeclareVariantDirective &) { diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index 699cb562da8cc..3a6115dae2da5 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -1540,20 +1540,6 @@ class OmpVisitor : public virtual DeclarationVisitor { bool Pre(const parser::OmpDeclareVariantDirective &x) { AddOmpSourceRange(x.source); - auto FindSymbolOrError = [&](const parser::Name &procName) { - auto *symbol{FindSymbol(NonDerivedTypeScope(), procName)}; - if (!symbol) { - context().Say(procName.source, - "Implicit subroutine declaration '%s' in !$OMP DECLARE VARIANT"_err_en_US, - procName.source); - } - }; - auto &baseProcName = std::get>(x.t); - if (baseProcName) { - FindSymbolOrError(*baseProcName); - } - auto &varProcName = std::get(x.t); - FindSymbolOrError(varProcName); return true; } @@ -1687,16 +1673,19 @@ class OmpVisitor : public virtual DeclarationVisitor { PopScope(); } } + + // These objects are handled explicitly, and the AST traversal should not + // reach a point where it calls the Pre functions for them. bool Pre(const parser::OmpMapperSpecifier &x) { - // 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::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::OmpBaseVariantNames &x) { + 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); @@ -1998,6 +1987,10 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) { ProcessReductionSpecifier(spec, clauses); visitClauses = false; }, + [&](const parser::OmpBaseVariantNames &names) { + Walk(std::get<0>(names.t)); + Walk(std::get<1>(names.t)); + }, [&](const parser::OmpLocator &locator) { // Manually resolve names in CRITICAL directives. This is because // these names do not denote Fortran objects, and the CRITICAL diff --git a/flang/test/Parser/OpenMP/declare-variant.f90 b/flang/test/Parser/OpenMP/declare-variant.f90 index 3366b143e62e6..f5c34abd84ac7 100644 --- a/flang/test/Parser/OpenMP/declare-variant.f90 +++ b/flang/test/Parser/OpenMP/declare-variant.f90 @@ -2,15 +2,19 @@ ! RUN: %flang_fc1 -fdebug-dump-parse-tree-no-sema -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s subroutine sub0 -!CHECK: !$OMP DECLARE VARIANT (sub:vsub) MATCH(CONSTRUCT={PARALLEL}) -!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -!PARSE-TREE: | Verbatim -!PARSE-TREE: | Name = 'sub' -!PARSE-TREE: | Name = 'vsub' +!CHECK: !$OMP DECLARE VARIANT(sub:vsub) MATCH(CONSTRUCT={PARALLEL}) + +!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpBaseVariantNames +!PARSE-TREE: | | OmpObject -> Designator -> DataRef -> Name = 'sub' +!PARSE-TREE: | | OmpObject -> Designator -> DataRef -> Name = 'vsub' !PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector !PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct !PARSE-TREE: | | OmpTraitSelector !PARSE-TREE: | | | OmpTraitSelectorName -> llvm::omp::Directive = parallel +!PARSE-TREE: | Flags = None + !$omp declare variant (sub:vsub) match (construct={parallel}) contains subroutine vsub @@ -30,14 +34,17 @@ subroutine vsub (v1) integer, value :: v1 end subroutine sub (v1) -!CHECK: !$OMP DECLARE VARIANT (vsub) MATCH(CONSTRUCT={DISPATCH} -!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -!PARSE-TREE: | Verbatim -!PARSE-TREE: | Name = 'vsub' +!CHECK: !$OMP DECLARE VARIANT(vsub) MATCH(CONSTRUCT={DISPATCH}) + +!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'vsub' !PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector !PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct !PARSE-TREE: | | OmpTraitSelector !PARSE-TREE: | | | OmpTraitSelectorName -> llvm::omp::Directive = dispatch +!PARSE-TREE: | Flags = None + !$omp declare variant(vsub), match(construct={dispatch}) integer, value :: v1 end @@ -56,17 +63,20 @@ subroutine vsub (v1, a1, a2) integer(omp_interop_kind), value :: a2 end subroutine sub (v1) -!CHECK: !$OMP DECLARE VARIANT (vsub) MATCH(CONSTRUCT={DISPATCH}) APPEND_ARGS(INTEROP(T& -!CHECK: !$OMP&ARGET),INTEROP(TARGET)) -!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -!PARSE-TREE: | Verbatim -!PARSE-TREE: | Name = 'vsub' +!CHECK: !$OMP DECLARE VARIANT(vsub) MATCH(CONSTRUCT={DISPATCH}) APPEND_ARGS(INTEROP(TA& +!CHECK: !$OMP&RGET),INTEROP(TARGET)) + +!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'vsub' !PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector !PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct !PARSE-TREE: | | OmpTraitSelector !PARSE-TREE: | | | OmpTraitSelectorName -> llvm::omp::Directive = dispatch !PARSE-TREE: | OmpClause -> AppendArgs -> OmpAppendArgsClause -> OmpAppendOp -> OmpInteropType -> Value = Target !PARSE-TREE: | OmpAppendOp -> OmpInteropType -> Value = Target +!PARSE-TREE: | Flags = None + !$omp declare variant(vsub), match(construct={dispatch}), append_args (interop(target), interop(target)) integer, value :: v1 end @@ -81,11 +91,12 @@ subroutine sb3 (x1, x2) contains subroutine sub (v1, v2) type(c_ptr), value :: v1, v2 -!CHECK: !$OMP DECLARE VARIANT (vsub) MATCH(CONSTRUCT={DISPATCH}) ADJUST_ARGS(NOTHING:v& -!CHECK: !$OMP&1) ADJUST_ARGS(NEED_DEVICE_PTR:v2) -!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -!PARSE-TREE: | Verbatim -!PARSE-TREE: | Name = 'vsub' +!CHECK: !$OMP DECLARE VARIANT(vsub) MATCH(CONSTRUCT={DISPATCH}) ADJUST_ARGS(NOTHING:v1& +!CHECK: !$OMP&) ADJUST_ARGS(NEED_DEVICE_PTR:v2) + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'vsub' !PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector !PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct !PARSE-TREE: | | OmpTraitSelector @@ -96,6 +107,8 @@ subroutine sub (v1, v2) !PARSE-TREE: | OmpClause -> AdjustArgs -> OmpAdjustArgsClause !PARSE-TREE: | | OmpAdjustOp -> Value = Need_Device_Ptr !PARSE-TREE: | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'v2' +!PARSE-TREE: | Flags = None + !$omp declare variant(vsub) match ( construct = { dispatch } ) adjust_args(nothing : v1 ) adjust_args(need_device_ptr : v2) end subroutine vsub(v1, v2) @@ -119,13 +132,15 @@ subroutine f2 (x, y) !$omp declare variant (f1) match (construct={simd(uniform(y))}) end end subroutine -!CHECK: !$OMP DECLARE VARIANT (f1) MATCH(CONSTRUCT={SIMD(UNIFORM(y))}) -!PARSE-TREE: | | | | DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -!PARSE-TREE-NEXT: | | | | | Verbatim -!PARSE-TREE-NEXT: | | | | | Name = 'f1' -!PARSE-TREE-NEXT: | | | | | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector -!PARSE-TREE-NEXT: | | | | | | OmpTraitSetSelectorName -> Value = Construct -!PARSE-TREE-NEXT: | | | | | | OmpTraitSelector -!PARSE-TREE-NEXT: | | | | | | | OmpTraitSelectorName -> Value = Simd -!PARSE-TREE-NEXT: | | | | | | | Properties -!PARSE-TREE-NEXT: | | | | | | | | OmpTraitProperty -> OmpClause -> Uniform -> Name = 'y' +!CHECK: !$OMP DECLARE VARIANT(f1) MATCH(CONSTRUCT={SIMD(UNIFORM(y))}) + +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'f1' +!PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector +!PARSE-TREE: | | OmpTraitSetSelectorName -> Value = Construct +!PARSE-TREE: | | OmpTraitSelector +!PARSE-TREE: | | | OmpTraitSelectorName -> Value = Simd +!PARSE-TREE: | | | Properties +!PARSE-TREE: | | | | OmpTraitProperty -> OmpClause -> Uniform -> Name = 'y' +!PARSE-TREE: | Flags = None diff --git a/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 b/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 index a25d750adc39d..f55ff958b0952 100644 --- a/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 +++ b/flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 @@ -145,12 +145,12 @@ subroutine g05 !UNPARSE: SUBROUTINE g05 !UNPARSE: END SUBROUTINE !UNPARSE: END INTERFACE -!UNPARSE: !$OMP DECLARE VARIANT (g05) MATCH(USER={CONDITION(.true._4)}) +!UNPARSE: !$OMP DECLARE_VARIANT(g05) MATCH(USER={CONDITION(.true._4)}) !UNPARSE: END SUBROUTINE -!PARSE-TREE: OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -!PARSE-TREE: | Verbatim -!PARSE-TREE: | Name = 'g05' +!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OmpDeclareVariantDirective -> OmpDirectiveSpecification +!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare variant +!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpLocator -> OmpObject -> Designator -> DataRef -> Name = 'g05' !PARSE-TREE: | OmpClauseList -> OmpClause -> Match -> OmpMatchClause -> OmpContextSelectorSpecification -> OmpTraitSetSelector !PARSE-TREE: | | OmpTraitSetSelectorName -> Value = User !PARSE-TREE: | | OmpTraitSelector @@ -159,6 +159,7 @@ subroutine g05 !PARSE-TREE: | | | | OmpTraitProperty -> Scalar -> Expr = '.true._4' !PARSE-TREE: | | | | | LiteralConstant -> LogicalLiteralConstant !PARSE-TREE: | | | | | | bool = 'true' +!PARSE-TREE: | Flags = None subroutine f06 implicit none diff --git a/flang/test/Semantics/OpenMP/declare-variant.f90 b/flang/test/Semantics/OpenMP/declare-variant.f90 index 84a0cdcd10d91..6fc94a4fb837f 100644 --- a/flang/test/Semantics/OpenMP/declare-variant.f90 +++ b/flang/test/Semantics/OpenMP/declare-variant.f90 @@ -1,9 +1,9 @@ ! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=51 subroutine sub0 -!ERROR: Implicit subroutine declaration 'vsub1' in !$OMP DECLARE VARIANT +!ERROR: The name 'vsub1' should refer to a procedure !$omp declare variant (sub:vsub1) match (construct={parallel}) -!ERROR: Implicit subroutine declaration 'sub1' in !$OMP DECLARE VARIANT +!ERROR: The name 'sub1' should refer to a procedure !$omp declare variant (sub1:vsub) match (construct={parallel}) contains subroutine vsub