(void)ConsumeAnnotationToken();
}
-/// Parse a list of interop-types. These are 'target' and 'targetsync'. Both
-/// are allowed but duplication of either is not meaningful.
-static Optional<OMPDeclareVariantAttr::InteropType>
-parseInteropTypeList(Parser &P) {
- const Token &Tok = P.getCurToken();
- bool HasError = false;
- bool IsTarget = false;
- bool IsTargetSync = false;
-
- while (Tok.is(tok::identifier)) {
- if (Tok.getIdentifierInfo()->isStr("target")) {
- // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
- // Each interop-type may be specified on an action-clause at most
- // once.
- if (IsTarget)
- P.Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
- IsTarget = true;
- } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
- if (IsTargetSync)
- P.Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
- IsTargetSync = true;
- } else {
- HasError = true;
- P.Diag(Tok, diag::err_omp_expected_interop_type);
- }
- P.ConsumeToken();
-
- if (!Tok.is(tok::comma))
- break;
- P.ConsumeToken();
- }
- if (HasError)
- return None;
-
- if (!IsTarget && !IsTargetSync) {
- P.Diag(Tok, diag::err_omp_expected_interop_type);
- return None;
- }
-
- // As of OpenMP 5.1,there are two interop-types, "target" and
- // "targetsync". Either or both are allowed for a single interop.
- if (IsTarget && IsTargetSync)
- return OMPDeclareVariantAttr::Target_TargetSync;
- if (IsTarget)
- return OMPDeclareVariantAttr::Target;
- return OMPDeclareVariantAttr::TargetSync;
-}
-
bool Parser::parseOpenMPAppendArgs(
SmallVectorImpl<OMPDeclareVariantAttr::InteropType> &InterOpTypes) {
bool HasError = false;
if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))
return true;
- // Parse the interop-types.
- if (Optional<OMPDeclareVariantAttr::InteropType> IType =
- parseInteropTypeList(*this))
- InterOpTypes.push_back(*IType);
- else
+ OMPInteropInfo InteropInfo;
+ 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);
+ }
IT.consumeClose();
if (Tok.is(tok::comma))
return false;
}
+/// Parses a comma-separated list of interop-types and a prefer_type list.
+///
+bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,
+ OpenMPClauseKind Kind) {
+ const Token &Tok = getCurToken();
+ bool HasError = false;
+ bool IsTarget = false;
+ bool IsTargetSync = false;
+
+ while (Tok.is(tok::identifier)) {
+ // Currently prefer_type is only allowed with 'init' and it must be first.
+ bool PreferTypeAllowed = Kind == OMPC_init &&
+ InteropInfo.PreferTypes.empty() && !IsTarget &&
+ !IsTargetSync;
+ if (Tok.getIdentifierInfo()->isStr("target")) {
+ // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
+ // Each interop-type may be specified on an action-clause at most
+ // once.
+ if (IsTarget)
+ Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";
+ IsTarget = true;
+ ConsumeToken();
+ } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {
+ if (IsTargetSync)
+ Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";
+ IsTargetSync = true;
+ ConsumeToken();
+ } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&
+ PreferTypeAllowed) {
+ ConsumeToken();
+ BalancedDelimiterTracker PT(*this, tok::l_paren,
+ tok::annot_pragma_openmp_end);
+ if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
+ HasError = true;
+
+ while (Tok.isNot(tok::r_paren)) {
+ SourceLocation Loc = Tok.getLocation();
+ ExprResult LHS = ParseCastExpression(AnyCastExpr);
+ ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
+ ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
+ /*DiscardedValue=*/false);
+ if (PTExpr.isUsable()) {
+ InteropInfo.PreferTypes.push_back(PTExpr.get());
+ } else {
+ HasError = true;
+ SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ }
+
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ }
+ PT.consumeClose();
+ } else {
+ HasError = true;
+ Diag(Tok, diag::err_omp_expected_interop_type);
+ ConsumeToken();
+ }
+ if (!Tok.is(tok::comma))
+ break;
+ ConsumeToken();
+ }
+
+ if (!HasError && !IsTarget && !IsTargetSync) {
+ Diag(Tok, diag::err_omp_expected_interop_type);
+ HasError = true;
+ }
+
+ if (Kind == OMPC_init) {
+ if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))
+ Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
+ if (Tok.is(tok::colon))
+ ConsumeToken();
+ }
+
+ // As of OpenMP 5.1,there are two interop-types, "target" and
+ // "targetsync". Either or both are allowed for a single interop.
+ InteropInfo.IsTarget = IsTarget;
+ InteropInfo.IsTargetSync = IsTargetSync;
+
+ return HasError;
+}
+
/// Parsing of OpenMP clauses that use an interop-var.
///
/// init-clause:
getOpenMPClauseName(Kind).data()))
return nullptr;
- bool IsTarget = false;
- bool IsTargetSync = false;
- SmallVector<Expr *, 4> Prefs;
-
- if (Kind == OMPC_init) {
-
- // Parse optional interop-modifier.
- if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "prefer_type") {
- ConsumeToken();
- BalancedDelimiterTracker PT(*this, tok::l_paren,
- tok::annot_pragma_openmp_end);
- if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))
- return nullptr;
-
- while (Tok.isNot(tok::r_paren)) {
- SourceLocation Loc = Tok.getLocation();
- ExprResult LHS = ParseCastExpression(AnyCastExpr);
- ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr(
- ParseRHSOfBinaryExpression(LHS, prec::Conditional));
- PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,
- /*DiscardedValue=*/false);
- if (PTExpr.isUsable())
- Prefs.push_back(PTExpr.get());
- else
- SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
- StopBeforeMatch);
-
- if (Tok.is(tok::comma))
- ConsumeToken();
- }
- PT.consumeClose();
- }
-
- if (!Prefs.empty()) {
- if (Tok.is(tok::comma))
- ConsumeToken();
- else
- Diag(Tok, diag::err_omp_expected_punc_after_interop_mod);
- }
-
- // Parse the interop-types.
- if (Optional<OMPDeclareVariantAttr::InteropType> IType =
- parseInteropTypeList(*this)) {
- IsTarget = IType != OMPDeclareVariantAttr::TargetSync;
- IsTargetSync = IType != OMPDeclareVariantAttr::Target;
- if (Tok.isNot(tok::colon))
- Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";
- }
- if (Tok.is(tok::colon))
- ConsumeToken();
- }
+ bool InteropError = false;
+ OMPInteropInfo InteropInfo;
+ if (Kind == OMPC_init)
+ InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
// Parse the variable.
SourceLocation VarLoc = Tok.getLocation();
if (!T.consumeClose())
RLoc = T.getCloseLocation();
- if (ParseOnly || !InteropVarExpr.isUsable() ||
- (Kind == OMPC_init && !IsTarget && !IsTargetSync))
+ if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)
return nullptr;
if (Kind == OMPC_init)
- return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), Prefs, IsTarget,
- IsTargetSync, Loc, T.getOpenLocation(),
- VarLoc, RLoc);
+ return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), InteropInfo, Loc,
+ T.getOpenLocation(), VarLoc, RLoc);
if (Kind == OMPC_use)
return Actions.ActOnOpenMPUseClause(InteropVarExpr.get(), Loc,
T.getOpenLocation(), VarLoc, RLoc);
///
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide different behavior.
- OMPClause *RebuildOMPInitClause(Expr *InteropVar, ArrayRef<Expr *> PrefExprs,
- bool IsTarget, bool IsTargetSync,
+ OMPClause *RebuildOMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo,
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation VarLoc,
SourceLocation EndLoc) {
- return getSema().ActOnOpenMPInitClause(InteropVar, PrefExprs, IsTarget,
- IsTargetSync, StartLoc, LParenLoc,
- VarLoc, EndLoc);
+ return getSema().ActOnOpenMPInitClause(InteropVar, InteropInfo, StartLoc,
+ LParenLoc, VarLoc, EndLoc);
}
/// Build a new OpenMP 'use' clause.
if (IVR.isInvalid())
return nullptr;
- llvm::SmallVector<Expr *, 8> PrefExprs;
- PrefExprs.reserve(C->varlist_size() - 1);
+ OMPInteropInfo InteropInfo;
+ InteropInfo.IsTarget = C->getIsTarget();
+ InteropInfo.IsTargetSync = C->getIsTargetSync();
+ InteropInfo.PreferTypes.reserve(C->varlist_size() - 1);
for (Expr *E : llvm::drop_begin(C->varlists())) {
ExprResult ER = getDerived().TransformExpr(cast<Expr>(E));
if (ER.isInvalid())
return nullptr;
- PrefExprs.push_back(ER.get());
+ InteropInfo.PreferTypes.push_back(ER.get());
}
- return getDerived().RebuildOMPInitClause(
- IVR.get(), PrefExprs, C->getIsTarget(), C->getIsTargetSync(),
- C->getBeginLoc(), C->getLParenLoc(), C->getVarLoc(), C->getEndLoc());
+ return getDerived().RebuildOMPInitClause(IVR.get(), InteropInfo,
+ C->getBeginLoc(), C->getLParenLoc(),
+ C->getVarLoc(), C->getEndLoc());
}
template <typename Derived>