diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index c7143fd41041..998fae657a4d 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -812,10 +812,13 @@ static ExprResult parseContextScore(Parser &P) { } /// Parse context selector for 'implementation' selector set: -/// 'vendor' '(' ')' -static void -parseImplementationSelector(Parser &P, - Sema::OpenMPDeclareVariantCtsSelectorData &Data) { +/// 'vendor' '(' [ 'score' '(' ')' ':' ] { ',' } +/// ')' +static void parseImplementationSelector( + Parser &P, SourceLocation Loc, + llvm::function_ref + Callback) { const Token &Tok = P.getCurToken(); // Parse inner context selector set name, if any. if (!Tok.is(tok::identifier)) { @@ -840,20 +843,33 @@ parseImplementationSelector(Parser &P, BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); (void)T.expectAndConsume(diag::err_expected_lparen_after, CtxSelectorName.data()); - Data.CtxScore = parseContextScore(P); - // Parse . - StringRef VendorName; - if (Tok.is(tok::identifier)) { - VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); - (void)P.ConsumeToken(); - } else { - P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected) - << "vendor identifier" << "vendor" << "implementation"; - } + const ExprResult Score = parseContextScore(P); + do { + // Parse . + StringRef VendorName; + if (Tok.is(tok::identifier)) { + Buffer.clear(); + VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); + (void)P.ConsumeToken(); + } else { + P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected) + << "vendor identifier" + << "vendor" + << "implementation"; + } + if (!VendorName.empty()) { + Sema::OpenMPDeclareVariantCtsSelectorData Data( + OMPDeclareVariantAttr::CtxSetImplementation, CSKind, VendorName, + Score); + Callback(SourceRange(Loc, Tok.getLocation()), Data); + } + if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) { + P.Diag(Tok, diag::err_expected_punc) + << (VendorName.empty() ? "vendor name" : VendorName); + } + } while (Tok.is(tok::identifier)); // Parse ')'. (void)T.consumeClose(); - if (!VendorName.empty()) - Data.ImplVendor = VendorName; break; } case OMPDeclareVariantAttr::CtxUnknown: @@ -865,8 +881,6 @@ parseImplementationSelector(Parser &P, ; return; } - Data.CtxSet = OMPDeclareVariantAttr::CtxSetImplementation; - Data.Ctx = CSKind; } /// Parses clauses for 'declare variant' directive. @@ -897,7 +911,6 @@ bool Parser::parseOpenMPContextSelectors( (void)ConsumeToken(); // TBD: add parsing of known context selectors. // Unknown selector - just ignore it completely. - Sema::OpenMPDeclareVariantCtsSelectorData Data; { // Parse '{'. BalancedDelimiterTracker TBr(*this, tok::l_brace, @@ -910,7 +923,7 @@ bool Parser::parseOpenMPContextSelectors( CtxSelectorSetName, CSSKind); switch (CSSKind) { case OMPDeclareVariantAttr::CtxSetImplementation: - parseImplementationSelector(*this, Data); + parseImplementationSelector(*this, Loc, Callback); break; case OMPDeclareVariantAttr::CtxSetUnknown: // Skip until either '}', ')', or end of directive. @@ -922,7 +935,6 @@ bool Parser::parseOpenMPContextSelectors( // Parse '}'. (void)TBr.consumeClose(); } - Callback(SourceRange(Loc, Tok.getLocation()), Data); // Consume ',' if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) (void)ExpectAndConsume(tok::comma); diff --git a/clang/test/OpenMP/declare_variant_ast_print.c b/clang/test/OpenMP/declare_variant_ast_print.c index ad1ef91eca14..07e55a9070aa 100644 --- a/clang/test/OpenMP/declare_variant_ast_print.c +++ b/clang/test/OpenMP/declare_variant_ast_print.c @@ -10,11 +10,12 @@ int foo(void); #pragma omp declare variant(foo) match(xxx={vvv}) #pragma omp declare variant(foo) match(implementation={vendor(ibm)}, implementation={vendor(llvm)}) #pragma omp declare variant(foo) match(implementation={vendor(unknown)}) -#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm)}) +#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm, xxx)}) int bar(void); // CHECK: int foo(); // CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(5):ibm)}) +// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(5):xxx)}) // CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(unknown)}) // CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(ibm)}) // CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(llvm)}) diff --git a/clang/test/OpenMP/declare_variant_ast_print.cpp b/clang/test/OpenMP/declare_variant_ast_print.cpp index 77f03f518552..c79b6b8da102 100644 --- a/clang/test/OpenMP/declare_variant_ast_print.cpp +++ b/clang/test/OpenMP/declare_variant_ast_print.cpp @@ -30,6 +30,7 @@ T foofoo() { return T(); } int bar(); // CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(C + 5):ibm)}) +// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(C + 5):xxx)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(ibm)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(llvm)}) @@ -42,11 +43,12 @@ int bar(); #pragma omp declare variant(foofoo ) match(user = {condition()}) #pragma omp declare variant(foofoo ) match(implementation={vendor(ibm)}, implementation={vendor(llvm)}) #pragma omp declare variant(foofoo ) match(implementation={vendor(unknown)}) -#pragma omp declare variant(foofoo ) match(implementation={vendor(score(C+5): ibm)}) +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(C+5): ibm, xxx)}) template T barbar(); // CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(3 + 5):ibm)}) +// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(3 + 5):xxx)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(ibm)}) // CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(llvm)}) diff --git a/clang/test/OpenMP/declare_variant_messages.c b/clang/test/OpenMP/declare_variant_messages.c index 7e69cec1f1b0..e8fed318f69a 100644 --- a/clang/test/OpenMP/declare_variant_messages.c +++ b/clang/test/OpenMP/declare_variant_messages.c @@ -27,12 +27,12 @@ int foo(void); #pragma omp declare variant(foo) match(xxx={vvv} xxx) // expected-error {{expected ','}} expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} #pragma omp declare variant(foo) match(xxx={vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}} #pragma omp declare variant(foo) match(implementation={xxx}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}} -#pragma omp declare variant(foo) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma omp declare variant(foo) match(implementation={vendor(}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(implementation={vendor(}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp declare variant(foo) match(implementation={vendor()}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} #pragma omp declare variant(foo) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}} -#pragma omp declare variant(foo) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} -#pragma omp declare variant(foo) match(implementation={vendor(score(2 ibm)}) // expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} +#pragma omp declare variant(foo) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(implementation={vendor(score(2 ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} #pragma omp declare variant(foo) match(implementation={vendor(score(foo()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integer constant expression}} #pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm)}) int bar(void); diff --git a/clang/test/OpenMP/declare_variant_messages.cpp b/clang/test/OpenMP/declare_variant_messages.cpp index 88e724d12470..aee5544bf293 100644 --- a/clang/test/OpenMP/declare_variant_messages.cpp +++ b/clang/test/OpenMP/declare_variant_messages.cpp @@ -30,12 +30,12 @@ T foofoo(); // expected-note 2 {{declared here}} #pragma omp declare variant(foofoo ) match(xxx = {vvv} xxx) // expected-error {{expected ','}} expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} #pragma omp declare variant(foofoo ) match(xxx = {vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}} #pragma omp declare variant(foofoo ) match(implementation={xxx}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}} -#pragma omp declare variant(foofoo ) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma omp declare variant(foofoo ) match(implementation={vendor(}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor}) // expected-error {{expected '(' after 'vendor'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp declare variant(foofoo ) match(implementation={vendor()}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} #pragma omp declare variant(foofoo ) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}} -#pragma omp declare variant(foofoo ) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} -#pragma omp declare variant(foofoo ) match(implementation={vendor(score(2 ibm)}) // expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(2 ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} #pragma omp declare variant(foofoo ) match(implementation={vendor(score(foofoo ()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integral constant expression}} expected-note {{non-constexpr function 'foofoo' cannot be used in a constant expression}} #pragma omp declare variant(foofoo ) match(implementation={vendor(score(5): ibm)}) int bar(); @@ -63,8 +63,8 @@ int bar(); #pragma omp declare variant(foofoo ) match(xxx = {vvv} xxx) // expected-error {{expected ','}} expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} #pragma omp declare variant(foofoo ) match(xxx = {vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}} #pragma omp declare variant(foofoo ) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{missing ':' after context selector score clause - ignoring}} -#pragma omp declare variant(foofoo ) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} -#pragma omp declare variant(foofoo ) match(implementation={vendor(score(C ibm)}) // expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score( ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error {{expected ')'}} expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(C ibm)}) // expected-error {{expected ')' or ',' after 'vendor name'}} expected-error 2 {{expected ')'}} expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}} expected-warning {{missing ':' after context selector score clause - ignoring}} expected-note 2 {{to match this '('}} #pragma omp declare variant(foofoo ) match(implementation={vendor(score(foofoo ()) ibm)}) // expected-warning {{missing ':' after context selector score clause - ignoring}} expected-error {{expression is not an integral constant expression}} expected-note {{non-constexpr function 'foofoo' cannot be used in a constant expression}} #pragma omp declare variant(foofoo ) match(implementation={vendor(score(C+5): ibm)}) template