[OPENMP50]Parsing/sema support for 'implementation/vendor' context

selector.

Added basic parsing/semantic support for
'implementation={vendor(<vendor>)}' context selector.

llvm-svn: 372917
This commit is contained in:
Alexey Bataev 2019-09-25 19:43:37 +00:00
parent 45c935bd0b
commit 9ff34745a2
12 changed files with 237 additions and 57 deletions

View File

@ -3288,18 +3288,51 @@ def OMPDeclareVariant : Attr {
let HasCustomParsing = 1;
let Documentation = [OMPDeclareVariantDocs];
let Args = [
ExprArgument<"VariantFuncRef">
ExprArgument<"VariantFuncRef">,
EnumArgument<"CtxSelectorSet", "CtxSelectorSetType",
[ "", "implementation"
],
[
"CtxSetUnknown", "CtxSetImplementation"
]>,
EnumArgument<"CtxSelector", "CtxSelectorType",
[ "", "vendor"
],
[
"CtxUnknown", "CtxVendor"
]>,
StringArgument<"ImplVendor", 1>
];
let AdditionalMembers = [{
void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy)
const {
assert(getCtxSelectorSet() != CtxSetUnknown &&
getCtxSelector() != CtxUnknown && "Unknown context selector.");
if (const Expr *E = getVariantFuncRef()) {
OS << "(";
E->printPretty(OS, nullptr, Policy);
OS << ")";
}
// TODO: add printing of real context selectors.
OS << " match(unknown={})";
OS << " match(";
switch (getCtxSelectorSet()) {
case CtxSetImplementation:
OS << "implementation={";
switch (getCtxSelector()) {
case CtxVendor:
OS << "vendor(";
OS << getImplVendor();
OS << ")";
break;
case CtxUnknown:
llvm_unreachable("Unknown context selector.");
}
OS << "}";
break;
case CtxSetUnknown:
llvm_unreachable("Unknown context selector set.");
}
OS << ")";
}
}];
}

View File

@ -1206,6 +1206,11 @@ def err_omp_declare_variant_no_ctx_selector : Error<
"expected context selector in '%0' clause on 'omp declare variant' directive">;
def err_omp_declare_variant_equal_expected : Error<
"expected '=' after '%0' context selector set name on 'omp declare variant' directive">;
def warn_omp_declare_variant_cs_name_expected : Warning<
"unknown context selector in '%0' context selector set of 'omp declare variant' directive, ignored">,
InGroup<OpenMPClauses>;
def err_omp_declare_variant_item_expected : Error<
"expected %0 in '%1' context selector of '%2' selector set of 'omp declare variant' directive">;
def warn_omp_more_one_device_type_clause : Warning<
"more than one 'device_type' clause is specified">,
InGroup<OpenMPClauses>;

View File

@ -197,6 +197,9 @@
#ifndef OPENMP_DECLARE_VARIANT_CLAUSE
#define OPENMP_DECLARE_VARIANT_CLAUSE(Name)
#endif
#ifndef OPENMP_MATCH_KIND
#define OPENMP_MATCH_KIND(Name)
#endif
// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
@ -965,6 +968,11 @@ OPENMP_DEVICE_TYPE_KIND(any)
// Clauses allowed for OpenMP directive 'declare variant'.
OPENMP_DECLARE_VARIANT_CLAUSE(match)
// Context selectors for 'match' clause.
// TODO: add other context selectors.
OPENMP_MATCH_KIND(implementation)
#undef OPENMP_MATCH_KIND
#undef OPENMP_DECLARE_VARIANT_CLAUSE
#undef OPENMP_DEVICE_TYPE_KIND
#undef OPENMP_ALLOCATE_CLAUSE

View File

@ -2836,9 +2836,11 @@ private:
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);
bool parseOpenMPContextSelectors(
SourceLocation Loc,
llvm::function_ref<
void(SourceRange, const Sema::OpenMPDeclareVariantCtsSelectorData &)>
Callback);
/// Parse clauses for '#pragma omp declare variant'.
void ParseOMPDeclareVariantClauses(DeclGroupPtrTy Ptr, CachedTokens &Toks,

View File

@ -9102,6 +9102,20 @@ private:
bool MightBeOdrUse);
public:
/// Struct to store the context selectors info for declare variant directive.
struct OpenMPDeclareVariantCtsSelectorData {
OMPDeclareVariantAttr::CtxSelectorSetType CtxSet =
OMPDeclareVariantAttr::CtxSetUnknown;
OMPDeclareVariantAttr::CtxSelectorType Ctx =
OMPDeclareVariantAttr::CtxUnknown;
StringRef ImplVendor;
explicit OpenMPDeclareVariantCtsSelectorData() = default;
explicit OpenMPDeclareVariantCtsSelectorData(
OMPDeclareVariantAttr::CtxSelectorSetType CtxSet,
OMPDeclareVariantAttr::CtxSelectorType Ctx, StringRef ImplVendor)
: CtxSet(CtxSet), Ctx(Ctx), ImplVendor(ImplVendor) {}
};
/// Checks if the variant/multiversion functions are compatible.
bool areMultiversionVariantFunctionsCompatible(
const FunctionDecl *OldFD, const FunctionDecl *NewFD,
@ -9542,10 +9556,9 @@ public:
/// \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);
/// 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.
@ -9553,8 +9566,11 @@ public:
/// applied to.
/// \param VariantRef Expression that references the variant function, which
/// must be used instead of the original one, specified in \p DG.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef,
SourceRange SR);
/// \param Data Set of context-specific data for the specified context
/// selector.
void ActOnOpenMPDeclareVariantDirective(
FunctionDecl *FD, Expr *VariantRef, SourceRange SR,
const Sema::OpenMPDeclareVariantCtsSelectorData &Data);
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,

View File

@ -786,12 +786,72 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
LinModifiers, Steps, SourceRange(Loc, EndLoc));
}
/// Parse context selector for 'implementation' selector set:
/// 'vendor' '(' <vendor> ')'
static void
parseImplementationSelector(Parser &P,
Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
const Token &Tok = P.getCurToken();
// Parse inner context selector set name, if any.
if (!Tok.is(tok::identifier)) {
P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
<< "implementation";
// Skip until either '}', ')', or end of directive.
while (!P.SkipUntil(tok::r_brace, tok::r_paren,
tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
;
return;
}
SmallString<16> Buffer;
StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
OMPDeclareVariantAttr::CtxSelectorType CSKind =
OMPDeclareVariantAttr::CtxUnknown;
(void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorType(CtxSelectorName,
CSKind);
(void)P.ConsumeToken();
switch (CSKind) {
case OMPDeclareVariantAttr::CtxVendor: {
// Parse '('.
BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
(void)T.expectAndConsume(diag::err_expected_lparen_after,
CtxSelectorName.data());
// Parse <vendor>.
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";
}
// Parse ')'.
(void)T.consumeClose();
if (!VendorName.empty())
Data.ImplVendor = VendorName;
break;
}
case OMPDeclareVariantAttr::CtxUnknown:
P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
<< "implementation";
// Skip until either '}', ')', or end of directive.
while (!P.SkipUntil(tok::r_brace, tok::r_paren,
tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
;
return;
}
Data.CtxSet = OMPDeclareVariantAttr::CtxSetImplementation;
Data.Ctx = CSKind;
}
/// Parses clauses for 'declare variant' directive.
/// clause:
/// <selector_set_name> '=' '{' <context_selectors> '}'
/// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ]
bool Parser::parseOpenMPContextSelectors(
SourceLocation Loc, llvm::function_ref<void(SourceRange)> Callback) {
SourceLocation Loc,
llvm::function_ref<void(SourceRange,
const Sema::OpenMPDeclareVariantCtsSelectorData &)>
Callback) {
do {
// Parse inner context selector set name.
if (!Tok.is(tok::identifier)) {
@ -800,30 +860,43 @@ bool Parser::parseOpenMPContextSelectors(
return true;
}
SmallString<16> Buffer;
StringRef CtxSelectorName = PP.getSpelling(Tok, Buffer);
StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer);
// Parse '='.
(void)ConsumeToken();
if (Tok.isNot(tok::equal)) {
Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
<< CtxSelectorName;
<< CtxSelectorSetName;
return true;
}
(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,
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))
;
OMPDeclareVariantAttr::CtxSelectorSetType CSSKind =
OMPDeclareVariantAttr::CtxSetUnknown;
(void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorSetType(
CtxSelectorSetName, CSSKind);
switch (CSSKind) {
case OMPDeclareVariantAttr::CtxSetImplementation:
parseImplementationSelector(*this, Data);
break;
case OMPDeclareVariantAttr::CtxSetUnknown:
// Skip until either '}', ')', or end of directive.
while (!SkipUntil(tok::r_brace, tok::r_paren,
tok::annot_pragma_openmp_end, StopBeforeMatch))
;
break;
}
// Parse '}'.
(void)TBr.consumeClose();
}
Callback(SourceRange(Loc, Tok.getLocation()));
Callback(SourceRange(Loc, Tok.getLocation()), Data);
// Consume ','
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end))
(void)ExpectAndConsume(tok::comma);
@ -888,11 +961,15 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
}
// Parse inner context selectors.
if (!parseOpenMPContextSelectors(Loc, [this, &DeclVarData](SourceRange SR) {
if (DeclVarData.hasValue())
Actions.ActOnOpenMPDeclareVariantDirective(
DeclVarData.getValue().first, DeclVarData.getValue().second, SR);
})) {
if (!parseOpenMPContextSelectors(
Loc, [this, &DeclVarData](
SourceRange SR,
const Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
if (DeclVarData.hasValue())
Actions.ActOnOpenMPDeclareVariantDirective(
DeclVarData.getValue().first, DeclVarData.getValue().second,
SR, Data);
})) {
// Parse ')'.
(void)T.consumeClose();
// Need to check for extra tokens.

View File

@ -5101,11 +5101,14 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
return std::make_pair(FD, cast<Expr>(DRE));
}
void Sema::ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD,
Expr *VariantRef,
SourceRange SR) {
auto *NewAttr =
OMPDeclareVariantAttr::CreateImplicit(Context, VariantRef, SR);
void Sema::ActOnOpenMPDeclareVariantDirective(
FunctionDecl *FD, Expr *VariantRef, SourceRange SR,
const Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
if (Data.CtxSet == OMPDeclareVariantAttr::CtxSetUnknown ||
Data.Ctx == OMPDeclareVariantAttr::CtxUnknown)
return;
auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
Context, VariantRef, Data.CtxSet, Data.Ctx, Data.ImplVendor, SR);
FD->addAttr(NewAttr);
}

View File

@ -395,9 +395,11 @@ static void instantiateOMPDeclareVariantAttr(
if (!DeclVarData)
return;
// Instantiate the attribute.
Sema::OpenMPDeclareVariantCtsSelectorData Data(
Attr.getCtxSelectorSet(), Attr.getCtxSelector(), Attr.getImplVendor());
S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first,
DeclVarData.getValue().second,
Attr.getRange());
Attr.getRange(), Data);
}
static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr(

View File

@ -8,10 +8,12 @@ int foo(void);
#pragma omp declare variant(foo) match(xxx={}, yyy={ccc})
#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)})
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: #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)})
// CHECK-NEXT: int bar();

View File

@ -17,20 +17,19 @@ T foofoo() { return T(); }
// CHECK-NEXT: return int();
// CHECK-NEXT: }
// CHECK: #pragma omp declare variant(foofoo<int>) match(unknown={})
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(unknown={})
// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(ibm)})
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(llvm)})
// CHECK-NEXT: int bar();
#pragma omp declare variant(foofoo <int>) match(xxx = {})
#pragma omp declare variant(foofoo <int>) match(xxx = {vvv})
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(unknown)})
int bar();
// CHECK: #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: #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: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(ibm)})
// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(llvm)})
// CHECK-NEXT: template <typename T> T barbar();
#pragma omp declare variant(foofoo <T>) match(xxx = {})
#pragma omp declare variant(foofoo <T>) match(xxx = {vvv})
@ -38,16 +37,14 @@ int bar();
#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>)})
#pragma omp declare variant(foofoo <T>) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
#pragma omp declare variant(foofoo <T>) match(implementation={vendor(unknown)})
template <typename T>
T barbar();
// CHECK: #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: #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: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(ibm)})
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(llvm)})
// CHECK-NEXT: template<> int barbar<int>();
// CHECK-NEXT: int baz() {
@ -67,15 +64,21 @@ template <class C>
void h_ref(C *hp, C *hp2, C *hq, C *lin) {
}
// CHECK: #pragma omp declare variant(h_ref<C>) match(unknown={})
// CHECK: #pragma omp declare variant(h_ref<C>) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(h_ref<C>) match(implementation={vendor(ibm)})
// CHECK-NEXT: #pragma omp declare variant(h_ref<C>) match(implementation={vendor(llvm)})
// CHECK-NEXT: template <class C> void h(C *hp, C *hp2, C *hq, C *lin) {
// CHECK-NEXT: }
#pragma omp declare variant(h_ref <C>) match(xxx = {})
#pragma omp declare variant(h_ref <C>) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
#pragma omp declare variant(h_ref <C>) match(implementation={vendor(unknown)})
template <class C>
void h(C *hp, C *hp2, C *hq, C *lin) {
}
// CHECK: #pragma omp declare variant(h_ref<float>) match(unknown={})
// CHECK: #pragma omp declare variant(h_ref<float>) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(h_ref<float>) match(implementation={vendor(ibm)})
// CHECK-NEXT: #pragma omp declare variant(h_ref<float>) match(implementation={vendor(llvm)})
// CHECK-NEXT: template<> void h<float>(float *hp, float *hp2, float *hq, float *lin) {
// CHECK-NEXT: }
@ -83,6 +86,8 @@ void h(C *hp, C *hp2, C *hq, C *lin) {
// CHECK-NEXT: h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
// CHECK-NEXT: }
#pragma omp declare variant(h_ref <double>) match(xxx = {})
#pragma omp declare variant(h_ref <double>) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
#pragma omp declare variant(h_ref <double>) match(implementation={vendor(unknown)})
template <>
void h(double *hp, double *hp2, double *hq, double *lin) {
h((float *)hp, (float *)hp2, (float *)hq, (float *)lin);
@ -92,27 +97,39 @@ void h(double *hp, double *hp2, double *hq, double *lin) {
int fn();
// CHECK: int fn(int);
int fn(int);
// CHECK: #pragma omp declare variant(fn) match(unknown={})
// CHECK: #pragma omp declare variant(fn) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(fn) match(implementation={vendor(ibm)})
// CHECK-NEXT: #pragma omp declare variant(fn) match(implementation={vendor(llvm)})
// CHECK-NEXT: int overload();
#pragma omp declare variant(fn) match(xxx = {})
#pragma omp declare variant(fn) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
#pragma omp declare variant(fn) match(implementation={vendor(unknown)})
int overload(void);
// CHECK: int fn_deduced_variant() {
// CHECK-NEXT: return 0;
// CHECK-NEXT: }
auto fn_deduced_variant() { return 0; }
// CHECK: #pragma omp declare variant(fn_deduced_variant) match(unknown={})
// CHECK: #pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(ibm)})
// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(llvm)})
// CHECK-NEXT: int fn_deduced();
#pragma omp declare variant(fn_deduced_variant) match(xxx = {})
#pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
#pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(unknown)})
int fn_deduced();
// CHECK: int fn_deduced_variant1();
int fn_deduced_variant1();
// CHECK: #pragma omp declare variant(fn_deduced_variant1) match(unknown={})
// CHECK: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(ibm)})
// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(llvm)})
// CHECK-NEXT: int fn_deduced1() {
// CHECK-NEXT: return 0;
// CHECK-NEXT: }
#pragma omp declare variant(fn_deduced_variant1) match(xxx = {})
#pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
#pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(unknown)})
auto fn_deduced1() { return 0; }
// CHECK: struct SpecialFuncs {
@ -126,8 +143,9 @@ auto fn_deduced1() { return 0; }
// CHECK-NEXT: }
// CHECK-NEXT: void bar(int) {
// CHECK-NEXT: }
// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::bar) match(unknown={})
// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::baz) match(unknown={})
// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::bar) match(implementation={vendor(ibm)})
// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::bar) match(implementation={vendor(llvm)})
// CHECK-NEXT: void foo1() {
// CHECK-NEXT: }
// CHECK-NEXT: } s;
@ -141,16 +159,22 @@ struct SpecialFuncs {
void bar(int) {}
#pragma omp declare variant(SpecialFuncs::baz) match(xxx = {})
#pragma omp declare variant(SpecialFuncs::bar) match(xxx = {})
#pragma omp declare variant(SpecialFuncs::bar) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
#pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(unknown)})
void foo1() {}
} s;
// CHECK: static void static_f_variant() {
// CHECK-NEXT: }
static void static_f_variant() {}
// CHECK: #pragma omp declare variant(static_f_variant) match(unknown={})
// CHECK: #pragma omp declare variant(static_f_variant) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(static_f_variant) match(implementation={vendor(ibm)})
// CHECK-NEXT: #pragma omp declare variant(static_f_variant) match(implementation={vendor(llvm)})
// CHECK-NEXT: static void static_f() {
// CHECK-NEXT: }
#pragma omp declare variant(static_f_variant) match(xxx = {})
#pragma omp declare variant(static_f_variant) match(implementation={vendor(ibm)}, implementation={vendor(llvm)})
#pragma omp declare variant(static_f_variant) match(implementation={vendor(unknown)})
static void static_f() {}
// CHECK: void bazzzz() {

View File

@ -26,6 +26,10 @@ int foo(void);
#pragma omp declare variant(foo) match(xxx={vvv})
#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 vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}}
int bar(void);
// expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}}
@ -89,7 +93,7 @@ void diff_ret(void);
void marked(void);
void not_marked(void);
// expected-note@+1 {{marked as 'declare variant' here}}
#pragma omp declare variant(not_marked) match(xxx={})
#pragma omp declare variant(not_marked) match(implementation={vendor(unknown)})
void marked_variant(void);
// expected-warning@+1 {{variant function in '#pragma omp declare variant' is itself marked as '#pragma omp declare variant'}}
#pragma omp declare variant(marked_variant) match(xxx={})

View File

@ -29,6 +29,10 @@ T foofoo();
#pragma omp declare variant(foofoo <int>) match(xxx = {vvv})
#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}}
#pragma omp declare variant(foofoo <int>) match(implementation={xxx}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}}
#pragma omp declare variant(foofoo <int>) 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 <int>) 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 <int>) match(implementation={vendor()}) // expected-error {{expected vendor identifier in 'vendor' context selector of 'implementation' selector set of 'omp declare variant' directive}}
int bar();
#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}}