let Documentation = [OMPDeclareVariantDocs];
let Args = [
ExprArgument<"VariantFuncRef">,
- ExprArgument<"Score">,
- EnumArgument<"CtxSelectorSet", "CtxSelectorSetType",
- [ "", "implementation"
- ],
- [
- "CtxSetUnknown", "CtxSetImplementation"
- ]>,
- EnumArgument<"CtxSelector", "CtxSelectorType",
- [ "", "vendor"
- ],
- [
- "CtxUnknown", "CtxVendor"
- ]>,
+ VariadicExprArgument<"Scores">,
+ VariadicUnsignedArgument<"CtxSelectorSets">,
+ VariadicUnsignedArgument<"CtxSelectors">,
VariadicStringArgument<"ImplVendors">
];
let AdditionalMembers = [{
- void printScore(raw_ostream & OS, const PrintingPolicy &Policy) const {
- if (const Expr *E = getScore()) {
+ void printScore(raw_ostream & OS, const PrintingPolicy &Policy, unsigned I) const {
+ if (const Expr *E = *std::next(scores_begin(), I)) {
OS << "score(";
E->printPretty(OS, nullptr, Policy);
OS << "):";
}
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);
}
// TODO: add printing of real context selectors.
OS << " match(";
- switch (getCtxSelectorSet()) {
- case CtxSetImplementation:
- OS << "implementation={";
- switch (getCtxSelector()) {
- case CtxVendor:
- OS << "vendor(";
- printScore(OS, Policy);
- if (implVendors_size() > 0) {
- OS << *implVendors(). begin();
- for (StringRef VendorName : llvm::drop_begin(implVendors(), 1))
- OS << ", " << VendorName;
+ for (unsigned I = 0, E = ctxSelectorSets_size(); I < E; ++I) {
+ auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
+ *std::next(ctxSelectorSets_begin(), I));
+ auto Ctx = static_cast<OpenMPContextSelectorKind>(
+ *std::next(ctxSelectors_begin(), I));
+ assert(CtxSet != OMP_CTX_SET_unknown && Ctx != OMP_CTX_unknown &&
+ "Unknown context selector.");
+ switch (CtxSet) {
+ case OMP_CTX_SET_implementation:
+ OS << "implementation={";
+ switch (Ctx) {
+ case OMP_CTX_vendor:
+ OS << "vendor(";
+ printScore(OS, Policy, I);
+ if (implVendors_size() > 0) {
+ OS << *implVendors(). begin();
+ for (StringRef VendorName : llvm::drop_begin(implVendors(), 1))
+ OS << ", " << VendorName;
+ }
+ OS << ")";
+ break;
+ case OMP_CTX_unknown:
+ llvm_unreachable("Unknown context selector.");
}
- OS << ")";
+ OS << "}";
break;
- case CtxUnknown:
- llvm_unreachable("Unknown context selector.");
+ case OMP_CTX_SET_unknown:
+ llvm_unreachable("Unknown context selector set.");
}
- OS << "}";
- break;
- case CtxSetUnknown:
- llvm_unreachable("Unknown context selector set.");
}
OS << ")";
}
#ifndef OPENMP_MATCH_KIND
#define OPENMP_MATCH_KIND(Name)
#endif
+#ifndef OPENMP_CONTEXT_SELECTOR_SET
+#define OPENMP_CONTEXT_SELECTOR_SET(Name)
+#endif
+#ifndef OPENMP_CONTEXT_SELECTOR
+#define OPENMP_CONTEXT_SELECTOR(Name)
+#endif
+
+// OpenMP context selector sets.
+OPENMP_CONTEXT_SELECTOR_SET(implementation)
+
+// OpenMP context selectors.
+OPENMP_CONTEXT_SELECTOR(vendor)
// OpenMP directives.
OPENMP_DIRECTIVE(threadprivate)
// TODO: add other context selectors.
OPENMP_MATCH_KIND(implementation)
+#undef OPENMP_CONTEXT_SELECTOR
+#undef OPENMP_CONTEXT_SELECTOR_SET
#undef OPENMP_MATCH_KIND
#undef OPENMP_DECLARE_VARIANT_CLAUSE
#undef OPENMP_DEVICE_TYPE_KIND
namespace clang {
+/// OpenMP context selector sets.
+enum OpenMPContextSelectorSetKind {
+#define OPENMP_CONTEXT_SELECTOR_SET(Name) OMP_CTX_SET_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMP_CTX_SET_unknown,
+};
+
+/// OpenMP context selectors.
+enum OpenMPContextSelectorKind {
+#define OPENMP_CONTEXT_SELECTOR(Name) OMP_CTX_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMP_CTX_unknown,
+};
+
+OpenMPContextSelectorSetKind getOpenMPContextSelectorSet(llvm::StringRef Str);
+llvm::StringRef
+getOpenMPContextSelectorSetName(OpenMPContextSelectorSetKind Kind);
+OpenMPContextSelectorKind getOpenMPContextSelector(llvm::StringRef Str);
+llvm::StringRef getOpenMPContextSelectorName(OpenMPContextSelectorKind Kind);
+
+/// Struct to store the context selectors info.
+template <typename T, typename VectorType, typename ScoreT>
+struct OpenMPCtxSelectorData {
+ OpenMPContextSelectorSetKind CtxSet = OMP_CTX_SET_unknown;
+ OpenMPContextSelectorKind Ctx = OMP_CTX_unknown;
+ ScoreT Score;
+ VectorType Names;
+ explicit OpenMPCtxSelectorData() = default;
+ explicit OpenMPCtxSelectorData(OpenMPContextSelectorSetKind CtxSet,
+ OpenMPContextSelectorKind Ctx,
+ const ScoreT &Score, VectorType &&Names)
+ : CtxSet(CtxSet), Ctx(Ctx), Score(Score), Names(Names) {}
+ template <typename U>
+ explicit OpenMPCtxSelectorData(OpenMPContextSelectorSetKind CtxSet,
+ OpenMPContextSelectorKind Ctx,
+ const ScoreT &Score, const U &Names)
+ : CtxSet(CtxSet), Ctx(Ctx), Score(Score),
+ Names(Names.begin(), Names.end()) {}
+};
+
/// OpenMP directives.
enum OpenMPDirectiveKind {
#define OPENMP_DIRECTIVE(Name) \
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, const Sema::OpenMPDeclareVariantCtsSelectorData &)>
- Callback);
+ bool
+ parseOpenMPContextSelectors(SourceLocation Loc,
+ SmallVectorImpl<Sema::OMPCtxSelectorData> &Data);
/// Parse clauses for '#pragma omp declare variant'.
void ParseOMPDeclareVariantClauses(DeclGroupPtrTy Ptr, CachedTokens &Toks,
public:
/// Struct to store the context selectors info for declare variant directive.
- struct OpenMPDeclareVariantCtsSelectorData {
- OMPDeclareVariantAttr::CtxSelectorSetType CtxSet =
- OMPDeclareVariantAttr::CtxSetUnknown;
- OMPDeclareVariantAttr::CtxSelectorType Ctx =
- OMPDeclareVariantAttr::CtxUnknown;
- MutableArrayRef<StringRef> ImplVendors;
- ExprResult CtxScore;
- explicit OpenMPDeclareVariantCtsSelectorData() = default;
- explicit OpenMPDeclareVariantCtsSelectorData(
- OMPDeclareVariantAttr::CtxSelectorSetType CtxSet,
- OMPDeclareVariantAttr::CtxSelectorType Ctx,
- MutableArrayRef<StringRef> ImplVendors, ExprResult CtxScore)
- : CtxSet(CtxSet), Ctx(Ctx), ImplVendors(ImplVendors),
- CtxScore(CtxScore) {}
- };
+ using OMPCtxStringType = SmallString<8>;
+ using OMPCtxSelectorData =
+ OpenMPCtxSelectorData<OMPCtxStringType, SmallVector<OMPCtxStringType, 4>,
+ ExprResult>;
/// Checks if the variant/multiversion functions are compatible.
bool areMultiversionVariantFunctionsCompatible(
/// must be used instead of the original one, specified in \p DG.
/// \param Data Set of context-specific data for the specified context
/// selector.
- void ActOnOpenMPDeclareVariantDirective(
- FunctionDecl *FD, Expr *VariantRef, SourceRange SR,
- const Sema::OpenMPDeclareVariantCtsSelectorData &Data);
+ void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef,
+ SourceRange SR,
+ ArrayRef<OMPCtxSelectorData> Data);
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,
using namespace clang;
+OpenMPContextSelectorSetKind
+clang::getOpenMPContextSelectorSet(llvm::StringRef Str) {
+ return llvm::StringSwitch<OpenMPContextSelectorSetKind>(Str)
+#define OPENMP_CONTEXT_SELECTOR_SET(Name) .Case(#Name, OMP_CTX_SET_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMP_CTX_SET_unknown);
+}
+
+llvm::StringRef
+clang::getOpenMPContextSelectorSetName(OpenMPContextSelectorSetKind Kind) {
+ switch (Kind) {
+ case OMP_CTX_SET_unknown:
+ return "unknown";
+#define OPENMP_CONTEXT_SELECTOR_SET(Name) \
+ case OMP_CTX_SET_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ break;
+ }
+ llvm_unreachable("Invalid OpenMP context selector set kind");
+}
+
+OpenMPContextSelectorKind clang::getOpenMPContextSelector(llvm::StringRef Str) {
+ return llvm::StringSwitch<OpenMPContextSelectorKind>(Str)
+#define OPENMP_CONTEXT_SELECTOR(Name) .Case(#Name, OMP_CTX_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMP_CTX_unknown);
+}
+
+llvm::StringRef
+clang::getOpenMPContextSelectorName(OpenMPContextSelectorKind Kind) {
+ switch (Kind) {
+ case OMP_CTX_unknown:
+ return "unknown";
+#define OPENMP_CONTEXT_SELECTOR(Name) \
+ case OMP_CTX_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ break;
+ }
+ llvm_unreachable("Invalid OpenMP context selector kind");
+}
+
OpenMPDirectiveKind clang::getOpenMPDirectiveKind(StringRef Str) {
return llvm::StringSwitch<OpenMPDirectiveKind>(Str)
#define OPENMP_DIRECTIVE(Name) .Case(#Name, OMPD_##Name)
return Address(Addr, Align);
}
+namespace {
+using OMPContextSelectorData =
+ OpenMPCtxSelectorData<StringRef, ArrayRef<StringRef>, llvm::APSInt>;
+using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>;
+} // anonymous namespace
+
/// Checks current context and returns true if it matches the context selector.
-template <OMPDeclareVariantAttr::CtxSelectorSetType CtxSet,
- OMPDeclareVariantAttr::CtxSelectorType Ctx>
-static bool checkContext(const OMPDeclareVariantAttr *A) {
- assert(CtxSet != OMPDeclareVariantAttr::CtxSetUnknown &&
- Ctx != OMPDeclareVariantAttr::CtxUnknown &&
+template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx>
+static bool checkContext(const OMPContextSelectorData &Data) {
+ assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown &&
"Unknown context selector or context selector set.");
return false;
}
/// Checks for implementation={vendor(<vendor>)} context selector.
/// \returns true iff <vendor>="llvm", false otherwise.
template <>
-bool checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
- OMPDeclareVariantAttr::CtxVendor>(
- const OMPDeclareVariantAttr *A) {
- return llvm::all_of(A->implVendors(),
+bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(
+ const OMPContextSelectorData &Data) {
+ return llvm::all_of(Data.Names,
[](StringRef S) { return !S.compare_lower("llvm"); });
}
-static bool greaterCtxScore(ASTContext &Ctx, const Expr *LHS, const Expr *RHS) {
- llvm::APSInt LHSVal = LHS->EvaluateKnownConstInt(Ctx);
- llvm::APSInt RHSVal = RHS->EvaluateKnownConstInt(Ctx);
- return llvm::APSInt::compareValues(LHSVal, RHSVal) >= 0;
+bool matchesContext(const CompleteOMPContextSelectorData &ContextData) {
+ for (const OMPContextSelectorData &Data : ContextData) {
+ switch (Data.CtxSet) {
+ case OMP_CTX_SET_implementation:
+ switch (Data.Ctx) {
+ case OMP_CTX_vendor:
+ if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data))
+ return false;
+ break;
+ case OMP_CTX_unknown:
+ llvm_unreachable("Unexpected context selector kind.");
+ }
+ break;
+ case OMP_CTX_SET_unknown:
+ llvm_unreachable("Unexpected context selector set kind.");
+ }
+ }
+ return true;
+}
+
+static CompleteOMPContextSelectorData
+translateAttrToContextSelectorData(ASTContext &C,
+ const OMPDeclareVariantAttr *A) {
+ CompleteOMPContextSelectorData Data;
+ for (unsigned I = 0, E = A->scores_size(); I < E; ++I) {
+ Data.emplace_back();
+ auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
+ *std::next(A->ctxSelectorSets_begin(), I));
+ auto Ctx = static_cast<OpenMPContextSelectorKind>(
+ *std::next(A->ctxSelectors_begin(), I));
+ Data.back().CtxSet = CtxSet;
+ Data.back().Ctx = Ctx;
+ const Expr *Score = *std::next(A->scores_begin(), I);
+ Data.back().Score = Score->EvaluateKnownConstInt(C);
+ switch (CtxSet) {
+ case OMP_CTX_SET_implementation:
+ switch (Ctx) {
+ case OMP_CTX_vendor:
+ Data.back().Names =
+ llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end());
+ break;
+ case OMP_CTX_unknown:
+ llvm_unreachable("Unexpected context selector kind.");
+ }
+ break;
+ case OMP_CTX_SET_unknown:
+ llvm_unreachable("Unexpected context selector set kind.");
+ }
+ }
+ return Data;
+}
+
+static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS,
+ const CompleteOMPContextSelectorData &RHS) {
+ // Score is calculated as sum of all scores + 1.
+ llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
+ for (const OMPContextSelectorData &Data : LHS) {
+ if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) {
+ LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
+ } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) {
+ LHSScore += Data.Score.extend(LHSScore.getBitWidth());
+ } else {
+ LHSScore += Data.Score;
+ }
+ }
+ llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false);
+ for (const OMPContextSelectorData &Data : RHS) {
+ if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) {
+ RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score;
+ } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) {
+ RHSScore += Data.Score.extend(RHSScore.getBitWidth());
+ } else {
+ RHSScore += Data.Score;
+ }
+ }
+ return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0;
}
/// Finds the variant function that matches current context with its context
if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>())
return FD;
// Iterate through all DeclareVariant attributes and check context selectors.
- auto &&Comparer = [&Ctx](const OMPDeclareVariantAttr *LHS,
- const OMPDeclareVariantAttr *RHS) {
- return greaterCtxScore(Ctx, LHS->getScore(), RHS->getScore());
- };
const OMPDeclareVariantAttr *TopMostAttr = nullptr;
+ CompleteOMPContextSelectorData TopMostData;
for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) {
- const OMPDeclareVariantAttr *SelectedAttr = nullptr;
- switch (A->getCtxSelectorSet()) {
- case OMPDeclareVariantAttr::CtxSetImplementation:
- switch (A->getCtxSelector()) {
- case OMPDeclareVariantAttr::CtxVendor:
- if (checkContext<OMPDeclareVariantAttr::CtxSetImplementation,
- OMPDeclareVariantAttr::CtxVendor>(A))
- SelectedAttr = A;
- break;
- case OMPDeclareVariantAttr::CtxUnknown:
- llvm_unreachable(
- "Unknown context selector in implementation selector set.");
- }
- break;
- case OMPDeclareVariantAttr::CtxSetUnknown:
- llvm_unreachable("Unknown context selector set.");
- }
+ CompleteOMPContextSelectorData Data =
+ translateAttrToContextSelectorData(Ctx, A);
+ if (!matchesContext(Data))
+ continue;
// If the attribute matches the context, find the attribute with the highest
// score.
- if (SelectedAttr && (!TopMostAttr || !Comparer(TopMostAttr, SelectedAttr)))
- TopMostAttr = SelectedAttr;
+ if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) {
+ TopMostAttr = A;
+ TopMostData.swap(Data);
+ }
}
if (!TopMostAttr)
return FD;
/// Parse optional 'score' '(' <expr> ')' ':'.
static ExprResult parseContextScore(Parser &P) {
ExprResult ScoreExpr;
- SmallString<16> Buffer;
+ Sema::OMPCtxStringType Buffer;
StringRef SelectorName =
P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
if (!SelectorName.equals("score"))
/// Parse context selector for 'implementation' selector set:
/// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> }
/// ')'
-static void parseImplementationSelector(
- Parser &P, SourceLocation Loc, llvm::StringMap<SourceLocation> &UsedCtx,
- llvm::function_ref<void(SourceRange,
- const Sema::OpenMPDeclareVariantCtsSelectorData &)>
- Callback) {
+static void
+parseImplementationSelector(Parser &P, SourceLocation Loc,
+ llvm::StringMap<SourceLocation> &UsedCtx,
+ SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
const Token &Tok = P.getCurToken();
// Parse inner context selector set name, if any.
if (!Tok.is(tok::identifier)) {
;
return;
}
- SmallString<16> Buffer;
+ Sema::OMPCtxStringType Buffer;
StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation());
if (!Res.second) {
P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
<< CtxSelectorName;
}
- OMPDeclareVariantAttr::CtxSelectorType CSKind =
- OMPDeclareVariantAttr::CtxUnknown;
- (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorType(CtxSelectorName,
- CSKind);
+ OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
(void)P.ConsumeToken();
switch (CSKind) {
- case OMPDeclareVariantAttr::CtxVendor: {
+ case OMP_CTX_vendor: {
// Parse '('.
BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
(void)T.expectAndConsume(diag::err_expected_lparen_after,
CtxSelectorName.data());
- const ExprResult Score = parseContextScore(P);
- llvm::UniqueVector<llvm::SmallString<16>> Vendors;
+ ExprResult Score = parseContextScore(P);
+ llvm::UniqueVector<Sema::OMPCtxStringType> Vendors;
do {
// Parse <vendor>.
StringRef VendorName;
} while (Tok.is(tok::identifier));
// Parse ')'.
(void)T.consumeClose();
- if (!Vendors.empty()) {
- SmallVector<StringRef, 4> ImplVendors(Vendors.size());
- llvm::copy(Vendors, ImplVendors.begin());
- Sema::OpenMPDeclareVariantCtsSelectorData Data(
- OMPDeclareVariantAttr::CtxSetImplementation, CSKind,
- llvm::makeMutableArrayRef(ImplVendors.begin(), ImplVendors.size()),
- Score);
- Callback(SourceRange(Loc, Tok.getLocation()), Data);
- }
+ if (!Vendors.empty())
+ Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors);
break;
}
- case OMPDeclareVariantAttr::CtxUnknown:
+ case OMP_CTX_unknown:
P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
<< "implementation";
// Skip until either '}', ')', or end of directive.
/// <selector_set_name> '=' '{' <context_selectors> '}'
/// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ]
bool Parser::parseOpenMPContextSelectors(
- SourceLocation Loc,
- llvm::function_ref<void(SourceRange,
- const Sema::OpenMPDeclareVariantCtsSelectorData &)>
- Callback) {
+ SourceLocation Loc, SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
llvm::StringMap<SourceLocation> UsedCtxSets;
do {
// Parse inner context selector set name.
<< getOpenMPClauseName(OMPC_match);
return true;
}
- SmallString<16> Buffer;
+ Sema::OMPCtxStringType Buffer;
StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer);
auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation());
if (!Res.second) {
tok::annot_pragma_openmp_end);
if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
return true;
- OMPDeclareVariantAttr::CtxSelectorSetType CSSKind =
- OMPDeclareVariantAttr::CtxSetUnknown;
- (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorSetType(
- CtxSelectorSetName, CSSKind);
+ OpenMPContextSelectorSetKind CSSKind =
+ getOpenMPContextSelectorSet(CtxSelectorSetName);
llvm::StringMap<SourceLocation> UsedCtx;
do {
switch (CSSKind) {
- case OMPDeclareVariantAttr::CtxSetImplementation:
- parseImplementationSelector(*this, Loc, UsedCtx, Callback);
+ case OMP_CTX_SET_implementation:
+ parseImplementationSelector(*this, Loc, UsedCtx, Data);
break;
- case OMPDeclareVariantAttr::CtxSetUnknown:
+ case OMP_CTX_SET_unknown:
// Skip until either '}', ')', or end of directive.
while (!SkipUntil(tok::r_brace, tok::r_paren,
tok::annot_pragma_openmp_end, StopBeforeMatch))
}
// Parse inner context selectors.
- if (!parseOpenMPContextSelectors(
- Loc, [this, &DeclVarData](
- SourceRange SR,
- const Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
- if (DeclVarData.hasValue())
- Actions.ActOnOpenMPDeclareVariantDirective(
- DeclVarData.getValue().first, DeclVarData.getValue().second,
- SR, Data);
- })) {
+ SmallVector<Sema::OMPCtxSelectorData, 4> Data;
+ if (!parseOpenMPContextSelectors(Loc, Data)) {
// Parse ')'.
(void)T.consumeClose();
// Need to check for extra tokens.
// Skip last tokens.
while (Tok.isNot(tok::annot_pragma_openmp_end))
ConsumeAnyToken();
+ if (DeclVarData.hasValue())
+ Actions.ActOnOpenMPDeclareVariantDirective(
+ DeclVarData.getValue().first, DeclVarData.getValue().second,
+ SourceRange(Loc, Tok.getLocation()), Data);
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
}
void Sema::ActOnOpenMPDeclareVariantDirective(
FunctionDecl *FD, Expr *VariantRef, SourceRange SR,
- const Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
- if (Data.CtxSet == OMPDeclareVariantAttr::CtxSetUnknown ||
- Data.Ctx == OMPDeclareVariantAttr::CtxUnknown)
+ ArrayRef<OMPCtxSelectorData> Data) {
+ if (Data.empty())
return;
- Expr *Score = nullptr;
- if (Data.CtxScore.isUsable()) {
- Score = Data.CtxScore.get();
- if (!Score->isTypeDependent() && !Score->isValueDependent() &&
- !Score->isInstantiationDependent() &&
- !Score->containsUnexpandedParameterPack()) {
- llvm::APSInt Result;
- ExprResult ICE = VerifyIntegerConstantExpression(Score, &Result);
- if (ICE.isInvalid())
- return;
+ SmallVector<Expr *, 4> CtxScores;
+ SmallVector<unsigned, 4> CtxSets;
+ SmallVector<unsigned, 4> Ctxs;
+ SmallVector<StringRef, 4> ImplVendors;
+ bool IsError = false;
+ for (const OMPCtxSelectorData &D : Data) {
+ OpenMPContextSelectorSetKind CtxSet = D.CtxSet;
+ OpenMPContextSelectorKind Ctx = D.Ctx;
+ if (CtxSet == OMP_CTX_SET_unknown || Ctx == OMP_CTX_unknown)
+ return;
+ Expr *Score = nullptr;
+ if (D.Score.isUsable()) {
+ Score = D.Score.get();
+ if (!Score->isTypeDependent() && !Score->isValueDependent() &&
+ !Score->isInstantiationDependent() &&
+ !Score->containsUnexpandedParameterPack()) {
+ Score =
+ PerformOpenMPImplicitIntegerConversion(Score->getExprLoc(), Score)
+ .get();
+ if (Score)
+ Score = VerifyIntegerConstantExpression(Score).get();
+ }
+ } else {
+ Score = ActOnIntegerConstant(SourceLocation(), 0).get();
}
- } else {
- Score = ActOnIntegerConstant(SourceLocation(), 0).get();
+ switch (CtxSet) {
+ case OMP_CTX_SET_implementation:
+ switch (Ctx) {
+ case OMP_CTX_vendor:
+ ImplVendors.append(D.Names.begin(), D.Names.end());
+ break;
+ case OMP_CTX_unknown:
+ llvm_unreachable("Unexpected context selector kind.");
+ }
+ break;
+ case OMP_CTX_SET_unknown:
+ llvm_unreachable("Unexpected context selector set kind.");
+ }
+ IsError = IsError || !Score;
+ CtxSets.push_back(CtxSet);
+ Ctxs.push_back(Ctx);
+ CtxScores.push_back(Score);
+ }
+ if (!IsError) {
+ auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
+ Context, VariantRef, CtxScores.begin(), CtxScores.size(),
+ CtxSets.begin(), CtxSets.size(), Ctxs.begin(), Ctxs.size(),
+ ImplVendors.begin(), ImplVendors.size(), SR);
+ FD->addAttr(NewAttr);
}
- auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
- Context, VariantRef, Score, Data.CtxSet, Data.Ctx,
- Data.ImplVendors.begin(), Data.ImplVendors.size(), SR);
- FD->addAttr(NewAttr);
}
void Sema::markOpenMPDeclareVariantFuncsReferenced(SourceLocation Loc,
if (Expr *E = Attr.getVariantFuncRef())
VariantFuncRef = Subst(E);
- ExprResult Score;
- if (Expr *E = Attr.getScore())
- Score = Subst(E);
-
// 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.
- Sema::OpenMPDeclareVariantCtsSelectorData Data(
- Attr.getCtxSelectorSet(), Attr.getCtxSelector(),
- llvm::makeMutableArrayRef(Attr.implVendors_begin(),
- Attr.implVendors_size()),
- Score);
+ SmallVector<Sema::OMPCtxSelectorData, 4> Data;
+ for (unsigned I = 0, E = Attr.scores_size(); I < E; ++I) {
+ ExprResult Score;
+ if (Expr *E = *std::next(Attr.scores_begin(), I))
+ Score = Subst(E);
+ // Instantiate the attribute.
+ auto CtxSet = static_cast<OpenMPContextSelectorSetKind>(
+ *std::next(Attr.ctxSelectorSets_begin(), I));
+ auto Ctx = static_cast<OpenMPContextSelectorKind>(
+ *std::next(Attr.ctxSelectors_begin(), I));
+ switch (CtxSet) {
+ case OMP_CTX_SET_implementation:
+ switch (Ctx) {
+ case OMP_CTX_vendor:
+ Data.emplace_back(CtxSet, Ctx, Score, Attr.implVendors());
+ break;
+ case OMP_CTX_unknown:
+ llvm_unreachable("Unexpected context selector kind.");
+ }
+ break;
+ case OMP_CTX_SET_unknown:
+ llvm_unreachable("Unexpected context selector set kind.");
+ }
+ }
S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first,
DeclVarData.getValue().second,
Attr.getRange(), Data);