summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2019-09-18 16:24:31 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2019-09-18 16:24:31 +0000
commitb54c5533a96089475662f89385f24b48a902b585 (patch)
tree30e57c2f9e1fb6a64f348a065aa9abb6026c56a0
parentf4160840d55986b582d7d4da610d122a3f9bba10 (diff)
downloadclang-b54c5533a96089475662f89385f24b48a902b585.tar.gz
[OPENMP5.0]Allow multiple context selectors in the context selector
sets. According to OpenMP 5.0, context selector set might include several context selectors, separated with commas. Patch fixes this problem. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@372235 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Parse/Parser.h11
-rw-r--r--include/clang/Sema/Sema.h19
-rw-r--r--lib/Parse/ParseOpenMP.cpp153
-rw-r--r--lib/Sema/SemaOpenMP.cpp63
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp12
-rw-r--r--test/OpenMP/declare_variant_ast_print.c3
-rw-r--r--test/OpenMP/declare_variant_ast_print.cpp4
-rw-r--r--test/OpenMP/declare_variant_messages.c12
-rw-r--r--test/OpenMP/declare_variant_messages.cpp20
9 files changed, 172 insertions, 125 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 5c0a831db6..d80ece998d 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -2834,10 +2834,15 @@ private:
DeclGroupPtrTy ParseOMPDeclareSimdClauses(DeclGroupPtrTy Ptr,
CachedTokens &Toks,
SourceLocation Loc);
+ /// Parses OpenMP context selectors and calls \p Callback for each
+ /// successfully parsed context selector.
+ bool
+ parseOpenMPContextSelectors(SourceLocation Loc,
+ llvm::function_ref<void(SourceRange)> Callback);
+
/// Parse clauses for '#pragma omp declare variant'.
- DeclGroupPtrTy ParseOMPDeclareVariantClauses(DeclGroupPtrTy Ptr,
- CachedTokens &Toks,
- SourceLocation Loc);
+ void ParseOMPDeclareVariantClauses(DeclGroupPtrTy Ptr, CachedTokens &Toks,
+ SourceLocation Loc);
/// Parse clauses for '#pragma omp declare target'.
DeclGroupPtrTy ParseOMPDeclareTargetClauses();
/// Parse '#pragma omp end declare target'.
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index c7f15f38df..7faea280b7 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -9529,15 +9529,26 @@ public:
ArrayRef<Expr *> Alignments, ArrayRef<Expr *> Linears,
ArrayRef<unsigned> LinModifiers, ArrayRef<Expr *> Steps, SourceRange SR);
+ /// Checks '\#pragma omp declare variant' variant function and original
+ /// functions after parsing of the associated method/function.
+ /// \param DG Function declaration to which declare variant directive is
+ /// applied to.
+ /// \param VariantRef Expression that references the variant function, which
+ /// must be used instead of the original one, specified in \p DG.
+ /// \returns None, if the function/variant function are not compatible with
+ /// the pragma,pair of original function/variant ref expression otherwise.
+ Optional<std::pair<FunctionDecl *, Expr *>>
+ checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef,
+ SourceRange SR);
+
/// Called on well-formed '\#pragma omp declare variant' after parsing of
/// the associated method/function.
- /// \param DG Function declaration to which declare variant directive is
+ /// \param FD Function declaration to which declare variant directive is
/// applied to.
/// \param VariantRef Expression that references the variant function, which
/// must be used instead of the original one, specified in \p DG.
- DeclGroupPtrTy ActOnOpenMPDeclareVariantDirective(DeclGroupPtrTy DG,
- Expr *VariantRef,
- SourceRange SR);
+ void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef,
+ SourceRange SR);
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,
diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp
index 293660ec4c..8d852b5dcb 100644
--- a/lib/Parse/ParseOpenMP.cpp
+++ b/lib/Parse/ParseOpenMP.cpp
@@ -788,65 +788,53 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
/// Parses clauses for 'declare variant' directive.
/// clause:
-/// 'match' '('
/// <selector_set_name> '=' '{' <context_selectors> '}'
-/// ')'
-static bool parseDeclareVariantClause(Parser &P) {
- Token Tok = P.getCurToken();
- // Parse 'match'.
- if (!Tok.is(tok::identifier) ||
- P.getPreprocessor().getSpelling(Tok).compare("match")) {
- P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
- << "match";
- while (!P.SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
- ;
- return true;
- }
- (void)P.ConsumeToken();
- // Parse '('.
- BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after, "match"))
- return true;
- // Parse inner context selector.
- Tok = P.getCurToken();
- if (!Tok.is(tok::identifier)) {
- P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector)
- << "match";
- return true;
- }
- SmallString<16> Buffer;
- StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
- // Parse '='.
- (void)P.ConsumeToken();
- Tok = P.getCurToken();
- if (Tok.isNot(tok::equal)) {
- P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
- << CtxSelectorName;
- return true;
- }
- (void)P.ConsumeToken();
- // Unknown selector - just ignore it completely.
- {
- // Parse '{'.
- BalancedDelimiterTracker TBr(P, tok::l_brace, tok::annot_pragma_openmp_end);
- if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
+/// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ]
+bool Parser::parseOpenMPContextSelectors(
+ SourceLocation Loc, llvm::function_ref<void(SourceRange)> Callback) {
+ do {
+ // Parse inner context selector set name.
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector)
+ << "match";
return true;
- while (!P.SkipUntil(tok::r_brace, tok::r_paren,
- tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
- ;
- // Parse '}'.
- (void)TBr.consumeClose();
- }
- // Parse ')'.
- (void)T.consumeClose();
- // TBD: add parsing of known context selectors.
+ }
+ SmallString<16> Buffer;
+ StringRef CtxSelectorName = PP.getSpelling(Tok, Buffer);
+ // Parse '='.
+ (void)ConsumeToken();
+ if (Tok.isNot(tok::equal)) {
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
+ << CtxSelectorName;
+ return true;
+ }
+ (void)ConsumeToken();
+ // TBD: add parsing of known context selectors.
+ // Unknown selector - just ignore it completely.
+ {
+ // Parse '{'.
+ BalancedDelimiterTracker TBr(*this, tok::l_brace,
+ tok::annot_pragma_openmp_end);
+ if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
+ return true;
+ while (!SkipUntil(tok::r_brace, tok::r_paren,
+ tok::annot_pragma_openmp_end, StopBeforeMatch))
+ ;
+ // Parse '}'.
+ (void)TBr.consumeClose();
+ }
+ Callback(SourceRange(Loc, Tok.getLocation()));
+ // Consume ','
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end))
+ (void)ExpectAndConsume(tok::comma);
+ } while (Tok.isAnyIdentifier());
return false;
}
/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
-Parser::DeclGroupPtrTy
-Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
- CachedTokens &Toks, SourceLocation Loc) {
+void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
+ CachedTokens &Toks,
+ SourceLocation Loc) {
PP.EnterToken(Tok, /*IsReinject*/ true);
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
/*IsReinject*/ true);
@@ -868,23 +856,53 @@ Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
;
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
- return Ptr;
+ return;
}
+ Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
+ Actions.checkOpenMPDeclareVariantFunction(
+ Ptr, AssociatedFunction.get(), SourceRange(Loc, Tok.getLocation()));
- bool IsError = parseDeclareVariantClause(*this);
- // Need to check for extra tokens.
- if (Tok.isNot(tok::annot_pragma_openmp_end)) {
- Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
- << getOpenMPDirectiveName(OMPD_declare_variant);
- while (Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
+ // Parse 'match'.
+ if (!Tok.is(tok::identifier) || PP.getSpelling(Tok).compare("match")) {
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
+ << "match";
+ while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
+ return;
+ }
+ (void)ConsumeToken();
+ // Parse '('.
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after, "match")) {
+ while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
+ ;
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
+ return;
+ }
+
+ // Parse inner context selectors.
+ if (!parseOpenMPContextSelectors(Loc, [this, &DeclVarData](SourceRange SR) {
+ if (DeclVarData.hasValue())
+ Actions.ActOnOpenMPDeclareVariantDirective(
+ DeclVarData.getValue().first, DeclVarData.getValue().second, SR);
+ })) {
+ // Parse ')'.
+ (void)T.consumeClose();
+ // Need to check for extra tokens.
+ if (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
+ << getOpenMPDirectiveName(OMPD_declare_variant);
+ }
}
+
+ // Skip last tokens.
+ while (Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
// Skip the last annot_pragma_openmp_end.
- SourceLocation EndLoc = ConsumeAnnotationToken();
- if (IsError)
- return Ptr;
- return Actions.ActOnOpenMPDeclareVariantDirective(
- Ptr, AssociatedFunction.get(), SourceRange(Loc, EndLoc));
+ (void)ConsumeAnnotationToken();
}
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
@@ -1248,7 +1266,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
assert(DKind == OMPD_declare_variant &&
"Expected declare variant directive only");
- return ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
+ ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
+ return Ptr;
}
case OMPD_declare_target: {
SourceLocation DTLoc = ConsumeAnyToken();
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index cd343bd13d..6f788fbb86 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -4892,18 +4892,18 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPDeclareSimdDirective(
return DG;
}
-Sema::DeclGroupPtrTy
-Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
- Expr *VariantRef, SourceRange SR) {
+Optional<std::pair<FunctionDecl *, Expr *>>
+Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
+ Expr *VariantRef, SourceRange SR) {
if (!DG || DG.get().isNull())
- return DeclGroupPtrTy();
+ return None;
const int VariantId = 1;
// Must be applied only to single decl.
if (!DG.get().isSingleDecl()) {
Diag(SR.getBegin(), diag::err_omp_single_decl_in_declare_simd_variant)
<< VariantId << SR;
- return DG;
+ return None;
}
Decl *ADecl = DG.get().getSingleDecl();
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(ADecl))
@@ -4914,7 +4914,7 @@ Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
if (!FD) {
Diag(ADecl->getLocation(), diag::err_omp_function_expected)
<< VariantId << SR;
- return DeclGroupPtrTy();
+ return None;
}
auto &&HasMultiVersionAttributes = [](const FunctionDecl *FD) {
@@ -4926,31 +4926,27 @@ Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
if (HasMultiVersionAttributes(FD)) {
Diag(FD->getLocation(), diag::err_omp_declare_variant_incompat_attributes)
<< SR;
- return DG;
+ return None;
}
// Allow #pragma omp declare variant only if the function is not used.
if (FD->isUsed(false)) {
Diag(SR.getBegin(), diag::err_omp_declare_variant_after_used)
<< FD->getLocation();
- return DG;
+ return None;
}
// The VariantRef must point to function.
if (!VariantRef) {
Diag(SR.getBegin(), diag::err_omp_function_expected) << VariantId;
- return DG;
+ return None;
}
// Do not check templates, wait until instantiation.
if (VariantRef->isTypeDependent() || VariantRef->isValueDependent() ||
VariantRef->containsUnexpandedParameterPack() ||
- VariantRef->isInstantiationDependent() || FD->isDependentContext()) {
- auto *NewAttr =
- OMPDeclareVariantAttr::CreateImplicit(Context, VariantRef, SR);
- FD->addAttr(NewAttr);
- return DG;
- }
+ VariantRef->isInstantiationDependent() || FD->isDependentContext())
+ return std::make_pair(FD, VariantRef);
// Convert VariantRef expression to the type of the original function to
// resolve possible conflicts.
@@ -4973,7 +4969,7 @@ Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
if (!ER.isUsable()) {
Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
<< VariantId << VariantRef->getSourceRange();
- return DG;
+ return None;
}
VariantRef = ER.get();
} else {
@@ -4990,12 +4986,12 @@ Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
Diag(VariantRef->getExprLoc(),
diag::err_omp_declare_variant_incompat_types)
<< VariantRef->getType() << FnPtrType << VariantRef->getSourceRange();
- return DG;
+ return None;
}
VariantRefCast = PerformImplicitConversion(
VariantRef, FnPtrType.getUnqualifiedType(), AA_Converting);
if (!VariantRefCast.isUsable())
- return DG;
+ return None;
// Drop previously built artificial addr_of unary op for member functions.
if (Method && !Method->isStatic()) {
Expr *PossibleAddrOfVariantRef = VariantRefCast.get();
@@ -5012,7 +5008,7 @@ Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
!ER.get()->IgnoreParenImpCasts()->getType()->isFunctionType()) {
Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
<< VariantId << VariantRef->getSourceRange();
- return DG;
+ return None;
}
// The VariantRef must point to function.
@@ -5020,13 +5016,13 @@ Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
if (!DRE) {
Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
<< VariantId << VariantRef->getSourceRange();
- return DG;
+ return None;
}
auto *NewFD = dyn_cast_or_null<FunctionDecl>(DRE->getDecl());
if (!NewFD) {
Diag(VariantRef->getExprLoc(), diag::err_omp_function_expected)
<< VariantId << VariantRef->getSourceRange();
- return DG;
+ return None;
}
// Check if variant function is not marked with declare variant directive.
@@ -5037,7 +5033,7 @@ Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
SourceRange SR =
NewFD->specific_attr_begin<OMPDeclareVariantAttr>()->getRange();
Diag(SR.getBegin(), diag::note_omp_marked_declare_variant_here) << SR;
- return DG;
+ return None;
}
enum DoesntSupport {
@@ -5053,38 +5049,38 @@ Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
if (CXXFD->isVirtual()) {
Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
<< VirtFuncs;
- return DG;
+ return None;
}
if (isa<CXXConstructorDecl>(FD)) {
Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
<< Constructors;
- return DG;
+ return None;
}
if (isa<CXXDestructorDecl>(FD)) {
Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
<< Destructors;
- return DG;
+ return None;
}
}
if (FD->isDeleted()) {
Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
<< DeletedFuncs;
- return DG;
+ return None;
}
if (FD->isDefaulted()) {
Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
<< DefaultedFuncs;
- return DG;
+ return None;
}
if (FD->isConstexpr()) {
Diag(FD->getLocation(), diag::err_omp_declare_variant_doesnt_support)
<< (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs);
- return DG;
+ return None;
}
// Check general compatibility.
@@ -5100,11 +5096,16 @@ Sema::ActOnOpenMPDeclareVariantDirective(Sema::DeclGroupPtrTy DG,
PDiag(diag::err_omp_declare_variant_diff)
<< FD->getLocation()),
/*TemplatesSupported=*/true, /*ConstexprSupported=*/false))
- return DG;
+ return None;
+ return std::make_pair(FD, cast<Expr>(DRE));
+}
- auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(Context, DRE, SR);
+void Sema::ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD,
+ Expr *VariantRef,
+ SourceRange SR) {
+ auto *NewAttr =
+ OMPDeclareVariantAttr::CreateImplicit(Context, VariantRef, SR);
FD->addAttr(NewAttr);
- return DG;
}
void Sema::markOpenMPDeclareVariantFuncsReferenced(SourceLocation Loc,
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 6585917925..5338242d25 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -388,8 +388,16 @@ static void instantiateOMPDeclareVariantAttr(
if (Expr *E = Attr.getVariantFuncRef())
VariantFuncRef = Subst(E);
- (void)S.ActOnOpenMPDeclareVariantDirective(
- S.ConvertDeclToDeclGroup(New), VariantFuncRef.get(), Attr.getRange());
+ // Check function/variant ref.
+ Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
+ S.checkOpenMPDeclareVariantFunction(
+ S.ConvertDeclToDeclGroup(New), VariantFuncRef.get(), Attr.getRange());
+ if (!DeclVarData)
+ return;
+ // Instantiate the attribute.
+ S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first,
+ DeclVarData.getValue().second,
+ Attr.getRange());
}
static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr(
diff --git a/test/OpenMP/declare_variant_ast_print.c b/test/OpenMP/declare_variant_ast_print.c
index e1632bc800..eb30095726 100644
--- a/test/OpenMP/declare_variant_ast_print.c
+++ b/test/OpenMP/declare_variant_ast_print.c
@@ -6,11 +6,12 @@
int foo(void);
-#pragma omp declare variant(foo) match(xxx={})
+#pragma omp declare variant(foo) match(xxx={}, yyy={ccc})
#pragma omp declare variant(foo) match(xxx={vvv})
int bar(void);
// CHECK: int foo();
// CHECK-NEXT: #pragma omp declare variant(foo) match(unknown={})
// CHECK-NEXT: #pragma omp declare variant(foo) match(unknown={})
+// CHECK-NEXT: #pragma omp declare variant(foo) match(unknown={})
// CHECK-NEXT: int bar();
diff --git a/test/OpenMP/declare_variant_ast_print.cpp b/test/OpenMP/declare_variant_ast_print.cpp
index b4b515d6b7..c22ca2b8a3 100644
--- a/test/OpenMP/declare_variant_ast_print.cpp
+++ b/test/OpenMP/declare_variant_ast_print.cpp
@@ -30,11 +30,12 @@ int bar();
// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(unknown={})
// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(unknown={})
// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(unknown={})
+// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(unknown={})
// CHECK-NEXT: template <typename T> T barbar();
#pragma omp declare variant(foofoo <T>) match(xxx = {})
#pragma omp declare variant(foofoo <T>) match(xxx = {vvv})
#pragma omp declare variant(foofoo <T>) match(user = {score(<expr>) : condition(<expr>)})
-#pragma omp declare variant(foofoo <T>) match(user = {score(<expr>) : condition(<expr>)})
+#pragma omp declare variant(foofoo <T>) match(user = {score(<expr>) : condition(<expr>)}, user = {condition(<expr>)})
#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)})
#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)})
template <typename T>
@@ -46,6 +47,7 @@ T barbar();
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(unknown={})
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(unknown={})
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(unknown={})
+// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(unknown={})
// CHECK-NEXT: template<> int barbar<int>();
// CHECK-NEXT: int baz() {
diff --git a/test/OpenMP/declare_variant_messages.c b/test/OpenMP/declare_variant_messages.c
index 93023fdd1f..13d5e6c1ed 100644
--- a/test/OpenMP/declare_variant_messages.c
+++ b/test/OpenMP/declare_variant_messages.c
@@ -16,15 +16,15 @@ int foo(void);
#pragma omp declare variant(foo) xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foo) match // expected-error {{expected '(' after 'match'}}
#pragma omp declare variant(foo) match( // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}}
-#pragma omp declare variant(foo) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
-#pragma omp declare variant(foo) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}}
-#pragma omp declare variant(foo) match(xxx=) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
-#pragma omp declare variant(foo) match(xxx=yyy) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
-#pragma omp declare variant(foo) match(xxx=yyy}) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foo) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foo) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}}
+#pragma omp declare variant(foo) match(xxx=) // expected-error {{expected '{' after '='}}
+#pragma omp declare variant(foo) match(xxx=yyy) // expected-error {{expected '{' after '='}}
+#pragma omp declare variant(foo) match(xxx=yyy}) // expected-error {{expected '{' after '='}}
#pragma omp declare variant(foo) match(xxx={) // expected-error {{expected '}'}} expected-note {{to match this '{'}}
#pragma omp declare variant(foo) match(xxx={})
#pragma omp declare variant(foo) match(xxx={vvv})
-#pragma omp declare variant(foo) match(xxx={vvv} xxx) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#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}}
int bar(void);
diff --git a/test/OpenMP/declare_variant_messages.cpp b/test/OpenMP/declare_variant_messages.cpp
index 42427ea184..89ec84356d 100644
--- a/test/OpenMP/declare_variant_messages.cpp
+++ b/test/OpenMP/declare_variant_messages.cpp
@@ -19,15 +19,15 @@ T foofoo();
#pragma omp declare variant(foofoo <int>) xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foofoo <int>) match // expected-error {{expected '(' after 'match'}}
#pragma omp declare variant(foofoo <int>) match( // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}}
-#pragma omp declare variant(foofoo <int>) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
-#pragma omp declare variant(foofoo <int>) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}}
-#pragma omp declare variant(foofoo <int>) match(xxx =) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
-#pragma omp declare variant(foofoo <int>) match(xxx = yyy) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
-#pragma omp declare variant(foofoo <int>) match(xxx = yyy }) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foofoo <int>) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <int>) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <int>) match(xxx =) // expected-error {{expected '{' after '='}}
+#pragma omp declare variant(foofoo <int>) match(xxx = yyy) // expected-error {{expected '{' after '='}}
+#pragma omp declare variant(foofoo <int>) match(xxx = yyy }) // expected-error {{expected '{' after '='}}
#pragma omp declare variant(foofoo <int>) match(xxx = {) // expected-error {{expected '}'}} expected-note {{to match this '{'}}
#pragma omp declare variant(foofoo <int>) match(xxx = {})
#pragma omp declare variant(foofoo <int>) match(xxx = {vvv})
-#pragma omp declare variant(foofoo <int>) match(xxx = {vvv} xxx) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp declare variant(foofoo <int>) 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 <int>) match(xxx = {vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
int bar();
@@ -41,9 +41,9 @@ int bar();
#pragma omp declare variant(foofoo <T>) xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foofoo <T>) match // expected-error {{expected '(' after 'match'}}
#pragma omp declare variant(foofoo <T>) match( // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}}
-#pragma omp declare variant(foofoo <T>) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
-#pragma omp declare variant(foofoo <T>) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}}
-#pragma omp declare variant(foofoo <T>) match(xxx =) // expected-error {{expected '{' after '='}} expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
+#pragma omp declare variant(foofoo <T>) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <T>) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}}
+#pragma omp declare variant(foofoo <T>) match(xxx =) // expected-error {{expected '{' after '='}}
#pragma omp declare variant(foofoo <T>) match(xxx = {) // expected-error {{expected '}'}} expected-note {{to match this '{'}}
#pragma omp declare variant(foofoo <T>) match(xxx = {})
#pragma omp declare variant(foofoo <T>) match(xxx = {vvv})
@@ -51,7 +51,7 @@ int bar();
#pragma omp declare variant(foofoo <T>) match(user = {score(<expr>) : condition(<expr>)})
#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)})
#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)})
-#pragma omp declare variant(foofoo <T>) match(xxx = {vvv} xxx) // expected-error {{expected ')'}} expected-note {{to match this '('}}
+#pragma omp declare variant(foofoo <T>) 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 <T>) match(xxx = {vvv}) xxx // expected-warning {{extra tokens at the end of '#pragma omp declare variant' are ignored}}
template <typename T>
T barbar();