[clang] fb4c451 - [OPENMP51]Initial parsing/sema for adjust_args clause for 'declare variant'
Mike Rice via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 13 09:43:30 PDT 2021
Author: Mike Rice
Date: 2021-10-13T09:34:09-07:00
New Revision: fb4c451001d06c600394382e2c6ad6872f78f646
URL: https://github.com/llvm/llvm-project/commit/fb4c451001d06c600394382e2c6ad6872f78f646
DIFF: https://github.com/llvm/llvm-project/commit/fb4c451001d06c600394382e2c6ad6872f78f646.diff
LOG: [OPENMP51]Initial parsing/sema for adjust_args clause for 'declare variant'
Adds initial parsing and sema for the 'adjust_args' clause.
Note that an AST clause is not created as it instead adds its expressions
to the OMPDeclareVariantAttr.
Differential Revision: https://reviews.llvm.org/D99905
Added:
clang/test/OpenMP/declare_variant_clauses_ast_print.cpp
clang/test/OpenMP/declare_variant_clauses_messages.cpp
Modified:
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/OpenMPKinds.def
clang/include/clang/Basic/OpenMPKinds.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/AttrImpl.cpp
clang/lib/Basic/OpenMPKinds.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/lib/Parse/ParseOpenMP.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/OpenMP/declare_variant_messages.c
clang/test/OpenMP/declare_variant_messages.cpp
flang/lib/Semantics/check-omp-structure.cpp
llvm/include/llvm/Frontend/OpenMP/OMP.td
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 6d31b2906bc58..e94466bd6121a 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -3690,6 +3690,8 @@ def OMPDeclareVariant : InheritableAttr {
let Args = [
ExprArgument<"VariantFuncRef">,
OMPTraitInfoArgument<"TraitInfos">,
+ VariadicExprArgument<"AdjustArgsNothing">,
+ VariadicExprArgument<"AdjustArgsNeedDevicePtr">
];
let AdditionalMembers = [{
OMPTraitInfo &getTraitInfo() { return *traitInfos; }
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index f42c55be63f93..e82eafba99546 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1357,7 +1357,8 @@ def err_omp_mapper_illegal_identifier : Error<
def err_omp_mapper_expected_declarator : Error<
"expected declarator on 'omp declare mapper' directive">;
def err_omp_declare_variant_wrong_clause : Error<
- "expected '%0' clause on 'omp declare variant' directive">;
+ "expected %select{'match'|'match' or 'adjust_args'}0 clause on "
+ "'omp declare variant' directive">;
def err_omp_declare_variant_duplicate_nested_trait : Error<
"nested OpenMP context selector contains duplicated trait '%0'"
" in selector '%1' and set '%2' with
diff erent score">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c5b3f2c5cca64..1634c23db3d26 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10817,6 +10817,10 @@ def err_omp_unroll_full_variable_trip_count : Error<
def note_omp_directive_here : Note<"'%0' directive found here">;
def err_omp_instantiation_not_supported
: Error<"instantiation of '%0' not supported yet">;
+def err_omp_adjust_arg_multiple_clauses : Error<
+ "'adjust_arg' argument %0 used in multiple clauses">;
+def err_omp_clause_requires_dispatch_construct : Error<
+ "'%0' clause requires 'dispatch' context selector">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
diff --git a/clang/include/clang/Basic/OpenMPKinds.def b/clang/include/clang/Basic/OpenMPKinds.def
index 4c014766180c5..a19daf91578ed 100644
--- a/clang/include/clang/Basic/OpenMPKinds.def
+++ b/clang/include/clang/Basic/OpenMPKinds.def
@@ -59,6 +59,9 @@
#ifndef OPENMP_REDUCTION_MODIFIER
#define OPENMP_REDUCTION_MODIFIER(Name)
#endif
+#ifndef OPENMP_ADJUST_ARGS_KIND
+#define OPENMP_ADJUST_ARGS_KIND(Name)
+#endif
// Static attributes for 'schedule' clause.
OPENMP_SCHEDULE_KIND(static)
@@ -149,6 +152,11 @@ OPENMP_REDUCTION_MODIFIER(default)
OPENMP_REDUCTION_MODIFIER(inscan)
OPENMP_REDUCTION_MODIFIER(task)
+// Adjust-op kinds for the 'adjust_args' clause.
+OPENMP_ADJUST_ARGS_KIND(nothing)
+OPENMP_ADJUST_ARGS_KIND(need_device_ptr)
+
+#undef OPENMP_ADJUST_ARGS_KIND
#undef OPENMP_REDUCTION_MODIFIER
#undef OPENMP_DEVICE_MODIFIER
#undef OPENMP_ORDER_KIND
diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h
index dbb3a223dc40f..c90bd429d87c8 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -167,6 +167,13 @@ enum OpenMPReductionClauseModifier {
OMPC_REDUCTION_unknown,
};
+/// OpenMP adjust-op kinds for 'adjust_args' clause.
+enum OpenMPAdjustArgsOpKind {
+#define OPENMP_ADJUST_ARGS_KIND(Name) OMPC_ADJUST_ARGS_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+ OMPC_ADJUST_ARGS_unknown,
+};
+
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str,
const LangOptions &LangOpts);
const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type);
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index e09803fddd10e..ff759cc77ea53 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -10977,8 +10977,10 @@ class Sema final {
/// \param VariantRef Expression that references the variant function, which
/// must be used instead of the original one, specified in \p DG.
/// \param TI The context traits associated with the function variant.
- void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef,
- OMPTraitInfo &TI, SourceRange SR);
+ void ActOnOpenMPDeclareVariantDirective(
+ FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
+ ArrayRef<Expr *> AdjustArgsNothing,
+ ArrayRef<Expr *> AdjustArgsNeedDevicePtr, SourceRange SR);
OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
Expr *Expr,
diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp
index 662f86722fa3a..e7b9828b4e344 100644
--- a/clang/lib/AST/AttrImpl.cpp
+++ b/clang/lib/AST/AttrImpl.cpp
@@ -195,6 +195,25 @@ void OMPDeclareVariantAttr::printPrettyPragma(
OS << ")";
}
OS << " match(" << traitInfos << ")";
+
+ auto PrintExprs = [&OS, &Policy](Expr **Begin, Expr **End) {
+ for (Expr **I = Begin; I != End; ++I) {
+ assert(*I && "Expected non-null Stmt");
+ if (I != Begin)
+ OS << ",";
+ (*I)->printPretty(OS, nullptr, Policy);
+ }
+ };
+ if (adjustArgsNothing_size()) {
+ OS << " adjust_args(nothing:";
+ PrintExprs(adjustArgsNothing_begin(), adjustArgsNothing_end());
+ OS << ")";
+ }
+ if (adjustArgsNeedDevicePtr_size()) {
+ OS << " adjust_args(need_device_ptr:";
+ PrintExprs(adjustArgsNeedDevicePtr_begin(), adjustArgsNeedDevicePtr_end());
+ OS << ")";
+ }
}
#include "clang/AST/AttrImpl.inc"
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index c86c0958fef45..4c209fb9cf6f8 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -125,6 +125,11 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
#define OPENMP_REDUCTION_MODIFIER(Name) .Case(#Name, OMPC_REDUCTION_##Name)
#include "clang/Basic/OpenMPKinds.def"
.Default(OMPC_REDUCTION_unknown);
+ case OMPC_adjust_args:
+ return llvm::StringSwitch<OpenMPAdjustArgsOpKind>(Str)
+#define OPENMP_ADJUST_ARGS_KIND(Name) .Case(#Name, OMPC_ADJUST_ARGS_##Name)
+#include "clang/Basic/OpenMPKinds.def"
+ .Default(OMPC_ADJUST_ARGS_unknown);
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
@@ -369,6 +374,16 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
#include "clang/Basic/OpenMPKinds.def"
}
llvm_unreachable("Invalid OpenMP 'reduction' clause modifier");
+ case OMPC_adjust_args:
+ switch (Type) {
+ case OMPC_ADJUST_ARGS_unknown:
+ return "unknown";
+#define OPENMP_ADJUST_ARGS_KIND(Name) \
+ case OMPC_ADJUST_ARGS_##Name: \
+ return #Name;
+#include "clang/Basic/OpenMPKinds.def"
+ }
+ llvm_unreachable("Invalid OpenMP 'adjust_args' clause kind");
case OMPC_unknown:
case OMPC_threadprivate:
case OMPC_if:
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 431cc62ef84f9..8ae45cae2d430 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -5989,6 +5989,7 @@ static void emitOMPAtomicExpr(CodeGenFunction &CGF, OpenMPClauseKind Kind,
case OMPC_nocontext:
case OMPC_filter:
case OMPC_when:
+ case OMPC_adjust_args:
llvm_unreachable("Clause is not allowed in 'omp atomic'.");
}
}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index ea8964f50ff10..68683b0f2bd9b 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1402,21 +1402,69 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
ASTContext &ASTCtx = Actions.getASTContext();
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
- if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI))
- return;
+ SmallVector<Expr *, 6> AdjustNothing;
+ SmallVector<Expr *, 6> AdjustNeedDevicePtr;
+
+ // At least one clause is required.
+ if (Tok.is(tok::annot_pragma_openmp_end)) {
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
+ << (getLangOpts().OpenMP < 51 ? 0 : 1);
+ }
+
+ bool IsError = false;
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
+ getLangOpts().OpenMP)) {
+ Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
+ << (getLangOpts().OpenMP < 51 ? 0 : 1);
+ IsError = true;
+ }
+ if (!IsError) {
+ switch (CKind) {
+ case OMPC_match:
+ IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
+ break;
+ case OMPC_adjust_args: {
+ ConsumeToken();
+ Parser::OpenMPVarListDataTy Data;
+ SmallVector<Expr *> Vars;
+ IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,
+ Vars, Data);
+ if (!IsError)
+ llvm::append_range(Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing
+ ? AdjustNothing
+ : AdjustNeedDevicePtr,
+ Vars);
+ break;
+ }
+ default:
+ llvm_unreachable("Unexpected clause for declare variant.");
+ }
+ }
+ if (IsError) {
+ while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
+ ;
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
+ return;
+ }
+ // Skip ',' if any.
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ }
Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
Actions.checkOpenMPDeclareVariantFunction(
Ptr, AssociatedFunction.get(), TI,
SourceRange(Loc, Tok.getLocation()));
- // Skip last tokens.
- while (Tok.isNot(tok::annot_pragma_openmp_end))
- ConsumeAnyToken();
if (DeclVarData && !TI.Sets.empty())
Actions.ActOnOpenMPDeclareVariantDirective(
- DeclVarData->first, DeclVarData->second, TI,
- SourceRange(Loc, Tok.getLocation()));
+ DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
+ AdjustNeedDevicePtr, SourceRange(Loc, Tok.getLocation()));
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
@@ -1431,24 +1479,15 @@ bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
: getOpenMPClauseKind(PP.getSpelling(Tok));
if (CKind != OMPC_match) {
Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
- << getOpenMPClauseName(OMPC_match);
- while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
- ;
- // Skip the last annot_pragma_openmp_end.
- (void)ConsumeAnnotationToken();
+ << (getLangOpts().OpenMP < 51 ? 0 : 1);
return true;
}
(void)ConsumeToken();
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPClauseName(OMPC_match).data())) {
- while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
- ;
- // Skip the last annot_pragma_openmp_end.
- (void)ConsumeAnnotationToken();
+ getOpenMPClauseName(OMPC_match).data()))
return true;
- }
// Parse inner context selectors.
parseOMPContextSelectors(Loc, TI);
@@ -2029,8 +2068,13 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
ASTContext &ASTCtx = Actions.getASTContext();
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
- if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI))
+ if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
+ while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ // Skip the last annot_pragma_openmp_end.
+ (void)ConsumeAnnotationToken();
break;
+ }
// Skip last tokens.
skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
@@ -4100,6 +4144,23 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
}
+ } else if (Kind == OMPC_adjust_args) {
+ // Handle adjust-op for adjust_args clause.
+ ColonProtectionRAIIObject ColonRAII(*this);
+ Data.ExtraModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",
+ getLangOpts());
+ Data.ExtraModifierLoc = Tok.getLocation();
+ if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) {
+ SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ } else {
+ ConsumeToken();
+ if (Tok.is(tok::colon))
+ Data.ColonLoc = Tok.getLocation();
+ ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
+ "adjust-op");
+ }
}
bool IsComma =
@@ -4107,7 +4168,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
(Kind == OMPC_reduction && !InvalidReductionId) ||
(Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
- (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown);
+ (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) ||
+ (Kind == OMPC_adjust_args &&
+ Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown);
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index b340091e3c2d0..da78212e29f45 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -6808,7 +6808,9 @@ void Sema::ActOnFinishedFunctionDefinitionInOpenMPDeclareVariantScope(
OMPDeclareVariantScope &DVScope = OMPDeclareVariantScopes.back();
auto *OMPDeclareVariantA = OMPDeclareVariantAttr::CreateImplicit(
- Context, VariantFuncRef, DVScope.TI);
+ Context, VariantFuncRef, DVScope.TI,
+ /*NothingArgs=*/nullptr, /*NothingArgsSize=*/0,
+ /*NeedDevicePtrArgs=*/nullptr, /*NeedDevicePtrArgsSize=*/0);
for (FunctionDecl *BaseFD : Bases)
BaseFD->addAttr(OMPDeclareVariantA);
}
@@ -7181,12 +7183,66 @@ Sema::checkOpenMPDeclareVariantFunction(Sema::DeclGroupPtrTy DG,
return std::make_pair(FD, cast<Expr>(DRE));
}
-void Sema::ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD,
- Expr *VariantRef,
- OMPTraitInfo &TI,
- SourceRange SR) {
- auto *NewAttr =
- OMPDeclareVariantAttr::CreateImplicit(Context, VariantRef, &TI, SR);
+void Sema::ActOnOpenMPDeclareVariantDirective(
+ FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI,
+ ArrayRef<Expr *> AdjustArgsNothing,
+ ArrayRef<Expr *> AdjustArgsNeedDevicePtr, 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
+ // dispatch selector of the construct selector set appears in the match
+ // clause.
+
+ SmallVector<Expr *, 8> AllAdjustArgs;
+ llvm::append_range(AllAdjustArgs, AdjustArgsNothing);
+ llvm::append_range(AllAdjustArgs, AdjustArgsNeedDevicePtr);
+
+ if (!AllAdjustArgs.empty()) {
+ VariantMatchInfo VMI;
+ TI.getAsVariantMatchInfo(Context, VMI);
+ if (!llvm::is_contained(
+ VMI.ConstructTraits,
+ llvm::omp::TraitProperty::construct_dispatch_dispatch)) {
+ Diag(AllAdjustArgs[0]->getExprLoc(),
+ diag::err_omp_clause_requires_dispatch_construct)
+ << getOpenMPClauseName(OMPC_adjust_args);
+ return;
+ }
+ }
+
+ // OpenMP 5.1 [2.3.5, declare variant directive, Restrictions]
+ // Each argument can only appear in a single adjust_args clause for each
+ // declare variant directive.
+ llvm::SmallPtrSet<const VarDecl *, 4> AdjustVars;
+
+ for (Expr *E : AllAdjustArgs) {
+ E = E->IgnoreParenImpCasts();
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) {
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(DRE->getDecl())) {
+ const VarDecl *CanonPVD = PVD->getCanonicalDecl();
+ if (FD->getNumParams() > PVD->getFunctionScopeIndex() &&
+ FD->getParamDecl(PVD->getFunctionScopeIndex())
+ ->getCanonicalDecl() == CanonPVD) {
+ // It's a parameter of the function, check duplicates.
+ if (!AdjustVars.insert(CanonPVD).second) {
+ Diag(DRE->getLocation(), diag::err_omp_adjust_arg_multiple_clauses)
+ << PVD;
+ return;
+ }
+ continue;
+ }
+ }
+ }
+ // Anything that is not a function parameter is an error.
+ Diag(E->getExprLoc(), diag::err_omp_param_or_this_in_clause) << FD << 0;
+ return;
+ }
+
+ auto *NewAttr = OMPDeclareVariantAttr::CreateImplicit(
+ Context, VariantRef, &TI, const_cast<Expr **>(AdjustArgsNothing.data()),
+ AdjustArgsNothing.size(),
+ const_cast<Expr **>(AdjustArgsNeedDevicePtr.data()),
+ AdjustArgsNeedDevicePtr.size(), SR);
FD->addAttr(NewAttr);
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index c9d5b03da4795..70c42a19978c3 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -481,7 +481,22 @@ static void instantiateOMPDeclareVariantAttr(
}
}
- S.ActOnOpenMPDeclareVariantDirective(FD, E, TI, Attr.getRange());
+ SmallVector<Expr *, 8> NothingExprs;
+ SmallVector<Expr *, 8> NeedDevicePtrExprs;
+ for (Expr *E : Attr.adjustArgsNothing()) {
+ ExprResult ER = Subst(E);
+ if (ER.isInvalid())
+ continue;
+ NothingExprs.push_back(ER.get());
+ }
+ for (Expr *E : Attr.adjustArgsNeedDevicePtr()) {
+ ExprResult ER = Subst(E);
+ if (ER.isInvalid())
+ continue;
+ NeedDevicePtrExprs.push_back(ER.get());
+ }
+ S.ActOnOpenMPDeclareVariantDirective(FD, E, TI, NothingExprs,
+ NeedDevicePtrExprs, Attr.getRange());
}
static void instantiateDependentAMDGPUFlatWorkGroupSizeAttr(
diff --git a/clang/test/OpenMP/declare_variant_clauses_ast_print.cpp b/clang/test/OpenMP/declare_variant_clauses_ast_print.cpp
new file mode 100644
index 0000000000000..2644842651ddb
--- /dev/null
+++ b/clang/test/OpenMP/declare_variant_clauses_ast_print.cpp
@@ -0,0 +1,107 @@
+//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
+//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
+//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
+//RUN: -fsyntax-only -verify -o - %s
+
+//RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -fopenmp -fopenmp-version=51 \
+//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
+//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
+//RUN: -fsyntax-only -verify -o - %s
+
+//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
+//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
+//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
+//RUN: -emit-pch -o %t %s
+
+// expected-no-diagnostics
+
+//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
+//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
+//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
+//RUN: -ast-print %s | FileCheck %s --check-prefix=PRINT
+
+//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
+//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
+//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
+//RUN: -ast-dump %s | FileCheck %s --check-prefix=DUMP
+
+//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
+//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
+//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
+//RUN: -include-pch %t -ast-print %s | FileCheck %s --check-prefix=PRINT
+
+//RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=51 \
+//RUN: -x c++ -std=c++14 -fexceptions -fcxx-exceptions \
+//RUN: -Wno-source-uses-openmp -Wno-openmp-clauses \
+//RUN: -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP
+
+#ifndef HEADER
+#define HEADER
+
+void foo_v1(float *AAA, float *BBB, int *I) {return;}
+void foo_v2(float *AAA, float *BBB, int *I) {return;}
+void foo_v3(float *AAA, float *BBB, int *I) {return;}
+
+//DUMP: FunctionDecl{{.*}} foo 'void (float *, float *, int *)'
+//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(x86, x86_64)}
+//DUMP: DeclRefExpr{{.*}}Function{{.*}}foo_v3
+//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'I'
+//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
+//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(ppc)}
+//DUMP: DeclRefExpr{{.*}}Function{{.*}}foo_v2
+//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'AAA'
+//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(arm)}
+//DUMP: DeclRefExpr{{.*}}Function{{.*}}foo_v1
+//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'AAA'
+//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
+//PRINT: #pragma omp declare variant(foo_v3) match(construct={dispatch}, device={arch(x86, x86_64)}) adjust_args(nothing:I) adjust_args(need_device_ptr:BBB)
+
+//PRINT: #pragma omp declare variant(foo_v2) match(construct={dispatch}, device={arch(ppc)}) adjust_args(need_device_ptr:AAA)
+
+//PRINT: omp declare variant(foo_v1) match(construct={dispatch}, device={arch(arm)}) adjust_args(need_device_ptr:AAA,BBB)
+
+#pragma omp declare variant(foo_v1) \
+ match(construct={dispatch}, device={arch(arm)}) \
+ adjust_args(need_device_ptr:AAA,BBB)
+
+#pragma omp declare variant(foo_v2) \
+ match(construct={dispatch}, device={arch(ppc)}), \
+ adjust_args(need_device_ptr:AAA)
+
+#pragma omp declare variant(foo_v3) \
+ adjust_args(need_device_ptr:BBB) adjust_args(nothing:I) \
+ match(construct={dispatch}, device={arch(x86,x86_64)})
+
+void foo(float *AAA, float *BBB, int *I) {return;}
+
+void Foo_Var(float *AAA, float *BBB) {return;}
+
+#pragma omp declare variant(Foo_Var) \
+ match(construct={dispatch}, device={arch(x86_64)}) \
+ adjust_args(need_device_ptr:AAA) adjust_args(nothing:BBB)
+template<typename T>
+void Foo(T *AAA, T *BBB) {return;}
+
+//PRINT: #pragma omp declare variant(Foo_Var) match(construct={dispatch}, device={arch(x86_64)}) adjust_args(nothing:BBB) adjust_args(need_device_ptr:AAA)
+//DUMP: FunctionDecl{{.*}} Foo 'void (T *, T *)'
+//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(x86_64)}
+//DUMP: DeclRefExpr{{.*}}Function{{.*}}Foo_Var
+//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
+//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'AAA'
+//
+//DUMP: FunctionDecl{{.*}} Foo 'void (float *, float *)'
+//DUMP: OMPDeclareVariantAttr{{.*}}device={arch(x86_64)}
+//DUMP: DeclRefExpr{{.*}}Function{{.*}}Foo_Var
+//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'BBB'
+//DUMP: DeclRefExpr{{.*}}ParmVar{{.*}}'AAA'
+
+void func()
+{
+ float *A;
+ float *B;
+
+ //#pragma omp dispatch
+ Foo(A, B);
+}
+
+#endif // HEADER
diff --git a/clang/test/OpenMP/declare_variant_clauses_messages.cpp b/clang/test/OpenMP/declare_variant_clauses_messages.cpp
new file mode 100644
index 0000000000000..6d68e68b02a08
--- /dev/null
+++ b/clang/test/OpenMP/declare_variant_clauses_messages.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -DOMP51 -std=c++11 -o - %s
+
+// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -DOMP50 -std=c++11 -o - %s
+
+int Other;
+
+void foo_v1(float *AAA, float *BBB, int *I) { return; }
+void foo_v2(float *AAA, float *BBB, int *I) { return; }
+void foo_v3(float *AAA, float *BBB, int *I) { return; }
+
+#ifdef OMP51
+// expected-error at +3 {{'adjust_arg' argument 'AAA' used in multiple clauses}}
+#pragma omp declare variant(foo_v1) \
+ match(construct={dispatch}, device={arch(arm)}) \
+ adjust_args(need_device_ptr:AAA,BBB) adjust_args(need_device_ptr:AAA)
+
+// expected-error at +3 {{'adjust_arg' argument 'AAA' used in multiple clauses}}
+#pragma omp declare variant(foo_v1) \
+ match(construct={dispatch}, device={arch(ppc)}), \
+ adjust_args(need_device_ptr:AAA) adjust_args(nothing:AAA)
+
+// expected-error at +2 {{use of undeclared identifier 'J'}}
+#pragma omp declare variant(foo_v1) \
+ adjust_args(nothing:J) \
+ match(construct={dispatch}, device={arch(x86,x86_64)})
+
+// expected-error at +2 {{expected reference to one of the parameters of function 'foo'}}
+#pragma omp declare variant(foo_v3) \
+ adjust_args(nothing:Other) \
+ match(construct={dispatch}, device={arch(x86,x86_64)})
+
+// expected-error at +2 {{'adjust_args' clause requires 'dispatch' context selector}}
+#pragma omp declare variant(foo_v3) \
+ adjust_args(nothing:BBB) match(construct={target}, device={arch(arm)})
+
+// expected-error at +2 {{'adjust_args' clause requires 'dispatch' context selector}}
+#pragma omp declare variant(foo_v3) \
+ adjust_args(nothing:BBB) match(device={arch(ppc)})
+#endif // OMP51
+#ifdef OMP50
+// expected-error at +2 {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foo_v1) \
+ adjust_args(need_device_ptr:AAA) match(device={arch(arm)})
+#endif // OMP50
+
+void foo(float *AAA, float *BBB, int *I) { return; }
+
diff --git a/clang/test/OpenMP/declare_variant_messages.c b/clang/test/OpenMP/declare_variant_messages.c
index e63c4b31371e5..0178ca15cabf0 100644
--- a/clang/test/OpenMP/declare_variant_messages.c
+++ b/clang/test/OpenMP/declare_variant_messages.c
@@ -20,12 +20,12 @@ int foo(void);
#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=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 '('}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#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(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}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#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 parentheses; 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 '('}}
@@ -58,9 +58,9 @@ int bar(void);
int score_and_cond_non_const();
#pragma omp declare variant(foo) match(construct={teams,parallel,for,simd})
-#pragma omp declare variant(foo) match(construct={target teams}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}}
-#pragma omp declare variant(foo) match(construct={parallel for}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}}
-#pragma omp declare variant(foo) match(construct={for simd}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}}
+#pragma omp declare variant(foo) match(construct={target teams}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foo) match(construct={parallel for}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
+#pragma omp declare variant(foo) match(construct={for simd}) // expected-error {{expected ')'}} expected-warning {{expected '}' after the context selectors for the context set "construct"; '}' assumed}} expected-note {{to match this '('}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
int construct(void);
#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}}
diff --git a/clang/test/OpenMP/declare_variant_messages.cpp b/clang/test/OpenMP/declare_variant_messages.cpp
index af16a2e40c357..b5091dda4fd15 100644
--- a/clang/test/OpenMP/declare_variant_messages.cpp
+++ b/clang/test/OpenMP/declare_variant_messages.cpp
@@ -28,7 +28,7 @@ T foofoo();
#pragma omp declare variant(foofoo <int>) 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 <int>) 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 <int>) 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 <int>) 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 <int>) 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}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foofoo <int>) 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 <int>) match(implementation={vendor}) // expected-warning {{the context selector 'vendor' in context set 'implementation' requires a context property defined in parentheses; selector ignored}} expected-note {{the ignored selector spans until here}}
#pragma omp declare variant(foofoo <int>) 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 '('}}
@@ -72,7 +72,7 @@ int bar();
#pragma omp declare variant(foofoo <T>) match(user = {condition(<expr>)}) // 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 <T>) match(user = {condition(<expr>)}) // 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 <T>) 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 <T>) 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 <T>) 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}} expected-error {{expected 'match' clause on 'omp declare variant' directive}}
#pragma omp declare variant(foofoo <int>) match(implementation={vendor(score ibm)}) // expected-error {{expected '(' after 'score'}} expected-warning {{expected '':'' after the score expression; '':'' assumed}}
#pragma omp declare variant(foofoo <int>) 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 <int>) 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 '('}}
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index c0924996ad477..88f5740765de6 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1422,6 +1422,7 @@ CHECK_SIMPLE_CLAUSE(Novariants, OMPC_novariants)
CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext)
CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter)
CHECK_SIMPLE_CLAUSE(When, OMPC_when)
+CHECK_SIMPLE_CLAUSE(AdjustArgs, OMPC_adjust_args)
CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)
CHECK_REQ_SCALAR_INT_CLAUSE(NumTasks, OMPC_num_tasks)
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index f968e49f758bf..67b97d2a64bae 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -314,6 +314,7 @@ def OMPC_Uniform : Clause<"uniform"> {
}
def OMPC_DeviceType : Clause<"device_type"> {}
def OMPC_Match : Clause<"match"> {}
+def OMPC_AdjustArgs : Clause<"adjust_args"> { }
def OMPC_Depobj : Clause<"depobj"> {
let clangClass = "OMPDepobjClause";
let isImplicit = true;
@@ -1518,6 +1519,9 @@ def OMP_DeclareVariant : Directive<"declare variant"> {
let allowedClauses = [
VersionedClause<OMPC_Match>
];
+ let allowedExclusiveClauses = [
+ VersionedClause<OMPC_AdjustArgs, 51>
+ ];
}
def OMP_MasterTaskloop : Directive<"master taskloop"> {
let allowedClauses = [
More information about the cfe-commits
mailing list