Index: clang/include/clang/AST/OpenMPClause.h =================================================================== --- clang/include/clang/AST/OpenMPClause.h +++ clang/include/clang/AST/OpenMPClause.h @@ -7709,13 +7709,6 @@ } }; -/// Contains 'interop' data for 'append_args' and 'init' clauses. -struct OMPInteropInfo final { - bool IsTarget = false; - bool IsTargetSync = false; - llvm::SmallVector PreferTypes; -}; - /// This represents the 'init' clause in '#pragma omp ...' directives. /// /// \code Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -221,6 +221,7 @@ // OMPTraitProperty := {Kind} // class OMPTraitInfoArgument : Argument; +class VariadicOMPInteropInfoArgument : Argument; class TypeArgument : Argument; class UnsignedArgument : Argument; @@ -3827,14 +3828,19 @@ OMPTraitInfoArgument<"TraitInfos">, VariadicExprArgument<"AdjustArgsNothing">, VariadicExprArgument<"AdjustArgsNeedDevicePtr">, - VariadicEnumArgument<"AppendArgs", "InteropType", - ["target", "targetsync", "target,targetsync"], - ["Target", "TargetSync", "Target_TargetSync"]> + VariadicOMPInteropInfoArgument<"AppendArgs">, ]; let AdditionalMembers = [{ OMPTraitInfo &getTraitInfo() { return *traitInfos; } void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy) const; + static const char *getInteropTypeString(OMPInteropInfo *I) { + if (I->IsTarget && I->IsTargetSync) + return "target,targetsync"; + if (I->IsTarget) + return "target"; + return "targetsync"; + } }]; } Index: clang/include/clang/Basic/OpenMPKinds.h =================================================================== --- clang/include/clang/Basic/OpenMPKinds.h +++ clang/include/clang/Basic/OpenMPKinds.h @@ -181,6 +181,16 @@ OMPC_BIND_unknown }; +/// Contains 'interop' data for 'append_args' and 'init' clauses. +class Expr; +struct OMPInteropInfo final { + OMPInteropInfo(bool IsTarget = false, bool IsTargetSync = false) + : IsTarget(IsTarget), IsTargetSync(IsTargetSync) {} + bool IsTarget; + bool IsTargetSync; + llvm::SmallVector PreferTypes; +}; + unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str, const LangOptions &LangOpts); const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type); Index: clang/include/clang/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -3179,8 +3179,7 @@ bool parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI); /// Parse an 'append_args' clause for '#pragma omp declare variant'. - bool parseOpenMPAppendArgs( - SmallVectorImpl &InterOpTypes); + bool parseOpenMPAppendArgs(SmallVectorImpl &InteropInfos); /// Parse a `match` clause for an '#pragma omp declare variant'. Return true /// if there was an error. Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -11373,9 +11373,8 @@ FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef AdjustArgsNothing, ArrayRef AdjustArgsNeedDevicePtr, - ArrayRef AppendArgs, - SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, - SourceRange SR); + ArrayRef AppendArgs, SourceLocation AdjustArgsLoc, + SourceLocation AppendArgsLoc, SourceRange SR); OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, Index: clang/lib/AST/AttrImpl.cpp =================================================================== --- clang/lib/AST/AttrImpl.cpp +++ clang/lib/AST/AttrImpl.cpp @@ -222,18 +222,18 @@ OS << ")"; } - auto PrintInteropTypes = [&OS](InteropType *Begin, InteropType *End) { - for (InteropType *I = Begin; I != End; ++I) { + auto PrintInteropInfo = [&OS](OMPInteropInfo *Begin, OMPInteropInfo *End) { + for (OMPInteropInfo *I = Begin; I != End; ++I) { if (I != Begin) OS << ", "; OS << "interop("; - OS << ConvertInteropTypeToStr(*I); + OS << getInteropTypeString(I); OS << ")"; } }; if (appendArgs_size()) { OS << " append_args("; - PrintInteropTypes(appendArgs_begin(), appendArgs_end()); + PrintInteropInfo(appendArgs_begin(), appendArgs_end()); OS << ")"; } } Index: clang/lib/Parse/ParseOpenMP.cpp =================================================================== --- clang/lib/Parse/ParseOpenMP.cpp +++ clang/lib/Parse/ParseOpenMP.cpp @@ -1419,7 +1419,7 @@ OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo(); SmallVector AdjustNothing; SmallVector AdjustNeedDevicePtr; - SmallVector AppendArgs; + SmallVector AppendArgs; SourceLocation AdjustArgsLoc, AppendArgsLoc; // At least one clause is required. @@ -1503,7 +1503,7 @@ } bool Parser::parseOpenMPAppendArgs( - SmallVectorImpl &InterOpTypes) { + SmallVectorImpl &InteropInfos) { bool HasError = false; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); @@ -1521,26 +1521,16 @@ return true; OMPInteropInfo InteropInfo; - if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args)) { + if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args)) HasError = true; - } else { - OMPDeclareVariantAttr::InteropType IT; - // As of OpenMP 5.1, there are two interop-types, "target" and - // "targetsync". Either or both are allowed for a single interop. - if (InteropInfo.IsTarget && InteropInfo.IsTargetSync) - IT = OMPDeclareVariantAttr::Target_TargetSync; - else if (InteropInfo.IsTarget) - IT = OMPDeclareVariantAttr::Target; - else - IT = OMPDeclareVariantAttr::TargetSync; - InterOpTypes.push_back(IT); - } + else + InteropInfos.push_back(InteropInfo); IT.consumeClose(); if (Tok.is(tok::comma)) ConsumeToken(); } - if (!HasError && InterOpTypes.empty()) { + if (!HasError && InteropInfos.empty()) { HasError = true; Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op); SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -7585,9 +7585,8 @@ FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef AdjustArgsNothing, ArrayRef AdjustArgsNeedDevicePtr, - ArrayRef AppendArgs, - SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, - SourceRange SR) { + ArrayRef AppendArgs, SourceLocation AdjustArgsLoc, + SourceLocation AppendArgsLoc, SourceRange SR) { // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions] // An adjust_args clause or append_args clause can only be specified if the @@ -7647,8 +7646,7 @@ AdjustArgsNothing.size(), const_cast(AdjustArgsNeedDevicePtr.data()), AdjustArgsNeedDevicePtr.size(), - const_cast(AppendArgs.data()), - AppendArgs.size(), SR); + const_cast(AppendArgs.data()), AppendArgs.size(), SR); FD->addAttr(NewAttr); } Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -506,7 +506,7 @@ SmallVector NothingExprs; SmallVector NeedDevicePtrExprs; - SmallVector AppendArgs; + SmallVector AppendArgs; for (Expr *E : Attr.adjustArgsNothing()) { ExprResult ER = Subst(E); @@ -520,7 +520,10 @@ continue; NeedDevicePtrExprs.push_back(ER.get()); } - llvm::append_range(AppendArgs, Attr.appendArgs()); + for (OMPInteropInfo &II : Attr.appendArgs()) { + // When prefer_type is implemented for append_args handle them here too. + AppendArgs.emplace_back(II.IsTarget, II.IsTargetSync); + } S.ActOnOpenMPDeclareVariantDirective( FD, E, TI, NothingExprs, NeedDevicePtrExprs, AppendArgs, SourceLocation(), Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -9671,9 +9671,7 @@ if (IVR.isInvalid()) return nullptr; - OMPInteropInfo InteropInfo; - InteropInfo.IsTarget = C->getIsTarget(); - InteropInfo.IsTargetSync = C->getIsTargetSync(); + OMPInteropInfo InteropInfo(C->getIsTarget(), C->getIsTargetSync()); InteropInfo.PreferTypes.reserve(C->varlist_size() - 1); for (Expr *E : llvm::drop_begin(C->varlists())) { ExprResult ER = getDerived().TransformExpr(cast(E)); Index: clang/lib/Serialization/ASTReaderDecl.cpp =================================================================== --- clang/lib/Serialization/ASTReaderDecl.cpp +++ clang/lib/Serialization/ASTReaderDecl.cpp @@ -2859,6 +2859,8 @@ return Reader.readInt(); } + bool readBool() { return Reader.readBool(); } + SourceRange readSourceRange() { return Reader.readSourceRange(); } Index: clang/utils/TableGen/ClangAttrEmitter.cpp =================================================================== --- clang/utils/TableGen/ClangAttrEmitter.cpp +++ clang/utils/TableGen/ClangAttrEmitter.cpp @@ -806,6 +806,49 @@ } }; + class VariadicOMPInteropInfoArgument : public VariadicArgument { + public: + VariadicOMPInteropInfoArgument(const Record &Arg, StringRef Attr) + : VariadicArgument(Arg, Attr, "OMPInteropInfo") {} + + void writeDump(raw_ostream &OS) const override { + OS << " for (" << getAttrName() << "Attr::" << getLowerName() + << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" + << getLowerName() << "_end(); I != E; ++I) {\n"; + OS << " if (I->IsTarget && I->IsTargetSync)\n"; + OS << " OS << \" Target_TargetSync\";\n"; + OS << " else if (I->IsTarget)\n"; + OS << " OS << \" Target\";\n"; + OS << " else\n"; + OS << " OS << \" TargetSync\";\n"; + OS << " }\n"; + } + + void writePCHReadDecls(raw_ostream &OS) const override { + OS << " unsigned " << getLowerName() << "Size = Record.readInt();\n"; + OS << " SmallVector " << getLowerName() << ";\n"; + OS << " " << getLowerName() << ".reserve(" << getLowerName() + << "Size);\n"; + OS << " for (unsigned I = 0, E = " << getLowerName() << "Size; "; + OS << "I != E; ++I) {\n"; + OS << " bool IsTarget = Record.readBool();\n"; + OS << " bool IsTargetSync = Record.readBool();\n"; + OS << " " << getLowerName() + << ".emplace_back(IsTarget, IsTargetSync);\n"; + OS << " }\n"; + } + + void writePCHWrite(raw_ostream &OS) const override { + OS << " Record.push_back(SA->" << getLowerName() << "_size());\n"; + OS << " for (" << getAttrName() << "Attr::" << getLowerName() + << "_iterator I = SA->" << getLowerName() << "_begin(), E = SA->" + << getLowerName() << "_end(); I != E; ++I) {\n"; + OS << " Record.writeBool(I->IsTarget);\n"; + OS << " Record.writeBool(I->IsTargetSync);\n"; + OS << " }\n"; + } + }; + class VariadicParamIdxArgument : public VariadicArgument { public: VariadicParamIdxArgument(const Record &Arg, StringRef Attr) @@ -1374,6 +1417,8 @@ Ptr = std::make_unique(Arg, Attr); else if (ArgName == "OMPTraitInfoArgument") Ptr = std::make_unique(Arg, Attr, "OMPTraitInfo *"); + else if (ArgName == "VariadicOMPInteropInfoArgument") + Ptr = std::make_unique(Arg, Attr); if (!Ptr) { // Search in reverse order so that the most-derived type is handled first.