aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseOpenMP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseOpenMP.cpp')
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp491
1 files changed, 332 insertions, 159 deletions
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 5f53f9d684e7..a31ceaeebd80 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -25,6 +25,7 @@
#include "llvm/ADT/UniqueVector.h"
#include "llvm/Frontend/OpenMP/OMPAssume.h"
#include "llvm/Frontend/OpenMP/OMPContext.h"
+#include <optional>
using namespace clang;
using namespace llvm::omp;
@@ -198,8 +199,8 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
if (DKind == OMPD_unknown)
return OMPD_unknown;
- for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
- if (DKind != F[I][0])
+ for (const auto &I : F) {
+ if (DKind != I[0])
continue;
Tok = P.getPreprocessor().LookAhead(0);
@@ -210,9 +211,9 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
if (SDKind == OMPD_unknown)
continue;
- if (SDKind == F[I][1]) {
+ if (SDKind == I[1]) {
P.ConsumeToken();
- DKind = F[I][2];
+ DKind = I[2];
}
}
return unsigned(DKind) < llvm::omp::Directive_enumSize
@@ -259,7 +260,7 @@ static DeclarationName parseOpenMPReductionId(Parser &P) {
case tok::identifier: // identifier
if (!WithOperator)
break;
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
default:
P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
@@ -475,7 +476,6 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
T.consumeOpen();
ExprVector Exprs;
- CommaLocsTy CommaLocs;
SourceLocation LParLoc = T.getOpenLocation();
auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
@@ -485,7 +485,7 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
CalledSignatureHelp = true;
return PreferredType;
};
- if (ParseExpressionList(Exprs, CommaLocs, [&] {
+ if (ParseExpressionList(Exprs, [&] {
PreferredType.enterFunctionArgument(Tok.getLocation(),
RunSignatureHelp);
})) {
@@ -499,9 +499,6 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
if (!T.consumeClose())
RLoc = T.getCloseLocation();
- assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
- "Unexpected number of commas!");
-
ExprResult Initializer =
Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
@@ -1419,7 +1416,7 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo();
SmallVector<Expr *, 6> AdjustNothing;
SmallVector<Expr *, 6> AdjustNeedDevicePtr;
- SmallVector<OMPDeclareVariantAttr::InteropType, 3> AppendArgs;
+ SmallVector<OMPInteropInfo, 3> AppendArgs;
SourceLocation AdjustArgsLoc, AppendArgsLoc;
// At least one clause is required.
@@ -1487,7 +1484,7 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
ConsumeToken();
}
- Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
+ std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
Actions.checkOpenMPDeclareVariantFunction(
Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),
SourceRange(Loc, Tok.getLocation()));
@@ -1502,56 +1499,8 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
(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) {
+ SmallVectorImpl<OMPInteropInfo> &InteropInfos) {
bool HasError = false;
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
@@ -1568,18 +1517,17 @@ bool Parser::parseOpenMPAppendArgs(
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
+ 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,
@@ -1676,6 +1624,42 @@ bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,
return false;
}
+/// <clause> [clause[ [,] clause] ... ]
+///
+/// clauses: for error directive
+/// 'at' '(' compilation | execution ')'
+/// 'severity' '(' fatal | warning ')'
+/// 'message' '(' msg-string ')'
+/// ....
+void Parser::ParseOpenMPClauses(OpenMPDirectiveKind DKind,
+ SmallVectorImpl<OMPClause *> &Clauses,
+ SourceLocation Loc) {
+ SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
+ llvm::omp::Clause_enumSize + 1>
+ FirstClauses(llvm::omp::Clause_enumSize + 1);
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ Actions.StartOpenMPClause(CKind);
+ OMPClause *Clause = ParseOpenMPClause(
+ DKind, CKind, !FirstClauses[unsigned(CKind)].getInt());
+ SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ FirstClauses[unsigned(CKind)].setInt(true);
+ if (Clause != nullptr)
+ Clauses.push_back(Clause);
+ if (Tok.is(tok::annot_pragma_openmp_end)) {
+ Actions.EndOpenMPClause();
+ break;
+ }
+ // Skip ',' if any.
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ Actions.EndOpenMPClause();
+ }
+}
+
/// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]...
/// where
///
@@ -1798,7 +1782,7 @@ struct SimpleClauseData {
};
} // anonymous namespace
-static Optional<SimpleClauseData>
+static std::optional<SimpleClauseData>
parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
const Token &Tok = P.getCurToken();
SourceLocation Loc = Tok.getLocation();
@@ -1807,7 +1791,7 @@ parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
getOpenMPClauseName(Kind).data()))
- return llvm::None;
+ return std::nullopt;
unsigned Type = getOpenMPSimpleClauseType(
Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),
@@ -1850,9 +1834,21 @@ void Parser::ParseOMPDeclareTargetClauses(
<< getOpenMPClauseName(OMPC_indirect) << 0;
break;
}
- bool IsToOrLinkClause =
+ bool IsToEnterOrLinkClause =
OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
- assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!");
+ assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
+ "Cannot be both!");
+
+ // Starting with OpenMP 5.2 the `to` clause has been replaced by the
+ // `enter` clause.
+ if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {
+ Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
+ break;
+ }
+ if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {
+ Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
+ break;
+ }
if (!IsDeviceTypeClause && !IsIndirectClause &&
DTCI.Kind == OMPD_begin_declare_target) {
@@ -1860,16 +1856,18 @@ void Parser::ParseOMPDeclareTargetClauses(
<< ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
break;
}
- if (!IsDeviceTypeClause && !IsToOrLinkClause && !IsIndirectClause) {
- Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
+ if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
+ Diag(Tok, getLangOpts().OpenMP >= 52
+ ? diag::err_omp_declare_target_unexpected_clause_52
+ : diag::err_omp_declare_target_unexpected_clause)
<< ClauseName
- << (getLangOpts().OpenMP >= 51 ? 4
- : getLangOpts().OpenMP >= 50 ? 2
- : 1);
+ << (getLangOpts().OpenMP >= 51
+ ? 4
+ : getLangOpts().OpenMP >= 50 ? 2 : 1);
break;
}
- if (IsToOrLinkClause || IsIndirectClause)
+ if (IsToEnterOrLinkClause || IsIndirectClause)
HasToOrLinkOrIndirectClause = true;
if (IsIndirectClause) {
@@ -1879,16 +1877,16 @@ void Parser::ParseOMPDeclareTargetClauses(
}
// Parse 'device_type' clause and go to next clause if any.
if (IsDeviceTypeClause) {
- Optional<SimpleClauseData> DevTypeData =
+ std::optional<SimpleClauseData> DevTypeData =
parseOpenMPSimpleClause(*this, OMPC_device_type);
if (DevTypeData) {
if (DeviceTypeLoc.isValid()) {
// We already saw another device_type clause, diagnose it.
- Diag(DevTypeData.value().Loc,
+ Diag(DevTypeData->Loc,
diag::warn_omp_more_one_device_type_clause);
break;
}
- switch (static_cast<OpenMPDeviceType>(DevTypeData.value().Type)) {
+ switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) {
case OMPC_DEVICE_TYPE_any:
DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
break;
@@ -1933,7 +1931,9 @@ void Parser::ParseOMPDeclareTargetClauses(
}
if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {
Diag(Tok,
- diag::err_omp_declare_target_unexpected_clause_after_implicit_to);
+ getLangOpts().OpenMP >= 52
+ ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
+ : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
break;
}
@@ -1948,7 +1948,10 @@ void Parser::ParseOMPDeclareTargetClauses(
// For declare target require at least 'to' or 'link' to be present.
if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
!HasToOrLinkOrIndirectClause)
- Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause)
+ Diag(DTCI.Loc,
+ getLangOpts().OpenMP >= 52
+ ? diag::err_omp_declare_target_missing_enter_or_link_clause
+ : diag::err_omp_declare_target_missing_to_or_link_clause)
<< (getLangOpts().OpenMP >= 51 ? 1 : 0);
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
@@ -2173,6 +2176,14 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
ConsumeAnnotationToken();
return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
}
+ case OMPD_error: {
+ SmallVector<OMPClause *, 1> Clauses;
+ SourceLocation StartLoc = ConsumeToken();
+ ParseOpenMPClauses(DKind, Clauses, StartLoc);
+ Actions.ActOnOpenMPErrorDirective(Clauses, StartLoc, SourceLocation(),
+ /*InExContext = */ false);
+ break;
+ }
case OMPD_assumes:
case OMPD_begin_assumes:
ParseOpenMPAssumesDirective(DKind, ConsumeToken());
@@ -2294,9 +2305,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
// Here we expect to see some function declaration.
if (AS == AS_none) {
assert(TagType == DeclSpec::TST_unspecified);
+ ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
MaybeParseCXX11Attributes(Attrs);
ParsingDeclSpec PDS(*this);
- Ptr = ParseExternalDeclaration(Attrs, &PDS);
+ Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
} else {
Ptr =
ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
@@ -2459,8 +2471,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
/// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
-/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' |
-/// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
+/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'error'
+/// | 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
/// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
/// 'master taskloop' | 'master taskloop simd' | 'parallel master
/// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
@@ -2746,6 +2758,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
case OMPD_depobj:
case OMPD_scan:
case OMPD_taskyield:
+ case OMPD_error:
case OMPD_barrier:
case OMPD_taskwait:
case OMPD_cancellation_point:
@@ -2758,10 +2771,14 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
ParsedStmtContext()) {
Diag(Tok, diag::err_omp_immediate_directive)
<< getOpenMPDirectiveName(DKind) << 0;
+ if (DKind == OMPD_error) {
+ SkipUntil(tok::annot_pragma_openmp_end);
+ break;
+ }
}
HasAssociatedStatement = false;
// Fall through for further analysis.
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case OMPD_parallel:
case OMPD_simd:
case OMPD_tile:
@@ -2945,7 +2962,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
DKind == OMPD_target_exit_data) {
Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
- Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
+ Actions.ActOnCompoundStmt(Loc, Loc, std::nullopt,
/*isStmtExpr=*/false));
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
}
@@ -3177,6 +3194,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_filter:
case OMPC_partial:
case OMPC_align:
+ case OMPC_message:
+ case OMPC_ompx_dyn_cgroup_mem:
// OpenMP [2.5, Restrictions]
// At most one num_threads clause can appear on the directive.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -3202,6 +3221,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions.
// At most one novariants clause can appear on a dispatch directive.
// At most one nocontext clause can appear on a dispatch directive.
+ // OpenMP [5.1, error directive, Restrictions]
+ // At most one message clause can appear on the directive
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
@@ -3211,13 +3232,16 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
Clause = ParseOpenMPClause(CKind, WrongDirective);
+ else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
+ Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
else
Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
break;
case OMPC_default:
case OMPC_proc_bind:
case OMPC_atomic_default_mem_order:
- case OMPC_order:
+ case OMPC_at:
+ case OMPC_severity:
case OMPC_bind:
// OpenMP [2.14.3.1, Restrictions]
// Only a single default clause may be specified on a parallel, task or
@@ -3227,9 +3251,12 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
// OpenMP [5.0, Requires directive, Restrictions]
// At most one atomic_default_mem_order clause can appear
// on the directive
+ // OpenMP [5.1, error directive, Restrictions]
+ // At most one at clause can appear on the directive
+ // At most one severity clause can appear on the directive
// OpenMP 5.1, 2.11.7 loop Construct, Restrictions.
// At most one bind clause can appear on a loop directive.
- if (!FirstClause && CKind != OMPC_order) {
+ if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
@@ -3241,19 +3268,22 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_schedule:
case OMPC_dist_schedule:
case OMPC_defaultmap:
+ case OMPC_order:
// OpenMP [2.7.1, Restrictions, p. 3]
// Only one schedule clause can appear on a loop directive.
// OpenMP 4.5 [2.10.4, Restrictions, p. 106]
// At most one defaultmap clause can appear on the directive.
// OpenMP 5.0 [2.12.5, target construct, Restrictions]
// At most one device clause can appear on the directive.
+ // OpenMP 5.1 [2.11.3, order clause, Restrictions]
+ // At most one order clause may appear on a construct.
if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
- !FirstClause) {
+ (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case OMPC_if:
Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
break;
@@ -3351,7 +3381,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
Clause = ParseOpenMPClause(CKind, WrongDirective);
break;
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case OMPC_init:
case OMPC_use:
Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
@@ -3496,6 +3526,90 @@ bool Parser::ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI,
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:
@@ -3528,57 +3642,10 @@ OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
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();
@@ -3594,14 +3661,12 @@ OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
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);
@@ -3630,24 +3695,24 @@ OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind,
///
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
bool ParseOnly) {
- llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
+ std::optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
if (!Val || ParseOnly)
return nullptr;
if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
- (static_cast<DefaultKind>(Val.value().Type) == OMP_DEFAULT_private ||
- static_cast<DefaultKind>(Val.value().Type) ==
+ (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||
+ static_cast<DefaultKind>(Val->Type) ==
OMP_DEFAULT_firstprivate)) {
- Diag(Val.value().LOpen, diag::err_omp_invalid_dsa)
- << getOpenMPClauseName(static_cast<DefaultKind>(Val.value().Type) ==
+ Diag(Val->LOpen, diag::err_omp_invalid_dsa)
+ << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==
OMP_DEFAULT_private
? OMPC_private
: OMPC_firstprivate)
<< getOpenMPClauseName(OMPC_default) << "5.1";
return nullptr;
}
- return Actions.ActOnOpenMPSimpleClause(Kind, Val.value().Type,
- Val.value().TypeLoc, Val.value().LOpen,
- Val.value().Loc, Val.value().RLoc);
+ return Actions.ActOnOpenMPSimpleClause(Kind, Val->Type,
+ Val->TypeLoc, Val->LOpen,
+ Val->Loc, Val->RLoc);
}
/// Parsing of OpenMP clauses like 'ordered'.
@@ -3801,6 +3866,34 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
Arg.push_back(OMPC_DEFAULTMAP_unknown);
KLoc.push_back(SourceLocation());
}
+ } else if (Kind == OMPC_order) {
+ enum { Modifier, OrderKind, NumberOfElements };
+ Arg.resize(NumberOfElements);
+ KLoc.resize(NumberOfElements);
+ Arg[Modifier] = OMPC_ORDER_MODIFIER_unknown;
+ Arg[OrderKind] = OMPC_ORDER_unknown;
+ unsigned KindModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
+ if (KindModifier > OMPC_ORDER_unknown) {
+ // Parse 'modifier'
+ Arg[Modifier] = KindModifier;
+ KLoc[Modifier] = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ // Parse ':'
+ if (Tok.is(tok::colon))
+ ConsumeAnyToken();
+ else
+ Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";
+ KindModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());
+ }
+ Arg[OrderKind] = KindModifier;
+ KLoc[OrderKind] = Tok.getLocation();
+ if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
+ Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
} else if (Kind == OMPC_device) {
// Only target executable directives support extended device construct.
if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 &&
@@ -3816,6 +3909,60 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
Arg.push_back(OMPC_DEVICE_unknown);
KLoc.emplace_back();
}
+ } else if (Kind == OMPC_grainsize) {
+ // Parse optional <grainsize modifier> ':'
+ OpenMPGrainsizeClauseModifier Modifier =
+ static_cast<OpenMPGrainsizeClauseModifier>(getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
+ getLangOpts()));
+ if (getLangOpts().OpenMP >= 51) {
+ if (NextToken().is(tok::colon)) {
+ Arg.push_back(Modifier);
+ KLoc.push_back(Tok.getLocation());
+ // Parse modifier
+ ConsumeAnyToken();
+ // Parse ':'
+ ConsumeAnyToken();
+ } else {
+ if (Modifier == OMPC_GRAINSIZE_strict) {
+ Diag(Tok, diag::err_modifier_expected_colon) << "strict";
+ // Parse modifier
+ ConsumeAnyToken();
+ }
+ Arg.push_back(OMPC_GRAINSIZE_unknown);
+ KLoc.emplace_back();
+ }
+ } else {
+ Arg.push_back(OMPC_GRAINSIZE_unknown);
+ KLoc.emplace_back();
+ }
+ } else if (Kind == OMPC_num_tasks) {
+ // Parse optional <num_tasks modifier> ':'
+ OpenMPNumTasksClauseModifier Modifier =
+ static_cast<OpenMPNumTasksClauseModifier>(getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),
+ getLangOpts()));
+ if (getLangOpts().OpenMP >= 51) {
+ if (NextToken().is(tok::colon)) {
+ Arg.push_back(Modifier);
+ KLoc.push_back(Tok.getLocation());
+ // Parse modifier
+ ConsumeAnyToken();
+ // Parse ':'
+ ConsumeAnyToken();
+ } else {
+ if (Modifier == OMPC_NUMTASKS_strict) {
+ Diag(Tok, diag::err_modifier_expected_colon) << "strict";
+ // Parse modifier
+ ConsumeAnyToken();
+ }
+ Arg.push_back(OMPC_NUMTASKS_unknown);
+ KLoc.emplace_back();
+ }
+ } else {
+ Arg.push_back(OMPC_NUMTASKS_unknown);
+ KLoc.emplace_back();
+ }
} else {
assert(Kind == OMPC_if);
KLoc.push_back(Tok.getLocation());
@@ -3838,7 +3985,8 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind,
bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
(Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
- Kind == OMPC_if || Kind == OMPC_device;
+ Kind == OMPC_if || Kind == OMPC_device ||
+ Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
if (NeedAnExpression) {
SourceLocation ELoc = Tok.getLocation();
ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
@@ -3984,7 +4132,8 @@ bool Parser::parseMapTypeModifiers(Sema::OpenMPVarListDataTy &Data) {
if (PP.LookAhead(0).is(tok::colon))
return false;
Diag(Tok, diag::err_omp_unknown_map_type_modifier)
- << (getLangOpts().OpenMP >= 51 ? 1 : 0)
+ << (getLangOpts().OpenMP >= 51 ? (getLangOpts().OpenMP >= 52 ? 2 : 1)
+ : 0)
<< getLangOpts().OpenMPExtensions;
ConsumeToken();
}
@@ -4173,6 +4322,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
return true;
bool HasIterator = false;
+ bool InvalidIterator = false;
bool NeedRParenForLinear = false;
BalancedDelimiterTracker LinearT(*this, tok::l_paren,
tok::annot_pragma_openmp_end);
@@ -4278,6 +4428,23 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Data.ColonLoc = ConsumeToken();
}
} else if (Kind == OMPC_map) {
+ // Handle optional iterator map modifier.
+ if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
+ HasIterator = true;
+ EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
+ Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
+ Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
+ ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
+ Data.IteratorExpr = IteratorRes.get();
+ // Parse ','
+ ExpectAndConsume(tok::comma);
+ if (getLangOpts().OpenMP < 52) {
+ Diag(Tok, diag::err_omp_unknown_map_type_modifier)
+ << (getLangOpts().OpenMP >= 51 ? 1 : 0)
+ << getLangOpts().OpenMPExtensions;
+ InvalidIterator = true;
+ }
+ }
// Handle map type for map clause.
ColonProtectionRAIIObject ColonRAII(*this);
@@ -4307,6 +4474,12 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
}
if (Data.ExtraModifier == OMPC_MAP_unknown) {
Data.ExtraModifier = OMPC_MAP_tofrom;
+ if (getLangOpts().OpenMP >= 52) {
+ if (DKind == OMPD_target_enter_data)
+ Data.ExtraModifier = OMPC_MAP_to;
+ else if (DKind == OMPD_target_exit_data)
+ Data.ExtraModifier = OMPC_MAP_from;
+ }
Data.IsMapTypeImplicit = true;
}
@@ -4469,7 +4642,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
ExitScope();
return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
(MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId ||
- IsInvalidMapperModifier;
+ IsInvalidMapperModifier || InvalidIterator;
}
/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',