@@ -1404,6 +1404,8 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
14041404 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo ();
14051405 SmallVector<Expr *, 6 > AdjustNothing;
14061406 SmallVector<Expr *, 6 > AdjustNeedDevicePtr;
1407+ SmallVector<OMPDeclareVariantAttr::InteropType, 3 > AppendArgs;
1408+ SourceLocation AdjustArgsLoc, AppendArgsLoc;
14071409
14081410 // At least one clause is required.
14091411 if (Tok.is (tok::annot_pragma_openmp_end)) {
@@ -1428,6 +1430,7 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
14281430 IsError = parseOMPDeclareVariantMatchClause (Loc, TI, ParentTI);
14291431 break ;
14301432 case OMPC_adjust_args: {
1433+ AdjustArgsLoc = Tok.getLocation ();
14311434 ConsumeToken ();
14321435 Parser::OpenMPVarListDataTy Data;
14331436 SmallVector<Expr *> Vars;
@@ -1440,6 +1443,19 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
14401443 Vars);
14411444 break ;
14421445 }
1446+ case OMPC_append_args:
1447+ if (!AppendArgs.empty ()) {
1448+ Diag (AppendArgsLoc, diag::err_omp_more_one_clause)
1449+ << getOpenMPDirectiveName (OMPD_declare_variant)
1450+ << getOpenMPClauseName (CKind) << 0 ;
1451+ IsError = true ;
1452+ }
1453+ if (!IsError) {
1454+ AppendArgsLoc = Tok.getLocation ();
1455+ ConsumeToken ();
1456+ IsError = parseOpenMPAppendArgs (AppendArgs);
1457+ }
1458+ break ;
14431459 default :
14441460 llvm_unreachable (" Unexpected clause for declare variant." );
14451461 }
@@ -1458,18 +1474,106 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
14581474
14591475 Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
14601476 Actions.checkOpenMPDeclareVariantFunction (
1461- Ptr, AssociatedFunction.get (), TI,
1477+ Ptr, AssociatedFunction.get (), TI, AppendArgs. size (),
14621478 SourceRange (Loc, Tok.getLocation ()));
14631479
14641480 if (DeclVarData && !TI.Sets .empty ())
14651481 Actions.ActOnOpenMPDeclareVariantDirective (
14661482 DeclVarData->first , DeclVarData->second , TI, AdjustNothing,
1467- AdjustNeedDevicePtr, SourceRange (Loc, Tok.getLocation ()));
1483+ AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc,
1484+ SourceRange (Loc, Tok.getLocation ()));
14681485
14691486 // Skip the last annot_pragma_openmp_end.
14701487 (void )ConsumeAnnotationToken ();
14711488}
14721489
1490+ // / Parse a list of interop-types. These are 'target' and 'targetsync'. Both
1491+ // / are allowed but duplication of either is not meaningful.
1492+ static Optional<OMPDeclareVariantAttr::InteropType>
1493+ parseInteropTypeList (Parser &P) {
1494+ const Token &Tok = P.getCurToken ();
1495+ bool HasError = false ;
1496+ bool IsTarget = false ;
1497+ bool IsTargetSync = false ;
1498+
1499+ while (Tok.is (tok::identifier)) {
1500+ if (Tok.getIdentifierInfo ()->isStr (" target" )) {
1501+ // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
1502+ // Each interop-type may be specified on an action-clause at most
1503+ // once.
1504+ if (IsTarget)
1505+ P.Diag (Tok, diag::warn_omp_more_one_interop_type) << " target" ;
1506+ IsTarget = true ;
1507+ } else if (Tok.getIdentifierInfo ()->isStr (" targetsync" )) {
1508+ if (IsTargetSync)
1509+ P.Diag (Tok, diag::warn_omp_more_one_interop_type) << " targetsync" ;
1510+ IsTargetSync = true ;
1511+ } else {
1512+ HasError = true ;
1513+ P.Diag (Tok, diag::err_omp_expected_interop_type);
1514+ }
1515+ P.ConsumeToken ();
1516+
1517+ if (!Tok.is (tok::comma))
1518+ break ;
1519+ P.ConsumeToken ();
1520+ }
1521+ if (HasError)
1522+ return None;
1523+
1524+ if (!IsTarget && !IsTargetSync) {
1525+ P.Diag (Tok, diag::err_omp_expected_interop_type);
1526+ return None;
1527+ }
1528+
1529+ // As of OpenMP 5.1,there are two interop-types, "target" and
1530+ // "targetsync". Either or both are allowed for a single interop.
1531+ if (IsTarget && IsTargetSync)
1532+ return OMPDeclareVariantAttr::Target_TargetSync;
1533+ if (IsTarget)
1534+ return OMPDeclareVariantAttr::Target;
1535+ return OMPDeclareVariantAttr::TargetSync;
1536+ }
1537+
1538+ bool Parser::parseOpenMPAppendArgs (
1539+ SmallVectorImpl<OMPDeclareVariantAttr::InteropType> &InterOpTypes) {
1540+ bool HasError = false ;
1541+ // Parse '('.
1542+ BalancedDelimiterTracker T (*this , tok::l_paren, tok::annot_pragma_openmp_end);
1543+ if (T.expectAndConsume (diag::err_expected_lparen_after,
1544+ getOpenMPClauseName (OMPC_append_args).data ()))
1545+ return true ;
1546+
1547+ // Parse the list of append-ops, each is;
1548+ // interop(interop-type[,interop-type]...)
1549+ while (Tok.is (tok::identifier) && Tok.getIdentifierInfo ()->isStr (" interop" )) {
1550+ ConsumeToken ();
1551+ BalancedDelimiterTracker IT (*this , tok::l_paren,
1552+ tok::annot_pragma_openmp_end);
1553+ if (IT.expectAndConsume (diag::err_expected_lparen_after, " interop" ))
1554+ return true ;
1555+
1556+ // Parse the interop-types.
1557+ if (Optional<OMPDeclareVariantAttr::InteropType> IType =
1558+ parseInteropTypeList (*this ))
1559+ InterOpTypes.push_back (IType.getValue ());
1560+ else
1561+ HasError = true ;
1562+
1563+ IT.consumeClose ();
1564+ if (Tok.is (tok::comma))
1565+ ConsumeToken ();
1566+ }
1567+ if (!HasError && InterOpTypes.empty ()) {
1568+ HasError = true ;
1569+ Diag (Tok.getLocation (), diag::err_omp_unexpected_append_op);
1570+ SkipUntil (tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1571+ StopBeforeMatch);
1572+ }
1573+ HasError = T.consumeClose () || HasError;
1574+ return HasError;
1575+ }
1576+
14731577bool Parser::parseOMPDeclareVariantMatchClause (SourceLocation Loc,
14741578 OMPTraitInfo &TI,
14751579 OMPTraitInfo *ParentTI) {
@@ -3342,36 +3446,15 @@ OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
33423446 }
33433447
33443448 // Parse the interop-types.
3345- bool HasError = false ;
3346- while (Tok.is (tok::identifier)) {
3347- if (PP.getSpelling (Tok) == " target" ) {
3348- // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
3349- // Each interop-type may be specified on an action-clause at most
3350- // once.
3351- if (IsTarget)
3352- Diag (Tok, diag::warn_omp_more_one_interop_type) << " target" ;
3353- IsTarget = true ;
3354- } else if (PP.getSpelling (Tok) == " targetsync" ) {
3355- if (IsTargetSync)
3356- Diag (Tok, diag::warn_omp_more_one_interop_type) << " targetsync" ;
3357- IsTargetSync = true ;
3358- } else {
3359- HasError = true ;
3360- Diag (Tok, diag::err_omp_expected_interop_type);
3361- }
3362- ConsumeToken ();
3363-
3364- if (!Tok.is (tok::comma))
3365- break ;
3366- ConsumeToken ();
3449+ if (Optional<OMPDeclareVariantAttr::InteropType> IType =
3450+ parseInteropTypeList (*this )) {
3451+ IsTarget = IType != OMPDeclareVariantAttr::TargetSync;
3452+ IsTargetSync = IType != OMPDeclareVariantAttr::Target;
3453+ if (Tok.isNot (tok::colon))
3454+ Diag (Tok, diag::warn_pragma_expected_colon) << " interop types" ;
33673455 }
3368- if (!HasError && !IsTarget && !IsTargetSync)
3369- Diag (Tok, diag::err_omp_expected_interop_type);
3370-
33713456 if (Tok.is (tok::colon))
33723457 ConsumeToken ();
3373- else if (IsTarget || IsTargetSync)
3374- Diag (Tok, diag::warn_pragma_expected_colon) << " interop types" ;
33753458 }
33763459
33773460 // Parse the variable.
0 commit comments