diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -17,6 +17,7 @@ #include "clang/AST/AttrIterator.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/AST/OpenMPClause.h" #include "clang/AST/Type.h" #include "clang/Basic/AttrKinds.h" #include "clang/Basic/AttributeCommonInfo.h" diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h --- a/clang/include/clang/AST/OpenMPClause.h +++ b/clang/include/clang/AST/OpenMPClause.h @@ -30,6 +30,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/Frontend/OpenMP/OMPContext.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" @@ -6295,6 +6296,41 @@ #include "clang/Basic/OpenMPKinds.def" }; +/// Helper datastructure representing the traits in a match clause of an +/// `declare variant` or `metadirective`. The outer level is an ordered +/// collection of selector sets, each with an associated kind and an ordered +/// collection of selectors. A selector has a kind, an optional score/condition, +/// and an ordered collection of properties. +struct OpenMPTraitInfo { + struct OpenMPTraitProperty { + llvm::omp::TraitProperty Kind = llvm::omp::TraitProperty::invalid; + }; + struct OpenMPTraitSelector { + Expr *ScoreOrCondition = nullptr; + llvm::omp::TraitSelector Kind = llvm::omp::TraitSelector::invalid; + llvm::SmallVector Properties; + }; + struct OpenMPTraitSet { + llvm::omp::TraitSet Kind = llvm::omp::TraitSet::invalid; + llvm::SmallVector Selectors; + }; + + /// The outermost level of selector sets. + llvm::SmallVector Sets; + + /// Create a variant match infor object from this trait info object. While the + /// former is a flat representation the actual main difference is that the + /// latter uses clang::Expr to store the score/condition while the former is + /// independent of clang. Thus, expressions and conditions are evaluated in + /// this method. + void getAsVariantMatchInfo(ASTContext &ASTCtx, + llvm::omp::VariantMatchInfo &VMI) const; + + /// Print a humand readable representation into \p OS. + void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const; +}; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const OpenMPTraitInfo &TI); + } // namespace clang #endif // LLVM_CLANG_AST_OPENMPCLAUSE_H diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -180,6 +180,11 @@ class NamedArgument : Argument; +// An argument of type \p type with name \p name. +class GenericPointerArgument : Argument { + string Type = type; +} + class TypeArgument : Argument; class UnsignedArgument : Argument; class VariadicUnsignedArgument : Argument; @@ -3323,20 +3328,9 @@ let Documentation = [OMPDeclareVariantDocs]; let Args = [ ExprArgument<"VariantFuncRef">, - VariadicExprArgument<"Scores">, - VariadicUnsignedArgument<"CtxSelectorSets">, - VariadicUnsignedArgument<"CtxSelectors">, - VariadicStringArgument<"ImplVendors">, - VariadicStringArgument<"DeviceKinds"> + GenericPointerArgument<"TraitInfos", "OpenMPTraitInfo*">, ]; let AdditionalMembers = [{ - 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 { if (const Expr *E = getVariantFuncRef()) { @@ -3344,66 +3338,8 @@ E->printPretty(OS, nullptr, Policy); OS << ")"; } - // TODO: add printing of real context selectors. OS << " match("; - int Used[OMP_CTX_SET_unknown] = {0}; - for (unsigned I = 0, E = ctxSelectorSets_size(); I < E; ++I) { - auto CtxSet = static_cast( - *std::next(ctxSelectorSets_begin(), I)); - if (Used[CtxSet]) - continue; - if (I > 0) - OS << ","; - switch (CtxSet) { - case OMP_CTX_SET_implementation: - OS << "implementation={"; - break; - case OMP_CTX_SET_device: - OS << "device={"; - break; - case OMP_CTX_SET_unknown: - llvm_unreachable("Unknown context selector set."); - } - Used[CtxSet] = 1; - for (unsigned K = I, EK = ctxSelectors_size(); K < EK; ++K) { - auto CtxSetK = static_cast( - *std::next(ctxSelectorSets_begin(), K)); - if (CtxSet != CtxSetK) - continue; - if (K != I) - OS << ","; - auto Ctx = static_cast( - *std::next(ctxSelectors_begin(), K)); - switch (Ctx) { - case OMP_CTX_vendor: - assert(CtxSet == OMP_CTX_SET_implementation && - "Expected implementation context selector set."); - OS << "vendor("; - printScore(OS, Policy, K); - if (implVendors_size() > 0) { - OS << *implVendors(). begin(); - for (StringRef VendorName : llvm::drop_begin(implVendors(), 1)) - OS << ", " << VendorName; - } - OS << ")"; - break; - case OMP_CTX_kind: - assert(CtxSet == OMP_CTX_SET_device && - "Expected device context selector set."); - OS << "kind("; - if (deviceKinds_size() > 0) { - OS << *deviceKinds().begin(); - for (StringRef KindName : llvm::drop_begin(deviceKinds(), 1)) - OS << ", " << KindName; - } - OS << ")"; - break; - case OMP_CTX_unknown: - llvm_unreachable("Unknown context selector."); - } - } - OS << "}"; - } + traitInfos->print(OS, Policy); OS << ")"; } }]; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1211,30 +1211,53 @@ "expected declarator on 'omp declare mapper' directive">; def err_omp_declare_variant_wrong_clause : Error< "expected '%0' clause on 'omp declare variant' directive">; -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">, +def warn_omp_declare_variant_string_literal_or_identifier : Warning< + "expected identifier or string literal describing a context %select{set|selector|property}0, %select{set|selector|property}0 skipped">, + InGroup; +def note_omp_declare_variant_ctx_options : Note< + "context %select{set|selector|property}0 options are: %1">; +def warn_omp_declare_variant_expected : Warning< + "expected '%0' after the %1, '%0' assumed">, + InGroup; +def warn_omp_declare_variant_ctx_not_a_property : Warning< + "'%0' is not a valid context property for the context selector '%1' and the context set '%2', property ignored">, + InGroup; +def note_omp_declare_variant_ctx_is_a : Note< + "'%0' is a context %select{set|selector|property}1 not a context %select{set|selector|property}2">; +def note_omp_declare_variant_ctx_try : Note< + "try 'match(%0={%1%2})'">; +def warn_omp_declare_variant_ctx_not_a_selector : Warning< + "'%0' is not a valid context selector for the context set '%1', selector ignored">, + InGroup; +def warn_omp_declare_variant_ctx_not_a_set : Warning< + "'%0' is not a valid context set in a `declare variant`, set ignored">, + InGroup; +def warn_omp_declare_variant_ctx_mutiple_use : Warning< + "the context %select{set|selector|property}0 '%1' was used already in the same 'omp declare variant' directiv, %select{set|selector|property}0 ignored">, InGroup; -def err_omp_declare_variant_item_expected : Error< - "expected %0 in '%1' context selector of '%2' selector set of 'omp declare variant' directive">; -def err_omp_declare_variant_ctx_set_mutiple_use : Error< - "context selector set '%0' is used already in the same 'omp declare variant' directive">; -def note_omp_declare_variant_ctx_set_used_here : Note< - "previously context selector set '%0' used here">; -def err_omp_expected_comma_brace : Error<"expected '}' or ',' after '%0'">; -def err_omp_declare_variant_ctx_mutiple_use : Error< - "context trait selector '%0' is used already in the same '%1' context selector set of 'omp declare variant' directive">; def note_omp_declare_variant_ctx_used_here : Note< - "previously context trait selector '%0' used here">; + "the previous context %select{set|selector|property}0 '%1' used here">; +def note_omp_declare_variant_ctx_continue_here : Note< + "the ignored %select{set|selector|property}0 spans until here">; +def warn_omp_ctx_incompatible_selector_for_set : Warning< + "the context selector '%0' is not valid for the context set '%1', selector ignored">, + InGroup; +def note_omp_ctx_compatible_set_for_selector : Note< + "the context selector '%0' can be nested in the context set '%1', try 'match(%1={%0%select{|(property)}2})'">; +def warn_omp_ctx_selector_without_properties : Warning< + "the context selector '%0' in context set '%1' requires a context property defined in parenthesis, selector ignored">, + InGroup; +def warn_omp_ctx_incompatible_property_for_selector : Warning< + "the context property '%0' is not valid for the context selector '%1' and the context set '%2', property ignored">, + InGroup; +def note_omp_ctx_compatible_set_and_selector_for_property : Note< + "the context property '%0' can be nested in the context selector '%1' which is nested in the context set '%2', try 'match(%2={%1(%0)})'">; +def warn_omp_ctx_incompatible_score_for_property : Warning< + "the context selector '%0' in the context set '%1' cannot have a score ('%2'), score ignored">, + InGroup; def warn_omp_more_one_device_type_clause : Warning< "more than one 'device_type' clause is specified">, InGroup; -def err_omp_wrong_device_kind_trait : Error< - "unknown '%0' device kind trait in the 'device' context selector set, expected" - " one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'">; // Pragma loop support. def err_pragma_loop_missing_argument : Error< diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h --- a/clang/include/clang/Basic/OpenMPKinds.h +++ b/clang/include/clang/Basic/OpenMPKinds.h @@ -19,45 +19,6 @@ 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 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 - 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. using OpenMPDirectiveKind = llvm::omp::Directive; diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def --- a/clang/include/clang/Basic/OpenMPKinds.def +++ b/clang/include/clang/Basic/OpenMPKinds.def @@ -206,23 +206,6 @@ #ifndef OPENMP_DECLARE_VARIANT_CLAUSE #define OPENMP_DECLARE_VARIANT_CLAUSE(Name) #endif -#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_SELECTOR_SET(device) - -// OpenMP context selectors. -OPENMP_CONTEXT_SELECTOR(vendor) -OPENMP_CONTEXT_SELECTOR(kind) // OpenMP clauses. OPENMP_CLAUSE(allocator, OMPAllocatorClause) @@ -1045,13 +1028,6 @@ // 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_CONTEXT_SELECTOR -#undef OPENMP_CONTEXT_SELECTOR_SET -#undef OPENMP_MATCH_KIND #undef OPENMP_DECLARE_VARIANT_CLAUSE #undef OPENMP_DEVICE_TYPE_KIND #undef OPENMP_ALLOCATE_CLAUSE diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2858,11 +2858,38 @@ 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, - SmallVectorImpl &Data); + + template + KindType getOpenMPCtxKindForToken(llvm::StringMap &Seen, + unsigned Lvl, ArgsTy... Args); + void + parseOMPTraitPropertyKind(OpenMPTraitInfo::OpenMPTraitProperty &TIProperty, + llvm::omp::TraitSet Set, + llvm::omp::TraitSelector Selector); + void + parseOMPTraitSelectorKind(OpenMPTraitInfo::OpenMPTraitSelector &TISelector, + llvm::omp::TraitSet Set, + llvm::StringMap &Seen); + void parseOMPTraitSetKind(OpenMPTraitInfo::OpenMPTraitSet &TISet, + llvm::StringMap &Seen); + + /// Parses an OpenMP context property. + void + parseOpenMPContextProperty(OpenMPTraitInfo::OpenMPTraitSelector &TISelector, + llvm::omp::TraitSet Set); + + /// Parses an OpenMP context selector. + void + parseOpenMPContextSelector(OpenMPTraitInfo::OpenMPTraitSelector &TISelector, + llvm::omp::TraitSet Set, + llvm::StringMap &SeenSelectors); + + /// Parses an OpenMP context selector set. + void parseOpenMPContextSelectorSet(OpenMPTraitInfo::OpenMPTraitSet &TISet, + llvm::StringMap &SeenSets); + + /// Parses an OpenMP context. + bool parseOpenMPContext(SourceLocation Loc, OpenMPTraitInfo &TI); /// Parse clauses for '#pragma omp declare variant'. void ParseOMPDeclareVariantClauses(DeclGroupPtrTy Ptr, CachedTokens &Toks, diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -9446,9 +9446,6 @@ public: /// Struct to store the context selectors info for declare variant directive. - using OMPCtxStringType = SmallString<8>; - using OMPCtxSelectorData = - OpenMPCtxSelectorData, ExprResult>; /// Checks if the variant/multiversion functions are compatible. bool areMultiversionVariantFunctionsCompatible( @@ -9921,8 +9918,9 @@ /// 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> checkOpenMPDeclareVariantFunction( - DeclGroupPtrTy DG, Expr *VariantRef, SourceRange SR); + Optional> + checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, + SourceRange SR); /// Called on well-formed '\#pragma omp declare variant' after parsing of /// the associated method/function. @@ -9930,11 +9928,9 @@ /// applied to. /// \param VariantRef Expression that references the variant function, which /// must be used instead of the original one, specified in \p DG. - /// \param Data Set of context-specific data for the specified context - /// selector. + /// \param TI The context traits associated with the function variant. void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, - SourceRange SR, - ArrayRef Data); + OpenMPTraitInfo *TI, SourceRange SR); OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h --- a/clang/include/clang/Serialization/ASTRecordReader.h +++ b/clang/include/clang/Serialization/ASTRecordReader.h @@ -22,6 +22,7 @@ #include "llvm/ADT/APSInt.h" namespace clang { +struct OpenMPTraitInfo; /// An object for streaming information from a record. class ASTRecordReader @@ -258,9 +259,18 @@ return Reader->ReadCXXTemporary(*F, Record, Idx); } + /// Read prototype for GenericPointerArguments in Attributes. Requires a + /// specialization for the used UserType. + template T *readUserType(); + /// Read an OpenMP clause, advancing Idx. OMPClause *readOMPClause(); + /// Read an OpenMP trait info object. + OpenMPTraitInfo *readOpenMPTraitInfo(); + + template <> OpenMPTraitInfo *readUserType() { return readOpenMPTraitInfo(); } + /// Read a source location, advancing Idx. SourceLocation readSourceLocation() { return Reader->ReadSourceLocation(*F, Record, Idx); diff --git a/clang/include/clang/Serialization/ASTRecordWriter.h b/clang/include/clang/Serialization/ASTRecordWriter.h --- a/clang/include/clang/Serialization/ASTRecordWriter.h +++ b/clang/include/clang/Serialization/ASTRecordWriter.h @@ -266,8 +266,18 @@ void AddCXXDefinitionData(const CXXRecordDecl *D); + /// Write prototype for GenericPointerArguments in Attributes. Requires a + /// specialization for the used UserType. + template void writeUserType(T *); + void writeOMPClause(OMPClause *C); + void writeOpenMPTraitInfo(const OpenMPTraitInfo *TI); + + template <> void writeUserType(OpenMPTraitInfo *TI) { + writeOpenMPTraitInfo(TI); + } + /// Emit a string. void AddString(StringRef Str) { return Writer->AddString(Str, *Record); diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp --- a/clang/lib/AST/OpenMPClause.cpp +++ b/clang/lib/AST/OpenMPClause.cpp @@ -1648,3 +1648,107 @@ } } +void OpenMPTraitInfo::getAsVariantMatchInfo( + ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const { + for (const OpenMPTraitSet &Set : Sets) { + for (const OpenMPTraitSelector &Selector : Set.Selectors) { + + // User conditions are special as we evaluate the condition here. + if (Selector.Kind == llvm::omp::TraitSelector::user_condition) { + assert(Selector.ScoreOrCondition && + "Ill-formed user condition, expected condition expression!"); + assert(Selector.Properties.size() == 1 && + Selector.Properties.front().Kind == + llvm::omp::TraitProperty::user_condition_unknown && + "Ill-formed user condition, expected unknown trait property!"); + + llvm::APInt CondVal = + Selector.ScoreOrCondition->EvaluateKnownConstInt(ASTCtx); + if (CondVal.isNullValue()) + VMI.addTrait(llvm::omp::TraitProperty::user_condition_false); + else + VMI.addTrait(llvm::omp::TraitProperty::user_condition_true); + continue; + } + + llvm::APInt Score; + llvm::APInt *ScorePtr = nullptr; + if (Selector.ScoreOrCondition) { + Score = Selector.ScoreOrCondition->EvaluateKnownConstInt(ASTCtx); + ScorePtr = &Score; + } + for (const OpenMPTraitProperty &Property : Selector.Properties) + VMI.addTrait(Set.Kind, Property.Kind, ScorePtr); + + if (Set.Kind != llvm::omp::TraitSet::construct) + continue; + + // TODO: This might not hold once we implement SIMD properly. + assert(Selector.Properties.size() == 1 && + Selector.Properties.front().Kind == + llvm::omp::getOpenMPContextTraitPropertyForSelector( + Selector.Kind) && + "Ill-formed construct selector!"); + + VMI.ConstructTraits.push_back(Selector.Properties.front().Kind); + } + } +} + +void OpenMPTraitInfo::print(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const { + bool FirstSet = true; + for (const OpenMPTraitInfo::OpenMPTraitSet &Set : Sets) { + if (!FirstSet) + OS << ", "; + FirstSet = false; + OS << llvm::omp::getOpenMPContextTraitSetName(Set.Kind) << "={"; + + bool FirstSelector = true; + for (const OpenMPTraitInfo::OpenMPTraitSelector &Selector : Set.Selectors) { + if (!FirstSelector) + OS << ", "; + FirstSelector = false; + OS << llvm::omp::getOpenMPContextTraitSelectorName(Selector.Kind); + + bool AllowsTraitScore = false; + bool RequiresProperty = false; + llvm::omp::isValidTraitSelectorForTraitSet( + Selector.Kind, Set.Kind, AllowsTraitScore, RequiresProperty); + + if (!RequiresProperty) + continue; + + OS << "("; + if (Selector.Kind == llvm::omp::TraitSelector::user_condition) { + Selector.ScoreOrCondition->printPretty(OS, nullptr, Policy); + } else { + + if (Selector.ScoreOrCondition) { + OS << "score("; + Selector.ScoreOrCondition->printPretty(OS, nullptr, Policy); + OS << "): "; + } + + bool FirstProperty = true; + for (const OpenMPTraitInfo::OpenMPTraitProperty &Property : + Selector.Properties) { + if (!FirstProperty) + OS << ", "; + FirstProperty = false; + OS << llvm::omp::getOpenMPContextTraitPropertyName(Property.Kind); + } + } + OS << ")"; + } + OS << "}"; + } +} + +llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS, + const OpenMPTraitInfo &TI) { + LangOptions LO; + PrintingPolicy Policy(LO); + TI.print(OS, Policy); + return OS; +} diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -20,49 +20,6 @@ using namespace clang; using namespace llvm::omp; -OpenMPContextSelectorSetKind -clang::getOpenMPContextSelectorSet(llvm::StringRef Str) { - return llvm::StringSwitch(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(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"); -} - OpenMPClauseKind clang::getOpenMPClauseKind(StringRef Str) { // 'flush' clause cannot be specified explicitly, because this is an implicit // clause for 'flush' directive. If the 'flush' clause is explicitly specified diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -11067,256 +11067,34 @@ return Address(Addr, Align); } -namespace { -using OMPContextSelectorData = - OpenMPCtxSelectorData, llvm::APSInt>; -using CompleteOMPContextSelectorData = SmallVector; -} // anonymous namespace - -/// Checks current context and returns true if it matches the context selector. -template -static bool checkContext(const OMPContextSelectorData &Data, - Arguments... Params) { - 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()} context selector. -/// \returns true iff ="llvm", false otherwise. -template <> -bool checkContext( - const OMPContextSelectorData &Data) { - return llvm::all_of(Data.Names, - [](StringRef S) { return !S.compare_lower("llvm"); }); -} - -/// Checks for device={kind()} context selector. -/// \returns true if ="host" and compilation is for host. -/// true if ="nohost" and compilation is for device. -/// true if ="cpu" and compilation is for Arm, X86 or PPC CPU. -/// true if ="gpu" and compilation is for NVPTX or AMDGCN. -/// false otherwise. -template <> -bool checkContext( - const OMPContextSelectorData &Data, CodeGenModule &CGM) { - for (StringRef Name : Data.Names) { - if (!Name.compare_lower("host")) { - if (CGM.getLangOpts().OpenMPIsDevice) - return false; - continue; - } - if (!Name.compare_lower("nohost")) { - if (!CGM.getLangOpts().OpenMPIsDevice) - return false; - continue; - } - switch (CGM.getTriple().getArch()) { - case llvm::Triple::arm: - case llvm::Triple::armeb: - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_be: - case llvm::Triple::aarch64_32: - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::ppc64le: - case llvm::Triple::x86: - case llvm::Triple::x86_64: - if (Name.compare_lower("cpu")) - return false; - break; - case llvm::Triple::amdgcn: - case llvm::Triple::nvptx: - case llvm::Triple::nvptx64: - if (Name.compare_lower("gpu")) - return false; - break; - case llvm::Triple::UnknownArch: - case llvm::Triple::arc: - case llvm::Triple::avr: - case llvm::Triple::bpfel: - case llvm::Triple::bpfeb: - case llvm::Triple::hexagon: - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - case llvm::Triple::msp430: - case llvm::Triple::r600: - case llvm::Triple::riscv32: - case llvm::Triple::riscv64: - case llvm::Triple::sparc: - case llvm::Triple::sparcv9: - case llvm::Triple::sparcel: - case llvm::Triple::systemz: - case llvm::Triple::tce: - case llvm::Triple::tcele: - case llvm::Triple::thumb: - case llvm::Triple::thumbeb: - case llvm::Triple::xcore: - case llvm::Triple::le32: - case llvm::Triple::le64: - case llvm::Triple::amdil: - case llvm::Triple::amdil64: - case llvm::Triple::hsail: - case llvm::Triple::hsail64: - case llvm::Triple::spir: - case llvm::Triple::spir64: - case llvm::Triple::kalimba: - case llvm::Triple::shave: - case llvm::Triple::lanai: - case llvm::Triple::wasm32: - case llvm::Triple::wasm64: - case llvm::Triple::renderscript32: - case llvm::Triple::renderscript64: - return false; - } - } - return true; -} - -bool matchesContext(CodeGenModule &CGM, - const CompleteOMPContextSelectorData &ContextData) { - for (const OMPContextSelectorData &Data : ContextData) { - switch (Data.Ctx) { - case OMP_CTX_vendor: - assert(Data.CtxSet == OMP_CTX_SET_implementation && - "Expected implementation context selector set."); - if (!checkContext(Data)) - return false; - break; - case OMP_CTX_kind: - assert(Data.CtxSet == OMP_CTX_SET_device && - "Expected device context selector set."); - if (!checkContext(Data, - CGM)) - return false; - break; - case OMP_CTX_unknown: - llvm_unreachable("Unknown context selector 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( - *std::next(A->ctxSelectorSets_begin(), I)); - auto Ctx = static_cast( - *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 (Ctx) { - case OMP_CTX_vendor: - assert(CtxSet == OMP_CTX_SET_implementation && - "Expected implementation context selector set."); - Data.back().Names = - llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end()); - break; - case OMP_CTX_kind: - assert(CtxSet == OMP_CTX_SET_device && - "Expected device context selector set."); - Data.back().Names = - llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end()); - break; - case OMP_CTX_unknown: - llvm_unreachable("Unknown context selector kind."); - } - } - return Data; -} - -static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS, - const CompleteOMPContextSelectorData &RHS) { - llvm::SmallDenseMap, llvm::StringSet<>, 4> RHSData; - for (const OMPContextSelectorData &D : RHS) { - auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx)); - Pair.getSecond().insert(D.Names.begin(), D.Names.end()); - } - bool AllSetsAreEqual = true; - for (const OMPContextSelectorData &D : LHS) { - auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx)); - if (It == RHSData.end()) - return false; - if (D.Names.size() > It->getSecond().size()) - return false; - if (llvm::set_union(It->getSecond(), D.Names)) - return false; - AllSetsAreEqual = - AllSetsAreEqual && (D.Names.size() == It->getSecond().size()); - } - - return LHS.size() != RHS.size() || !AllSetsAreEqual; -} - -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); - bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS); - if (RHSIsSubsetOfLHS) { - LHSScore = llvm::APSInt::get(0); - } else { - 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); - if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) { - RHSScore = llvm::APSInt::get(0); - } else { - 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 /// selector. static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, const FunctionDecl *FD) { if (!FD->hasAttrs() || !FD->hasAttr()) return FD; - // Iterate through all DeclareVariant attributes and check context selectors. - const OMPDeclareVariantAttr *TopMostAttr = nullptr; - CompleteOMPContextSelectorData TopMostData; + + SmallVector VariantExprs; + SmallVector VMIs; for (const auto *A : FD->specific_attrs()) { - CompleteOMPContextSelectorData Data = - translateAttrToContextSelectorData(CGM.getContext(), A); - if (!matchesContext(CGM, Data)) + const OpenMPTraitInfo *TI = A->getTraitInfos(); + if (!TI) continue; - // If the attribute matches the context, find the attribute with the highest - // score. - if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) { - TopMostAttr = A; - TopMostData.swap(Data); - } + VMIs.push_back(VariantMatchInfo()); + TI->getAsVariantMatchInfo(CGM.getContext(), VMIs.back()); + VariantExprs.push_back(A->getVariantFuncRef()); } - if (!TopMostAttr) + + OMPContext Ctx(CGM.getLangOpts().OpenMPIsDevice, CGM.getTriple()); + // TODO: Keep the context in the OMPIRBuilder so we can add constructs as we + // build them. + + int BestMatchIdx = getBestVariantMatchForContext(VMIs, Ctx); + if (BestMatchIdx < 0) return FD; + return cast( - cast(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) + cast(VariantExprs[BestMatchIdx]->IgnoreParenImpCasts()) ->getDecl()); } diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -18,6 +18,7 @@ #include "clang/Sema/Scope.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/UniqueVector.h" +#include "llvm/Frontend/OpenMP/OMPContext.h" using namespace clang; using namespace llvm::omp; @@ -804,10 +805,215 @@ LinModifiers, Steps, SourceRange(Loc, EndLoc)); } +static StringRef +getNameFromIdOrString(Parser &P, Token &Tok, unsigned Lvl, + llvm::function_ref StringLiteralParser) { + if (Tok.is(tok::identifier)) { + llvm::SmallString<16> Buffer; + StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer); + (void)P.ConsumeToken(); + return Name; + } + + if (tok::isStringLiteral(Tok.getKind())) + return StringLiteralParser(); + + P.Diag(Tok.getLocation(), + diag::warn_omp_declare_variant_string_literal_or_identifier) + << Lvl; + return ""; +} +static bool checkForDuplicates(Parser &P, StringRef Name, + SourceLocation NameLoc, + llvm::StringMap &Seen, + unsigned Lvl) { + auto Res = Seen.try_emplace(Name, NameLoc); + if (Res.second) + return false; + + // Each trait-set-selector-name and trait-selector-name can only be + // specified once. + P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use) + << Lvl << Name; + P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) + << Lvl << Name; + return true; +} + +void Parser::parseOMPTraitPropertyKind( + OpenMPTraitInfo::OpenMPTraitProperty &TIProperty, llvm::omp::TraitSet Set, + llvm::omp::TraitSelector Selector) { + const unsigned Lvl = 2; + TIProperty.Kind = TraitProperty::invalid; + + SourceLocation NameLoc = Tok.getLocation(); + auto StringLiteralParser = [this]() -> StringRef { + ExprResult Res = ParseStringLiteralExpression(true); + return Res.isUsable() ? Res.getAs()->getString() : ""; + }; + StringRef Name = getNameFromIdOrString(*this, Tok, Lvl, StringLiteralParser); + if (Name.empty()) { + Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) + << Lvl << listOpenMPContextTraitProperties(Set, Selector); + return; + } + + TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Name); + if (TIProperty.Kind != TraitProperty::invalid) + return; + + // It follows diagnosis and helping notes. + // TODO: We should move the diagnosis string generation into libFrontend. + Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property) + << Name << getOpenMPContextTraitSelectorName(Selector) + << getOpenMPContextTraitSetName(Set); + + TraitSet SetForName = getOpenMPContextTraitSetKind(Name); + if (SetForName != TraitSet::invalid) { + Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) + << Name << /* Set lvl */ 0 << Lvl; + Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) + << Name << "" + << "()"; + return; + } + TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name); + if (SelectorForName != TraitSelector::invalid) { + Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) + << Name << /* Selector lvl */ 1 << Lvl; + bool AllowsTraitScore = false; + bool RequiresProperty = false; + isValidTraitSelectorForTraitSet( + SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName), + AllowsTraitScore, RequiresProperty); + Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) + << getOpenMPContextTraitSetName( + getOpenMPContextTraitSetForSelector(SelectorForName)) + << Name << (RequiresProperty ? "()" : ""); + return; + } + for (auto &PotentialSet : {TraitSet::construct, TraitSet::user, + TraitSet::implementation, TraitSet::device}) { + TraitProperty PropertyForName = + getOpenMPContextTraitPropertyKind(PotentialSet, Name); + if (PropertyForName == TraitProperty::invalid) + continue; + Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) + << getOpenMPContextTraitSetName( + getOpenMPContextTraitSetForProperty(PropertyForName)) + << getOpenMPContextTraitSelectorName( + getOpenMPContextTraitSelectorForProperty(PropertyForName)) + << ("(" + Name + ")").str(); + return; + } + Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) + << Lvl << listOpenMPContextTraitProperties(Set, Selector); +} + +/// Parses an OpenMP context property. +/// +void Parser::parseOpenMPContextProperty( + OpenMPTraitInfo::OpenMPTraitSelector &TISelector, llvm::omp::TraitSet Set) { + assert(TISelector.Kind != TraitSelector::user_condition && + "User conditions are special properties not handled here!"); + const unsigned Lvl = 2; + + SourceLocation PropertyLoc = Tok.getLocation(); + OpenMPTraitInfo::OpenMPTraitProperty TIProperty; + parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind); + + // If we have an invalid property here we already issued a warning. + if (TIProperty.Kind == TraitProperty::invalid) { + if (PropertyLoc != Tok.getLocation()) + Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) + << Lvl; + return; + } + + if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind, + TISelector.Kind, Set)) { + // If we make it here the property, selector, set, score, condition, ... are + // all valid (or have been corrected). Thus we can record the property. + TISelector.Properties.push_back(TIProperty); + return; + } + + Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector) + << getOpenMPContextTraitPropertyName(TIProperty.Kind) + << getOpenMPContextTraitSelectorName(TISelector.Kind) + << getOpenMPContextTraitSetName(Set); + Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property) + << getOpenMPContextTraitPropertyName(TIProperty.Kind) + << getOpenMPContextTraitSelectorName( + getOpenMPContextTraitSelectorForProperty(TIProperty.Kind)) + << getOpenMPContextTraitSetName( + getOpenMPContextTraitSetForProperty(TIProperty.Kind)); + Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) + << Lvl; +} + +void Parser::parseOMPTraitSelectorKind( + OpenMPTraitInfo::OpenMPTraitSelector &TISelector, llvm::omp::TraitSet Set, + llvm::StringMap &Seen) { + const unsigned Lvl = 1; + TISelector.Kind = TraitSelector::invalid; + + SourceLocation NameLoc = Tok.getLocation(); + auto StringLiteralParser = [this]() -> StringRef { + ExprResult Res = ParseStringLiteralExpression(true); + return Res.isUsable() ? Res.getAs()->getString() : ""; + }; + StringRef Name = getNameFromIdOrString(*this, Tok, Lvl, StringLiteralParser); + if (Name.empty()) { + Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) + << Lvl << listOpenMPContextTraitSelectors(Set); + return; + } + + TISelector.Kind = getOpenMPContextTraitSelectorKind(Name); + if (TISelector.Kind != TraitSelector::invalid) { + if (checkForDuplicates(*this, Name, NameLoc, Seen, Lvl)) + TISelector.Kind = TraitSelector::invalid; + return; + } + + // It follows diagnosis and helping notes. + Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector) + << Name << getOpenMPContextTraitSetName(Set); + + TraitSet SetForName = getOpenMPContextTraitSetKind(Name); + if (SetForName != TraitSet::invalid) { + Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) + << Name << /* Set lvl */ 0 << Lvl; + Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) + << Name << "" + << ""; + return; + } + for (auto &PotentialSet : {TraitSet::construct, TraitSet::user, + TraitSet::implementation, TraitSet::device}) { + TraitProperty PropertyForName = + getOpenMPContextTraitPropertyKind(PotentialSet, Name); + if (PropertyForName == TraitProperty::invalid) + continue; + Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) + << Name << /* Property lvl */ 2 << Lvl; + Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) + << getOpenMPContextTraitSetName( + getOpenMPContextTraitSetForProperty(PropertyForName)) + << getOpenMPContextTraitSelectorName( + getOpenMPContextTraitSelectorForProperty(PropertyForName)) + << ("(" + Name + ")").str(); + return; + } + Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) + << Lvl << listOpenMPContextTraitSelectors(Set); +} + /// Parse optional 'score' '(' ')' ':'. static ExprResult parseContextScore(Parser &P) { ExprResult ScoreExpr; - Sema::OMPCtxStringType Buffer; + llvm::SmallString<16> Buffer; StringRef SelectorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); if (!SelectorName.equals("score")) @@ -819,246 +1025,269 @@ if (P.getCurToken().is(tok::colon)) (void)P.ConsumeAnyToken(); else - P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon) - << "context selector score clause"; + P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected) + << "':'" + << "score expression"; return ScoreExpr; } -/// Parse context selector for 'implementation' selector set: -/// 'vendor' '(' [ 'score' '(' ')' ':' ] { ',' } -/// ')' -static void -parseImplementationSelector(Parser &P, SourceLocation Loc, - llvm::StringMap &UsedCtx, - SmallVectorImpl &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; - } - Sema::OMPCtxStringType Buffer; - StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer); - auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation()); - if (!Res.second) { - // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. - // Each trait-selector-name can only be specified once. - P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use) - << CtxSelectorName << "implementation"; - P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) - << CtxSelectorName; - } - OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName); - (void)P.ConsumeToken(); - switch (CSKind) { - 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()); - ExprResult Score = parseContextScore(P); - llvm::UniqueVector Vendors; - do { - // Parse . - StringRef VendorName; - if (Tok.is(tok::identifier)) { - Buffer.clear(); - VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); - (void)P.ConsumeToken(); - if (!VendorName.empty()) - Vendors.insert(VendorName); - } else { - P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected) - << "vendor identifier" - << "vendor" - << "implementation"; +/// Parses an OpenMP context selector. +/// +/// ['('[] [, ]* ')'] +void Parser::parseOpenMPContextSelector( + OpenMPTraitInfo::OpenMPTraitSelector &TISelector, llvm::omp::TraitSet Set, + llvm::StringMap &SeenSelectors) { + const unsigned Lvl = 1; + auto OuterPC = ParenCount; + + // If anything went wrong we issue an error or warning and then skip the rest + // of the selector. However, commas are ambiguous so we look for the nesting + // of parenthesis here as well. + auto FinishSelector = [OuterPC, this]() -> void { + bool Done = false; + while (!Done) { + while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma, + tok::annot_pragma_openmp_end}, + StopBeforeMatch)) + ; + if (Tok.is(tok::r_paren) && OuterPC > ParenCount) + (void)ConsumeParen(); + if (OuterPC <= ParenCount) { + Done = true; + break; } - if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) { - P.Diag(Tok, diag::err_expected_punc) - << (VendorName.empty() ? "vendor name" : VendorName); + if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) { + Done = true; + break; } - } while (Tok.is(tok::identifier)); - // Parse ')'. - (void)T.consumeClose(); - if (!Vendors.empty()) - Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors); - break; + (void)ConsumeAnyToken(); + } + Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) + << Lvl; + }; + + SourceLocation SelectorLoc = Tok.getLocation(); + parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors); + if (TISelector.Kind == TraitSelector::invalid) + return FinishSelector(); + + bool AllowsTraitScore = false; + bool RequiresProperty = false; + if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore, + RequiresProperty)) { + Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set) + << getOpenMPContextTraitSelectorName(TISelector.Kind) + << getOpenMPContextTraitSetName(Set); + Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector) + << getOpenMPContextTraitSelectorName(TISelector.Kind) + << getOpenMPContextTraitSetName( + getOpenMPContextTraitSetForSelector(TISelector.Kind)) + << RequiresProperty; + return FinishSelector(); + } + + if (!RequiresProperty) { + TISelector.Properties.push_back( + {getOpenMPContextTraitPropertyForSelector(TISelector.Kind)}); + return; } - case OMP_CTX_kind: - case OMP_CTX_unknown: - 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)) - ; + + if (!Tok.is(tok::l_paren)) { + Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties) + << getOpenMPContextTraitSelectorName(TISelector.Kind) + << getOpenMPContextTraitSetName(Set); + return FinishSelector(); + } + + if (TISelector.Kind == TraitSelector::user_condition) { + SourceLocation RLoc; + ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc); + if (!Condition.isUsable()) + return FinishSelector(); + TISelector.ScoreOrCondition = Condition.get(); + TISelector.Properties.push_back({TraitProperty::user_condition_unknown}); return; } + + BalancedDelimiterTracker BDT(*this, tok::l_paren, + tok::annot_pragma_openmp_end); + // Parse '('. + (void)BDT.consumeOpen(); + + ExprResult Score = parseContextScore(*this); + + if (!AllowsTraitScore && Score.isUsable()) { + Diag(Score.get()->getBeginLoc(), + diag::warn_omp_ctx_incompatible_score_for_property) + << getOpenMPContextTraitSelectorName(TISelector.Kind) + << getOpenMPContextTraitSetName(Set) << Score.get(); + Score = ExprResult(); + } + + if (Score.isUsable()) + TISelector.ScoreOrCondition = Score.get(); + + do { + parseOpenMPContextProperty(TISelector, Set); + } while (TryConsumeToken(tok::comma)); + + // Parse ')'. + BDT.consumeClose(); } -/// Parse context selector for 'device' selector set: -/// 'kind' '(' { ',' } ')' -static void -parseDeviceSelector(Parser &P, SourceLocation Loc, - llvm::StringMap &UsedCtx, - SmallVectorImpl &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) - << "device"; - // Skip until either '}', ')', or end of directive. - while (!P.SkipUntil(tok::r_brace, tok::r_paren, - tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) - ; +void Parser::parseOMPTraitSetKind(OpenMPTraitInfo::OpenMPTraitSet &TISet, + llvm::StringMap &Seen) { + const unsigned Lvl = 0; + TISet.Kind = TraitSet::invalid; + + SourceLocation NameLoc = Tok.getLocation(); + auto StringLiteralParser = [this]() -> StringRef { + ExprResult Res = ParseStringLiteralExpression(true); + return Res.isUsable() ? Res.getAs()->getString() : ""; + }; + StringRef Name = getNameFromIdOrString(*this, Tok, Lvl, StringLiteralParser); + if (Name.empty()) { + Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) + << Lvl << listOpenMPContextTraitSets(); return; } - Sema::OMPCtxStringType Buffer; - StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer); - auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation()); - if (!Res.second) { - // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. - // Each trait-selector-name can only be specified once. - P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use) - << CtxSelectorName << "device"; - P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) - << CtxSelectorName; - } - OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName); - (void)P.ConsumeToken(); - switch (CSKind) { - case OMP_CTX_kind: { - // Parse '('. - BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); - (void)T.expectAndConsume(diag::err_expected_lparen_after, - CtxSelectorName.data()); - llvm::UniqueVector Kinds; - do { - // Parse . - StringRef KindName; - if (Tok.is(tok::identifier)) { - Buffer.clear(); - KindName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); - SourceLocation SLoc = P.getCurToken().getLocation(); - (void)P.ConsumeToken(); - if (llvm::StringSwitch(KindName) - .Case("host", false) - .Case("nohost", false) - .Case("cpu", false) - .Case("gpu", false) - .Case("fpga", false) - .Default(true)) { - P.Diag(SLoc, diag::err_omp_wrong_device_kind_trait) << KindName; - } else { - Kinds.insert(KindName); - } - } else { - P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected) - << "'host', 'nohost', 'cpu', 'gpu', or 'fpga'" - << "kind" - << "device"; + + TISet.Kind = getOpenMPContextTraitSetKind(Name); + if (TISet.Kind != TraitSet::invalid) { + if (checkForDuplicates(*this, Name, NameLoc, Seen, Lvl)) + TISet.Kind = TraitSet::invalid; + return; + } + + // It follows diagnosis and helping notes. + Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name; + + TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name); + if (SelectorForName != TraitSelector::invalid) { + Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) + << Name << /* Selector lvl */ 1 << Lvl; + bool AllowsTraitScore = false; + bool RequiresProperty = false; + isValidTraitSelectorForTraitSet( + SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName), + AllowsTraitScore, RequiresProperty); + Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) + << getOpenMPContextTraitSetName( + getOpenMPContextTraitSetForSelector(SelectorForName)) + << Name << (RequiresProperty ? "()" : ""); + return; + } + for (auto &PotentialSet : {TraitSet::construct, TraitSet::user, + TraitSet::implementation, TraitSet::device}) { + TraitProperty PropertyForName = + getOpenMPContextTraitPropertyKind(PotentialSet, Name); + if (PropertyForName == TraitProperty::invalid) + continue; + Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) + << Name << /* Property lvl */ 2 << Lvl; + Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) + << getOpenMPContextTraitSetName( + getOpenMPContextTraitSetForProperty(PropertyForName)) + << getOpenMPContextTraitSelectorName( + getOpenMPContextTraitSelectorForProperty(PropertyForName)) + << ("(" + Name + ")").str(); + return; + } + Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) + << Lvl << listOpenMPContextTraitSets(); +} + +/// Parses an OpenMP context selector set. +/// +/// '=' '{' [, ]* '}' +void Parser::parseOpenMPContextSelectorSet( + OpenMPTraitInfo::OpenMPTraitSet &TISet, + llvm::StringMap &SeenSets) { + const unsigned Lvl = 0; + auto OuterBC = BraceCount; + + // If anything went wrong we issue an error or warning and then skip the rest + // of the set. However, commas are ambiguous so we look for the nesting + // of braces here as well. + auto FinishSelectorSet = [this, OuterBC]() -> void { + bool Done = false; + while (!Done) { + while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren, + tok::annot_pragma_openmp_end}, + StopBeforeMatch)) + ; + if (Tok.is(tok::r_brace) && OuterBC > BraceCount) + (void)ConsumeBrace(); + if (OuterBC <= BraceCount) { + Done = true; + break; } - if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) { - P.Diag(Tok, diag::err_expected_punc) - << (KindName.empty() ? "kind of device" : KindName); + if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) { + Done = true; + break; } - } while (Tok.is(tok::identifier)); - // Parse ')'. - (void)T.consumeClose(); - if (!Kinds.empty()) - Data.emplace_back(OMP_CTX_SET_device, CSKind, ExprResult(), Kinds); - break; + (void)ConsumeAnyToken(); + } + Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) + << Lvl; + }; + + parseOMPTraitSetKind(TISet, SeenSets); + if (TISet.Kind == TraitSet::invalid) + return FinishSelectorSet(); + + // Parse '='. + if (!TryConsumeToken(tok::equal)) + Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) + << "=" + << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) + + "\"") + .str(); + + // Parse '{'. + if (Tok.is(tok::l_brace)) { + (void)ConsumeBrace(); + } else { + Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) + << "{" + << ("'=' that follows the context set name \"" + + getOpenMPContextTraitSetName(TISet.Kind) + "\"") + .str(); } - case OMP_CTX_vendor: - case OMP_CTX_unknown: - P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) - << "device"; - // Skip until either '}', ')', or end of directive. - while (!P.SkipUntil(tok::r_brace, tok::r_paren, - tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) - ; - return; + + llvm::StringMap SeenSelectors; + do { + OpenMPTraitInfo::OpenMPTraitSelector TISelector; + parseOpenMPContextSelector(TISelector, TISet.Kind, SeenSelectors); + if (TISelector.Kind != TraitSelector::invalid && + !TISelector.Properties.empty()) + TISet.Selectors.push_back(TISelector); + } while (TryConsumeToken(tok::comma)); + + // Parse '}'. + if (Tok.is(tok::r_brace)) { + (void)ConsumeBrace(); + } else { + Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) + << "}" + << ("context selectors for the context set \"" + + getOpenMPContextTraitSetName(TISet.Kind) + "\"") + .str(); } } -/// Parses clauses for 'declare variant' directive. -/// clause: -/// '=' '{' '}' -/// [ ',' '=' '{' '}' ] -bool Parser::parseOpenMPContextSelectors( - SourceLocation Loc, SmallVectorImpl &Data) { - llvm::StringMap UsedCtxSets; +/// Parse an OpenMP context: +/// +/// [, ]* +bool Parser::parseOpenMPContext(SourceLocation Loc, OpenMPTraitInfo &TI) { + llvm::StringMap SeenSets; do { - // Parse inner context selector set name. - if (!Tok.is(tok::identifier)) { - Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector) - << getOpenMPClauseName(OMPC_match); - return true; - } - Sema::OMPCtxStringType Buffer; - StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer); - auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation()); - if (!Res.second) { - // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. - // Each trait-set-selector-name can only be specified once. - Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_set_mutiple_use) - << CtxSelectorSetName; - Diag(Res.first->getValue(), - diag::note_omp_declare_variant_ctx_set_used_here) - << CtxSelectorSetName; - } - // Parse '='. - (void)ConsumeToken(); - if (Tok.isNot(tok::equal)) { - Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected) - << CtxSelectorSetName; - 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; - OpenMPContextSelectorSetKind CSSKind = - getOpenMPContextSelectorSet(CtxSelectorSetName); - llvm::StringMap UsedCtx; - do { - switch (CSSKind) { - case OMP_CTX_SET_implementation: - parseImplementationSelector(*this, Loc, UsedCtx, Data); - break; - case OMP_CTX_SET_device: - parseDeviceSelector(*this, Loc, UsedCtx, Data); - break; - 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)) - ; - break; - } - const Token PrevTok = Tok; - if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace)) - Diag(Tok, diag::err_omp_expected_comma_brace) - << (PrevTok.isAnnotation() ? "context selector trait" - : PP.getSpelling(PrevTok)); - } while (Tok.is(tok::identifier)); - // Parse '}'. - (void)TBr.consumeClose(); - } - // Consume ',' - if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) - (void)ExpectAndConsume(tok::comma); - } while (Tok.isAnyIdentifier()); + OpenMPTraitInfo::OpenMPTraitSet TISet; + parseOpenMPContextSelectorSet(TISet, SeenSets); + if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty()) + TI.Sets.push_back(TISet); + } while (TryConsumeToken(tok::comma)); + return false; } @@ -1126,24 +1355,19 @@ } // Parse inner context selectors. - SmallVector Data; - if (!parseOpenMPContextSelectors(Loc, Data)) { - // 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); - } - } + OpenMPTraitInfo *TI = new OpenMPTraitInfo(); + parseOpenMPContext(Loc, *TI); + + // Parse ')' + (void)T.consumeClose(); // Skip last tokens. while (Tok.isNot(tok::annot_pragma_openmp_end)) ConsumeAnyToken(); - if (DeclVarData.hasValue()) + if (DeclVarData.hasValue() && !TI->Sets.empty()) Actions.ActOnOpenMPDeclareVariantDirective( - DeclVarData.getValue().first, DeclVarData.getValue().second, - SourceRange(Loc, Tok.getLocation()), Data); + DeclVarData.getValue().first, DeclVarData.getValue().second, TI, + SourceRange(Loc, Tok.getLocation())); // Skip the last annot_pragma_openmp_end. (void)ConsumeAnnotationToken(); } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -5444,75 +5444,13 @@ return std::make_pair(FD, cast(DRE)); } -void Sema::ActOnOpenMPDeclareVariantDirective( - FunctionDecl *FD, Expr *VariantRef, SourceRange SR, - ArrayRef Data) { - if (Data.empty()) - return; - SmallVector CtxScores; - SmallVector CtxSets; - SmallVector Ctxs; - SmallVector ImplVendors, DeviceKinds; - 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 { - // OpenMP 5.0, 2.3.3 Matching and Scoring Context Selectors. - // The kind, arch, and isa selectors are given the values 2^l, 2^(l+1) and - // 2^(l+2), respectively, where l is the number of traits in the construct - // set. - // TODO: implement correct logic for isa and arch traits. - // TODO: take the construct context set into account when it is - // implemented. - int L = 0; // Currently set the number of traits in construct set to 0, - // since the construct trait set in not supported yet. - if (CtxSet == OMP_CTX_SET_device && Ctx == OMP_CTX_kind) - Score = ActOnIntegerConstant(SourceLocation(), std::pow(2, L)).get(); - else - Score = ActOnIntegerConstant(SourceLocation(), 0).get(); - } - switch (Ctx) { - case OMP_CTX_vendor: - assert(CtxSet == OMP_CTX_SET_implementation && - "Expected implementation context selector set."); - ImplVendors.append(D.Names.begin(), D.Names.end()); - break; - case OMP_CTX_kind: - assert(CtxSet == OMP_CTX_SET_device && - "Expected device context selector set."); - DeviceKinds.append(D.Names.begin(), D.Names.end()); - break; - case OMP_CTX_unknown: - llvm_unreachable("Unknown context selector 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(), DeviceKinds.begin(), - DeviceKinds.size(), SR); - FD->addAttr(NewAttr); - } +void Sema::ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, + Expr *VariantRef, + OpenMPTraitInfo *TI, + SourceRange SR) { + auto *NewAttr = + OMPDeclareVariantAttr::CreateImplicit(Context, VariantRef, TI, SR); + FD->addAttr(NewAttr); } void Sema::markOpenMPDeclareVariantFuncsReferenced(SourceLocation Loc, diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -399,44 +399,27 @@ S.ConvertDeclToDeclGroup(New), VariantFuncRef.get(), Attr.getRange()); if (!DeclVarData) return; - SmallVector 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( - *std::next(Attr.ctxSelectorSets_begin(), I)); - auto Ctx = static_cast( - *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_kind: - case OMP_CTX_unknown: - llvm_unreachable("Unexpected context selector kind."); - } - break; - case OMP_CTX_SET_device: - switch (Ctx) { - case OMP_CTX_kind: - Data.emplace_back(CtxSet, Ctx, Score, Attr.deviceKinds()); - break; - case OMP_CTX_vendor: - case OMP_CTX_unknown: - llvm_unreachable("Unexpected context selector kind."); - } - break; - case OMP_CTX_SET_unknown: - llvm_unreachable("Unexpected context selector set kind."); + + // Copy the template version of the OpenMPTraitInfo and run substitute on all + // score and condition expressiosn. + OpenMPTraitInfo *TI = new OpenMPTraitInfo(); + *TI = *Attr.getTraitInfos(); + + for (OpenMPTraitInfo::OpenMPTraitSet &Set : TI->Sets) { + for (OpenMPTraitInfo::OpenMPTraitSelector &Selector : Set.Selectors) { + if (!Selector.ScoreOrCondition) + continue; + ExprResult ScoreOrConditionRes = Subst(Selector.ScoreOrCondition); + if (ScoreOrConditionRes.isUsable()) + Selector.ScoreOrCondition = ScoreOrConditionRes.get(); + else + Selector.ScoreOrCondition = nullptr; } } + S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first, - DeclVarData.getValue().second, - Attr.getRange(), Data); + DeclVarData.getValue().second, TI, + Attr.getRange()); } static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr( diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -12454,3 +12454,22 @@ } C->setComponents(Components, ListSizes); } + +OpenMPTraitInfo *ASTRecordReader::readOpenMPTraitInfo() { + OpenMPTraitInfo *TI = new OpenMPTraitInfo(); + TI->Sets.resize(readUInt32()); + for (auto &Set : TI->Sets) { + Set.Kind = readEnum(); + Set.Selectors.resize(readUInt32()); + for (auto &Selector : Set.Selectors) { + Selector.Kind = readEnum(); + Selector.ScoreOrCondition = nullptr; + if (readBool()) + Selector.ScoreOrCondition = readExprRef(); + Selector.Properties.resize(readUInt32()); + for (auto &Property : Selector.Properties) + Property.Kind = readEnum(); + } + } + return TI; +} diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2722,6 +2722,8 @@ return Reader.readVersionTuple(); } + template T *readUserType() { return Reader.readUserType(); } + template T *GetLocalDeclAs(uint32_t LocalID) { return Reader.GetLocalDeclAs(LocalID); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -6537,3 +6537,20 @@ Record.AddSourceLocation(C->getLParenLoc()); Record.AddSourceLocation(C->getAtomicDefaultMemOrderKindKwLoc()); } + +void ASTRecordWriter::writeOpenMPTraitInfo(const OpenMPTraitInfo *TI) { + writeUInt32(TI->Sets.size()); + for (auto &Set : TI->Sets) { + writeEnum(Set.Kind); + writeUInt32(Set.Selectors.size()); + for (auto &Selector : Set.Selectors) { + writeEnum(Selector.Kind); + writeBool(Selector.ScoreOrCondition); + if (Selector.ScoreOrCondition) + writeExprRef(Selector.ScoreOrCondition); + writeUInt32(Selector.Properties.size()); + for (auto &Property : Selector.Properties) + writeEnum(Property.Kind); + } + } +} diff --git a/clang/test/OpenMP/declare_variant_ast_print.c b/clang/test/OpenMP/declare_variant_ast_print.c --- a/clang/test/OpenMP/declare_variant_ast_print.c +++ b/clang/test/OpenMP/declare_variant_ast_print.c @@ -8,7 +8,7 @@ #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(llvm)}, device={kind(fpga)}) +#pragma omp declare variant(foo) match(implementation={vendor(score(0):llvm)}, device={kind(fpga)}) #pragma omp declare variant(foo) match(implementation={vendor(llvm), xxx}) #pragma omp declare variant(foo) match(implementation={vendor(unknown)}, device={kind(gpu)}) #pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm, xxx, ibm)}, device={kind(cpu, nohost)}) @@ -19,8 +19,8 @@ // CHECK: int foo(); // CHECK-NEXT: #pragma omp declare variant(foo) match(device={kind(nohost)}) // CHECK-NEXT: #pragma omp declare variant(foo) match(device={kind(host)}) -// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(5):ibm, xxx)},device={kind(cpu, nohost)}) -// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(0):unknown)},device={kind(gpu)}) -// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(0):llvm)}) -// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(0):llvm)},device={kind(fpga)}) +// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm, ibm)}, device={kind(cpu, nohost)}) +// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(unknown)}, device={kind(gpu)}) +// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(llvm)}) +// CHECK-NEXT: #pragma omp declare variant(foo) match(implementation={vendor(score(0): llvm)}, device={kind(fpga)}) // CHECK-NEXT: int bar(); diff --git a/clang/test/OpenMP/declare_variant_ast_print.cpp b/clang/test/OpenMP/declare_variant_ast_print.cpp --- a/clang/test/OpenMP/declare_variant_ast_print.cpp +++ b/clang/test/OpenMP/declare_variant_ast_print.cpp @@ -17,36 +17,40 @@ // CHECK-NEXT: return int(); // CHECK-NEXT: } -// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(5):ibm)},device={kind(fpga)}) -// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(score(0):unknown)}) -// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(score(0):llvm)},device={kind(cpu)}) +// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(5): ibm)}, device={kind(fpga)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(score(0): llvm)}, device={kind(cpu)}) // CHECK-NEXT: int bar(); #pragma omp declare variant(foofoo ) match(xxx = {}) #pragma omp declare variant(foofoo ) match(xxx = {vvv}) -#pragma omp declare variant(foofoo ) match(implementation={vendor(llvm), xxx}, device={kind(cpu)}) -#pragma omp declare variant(foofoo ) match(implementation={vendor(unknown)}) -#pragma omp declare variant(foofoo ) match(implementation={vendor(score(5): ibm)}, device={kind(fpga)}) +#pragma omp declare variant(foofoo ) match(implementation = {vendor(score(0): "llvm"), xxx}, device = {kind(cpu)}) +#pragma omp declare variant(foofoo ) match(implementation = {vendor("unknown")}) +#pragma omp declare variant(foofoo ) match(implementation = {vendor(score(5): ibm)}, device = {kind(fpga)}) int bar(); -// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(C + 5):ibm, xxx)},device={kind(cpu, host)}) -// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(score(0):unknown)}) -// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(score(0):llvm)},device={kind(cpu)}) +// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(C + 5): ibm, ibm)}, device={kind(cpu, host)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(llvm)}, device={kind(cpu)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(user={condition(false)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(user={condition(true)}) // CHECK-NEXT: template T barbar(); #pragma omp declare variant(foofoo ) match(xxx = {}) #pragma omp declare variant(foofoo ) match(xxx = {vvv}) -#pragma omp declare variant(foofoo ) match(user = {score() : condition()}) -#pragma omp declare variant(foofoo ) match(user = {score() : condition()}) -#pragma omp declare variant(foofoo ) match(user = {condition()}) -#pragma omp declare variant(foofoo ) match(user = {condition()}) -#pragma omp declare variant(foofoo ) match(implementation={vendor(llvm)},device={kind(cpu)}) +#pragma omp declare variant(foofoo ) match(user = {score(1 * 1 + 1) : condition(100 > 10 + 2)}) +#pragma omp declare variant(foofoo ) match(user = {score(0) : condition(0)}) +#pragma omp declare variant(foofoo ) match(user = {condition(true)}) +#pragma omp declare variant(foofoo ) match(user = {condition(false)}) +#pragma omp declare variant(foofoo ) match(implementation = {vendor(llvm)}, device = {kind(cpu)}) #pragma omp declare variant(foofoo ) match(implementation={vendor(unknown)}) #pragma omp declare variant(foofoo ) match(implementation={vendor(score(C+5): ibm, xxx, ibm)},device={kind(cpu,host)}) template T barbar(); -// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(3 + 5):ibm, xxx)},device={kind(cpu, host)}) -// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(score(0):unknown)}) -// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(score(0):llvm)},device={kind(cpu)}) +// CHECK: #pragma omp declare variant(foofoo) match(implementation={vendor(score(3 + 5): ibm, ibm)}, device={kind(cpu, host)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(unknown)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(implementation={vendor(llvm)}, device={kind(cpu)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(user={condition(false)}) +// CHECK-NEXT: #pragma omp declare variant(foofoo) match(user={condition(true)}) // CHECK-NEXT: template<> int barbar(); // CHECK-NEXT: int baz() { @@ -66,19 +70,19 @@ void h_ref(C *hp, C *hp2, C *hq, C *lin) { } -// CHECK: #pragma omp declare variant(h_ref) match(implementation={vendor(score(0):unknown)},device={kind(nohost)}) -// CHECK-NEXT: #pragma omp declare variant(h_ref) match(implementation={vendor(score(0):llvm)},device={kind(gpu)}) +// CHECK: #pragma omp declare variant(h_ref) match(implementation={vendor(unknown)}, device={kind(nohost)}) +// CHECK-NEXT: #pragma omp declare variant(h_ref) match(implementation={vendor(llvm)}, device={kind(gpu)}) // CHECK-NEXT: template void h(C *hp, C *hp2, C *hq, C *lin) { // CHECK-NEXT: } #pragma omp declare variant(h_ref ) match(xxx = {}) -#pragma omp declare variant(h_ref ) match(implementation={vendor(llvm)}, device={kind(gpu)}) -#pragma omp declare variant(h_ref ) match(implementation={vendor(unknown)},device={kind(nohost)}) +#pragma omp declare variant(h_ref ) match(implementation = {vendor(llvm)}, device = {kind(gpu)}) +#pragma omp declare variant(h_ref ) match(implementation = {vendor(unknown)}, device = {kind(nohost)}) template void h(C *hp, C *hp2, C *hq, C *lin) { } -// CHECK: #pragma omp declare variant(h_ref) match(implementation={vendor(score(0):unknown)},device={kind(nohost)}) -// CHECK-NEXT: #pragma omp declare variant(h_ref) match(implementation={vendor(score(0):llvm)},device={kind(gpu)}) +// CHECK: #pragma omp declare variant(h_ref) match(implementation={vendor(unknown)}, device={kind(nohost)}) +// CHECK-NEXT: #pragma omp declare variant(h_ref) match(implementation={vendor(llvm)}, device={kind(gpu)}) // CHECK-NEXT: template<> void h(float *hp, float *hp2, float *hq, float *lin) { // CHECK-NEXT: } @@ -86,7 +90,7 @@ // CHECK-NEXT: h((float *)hp, (float *)hp2, (float *)hq, (float *)lin); // CHECK-NEXT: } #pragma omp declare variant(h_ref ) match(xxx = {}) -#pragma omp declare variant(h_ref ) match(implementation={vendor(ibm)},device={kind(cpu,gpu)}) +#pragma omp declare variant(h_ref ) match(implementation = {vendor(ibm)}, device = {kind(cpu, gpu)}) #pragma omp declare variant(h_ref ) match(implementation={vendor(unknown)}) template <> void h(double *hp, double *hp2, double *hq, double *lin) { @@ -97,36 +101,36 @@ int fn(); // CHECK: int fn(int); int fn(int); -// CHECK: #pragma omp declare variant(fn) match(implementation={vendor(score(0):unknown)},device={kind(cpu, gpu)}) -// CHECK-NEXT: #pragma omp declare variant(fn) match(implementation={vendor(score(0):llvm)}) +// CHECK: #pragma omp declare variant(fn) match(implementation={vendor(unknown)}, device={kind(cpu, gpu)}) +// 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(llvm)}) -#pragma omp declare variant(fn) match(implementation={vendor(unknown)},device={kind(cpu,gpu)}) +#pragma omp declare variant(fn) match(implementation = {vendor(unknown)}, device = {kind(cpu, gpu)}) 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(implementation={vendor(score(0):unknown)},device={kind(gpu, nohost)}) -// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(score(0):llvm)},device={kind(cpu, host)}) +// CHECK: #pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(unknown)}, device={kind(gpu, nohost)}) +// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(llvm)}, device={kind(cpu, host)}) // CHECK-NEXT: int fn_deduced(); #pragma omp declare variant(fn_deduced_variant) match(xxx = {}) -#pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(llvm)},device={kind(cpu,host)}) -#pragma omp declare variant(fn_deduced_variant) match(implementation={vendor(unknown)},device={kind(gpu,nohost)}) +#pragma omp declare variant(fn_deduced_variant) match(implementation = {vendor(llvm)}, device = {kind(cpu, host)}) +#pragma omp declare variant(fn_deduced_variant) match(implementation = {vendor(unknown)}, device = {kind(gpu, nohost)}) int fn_deduced(); // CHECK: int fn_deduced_variant1(); int fn_deduced_variant1(); -// CHECK: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(score(0):unknown)},device={kind(cpu, host)}) -// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(score(0):ibm)},device={kind(gpu, nohost)}) +// CHECK: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(unknown)}, device={kind(cpu, host)}) +// CHECK-NEXT: #pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(ibm)}, device={kind(gpu, nohost)}) // 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)},device={kind(gpu,nohost)}) -#pragma omp declare variant(fn_deduced_variant1) match(implementation={vendor(unknown)},device={kind(cpu,host)}) +#pragma omp declare variant(fn_deduced_variant1) match(implementation = {vendor(ibm)}, device = {kind(gpu, nohost)}) +#pragma omp declare variant(fn_deduced_variant1) match(implementation = {vendor(unknown)}, device = {kind(cpu, host)}) auto fn_deduced1() { return 0; } // CHECK: struct SpecialFuncs { @@ -140,11 +144,11 @@ // CHECK-NEXT: } // CHECK-NEXT: void bar(int) { // CHECK-NEXT: } -// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(score(0):unknown)},device={kind(nohost)}) -// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::bar) match(implementation={vendor(score(0):ibm)},device={kind(cpu)}) +// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(unknown)}, device={kind(nohost)}) +// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::bar) match(implementation={vendor(ibm)}, device={kind(cpu)}) // CHECK-NEXT: void foo1() { // CHECK-NEXT: } -// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(score(0):unknown)},device={kind(cpu, host)}) +// CHECK-NEXT: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(unknown)}, device={kind(cpu, host)}) // CHECK-NEXT: void xxx(); // CHECK-NEXT: } s; struct SpecialFuncs { @@ -157,14 +161,14 @@ 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)},device={kind(cpu)}) -#pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(unknown)},device={kind(nohost)}) +#pragma omp declare variant(SpecialFuncs::bar) match(implementation = {vendor(ibm)}, device = {kind(cpu)}) +#pragma omp declare variant(SpecialFuncs::baz) match(implementation = {vendor(unknown)}, device = {kind(nohost)}) void foo1() {} -#pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(unknown)},device={kind(cpu, host)}) +#pragma omp declare variant(SpecialFuncs::baz) match(implementation = {vendor(unknown)}, device = {kind(cpu, host)}) void xxx(); } s; -// CHECK: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(score(0):unknown)},device={kind(cpu, host)}) +// CHECK: #pragma omp declare variant(SpecialFuncs::baz) match(implementation={vendor(unknown)}, device={kind(cpu, host)}) // CHECK-NEXT: void SpecialFuncs::xxx() { // CHECK-NEXT: } void SpecialFuncs::xxx() {} @@ -172,12 +176,12 @@ // CHECK: static void static_f_variant() { // CHECK-NEXT: } static void static_f_variant() {} -// CHECK: #pragma omp declare variant(static_f_variant) match(implementation={vendor(score(0):unknown)}) -// CHECK-NEXT: #pragma omp declare variant(static_f_variant) match(implementation={vendor(score(0):llvm)},device={kind(fpga)}) +// CHECK: #pragma omp declare variant(static_f_variant) match(implementation={vendor(unknown)}) +// CHECK-NEXT: #pragma omp declare variant(static_f_variant) match(implementation={vendor(llvm)}, device={kind(fpga)}) // 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(llvm)},device={kind(fpga)}) +#pragma omp declare variant(static_f_variant) match(implementation = {vendor(llvm)}, device = {kind(fpga)}) #pragma omp declare variant(static_f_variant) match(implementation={vendor(unknown)}) static void static_f() {} @@ -192,19 +196,19 @@ // CHECK: int fn_linkage_variant(); // CHECK: extern "C" { -// CHECK: #pragma omp declare variant(fn_linkage_variant) match(implementation={vendor(score(0):xxx)},device={kind(cpu, host)}) +// CHECK: #pragma omp declare variant(fn_linkage_variant) match(implementation={vendor(ti)}, device={kind(cpu, host)}) // CHECK: int fn_linkage(); // CHECK: } int fn_linkage_variant(); extern "C" { -#pragma omp declare variant(fn_linkage_variant) match(implementation = {vendor(xxx)},device={kind(cpu,host)}) +#pragma omp declare variant(fn_linkage_variant) match(implementation = {vendor(ti)}, device = {kind(cpu, host)}) int fn_linkage(); } // CHECK: extern "C" int fn_linkage_variant1() -// CHECK: #pragma omp declare variant(fn_linkage_variant1) match(implementation={vendor(score(0):xxx)},device={kind(cpu, host)}) +// CHECK: #pragma omp declare variant(fn_linkage_variant1) match(implementation={vendor(gnu)}, device={kind(cpu, host)}) // CHECK: int fn_linkage1(); extern "C" int fn_linkage_variant1(); -#pragma omp declare variant(fn_linkage_variant1) match(implementation = {vendor(xxx)},device={kind(cpu,host)}) +#pragma omp declare variant(fn_linkage_variant1) match(implementation = {vendor(gnu)}, device = {kind(cpu, host)}) int fn_linkage1(); diff --git a/clang/test/OpenMP/declare_variant_device_kind_codegen.cpp b/clang/test/OpenMP/declare_variant_device_kind_codegen.cpp --- a/clang/test/OpenMP/declare_variant_device_kind_codegen.cpp +++ b/clang/test/OpenMP/declare_variant_device_kind_codegen.cpp @@ -71,18 +71,18 @@ #pragma omp declare target #ifdef HOST -#define CORRECT host -#define SUBSET host, cpu +#define SUBSET host +#define CORRECT host, cpu #define WRONG host, nohost #endif // HOST #ifdef CPU -#define CORRECT cpu -#define SUBSET host, cpu +#define SUBSET cpu +#define CORRECT cpu, any #define WRONG cpu, gpu #endif // CPU #ifdef NOHOST -#define CORRECT nohost -#define SUBSET nohost, cpu +#define SUBSET nohost +#define CORRECT nohost, cpu #define WRONG nohost, host #endif // NOHOST diff --git a/clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp b/clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp --- a/clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp +++ b/clang/test/OpenMP/declare_variant_implementation_vendor_codegen.cpp @@ -65,10 +65,10 @@ ~SpecialFuncs(); int method_() { return 6; } -#pragma omp declare variant(SpecialFuncs::method_) \ +#pragma omp declare variant(SpecialFuncs::method_) \ match(implementation = {vendor(llvm)}) int method() { return 1; } -#pragma omp declare variant(SpecialFuncs::method_) \ +#pragma omp declare variant(SpecialFuncs::method_) \ match(implementation = {vendor(llvm)}) int Method(); } s; @@ -81,10 +81,10 @@ ~SpecSpecialFuncs(); int method_(); -#pragma omp declare variant(SpecSpecialFuncs::method_) \ +#pragma omp declare variant(SpecSpecialFuncs::method_) \ match(implementation = {vendor(llvm)}) int method() { return 1; } -#pragma omp declare variant(SpecSpecialFuncs::method_) \ +#pragma omp declare variant(SpecSpecialFuncs::method_) \ match(implementation = {vendor(llvm)}) int Method(); } s1; @@ -101,7 +101,8 @@ int prio1() { return 82; } #pragma omp declare variant(prio) match(implementation = {vendor(llvm)}) -#pragma omp declare variant(prio1) match(implementation = {vendor(score(1): llvm)}) +#pragma omp declare variant(prio1) match(implementation = {vendor(score(1) \ + : llvm)}) int prio_() { return 1; } static int prio2() { return 83; } diff --git a/clang/test/OpenMP/declare_variant_messages.c b/clang/test/OpenMP/declare_variant_messages.c --- a/clang/test/OpenMP/declare_variant_messages.c +++ b/clang/test/OpenMP/declare_variant_messages.c @@ -2,95 +2,95 @@ // RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c -std=c99 -fms-extensions -Wno-pragma-pack %s -// expected-error@+1 {{expected an OpenMP directive}} -#pragma omp declare + +#pragma omp declare // expected-error {{expected an OpenMP directive}} int foo(void); #pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}} -#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} #pragma omp declare variant(foo // expected-error {{expected ')'}} expected-error {{expected 'match' clause on 'omp declare variant' directive}} expected-note {{to match this '('}} #pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}} #pragma omp declare variant(foo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} #pragma omp declare variant(foo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} #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}} -#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 '}' or ',' after ')'}} expected-error {{expected '}'}} expected-note {{to match this '{'}} -#pragma omp declare variant(foo) match(xxx={}) -#pragma omp declare variant(foo) match(xxx={vvv, 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}} expected-error {{context selector set 'xxx' is used already in the same 'omp declare variant' directive}} expected-note {{previously context selector set 'xxx' used here}} -#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 ')' 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 ')' 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), vendor(llvm)}) // expected-error {{context trait selector 'vendor' is used already in the same 'implementation' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'vendor' used here}} -#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm), kind(cpu)}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}} -#pragma omp declare variant(foo) match(device={xxx}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} -#pragma omp declare variant(foo) match(device={kind}) // expected-error {{expected '(' after 'kind'}} expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma omp declare variant(foo) match(device={kind(}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}} -#pragma omp declare variant(foo) match(device={kind()}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} -#pragma omp declare variant(foo) match(device={kind(score cpu)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foo) match(device={kind(score( ibm)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foo) match(device={kind(score(2 gpu)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foo) match(device={kind(score(foo()) ibm)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foo) match(device={kind(score(5): host), kind(llvm)}) // expected-error {{context trait selector 'kind' is used already in the same 'device' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'kind' used here}} expected-error {{expected ')' or ',' after 'score'}} expected-note {{to match this '('}} expected-error {{expected ')'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} expected-error {{unknown 'llvm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foo) match(device={kind(score(5): nohost), vendor(llvm)}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}}} +#pragma omp declare variant(foo) match( // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context set, set skipped}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match() // expected-warning {{expected identifier or string literal describing a context set, set skipped}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp declare variant(foo) match(xxx) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp declare variant(foo) match(xxx=) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp declare variant(foo) match(xxx=yyy) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp declare variant(foo) match(xxx=yyy}) // expected-error {{expected ')'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(xxx={) // expected-error {{expected ')'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp declare variant(foo) match(xxx={vvv, vvv}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp declare variant(foo) match(xxx={vvv} xxx) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp declare variant(foo) match(xxx={vvv}) xxx // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp declare variant(foo) match(implementation={xxx}) // expected-warning {{'xxx' is not a valid context selector for the context set 'implementation', selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foo) match(implementation={vendor}) // expected-warning {{the context selector 'vendor' in context set 'implementation' requires a context property defined in parenthesis, selector ignored}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foo) match(implementation={vendor(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(implementation={vendor()}) // expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} +#pragma omp declare variant(foo) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} +#pragma omp declare variant(foo) match(implementation={vendor(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(implementation={vendor(score(2 ibm)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(implementation={vendor(score(foo()) ibm)}) // expected-warning {{expected '':'' after the score expression, '':'' assumed}} +#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm), vendor(llvm)}) // expected-warning {{the context selector 'vendor' was used already in the same 'omp declare variant' directiv, selector ignored}} expected-note {{the previous context selector 'vendor' used here}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foo) match(implementation={vendor(score(5): ibm), kind(cpu)}) // expected-warning {{the context selector 'kind' is not valid for the context set 'implementation', selector ignored}} expected-note {{the context selector 'kind' can be nested in the context set 'device', try 'match(device={kind(property)})'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foo) match(device={xxx}) // expected-warning {{'xxx' is not a valid context selector for the context set 'device', selector ignored}} expected-note {{context selector options are: 'kind' 'isa' 'arch'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foo) match(device={kind}) // expected-warning {{the context selector 'kind' in context set 'device' requires a context property defined in parenthesis, selector ignored}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foo) match(device={kind(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(device={kind()}) // expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} +#pragma omp declare variant(foo) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} +#pragma omp declare variant(foo) match(device={kind(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(device={kind(score(2 gpu)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('2'), score ignored}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}} +#pragma omp declare variant(foo) match(device={kind(score(foo()) ibm)}) // expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foo()'), score ignored}} expected-warning {{'ibm' is not a valid context property for the context selector 'kind' and the context set 'device', property ignored}} expected-note {{try 'match(implementation={vendor(ibm)})'}} expected-note {{the ignored property spans until here}} +#pragma omp declare variant(foo) match(device={kind(score(5): host), kind(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('5'), score ignored}} expected-warning {{the context selector 'kind' was used already in the same 'omp declare variant' directiv, selector ignored}} expected-note {{the previous context selector 'kind' used here}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foo) match(device={kind(score(5): nohost), vendor(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('5'), score ignored}} expected-warning {{the context selector 'vendor' is not valid for the context set 'device', selector ignored}} expected-note {{the context selector 'vendor' can be nested in the context set 'implementation', try 'match(implementation={vendor(property)})'}} expected-note {{the ignored selector spans until here}} int bar(void); -// expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}} -#pragma omp declare variant(foo) match(xxx={}) -int a; -// expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}} -#pragma omp declare variant(foo) match(xxx={}) -#pragma omp threadprivate(a) + +#pragma omp declare variant(foo) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +int a; // expected-error {{'#pragma omp declare variant' can only be applied to functions}} + +#pragma omp declare variant(foo) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp threadprivate(a) // expected-error {{'#pragma omp declare variant' can only be applied to functions}} int var; #pragma omp threadprivate(var) -// expected-error@+2 {{expected an OpenMP directive}} expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant(foo) match(xxx={}) -#pragma omp declare -// expected-error@+3 {{function declaration is expected after 'declare variant' directive}} -// expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant(foo) match(xxx={}) -#pragma omp declare variant(foo) match(xxx={}) +#pragma omp declare variant(foo) match(xxx={}) // expected-error {{function declaration is expected after 'declare variant' directive}} +#pragma omp declare // expected-error {{expected an OpenMP directive}} + + + +#pragma omp declare variant(foo) match(xxx={}) // expected-error {{function declaration is expected after 'declare variant' directive}} +#pragma omp declare variant(foo) match(xxx={}) // expected-error {{function declaration is expected after 'declare variant' directive}} #pragma options align=packed int main(); -// expected-error@+3 {{function declaration is expected after 'declare variant' directive}} -// expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant(foo) match(xxx={}) -#pragma omp declare variant(foo) match(xxx={}) + + +#pragma omp declare variant(foo) match(xxx={}) // expected-error {{function declaration is expected after 'declare variant' directive}} +#pragma omp declare variant(foo) match(xxx={}) // expected-error {{function declaration is expected after 'declare variant' directive}} #pragma init_seg(compiler) int main(); -// expected-error@+1 {{single declaration is expected after 'declare variant' directive}} -#pragma omp declare variant(foo) match(xxx={}) + +#pragma omp declare variant(foo) match(xxx={}) // expected-error {{single declaration is expected after 'declare variant' directive}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} int b, c; int no_proto(); -#pragma omp declare variant(no_proto) match(xxx={}) +#pragma omp declare variant(no_proto) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} int no_proto_too(); int proto1(int); -// expected-note@+2 {{previous declaration is here}} -#pragma omp declare variant(proto1) match(xxx={}) -int diff_proto(); -// expected-error@+1 {{conflicting types for 'diff_proto'}} -int diff_proto(double); -#pragma omp declare variant(no_proto) match(xxx={}) +#pragma omp declare variant(proto1) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +int diff_proto(); // expected-note {{previous declaration is here}} + +int diff_proto(double); // expected-error {{conflicting types for 'diff_proto'}} + +#pragma omp declare variant(no_proto) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} int diff_proto1(double); int after_use_variant(void); @@ -99,37 +99,37 @@ return after_use(); } -// expected-warning@+1 {{'#pragma omp declare variant' cannot be applied for function after first usage; the original function might be used}} -#pragma omp declare variant(after_use_variant) match(xxx={}) + +#pragma omp declare variant(after_use_variant) match(xxx={}) // expected-warning {{'#pragma omp declare variant' cannot be applied for function after first usage; the original function might be used}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} int after_use(void); -#pragma omp declare variant(after_use_variant) match(xxx={}) +#pragma omp declare variant(after_use_variant) match(xxx={}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} int defined(void) { return 0; } int defined1(void) { return 0; } -// expected-warning@+1 {{#pragma omp declare variant' cannot be applied to the function that was defined already; the original function might be used}} -#pragma omp declare variant(after_use_variant) match(xxx={}) + +#pragma omp declare variant(after_use_variant) match(xxx={}) // expected-warning {{'#pragma omp declare variant' cannot be applied to the function that was defined already; the original function might be used}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} int defined1(void); int diff_cc_variant(void); -// expected-error@+1 {{variant in '#pragma omp declare variant' with type 'int (void)' is incompatible with type 'int (void) __attribute__((vectorcall))'}} -#pragma omp declare variant(diff_cc_variant) match(xxx={}) + +#pragma omp declare variant(diff_cc_variant) match(xxx={}) // expected-error {{variant in '#pragma omp declare variant' with type 'int (void)' is incompatible with type 'int (void) __attribute__((vectorcall))'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} __vectorcall int diff_cc(void); int diff_ret_variant(void); -// expected-error@+1 {{variant in '#pragma omp declare variant' with type 'int (void)' is incompatible with type 'void (void)'}} -#pragma omp declare variant(diff_ret_variant) match(xxx={}) + +#pragma omp declare variant(diff_ret_variant) match(xxx={}) // expected-error {{variant in '#pragma omp declare variant' with type 'int (void)' is incompatible with type 'void (void)'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} 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(implementation={vendor(unknown)}, device={kind(cpu)}) + +#pragma omp declare variant(not_marked) match(implementation={vendor(unknown)}, device={kind(cpu)}) // expected-note {{marked as 'declare variant' here}} 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={}) + +#pragma omp declare variant(marked_variant) match(xxx={}) // expected-warning {{variant function in '#pragma omp declare variant' is itself marked as '#pragma omp declare variant'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} void marked(void); -// expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant -// expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant + +#pragma omp declare variant // expected-error {{function declaration is expected after 'declare variant' directive}} + +#pragma omp declare variant // expected-error {{function declaration is expected after 'declare variant' directive}} diff --git a/clang/test/OpenMP/declare_variant_messages.cpp b/clang/test/OpenMP/declare_variant_messages.cpp --- a/clang/test/OpenMP/declare_variant_messages.cpp +++ b/clang/test/OpenMP/declare_variant_messages.cpp @@ -2,137 +2,137 @@ // RUN: %clang_cc1 -triple=x86_64-pc-win32 -verify -fopenmp-simd -x c++ -std=c++14 -fms-extensions -Wno-pragma-pack -fexceptions -fcxx-exceptions %s -// expected-error@+1 {{expected an OpenMP directive}} -#pragma omp declare + +#pragma omp declare // expected-error {{expected an OpenMP directive}} int foo(); template -T foofoo(); // expected-note 2 {{declared here}} - -#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}} -#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma omp declare variant(foo // expected-error {{expected ')'}} expected-error {{expected 'match' clause on 'omp declare variant' directive}} expected-note {{to match this '('}} -#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}} -#pragma omp declare variant(foo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) match // expected-error {{expected '(' after 'match'}} -#pragma omp declare variant(foofoo ) match( // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) match(xxx =) // expected-error {{expected '{' after '='}} -#pragma omp declare variant(foofoo ) match(xxx = yyy) // expected-error {{expected '{' after '='}} -#pragma omp declare variant(foofoo ) match(xxx = yyy }) // expected-error {{expected '{' after '='}} -#pragma omp declare variant(foofoo ) match(xxx = {) // expected-error {{expected '}' or ',' after ')'}} expected-error {{expected '}'}} expected-note {{to match this '{'}} -#pragma omp declare variant(foofoo ) match(xxx = {}) -#pragma omp declare variant(foofoo ) match(xxx = {vvv, vvv}) -#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}} expected-error {{context selector set 'xxx' is used already in the same 'omp declare variant' directive}} expected-note {{previously context selector set 'xxx' used here}} -#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 ')' 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 ')' 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), vendor(llvm)}) // expected-error {{context trait selector 'vendor' is used already in the same 'implementation' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'vendor' used here}} -#pragma omp declare variant(foofoo ) match(implementation={vendor(score(5): ibm), kind(cpu)}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}} -#pragma omp declare variant(foofoo ) match(device={xxx}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} -#pragma omp declare variant(foofoo ) match(device={kind}) // expected-error {{expected '(' after 'kind'}} expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma omp declare variant(foofoo ) match(device={kind(}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}} -#pragma omp declare variant(foofoo ) match(device={kind()}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) match(device={kind(score cpu)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foofoo ) match(device={kind(score( ibm)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foofoo ) match(device={kind(score(2 gpu)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foofoo ) match(device={kind(score(foofoo ()) ibm)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foofoo ) match(device={kind(score(5): host), kind(llvm)}) // expected-error {{context trait selector 'kind' is used already in the same 'device' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'kind' used here}} expected-error {{expected ')' or ',' after 'score'}} expected-note {{to match this '('}} expected-error {{expected ')'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} expected-error {{unknown 'llvm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foofoo ) match(device={kind(score(5): nohost), vendor(llvm)}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} +T foofoo(); + +#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}} +#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp declare variant(foo // expected-error {{expected ')'}} expected-error {{expected 'match' clause on 'omp declare variant' directive}} expected-note {{to match this '('}} +#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}} +#pragma omp declare variant(foo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} +#pragma omp declare variant(foofoo ) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} +#pragma omp declare variant(foofoo ) xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}} +#pragma omp declare variant(foofoo ) match // expected-error {{expected '(' after 'match'}} +#pragma omp declare variant(foofoo ) match( // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context set, set skipped}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match() // expected-warning {{expected identifier or string literal describing a context set, set skipped}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp declare variant(foofoo ) match(implementation) // expected-warning {{expected '=' after the context set name "implementation", '=' assumed}} expected-warning {{expected '{' after the '=' that follows the context set name "implementation", '{' assumed}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-warning {{expected '}' after the context selectors for the context set "implementation", '}' assumed}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation =) // expected-warning {{expected '{' after the '=' that follows the context set name "implementation", '{' assumed}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-warning {{expected '}' after the context selectors for the context set "implementation", '}' assumed}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation = yyy) // expected-warning {{expected '{' after the '=' that follows the context set name "implementation", '{' assumed}} expected-warning {{'yyy' is not a valid context selector for the context set 'implementation', selector ignored}} expected-warning {{expected '}' after the context selectors for the context set "implementation", '}' assumed}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation = yyy }) // expected-warning {{expected '{' after the '=' that follows the context set name "implementation", '{' assumed}} expected-warning {{'yyy' is not a valid context selector for the context set 'implementation', selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation = {) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-warning {{expected '}' after the context selectors for the context set "implementation", '}' assumed}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation = {vvv, vvv}) // expected-warning {{'vvv' is not a valid context selector for the context set 'implementation', selector ignored}} expected-warning {{'vvv' is not a valid context selector for the context set 'implementation', selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation = {vvv} implementation) // expected-error {{expected ')'}} expected-warning {{'vvv' is not a valid context selector for the context set 'implementation', selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation = {vvv}) implementation // expected-warning {{'vvv' is not a valid context selector for the context set 'implementation', selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation={xxx}) // expected-warning {{'xxx' is not a valid context selector for the context set 'implementation', selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation={vendor}) // expected-warning {{the context selector 'vendor' in context set 'implementation' requires a context property defined in parenthesis, selector ignored}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor()}) // expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(2 ibm)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(foofoo ()) ibm)}) // expected-warning {{expected '':'' after the score expression, '':'' assumed}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(5): ibm), vendor(llvm)}) // expected-warning {{the context selector 'vendor' was used already in the same 'omp declare variant' directiv, selector ignored}} expected-note {{the previous context selector 'vendor' used here}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(5): ibm), kind(cpu)}) // expected-warning {{the context selector 'kind' is not valid for the context set 'implementation', selector ignored}} expected-note {{the context selector 'kind' can be nested in the context set 'device', try 'match(device={kind(property)})'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(device={xxx}) // expected-warning {{'xxx' is not a valid context selector for the context set 'device', selector ignored}} expected-note {{context selector options are: 'kind' 'isa' 'arch'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(device={kind}) // expected-warning {{the context selector 'kind' in context set 'device' requires a context property defined in parenthesis, selector ignored}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(device={kind(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(device={kind()}) // expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} +#pragma omp declare variant(foofoo ) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} +#pragma omp declare variant(foofoo ) match(device={kind(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(device={kind(score(2 gpu)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('2'), score ignored}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(device={kind(score(foofoo ()) ibm)}) // expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foofoo()'), score ignored}} expected-warning {{'ibm' is not a valid context property for the context selector 'kind' and the context set 'device', property ignored}} expected-note {{try 'match(implementation={vendor(ibm)})'}} expected-note {{the ignored property spans until here}} +#pragma omp declare variant(foofoo ) match(device={kind(score(5): host), kind(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('5'), score ignored}} expected-warning {{the context selector 'kind' was used already in the same 'omp declare variant' directiv, selector ignored}} expected-note {{the previous context selector 'kind' used here}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(device={kind(score(5): nohost), vendor(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('5'), score ignored}} expected-warning {{the context selector 'vendor' is not valid for the context set 'device', selector ignored}} expected-note {{the context selector 'vendor' can be nested in the context set 'implementation', try 'match(implementation={vendor(property)})'}} expected-note {{the ignored selector spans until here}} int bar(); -#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}} -#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma omp declare variant(foofoo // expected-error {{expected ')'}} expected-error {{expected 'match' clause on 'omp declare variant' directive}} expected-note {{to match this '('}} -#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}} -#pragma omp declare variant(foo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) match // expected-error {{expected '(' after 'match'}} -#pragma omp declare variant(foofoo ) match( // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) match() // expected-error {{expected context selector in 'match' clause on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) match(xxx) // expected-error {{expected '=' after 'xxx' context selector set name on 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) match(xxx =) // expected-error {{expected '{' after '='}} -#pragma omp declare variant(foofoo ) match(xxx = {) // expected-error {{expected '}' or ',' after ')'}} expected-error {{expected '}'}} expected-note {{to match this '{'}} -#pragma omp declare variant(foofoo ) match(xxx = {}) -#pragma omp declare variant(foofoo ) match(xxx = {vvv, vvv}) -#pragma omp declare variant(foofoo ) match(user = {score() : condition()}) -#pragma omp declare variant(foofoo ) match(user = {score() : condition()}) -#pragma omp declare variant(foofoo ) match(user = {condition()}) -#pragma omp declare variant(foofoo ) match(user = {condition()}) -#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}} expected-error {{context selector set 'xxx' is used already in the same 'omp declare variant' directive}} expected-note {{previously context selector set 'xxx' used here}} -#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 ')' 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), vendor(llvm)}) // expected-error {{context trait selector 'vendor' is used already in the same 'implementation' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'vendor' used here}} -#pragma omp declare variant(foofoo ) match(implementation={vendor(score(5): ibm), kind(cpu)}) // expected-warning {{unknown context selector in 'implementation' context selector set of 'omp declare variant' directive, ignored}} -#pragma omp declare variant(foofoo ) match(device={xxx}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} -#pragma omp declare variant(foofoo ) match(device={kind}) // expected-error {{expected '(' after 'kind'}} expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error {{expected ')'}} expected-error {{expected ')'}} expected-note {{to match this '('}} -#pragma omp declare variant(foofoo ) match(device={kind(}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} expected-error 2 {{expected ')'}} expected-note {{to match this '('}} -#pragma omp declare variant(foofoo ) match(device={kind()}) // expected-error {{expected 'host', 'nohost', 'cpu', 'gpu', or 'fpga' in 'kind' context selector of 'device' selector set of 'omp declare variant' directive}} -#pragma omp declare variant(foofoo ) match(device={kind(score cpu)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foofoo ) match(device={kind(score( ibm)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foofoo ) match(device={kind(score(C gpu)}) // expected-error 2 {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foofoo ) match(device={kind(score(foofoo ()) ibm)}) // expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foofoo ) match(device={kind(score(C+5): host), kind(llvm)}) // expected-error {{context trait selector 'kind' is used already in the same 'device' context selector set of 'omp declare variant' directive}} expected-note {{previously context trait selector 'kind' used here}} expected-error {{expected ')' or ',' after 'score'}} expected-note {{to match this '('}} expected-error {{expected ')'}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} expected-error {{unknown 'llvm' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} -#pragma omp declare variant(foofoo ) match(device={kind(score(C+5): nohost), vendor(llvm)}) // expected-warning {{unknown context selector in 'device' context selector set of 'omp declare variant' directive, ignored}} expected-error {{expected ')' or ',' after 'score'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{unknown 'score' device kind trait in the 'device' context selector set, expected one of 'host', 'nohost', 'cpu', 'gpu' or 'fpga'}} +#pragma omp declare variant // expected-error {{expected '(' after 'declare variant'}} +#pragma omp declare variant( // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo // expected-error {{expected ')'}} expected-error {{expected 'match' clause on 'omp declare variant' directive}} expected-note {{to match this '('}} +#pragma omp declare variant(x) // expected-error {{use of undeclared identifier 'x'}} +#pragma omp declare variant(foo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} +#pragma omp declare variant(foofoo) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} +#pragma omp declare variant(foofoo ) // expected-error {{expected 'match' clause on 'omp declare variant' directive}} +#pragma omp declare variant(foofoo ) xxx // expected-error {{expected 'match' clause on 'omp declare variant' directive}} +#pragma omp declare variant(foofoo ) match // expected-error {{expected '(' after 'match'}} +#pragma omp declare variant(foofoo ) match( // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context set, set skipped}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match() // expected-warning {{expected identifier or string literal describing a context set, set skipped}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +#pragma omp declare variant(foofoo ) match(implementation) // expected-warning {{expected '=' after the context set name "implementation", '=' assumed}} expected-warning {{expected '{' after the '=' that follows the context set name "implementation", '{' assumed}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-warning {{expected '}' after the context selectors for the context set "implementation", '}' assumed}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation =) // expected-warning {{expected '{' after the '=' that follows the context set name "implementation", '{' assumed}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-warning {{expected '}' after the context selectors for the context set "implementation", '}' assumed}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation = {) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-warning {{expected '}' after the context selectors for the context set "implementation", '}' assumed}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation = {vvv, vvv}) // expected-warning {{'vvv' is not a valid context selector for the context set 'implementation', selector ignored}} expected-warning {{'vvv' is not a valid context selector for the context set 'implementation', selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(user = {score() : condition()}) // expected-warning {{'score' is not a valid context selector for the context set 'user', selector ignored}} expected-note {{context selector options are: 'condition'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(user = {score() : condition()}) // expected-warning {{'score' is not a valid context selector for the context set 'user', selector ignored}} expected-note {{context selector options are: 'condition'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(user = {condition()}) // expected-error {{expected expression}} expected-error {{use of undeclared identifier 'expr'}} expected-error {{expected expression}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(user = {condition()}) // expected-error {{expected expression}} expected-error {{use of undeclared identifier 'expr'}} expected-error {{expected expression}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation = {vvv} implementation) // expected-error {{expected ')'}} expected-warning {{'vvv' is not a valid context selector for the context set 'implementation', selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation = {vvv}) xxx // expected-warning {{'vvv' is not a valid context selector for the context set 'implementation', selector ignored}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(C ibm)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'amd' 'arm' 'bsc' 'cray' 'fujitsu' 'gnu' 'ibm' 'intel' 'llvm' 'pgi' 'ti' 'unknown'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(foofoo ()) ibm)}) // expected-warning {{expected '':'' after the score expression, '':'' assumed}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(C+5): ibm), vendor(llvm)}) // expected-warning {{the context selector 'vendor' was used already in the same 'omp declare variant' directiv, selector ignored}} expected-note {{the previous context selector 'vendor' used here}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(implementation={vendor(score(5): ibm), kind(cpu)}) // expected-warning {{the context selector 'kind' is not valid for the context set 'implementation', selector ignored}} expected-note {{the context selector 'kind' can be nested in the context set 'device', try 'match(device={kind(property)})'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(device={xxx}) // expected-warning {{'xxx' is not a valid context selector for the context set 'device', selector ignored}} expected-note {{context selector options are: 'kind' 'isa' 'arch'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(device={kind}) // expected-warning {{the context selector 'kind' in context set 'device' requires a context property defined in parenthesis, selector ignored}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(device={kind(}) // expected-error {{expected ')'}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(device={kind()}) // expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} +#pragma omp declare variant(foofoo ) match(device={kind(score cpu)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} +#pragma omp declare variant(foofoo ) match(device={kind(score( ibm)}) // expected-error {{use of undeclared identifier 'ibm'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(device={kind(score(C gpu)}) // expected-error {{expected ')'}} expected-error {{expected ')'}} expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('C'), score ignored}} expected-warning {{expected identifier or string literal describing a context property, property skipped}} expected-note {{to match this '('}} expected-note {{context property options are: 'host' 'nohost' 'cpu' 'gpu' 'fpga' 'any'}} expected-note {{to match this '('}} +#pragma omp declare variant(foofoo ) match(device={kind(score(foofoo ()) ibm)}) // expected-warning {{expected '':'' after the score expression, '':'' assumed}} expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('foofoo()'), score ignored}} expected-warning {{'ibm' is not a valid context property for the context selector 'kind' and the context set 'device', property ignored}} expected-note {{try 'match(implementation={vendor(ibm)})'}} expected-note {{the ignored property spans until here}} +#pragma omp declare variant(foofoo ) match(device={kind(score(C+5): host), kind(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('C + 5'), score ignored}} expected-warning {{the context selector 'kind' was used already in the same 'omp declare variant' directiv, selector ignored}} expected-note {{the previous context selector 'kind' used here}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(foofoo ) match(device={kind(score(C+5): nohost), vendor(llvm)}) // expected-warning {{the context selector 'kind' in the context set 'device' cannot have a score ('C + 5'), score ignored}} expected-warning {{the context selector 'vendor' is not valid for the context set 'device', selector ignored}} expected-note {{the context selector 'vendor' can be nested in the context set 'implementation', try 'match(implementation={vendor(property)})'}} expected-note {{the ignored selector spans until here}} template T barbar(); -// expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}} -#pragma omp declare variant(barbar ) match(xxx = {}) -int a; -// expected-error@+2 {{'#pragma omp declare variant' can only be applied to functions}} -#pragma omp declare variant(barbar ) match(xxx = {}) -#pragma omp threadprivate(a) + +#pragma omp declare variant(barbar ) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +int a; // expected-error {{'#pragma omp declare variant' can only be applied to functions}} + +#pragma omp declare variant(barbar ) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp threadprivate(a) // expected-error {{'#pragma omp declare variant' can only be applied to functions}} int var; #pragma omp threadprivate(var) -// expected-error@+2 {{expected an OpenMP directive}} expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant(barbar ) match(xxx = {}) -#pragma omp declare -// expected-error@+3 {{function declaration is expected after 'declare variant' directive}} -// expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant(barbar ) match(xxx = {}) -#pragma omp declare variant(barbar ) match(xxx = {}) +#pragma omp declare variant(barbar ) match(implementation = {}) // expected-error {{function declaration is expected after 'declare variant' directive}} +#pragma omp declare // expected-error {{expected an OpenMP directive}} + + + +#pragma omp declare variant(barbar ) match(implementation = {}) // expected-error {{function declaration is expected after 'declare variant' directive}} +#pragma omp declare variant(barbar ) match(xxx = {}) // expected-error {{function declaration is expected after 'declare variant' directive}} #pragma options align = packed int main(); -// expected-error@+3 {{function declaration is expected after 'declare variant' directive}} -// expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant(barbar ) match(xxx = {}) -#pragma omp declare variant(barbar ) match(xxx = {}) + + +#pragma omp declare variant(barbar ) match(implementation = {}) // expected-error {{function declaration is expected after 'declare variant' directive}} +#pragma omp declare variant(barbar ) match(xxx = {}) // expected-error {{function declaration is expected after 'declare variant' directive}} #pragma init_seg(compiler) int main(); -// expected-error@+1 {{single declaration is expected after 'declare variant' directive}} -#pragma omp declare variant(barbar ) match(xxx = {}) + +#pragma omp declare variant(barbar ) match(implementation = {}) // expected-error {{single declaration is expected after 'declare variant' directive}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} int b, c; -// expected-error@+1 {{'C' does not refer to a value}} -#pragma omp declare variant(C) match(xxx = {}) -// expected-note@+1 {{declared here}} -template + +#pragma omp declare variant(C) match(implementation = {}) // expected-error {{'C' does not refer to a value}} + +template // expected-note {{declared here}} void h(C *hp, C *hp2, C *hq, C *lin) { b = 0; } -// expected-error@+1 {{variant in '#pragma omp declare variant' with type '' is incompatible with type 'void (int *, int *, int *, int *)'}} -#pragma omp declare variant(barbar ) match(xxx = {}) + +#pragma omp declare variant(barbar ) match(implementation = {}) // expected-error {{variant in '#pragma omp declare variant' with type '' is incompatible with type 'void (int *, int *, int *, int *)'}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} template <> void h(int *hp, int *hp2, int *hq, int *lin); @@ -142,113 +142,113 @@ return after_use(); } -// expected-warning@+1 {{'#pragma omp declare variant' cannot be applied for function after first usage; the original function might be used}} -#pragma omp declare variant(after_use_variant) match(xxx = {}) + +#pragma omp declare variant(after_use_variant) match(implementation = {}) // expected-warning {{'#pragma omp declare variant' cannot be applied for function after first usage; the original function might be used}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} int after_use(void); int fn(); int fn(int); -#pragma omp declare variant(fn) match(xxx = {}) +#pragma omp declare variant(fn) match(xxx = {}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} int overload(void); int fn1(); int fn1(int); -// expected-error@+1 {{variant in '#pragma omp declare variant' with type '' is incompatible with type 'int (float)'}} -#pragma omp declare variant(fn1) match(xxx = {}) + +#pragma omp declare variant(fn1) match(implementation = {}) // expected-error {{variant in '#pragma omp declare variant' with type '' is incompatible with type 'int (float)'}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} int overload1(float); int fn_constexpr_variant(); -// expected-error@+2 {{'#pragma omp declare variant' does not support constexpr functions}} -#pragma omp declare variant(fn_constexpr_variant) match(xxx = {}) -constexpr int fn_constexpr(); + +#pragma omp declare variant(fn_constexpr_variant) match(xxx = {}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +constexpr int fn_constexpr(); // expected-error {{'#pragma omp declare variant' does not support constexpr functions}} constexpr int fn_constexpr_variant1(); -// expected-error@+1 {{'#pragma omp declare variant' does not support constexpr functions}} -#pragma omp declare variant(fn_constexpr_variant1) match(xxx = {}) + +#pragma omp declare variant(fn_constexpr_variant1) match(implementation = {}) // expected-error {{'#pragma omp declare variant' does not support constexpr functions}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} int fn_constexpr1(); int fn_sc_variant(); -// expected-error@+1 {{function with '#pragma omp declare variant' has a different storage class}} -#pragma omp declare variant(fn_sc_variant) match(xxx = {}) + +#pragma omp declare variant(fn_sc_variant) match(xxx = {}) // expected-error {{function with '#pragma omp declare variant' has a different storage class}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} static int fn_sc(); static int fn_sc_variant1(); -// expected-error@+1 {{function with '#pragma omp declare variant' has a different storage class}} -#pragma omp declare variant(fn_sc_variant1) match(xxx = {}) + +#pragma omp declare variant(fn_sc_variant1) match(implementation = {}) // expected-error {{function with '#pragma omp declare variant' has a different storage class}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} int fn_sc1(); int fn_inline_variant(); -// expected-error@+1 {{function with '#pragma omp declare variant' has a different inline specification}} -#pragma omp declare variant(fn_inline_variant) match(xxx = {}) + +#pragma omp declare variant(fn_inline_variant) match(xxx = {}) // expected-error {{function with '#pragma omp declare variant' has a different inline specification}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} inline int fn_inline(); inline int fn_inline_variant1(); -// expected-error@+1 {{function with '#pragma omp declare variant' has a different inline specification}} -#pragma omp declare variant(fn_inline_variant1) match(xxx = {}) + +#pragma omp declare variant(fn_inline_variant1) match(implementation = {}) // expected-error {{function with '#pragma omp declare variant' has a different inline specification}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} int fn_inline1(); auto fn_deduced_variant() { return 0; } -#pragma omp declare variant(fn_deduced_variant) match(xxx = {}) +#pragma omp declare variant(fn_deduced_variant) match(xxx = {}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} int fn_deduced(); int fn_deduced_variant1(); -#pragma omp declare variant(fn_deduced_variant1) match(xxx = {}) +#pragma omp declare variant(fn_deduced_variant1) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} auto fn_deduced1() { return 0; } auto fn_deduced3() { return 0; } -// expected-warning@+1 {{'#pragma omp declare variant' cannot be applied to the function that was defined already; the original function might be used}} -#pragma omp declare variant(fn_deduced_variant1) match(xxx = {}) + +#pragma omp declare variant(fn_deduced_variant1) match(implementation = {}) // expected-warning {{'#pragma omp declare variant' cannot be applied to the function that was defined already; the original function might be used}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} auto fn_deduced3(); auto fn_deduced_variant2() { return 0; } -// expected-error@+1 {{variant in '#pragma omp declare variant' with type 'int ()' is incompatible with type 'float ()'}} -#pragma omp declare variant(fn_deduced_variant2) match(xxx = {}) + +#pragma omp declare variant(fn_deduced_variant2) match(xxx = {}) // expected-error {{variant in '#pragma omp declare variant' with type 'int ()' is incompatible with type 'float ()'}} expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} float fn_deduced2(); -// expected-error@+1 {{exception specification in declaration does not match previous declaration}} -int fn_except_variant() noexcept(true); -// expected-note@+2 {{previous declaration is here}} -#pragma omp declare variant(fn_except_variant) match(xxx = {}) -int fn_except() noexcept(false); -// expected-error@+1 {{exception specification in declaration does not match previous declaration}} -int fn_except_variant1() noexcept(false); -// expected-note@+2 {{previous declaration is here}} -#pragma omp declare variant(fn_except_variant1) match(xxx = {}) -int fn_except1() noexcept(true); +int fn_except_variant() noexcept(true); // expected-error {{exception specification in declaration does not match previous declaration}} + +#pragma omp declare variant(fn_except_variant) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +int fn_except() noexcept(false); // expected-note {{previous declaration is here}} + + +int fn_except_variant1() noexcept(false); // expected-error {{exception specification in declaration does not match previous declaration}} + +#pragma omp declare variant(fn_except_variant1) match(xxx = {}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} +int fn_except1() noexcept(true); // expected-note {{previous declaration is here}} struct SpecialFuncs { void vd(); - // expected-error@+2 {{'#pragma omp declare variant' does not support constructors}} -#pragma omp declare variant(SpecialFuncs::vd) match(xxx = {}) - SpecialFuncs(); - // expected-error@+2 {{'#pragma omp declare variant' does not support destructors}} -#pragma omp declare variant(SpecialFuncs::vd) match(xxx = {}) - ~SpecialFuncs(); + +#pragma omp declare variant(SpecialFuncs::vd) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} + SpecialFuncs(); // expected-error {{'#pragma omp declare variant' does not support constructors}} + +#pragma omp declare variant(SpecialFuncs::vd) match(xxx = {}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} + ~SpecialFuncs(); // expected-error {{'#pragma omp declare variant' does not support destructors}} void baz(); void bar(); void bar(int); -#pragma omp declare variant(SpecialFuncs::baz) match(xxx = {}) -#pragma omp declare variant(SpecialFuncs::bar) match(xxx = {}) -// expected-error@+1 {{variant in '#pragma omp declare variant' with type 'int (*)()' is incompatible with type 'void (SpecialFuncs::*)()'}} -#pragma omp declare variant(fn_sc_variant1) match(xxx = {}) +#pragma omp declare variant(SpecialFuncs::baz) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} +#pragma omp declare variant(SpecialFuncs::bar) match(xxx = {}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} + +#pragma omp declare variant(fn_sc_variant1) match(implementation = {}) // expected-error {{variant in '#pragma omp declare variant' with type 'int (*)()' is incompatible with type 'void (SpecialFuncs::*)()'}} expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} void foo1(); SpecialFuncs& foo(const SpecialFuncs&); SpecialFuncs& bar(SpecialFuncs&&); - // expected-error@+2 {{'#pragma omp declare variant' does not support defaulted functions}} -#pragma omp declare variant(SpecialFuncs::foo) match(xxx = {}) - SpecialFuncs& operator=(const SpecialFuncs&) = default; - // expected-error@+2 {{'#pragma omp declare variant' does not support deleted functions}} -#pragma omp declare variant(SpecialFuncs::bar) match(xxx = {}) - SpecialFuncs& operator=(SpecialFuncs&&) = delete; + +#pragma omp declare variant(SpecialFuncs::foo) match(xxx = {}) // expected-warning {{'xxx' is not a valid context set in a `declare variant`, set ignored}} expected-note {{context set options are: 'construct' 'device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} + SpecialFuncs& operator=(const SpecialFuncs&) = default; // expected-error {{'#pragma omp declare variant' does not support defaulted functions}} + +#pragma omp declare variant(SpecialFuncs::bar) match(implementation = {}) // expected-warning {{expected identifier or string literal describing a context selector, selector skipped}} expected-note {{context selector options are: 'vendor' 'extension' 'unified_address' 'unified_shared_memory' 'reverse_offload' 'dynamic_allocators' 'atomic_default_mem_order'}} expected-note {{the ignored selector spans until here}} + SpecialFuncs& operator=(SpecialFuncs&&) = delete; // expected-error {{'#pragma omp declare variant' does not support deleted functions}} }; namespace N { -// expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant + +#pragma omp declare variant // expected-error {{function declaration is expected after 'declare variant' directive}} } // namespace N -// expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant -// expected-error@+1 {{function declaration is expected after 'declare variant' directive}} -#pragma omp declare variant + +#pragma omp declare variant // expected-error {{function declaration is expected after 'declare variant' directive}} + +#pragma omp declare variant // expected-error {{function declaration is expected after 'declare variant' directive}} diff --git a/clang/test/OpenMP/declare_variant_mixed_codegen.cpp b/clang/test/OpenMP/declare_variant_mixed_codegen.cpp --- a/clang/test/OpenMP/declare_variant_mixed_codegen.cpp +++ b/clang/test/OpenMP/declare_variant_mixed_codegen.cpp @@ -49,7 +49,7 @@ static int stat_unused_no_emit() { return 1; } static int stat_unused_(); #pragma omp declare variant(stat_unused_) match(implementation = {vendor(llvm)}, device={kind(cpu)}) -#pragma omp declare variant(stat_unused_no_emit) match(implementation = {vendor(xxx)}, device={kind(gpu)}) +#pragma omp declare variant(stat_unused_no_emit) match(implementation = {vendor(unknown)}, device = {kind(gpu)}) static int stat_unused() { return 1; } static int stat_used_(); @@ -103,16 +103,16 @@ int prio() { return 81; } int prio1() { return 82; } -#pragma omp declare variant(prio) match(implementation = {vendor(score(2): llvm)}, device={kind(cpu,host)}) -#pragma omp declare variant(prio1) match(implementation = {vendor(score(1): llvm)}, device={kind(cpu)}) +#pragma omp declare variant(prio1) match(implementation = {vendor(score(2): llvm)}, device={kind(cpu,host)}) +#pragma omp declare variant(prio) match(implementation = {vendor(score(1): llvm)}, device={kind(cpu)}) int prio_() { return 1; } static int prio2() { return 83; } static int prio3() { return 84; } static int prio4() { return 84; } -#pragma omp declare variant(prio4) match(implementation = {vendor(score(8): llvm)},device={kind(cpu,host)}) -#pragma omp declare variant(prio2) match(implementation = {vendor(score(5): llvm)}) +#pragma omp declare variant(prio4) match(implementation = {vendor(score(5): llvm)}) +#pragma omp declare variant(prio2) match(implementation = {vendor(score(8): llvm)}, device={kind(cpu,host)}) #pragma omp declare variant(prio3) match(implementation = {vendor(score(7): llvm)}, device={kind(cpu)}) static int prio1_() { return 1; } @@ -137,7 +137,7 @@ #pragma omp declare variant(fn_variant2) match(implementation = {vendor(llvm)}, device={kind(fpga)}) int fn2() { return 87; } -#pragma omp declare variant(stat_unused_no_emit) match(implementation = {vendor(xxx)}, device={kind(gpu)}) +#pragma omp declare variant(stat_unused_no_emit) match(implementation = {vendor(unknown)}, device = {kind(gpu)}) template static T stat_unused_T() { return 88; } diff --git a/clang/test/OpenMP/nvptx_declare_variant_device_kind_codegen.cpp b/clang/test/OpenMP/nvptx_declare_variant_device_kind_codegen.cpp --- a/clang/test/OpenMP/nvptx_declare_variant_device_kind_codegen.cpp +++ b/clang/test/OpenMP/nvptx_declare_variant_device_kind_codegen.cpp @@ -43,13 +43,13 @@ #define HEADER #ifdef GPU -#define CORRECT gpu -#define SUBSET nohost, gpu +#define SUBSET gpu +#define CORRECT nohost, gpu #define WRONG cpu, gpu #endif // GPU #ifdef NOHOST -#define CORRECT nohost -#define SUBSET nohost, gpu +#define SUBSET nohost +#define CORRECT nohost, gpu #define WRONG nohost, host #endif // NOHOST diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -107,6 +107,8 @@ .Case("IdentifierInfo *", "Record.readIdentifier()") .Case("StringRef", "Record.readString()") .Case("ParamIdx", "ParamIdx::deserialize(Record.readInt())") + .EndsWith("*", "Record.readUserType<" + + std::string(type, 0, type.size() - 1) + ">()") .Default("Record.readInt()"); } @@ -126,6 +128,7 @@ .Case("IdentifierInfo *", "AddIdentifierRef(" + std::string(name) + ");\n") .Case("StringRef", "AddString(" + std::string(name) + ");\n") .Case("ParamIdx", "push_back(" + std::string(name) + ".serialize());\n") + .EndsWith("*", "writeUserType(" + std::string(name) + ");\n") .Default("push_back(" + std::string(name) + ");\n"); } @@ -356,7 +359,8 @@ OS << " OS << \" \" << SA->get" << getUpperName() << "().getSourceIndex();\n"; } else { - llvm_unreachable("Unknown SimpleArgument type!"); + OS << " if (SA->get" << getUpperName() << "())\n "; + OS << " OS << \" \" << *SA->get" << getUpperName() << "();\n"; } } }; @@ -1303,6 +1307,9 @@ Ptr = std::make_unique(Arg, Attr); else if (ArgName == "VersionArgument") Ptr = std::make_unique(Arg, Attr); + else if (ArgName == "GenericPointerArgument") + Ptr = std::make_unique(Arg, Attr, + Arg.getValueAsString("Type")); if (!Ptr) { // Search in reverse order so that the most-derived type is handled first. diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPContext.h b/llvm/include/llvm/Frontend/OpenMP/OMPContext.h --- a/llvm/include/llvm/Frontend/OpenMP/OMPContext.h +++ b/llvm/include/llvm/Frontend/OpenMP/OMPContext.h @@ -49,6 +49,9 @@ /// Parse \p Str and return the trait set it matches or TraitSet::invalid. TraitSet getOpenMPContextTraitSetKind(StringRef Str); +/// Return the trait set for which \p Selector is a selector. +TraitSet getOpenMPContextTraitSetForSelector(TraitSelector Selector); + /// Return the trait set for which \p Property is a property. TraitSet getOpenMPContextTraitSetForProperty(TraitProperty Property); @@ -67,9 +70,7 @@ /// Parse \p Str and return the trait set it matches or /// TraitProperty::invalid. -TraitProperty getOpenMPContextTraitPropertyKind(TraitSet Set, - TraitSelector Selector, - StringRef Str); +TraitProperty getOpenMPContextTraitPropertyKind(TraitSet Set, StringRef Str); /// Return the trait property for a singleton selector \p Selector. TraitProperty getOpenMPContextTraitPropertyForSelector(TraitSelector Selector); @@ -80,6 +81,15 @@ /// Return a textual representation of the trait property \p Kind with selector /// and set name included. StringRef getOpenMPContextTraitPropertyFullName(TraitProperty Kind); + +/// Return a string listing all trait sets. +std::string listOpenMPContextTraitSets(); + +/// Return a string listing all trait selectors for \p Set. +std::string listOpenMPContextTraitSelectors(TraitSet Set); + +/// Return a string listing all trait properties for \p Set and \p Selector. +std::string listOpenMPContextTraitProperties(TraitSet Set, TraitSelector Selector); ///} /// Return true if \p Selector can be nested in \p Set. Also sets diff --git a/llvm/lib/Frontend/OpenMP/OMPContext.cpp b/llvm/lib/Frontend/OpenMP/OMPContext.cpp --- a/llvm/lib/Frontend/OpenMP/OMPContext.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPContext.cpp @@ -277,6 +277,15 @@ #include "llvm/Frontend/OpenMP/OMPKinds.def" .Default(TraitSet::invalid); } + +TraitSet llvm::omp::getOpenMPContextTraitSetForSelector(TraitSelector Selector) { + switch (Selector) { +#define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ + case TraitSelector::Enum: \ + return TraitSet::TraitSetEnum; +#include "llvm/Frontend/OpenMP/OMPKinds.def" + } +} TraitSet llvm::omp::getOpenMPContextTraitSetForProperty(TraitProperty Property) { switch (Property) { @@ -323,10 +332,9 @@ } TraitProperty llvm::omp::getOpenMPContextTraitPropertyKind( - TraitSet Set, TraitSelector Selector, StringRef S) { + TraitSet Set, StringRef S) { #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ - if (Set == TraitSet::TraitSetEnum && \ - Selector == TraitSelector::TraitSelectorEnum && Str == S) \ + if (Set == TraitSet::TraitSetEnum && Str == S) \ return TraitProperty::Enum; #include "llvm/Frontend/OpenMP/OMPKinds.def" return TraitProperty::invalid; @@ -387,3 +395,36 @@ } llvm_unreachable("Unknown trait property!"); } + +std::string llvm::omp::listOpenMPContextTraitSets() { + std::string S; +#define OMP_TRAIT_SET(Enum, Str) \ + if (Str != "invalid") \ + S.append("'").append(Str).append("'").append(" "); +#include "llvm/Frontend/OpenMP/OMPKinds.def" + S.pop_back(); + return S; +} + +std::string llvm::omp::listOpenMPContextTraitSelectors(TraitSet Set) { + std::string S; +#define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ + if (TraitSet::TraitSetEnum == Set && Str != "Invalid") \ + S.append("'").append(Str).append("'").append(" "); +#include "llvm/Frontend/OpenMP/OMPKinds.def" + S.pop_back(); + return S; +} + +std::string +llvm::omp::listOpenMPContextTraitProperties(TraitSet Set, + TraitSelector Selector) { + std::string S; +#define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ + if (TraitSet::TraitSetEnum == Set && \ + TraitSelector::TraitSelectorEnum == Selector && Str != "invalid") \ + S.append("'").append(Str).append("'").append(" "); +#include "llvm/Frontend/OpenMP/OMPKinds.def" + S.pop_back(); + return S; +}