[
"CtxUnknown", "CtxVendor"
]>,
- StringArgument<"ImplVendor", 1>
+ VariadicStringArgument<"ImplVendors">
];
let AdditionalMembers = [{
void printScore(raw_ostream & OS, const PrintingPolicy &Policy) const {
case CtxVendor:
OS << "vendor(";
printScore(OS, Policy);
- OS << getImplVendor();
+ if (implVendors_size() > 0) {
+ OS << *implVendors(). begin();
+ for (StringRef VendorName : llvm::drop_begin(implVendors(), 1))
+ OS << ", " << VendorName;
+ }
OS << ")";
break;
case CtxUnknown:
OMPDeclareVariantAttr::CtxSetUnknown;
OMPDeclareVariantAttr::CtxSelectorType Ctx =
OMPDeclareVariantAttr::CtxUnknown;
- StringRef ImplVendor;
+ MutableArrayRef<StringRef> ImplVendors;
ExprResult CtxScore;
explicit OpenMPDeclareVariantCtsSelectorData() = default;
explicit OpenMPDeclareVariantCtsSelectorData(
OMPDeclareVariantAttr::CtxSelectorSetType CtxSet,
- OMPDeclareVariantAttr::CtxSelectorType Ctx, StringRef ImplVendor,
- ExprResult CtxScore)
- : CtxSet(CtxSet), Ctx(Ctx), ImplVendor(ImplVendor), CtxScore(CtxScore) {
- }
+ OMPDeclareVariantAttr::CtxSelectorType Ctx,
+ MutableArrayRef<StringRef> ImplVendors, ExprResult CtxScore)
+ : CtxSet(CtxSet), Ctx(Ctx), ImplVendors(ImplVendors),
+ CtxScore(CtxScore) {}
};
/// Checks if the variant/multiversion functions are compatible.
bool checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
OMPDeclareVariantAttr::CtxVendor>(
const OMPDeclareVariantAttr *A) {
- return !A->getImplVendor().compare("llvm");
+ return llvm::all_of(A->implVendors(),
+ [](StringRef S) { return !S.compare_lower("llvm"); });
}
static bool greaterCtxScore(ASTContext &Ctx, const Expr *LHS, const Expr *RHS) {
(void)T.expectAndConsume(diag::err_expected_lparen_after,
CtxSelectorName.data());
const ExprResult Score = parseContextScore(P);
+ SmallVector<llvm::SmallString<16>, 4> Vendors;
do {
// Parse <vendor>.
StringRef VendorName;
Buffer.clear();
VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
(void)P.ConsumeToken();
+ if (!VendorName.empty())
+ Vendors.push_back(VendorName);
} 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 (!Vendors.empty()) {
+ SmallVector<StringRef, 4> ImplVendors(Vendors.size());
+ for (int I = 0, E = Vendors.size(); I < E; ++I)
+ ImplVendors[I] = Vendors[I];
+ Sema::OpenMPDeclareVariantCtsSelectorData Data(
+ OMPDeclareVariantAttr::CtxSetImplementation, CSKind, ImplVendors,
+ Score);
+ Callback(SourceRange(Loc, Tok.getLocation()), Data);
+ }
break;
}
case OMPDeclareVariantAttr::CtxUnknown:
}
}
auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
- Context, VariantRef, Score, Data.CtxSet, ST, Data.Ctx, Data.ImplVendor,
- SR);
+ Context, VariantRef, Score, Data.CtxSet, ST, Data.Ctx,
+ Data.ImplVendors.begin(), Data.ImplVendors.size(), SR);
FD->addAttr(NewAttr);
}
if (!DeclVarData)
return;
// Instantiate the attribute.
- Sema::OpenMPDeclareVariantCtsSelectorData Data(Attr.getCtxSelectorSet(),
- Attr.getCtxSelector(),
- Attr.getImplVendor(), Score);
+ Sema::OpenMPDeclareVariantCtsSelectorData Data(
+ Attr.getCtxSelectorSet(), Attr.getCtxSelector(),
+ llvm::makeMutableArrayRef(Attr.implVendors_begin(),
+ Attr.implVendors_size()),
+ Score);
S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first,
DeclVarData.getValue().second,
Attr.getRange(), Data);
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(score(5):ibm, xxx)})
// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(llvm)})
// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(llvm)})
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score(5): ibm)})
int bar();
-// CHECK: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(score(C + 5):ibm)})
-// CHECK: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(score(C + 5):xxx)})
+// CHECK: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(score(C + 5):ibm, xxx)})
// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(foofoo<T>) match(implementation={vendor(llvm)})
// CHECK-NEXT: template <typename T, int C> T barbar();
template <typename T, int C>
T barbar();
-// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(3 + 5):ibm)})
-// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(3 + 5):xxx)})
+// CHECK: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(score(3 + 5):ibm, xxx)})
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(unknown)})
// CHECK-NEXT: #pragma omp declare variant(foofoo<int>) match(implementation={vendor(llvm)})
// CHECK-NEXT: template<> int barbar<int, 3>();
// CHECK-DAG: @_Z4callv = {{.*}}alias i32 (), i32 ()* @_Z4testv
// CHECK-DAG: @_ZL9stat_usedv = internal alias i32 (), i32 ()* @_ZL10stat_used_v
// CHECK-DAG: @_ZN12SpecialFuncs6MethodEv = {{.*}}alias i32 (%struct.SpecialFuncs*), i32 (%struct.SpecialFuncs*)* @_ZN12SpecialFuncs7method_Ev
+// CHECK-DAG: @fn_linkage = {{.*}}alias i32 (), i32 ()* @_Z18fn_linkage_variantv
+// CHECK-DAG: @_Z11fn_linkage1v = {{.*}}alias i32 (), i32 ()* @fn_linkage_variant1
// CHECK-DAG: declare {{.*}}i32 @_Z5bazzzv()
// CHECK-DAG: declare {{.*}}i32 @_Z3bazv()
// CHECK-DAG: ret i32 2
// CHECK-DAG: ret i32 83
// CHECK-DAG: ret i32 85
// CHECK-DAG: ret i32 86
+// CHECK-DAG: ret i32 87
// CHECK-NOT: ret i32 {{1|4|81|84}}
#ifndef HEADER
#pragma omp declare variant(fn_linkage_variant1) match(implementation = {vendor(llvm)})
int fn_linkage1() { return 1; }
+int fn_variant2() { return 1; }
+#pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm, ibm)})
+int fn2() { return 87; }
+
#endif // HEADER