diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp | 1388 |
1 files changed, 1122 insertions, 266 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp index 18e43c3734ac..da5f6605c6ff 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseOpenMP.cpp @@ -19,11 +19,14 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/StringSwitch.h" #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; @@ -149,10 +152,12 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) { {OMPD_for, OMPD_simd, OMPD_for_simd}, {OMPD_parallel, OMPD_for, OMPD_parallel_for}, {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, + {OMPD_parallel, OMPD_loop, OMPD_parallel_loop}, {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}, {OMPD_target, OMPD_parallel, OMPD_target_parallel}, {OMPD_target, OMPD_simd, OMPD_target_simd}, + {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop}, {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for}, {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd}, {OMPD_teams, OMPD_distribute, OMPD_teams_distribute}, @@ -162,8 +167,10 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) { OMPD_teams_distribute_parallel_for}, {OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd}, + {OMPD_teams, OMPD_loop, OMPD_teams_loop}, {OMPD_target, OMPD_teams, OMPD_target_teams}, {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute}, + {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop}, {OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel}, {OMPD_target_teams_distribute, OMPD_simd, @@ -173,11 +180,17 @@ static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) { {OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd}, {OMPD_master, OMPD_taskloop, OMPD_master_taskloop}, + {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop}, {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd}, + {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd}, {OMPD_parallel, OMPD_master, OMPD_parallel_master}, + {OMPD_parallel, OMPD_masked, OMPD_parallel_masked}, {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}, + {OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop}, {OMPD_parallel_master_taskloop, OMPD_simd, - OMPD_parallel_master_taskloop_simd}}; + OMPD_parallel_master_taskloop_simd}, + {OMPD_parallel_masked_taskloop, OMPD_simd, + OMPD_parallel_masked_taskloop_simd}}; enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; Token Tok = P.getCurToken(); OpenMPDirectiveKindExWrapper DKind = @@ -187,8 +200,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); @@ -199,9 +212,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 @@ -248,7 +261,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, @@ -464,17 +477,16 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { T.consumeOpen(); ExprVector Exprs; - CommaLocsTy CommaLocs; SourceLocation LParLoc = T.getOpenLocation(); auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() { QualType PreferredType = Actions.ProduceConstructorSignatureHelp( - getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), - OmpPrivParm->getLocation(), Exprs, LParLoc); + OmpPrivParm->getType()->getCanonicalTypeInternal(), + OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false); CalledSignatureHelp = true; return PreferredType; }; - if (ParseExpressionList(Exprs, CommaLocs, [&] { + if (ParseExpressionList(Exprs, [&] { PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp); })) { @@ -488,9 +500,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(), @@ -634,7 +643,7 @@ TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range, // Parse the declarator. DeclaratorContext Context = DeclaratorContext::Prototype; - Declarator DeclaratorInfo(DS, Context); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context); ParseDeclarator(DeclaratorInfo); Range = DeclaratorInfo.getSourceRange(); if (DeclaratorInfo.getIdentifier() == nullptr) { @@ -739,7 +748,7 @@ static bool parseDeclareSimdClauses( OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); if (CKind == OMPC_uniform || CKind == OMPC_aligned || CKind == OMPC_linear) { - Parser::OpenMPVarListDataTy Data; + Sema::OpenMPVarListDataTy Data; SmallVectorImpl<Expr *> *Vars = &Uniforms; if (CKind == OMPC_aligned) { Vars = &Aligneds; @@ -828,7 +837,7 @@ static StringRef stringLiteralParser(Parser &P) { static StringRef getNameFromIdOrString(Parser &P, Token &Tok, OMPContextLvl Lvl) { - if (Tok.is(tok::identifier)) { + if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) { llvm::SmallString<16> Buffer; StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer); (void)P.ConsumeToken(); @@ -952,6 +961,10 @@ static bool checkExtensionProperty(Parser &P, SourceLocation Loc, TraitProperty::implementation_extension_allow_templates) return true; + if (TIProperty.Kind == + TraitProperty::implementation_extension_bind_to_declaration) + return true; + auto IsMatchExtension = [](OMPTraitProperty &TP) { return (TP.Kind == llvm::omp::TraitProperty::implementation_extension_match_all || @@ -1402,26 +1415,129 @@ 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; + SmallVector<OMPInteropInfo, 3> AppendArgs; + SourceLocation AdjustArgsLoc, AppendArgsLoc; + + // 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: { + AdjustArgsLoc = Tok.getLocation(); + ConsumeToken(); + Sema::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; + } + case OMPC_append_args: + if (!AppendArgs.empty()) { + Diag(AppendArgsLoc, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(OMPD_declare_variant) + << getOpenMPClauseName(CKind) << 0; + IsError = true; + } + if (!IsError) { + AppendArgsLoc = Tok.getLocation(); + ConsumeToken(); + IsError = parseOpenMPAppendArgs(AppendArgs); + } + 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 = + std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = Actions.checkOpenMPDeclareVariantFunction( - Ptr, AssociatedFunction.get(), TI, + Ptr, AssociatedFunction.get(), TI, AppendArgs.size(), 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, + DeclVarData->first, DeclVarData->second, TI, AdjustNothing, + AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc, SourceRange(Loc, Tok.getLocation())); // Skip the last annot_pragma_openmp_end. (void)ConsumeAnnotationToken(); } +bool Parser::parseOpenMPAppendArgs( + SmallVectorImpl<OMPInteropInfo> &InteropInfos) { + bool HasError = false; + // Parse '('. + BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPClauseName(OMPC_append_args).data())) + return true; + + // Parse the list of append-ops, each is; + // interop(interop-type[,interop-type]...) + while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) { + ConsumeToken(); + BalancedDelimiterTracker IT(*this, tok::l_paren, + tok::annot_pragma_openmp_end); + if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop")) + return true; + + 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 && InteropInfos.empty()) { + HasError = true; + Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op); + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); + } + HasError = T.consumeClose() || HasError; + return HasError; +} + bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc, OMPTraitInfo &TI, OMPTraitInfo *ParentTI) { @@ -1431,24 +1547,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); @@ -1518,6 +1625,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 /// @@ -1532,7 +1675,7 @@ bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc, /// void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind, SourceLocation Loc) { - SmallVector<StringRef, 4> Assumptions; + SmallVector<std::string, 4> Assumptions; bool SkippedClauses = false; auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) { @@ -1599,9 +1742,11 @@ void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind, } assert(II && "Expected an identifier clause!"); - StringRef Assumption = II->getName(); + std::string Assumption = II->getName().str(); if (ACMI.StartsWith) - Assumption = Assumption.substr(ACMI.Identifier.size()); + Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size()); + else + Assumption = "omp_" + Assumption; Assumptions.push_back(Assumption); } @@ -1618,7 +1763,7 @@ void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) { /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. /// /// default-clause: -/// 'default' '(' 'none' | 'shared' | 'firstprivate' ') +/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ') /// /// proc_bind-clause: /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') @@ -1638,7 +1783,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(); @@ -1647,11 +1792,11 @@ 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), - P.getLangOpts().OpenMP); + P.getLangOpts()); SourceLocation TypeLoc = Tok.getLocation(); if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && Tok.isNot(tok::annot_pragma_openmp_end)) @@ -1668,50 +1813,81 @@ parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) { void Parser::ParseOMPDeclareTargetClauses( Sema::DeclareTargetContextInfo &DTCI) { SourceLocation DeviceTypeLoc; - bool RequiresToOrLinkClause = false; - bool HasToOrLinkClause = false; + bool RequiresToOrLinkOrIndirectClause = false; + bool HasToOrLinkOrIndirectClause = false; while (Tok.isNot(tok::annot_pragma_openmp_end)) { OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; bool HasIdentifier = Tok.is(tok::identifier); if (HasIdentifier) { // If we see any clause we need a to or link clause. - RequiresToOrLinkClause = true; + RequiresToOrLinkOrIndirectClause = true; IdentifierInfo *II = Tok.getIdentifierInfo(); StringRef ClauseName = II->getName(); bool IsDeviceTypeClause = getLangOpts().OpenMP >= 50 && getOpenMPClauseKind(ClauseName) == OMPC_device_type; - bool IsToOrLinkClause = + bool IsIndirectClause = getLangOpts().OpenMP >= 51 && + getOpenMPClauseKind(ClauseName) == OMPC_indirect; + if (DTCI.Indirect && IsIndirectClause) { + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(OMPD_declare_target) + << getOpenMPClauseName(OMPC_indirect) << 0; + break; + } + bool IsToEnterOrLinkClause = OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT); - assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!"); + assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) && + "Cannot be both!"); - if (!IsDeviceTypeClause && DTCI.Kind == OMPD_begin_declare_target) { - Diag(Tok, diag::err_omp_declare_target_unexpected_clause) - << ClauseName << 0; + // 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 && !IsToOrLinkClause) { + + if (!IsDeviceTypeClause && !IsIndirectClause && + DTCI.Kind == OMPD_begin_declare_target) { Diag(Tok, diag::err_omp_declare_target_unexpected_clause) - << ClauseName << (getLangOpts().OpenMP >= 50 ? 2 : 1); + << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0); + break; + } + 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); break; } - if (IsToOrLinkClause) - HasToOrLinkClause = true; + if (IsToEnterOrLinkClause || IsIndirectClause) + HasToOrLinkOrIndirectClause = true; + if (IsIndirectClause) { + if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false)) + break; + continue; + } // 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.hasValue()) { + if (DevTypeData) { if (DeviceTypeLoc.isValid()) { // We already saw another device_type clause, diagnose it. - Diag(DevTypeData.getValue().Loc, + Diag(DevTypeData->Loc, diag::warn_omp_more_one_device_type_clause); break; } - switch (static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) { + switch (static_cast<OpenMPDeviceType>(DevTypeData->Type)) { case OMPC_DEVICE_TYPE_any: DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any; break; @@ -1724,7 +1900,7 @@ void Parser::ParseOMPDeclareTargetClauses( case OMPC_DEVICE_TYPE_unknown: llvm_unreachable("Unexpected device_type"); } - DeviceTypeLoc = DevTypeData.getValue().Loc; + DeviceTypeLoc = DevTypeData->Loc; } continue; } @@ -1756,7 +1932,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; } @@ -1765,10 +1943,17 @@ void Parser::ParseOMPDeclareTargetClauses( ConsumeToken(); } + if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any) + Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type); + // For declare target require at least 'to' or 'link' to be present. - if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkClause && - !HasToOrLinkClause) - Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause); + if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause && + !HasToOrLinkOrIndirectClause) + 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); } @@ -1855,7 +2040,7 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind, /// annot_pragma_openmp_end /// Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( - AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed, + AccessSpecifier &AS, ParsedAttributes &Attrs, bool Delayed, DeclSpec::TST TagType, Decl *Tag) { assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && "Not an OpenMP directive!"); @@ -1992,6 +2177,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()); @@ -2027,8 +2220,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); @@ -2038,14 +2236,16 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( VariantMatchInfo VMI; TI.getAsVariantMatchInfo(ASTCtx, VMI); - std::function<void(StringRef)> DiagUnknownTrait = [this, Loc]( - StringRef ISATrait) { - // TODO Track the selector locations in a way that is accessible here to - // improve the diagnostic location. - Diag(Loc, diag::warn_unknown_begin_declare_variant_isa_trait) << ISATrait; - }; - TargetOMPContext OMPCtx(ASTCtx, std::move(DiagUnknownTrait), - /* CurrentFunctionDecl */ nullptr); + std::function<void(StringRef)> DiagUnknownTrait = + [this, Loc](StringRef ISATrait) { + // TODO Track the selector locations in a way that is accessible here + // to improve the diagnostic location. + Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait; + }; + TargetOMPContext OMPCtx( + ASTCtx, std::move(DiagUnknownTrait), + /* CurrentFunctionDecl */ nullptr, + /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>()); if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) { Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI); @@ -2106,9 +2306,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); @@ -2130,11 +2331,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_declare_target: { SourceLocation DTLoc = ConsumeAnyToken(); bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end); - bool HasImplicitMappings = - DKind == OMPD_begin_declare_target || !HasClauses; Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc); if (HasClauses) ParseOMPDeclareTargetClauses(DTCI); + bool HasImplicitMappings = DKind == OMPD_begin_declare_target || + !HasClauses || + (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect); // Skip the last annot_pragma_openmp_end. ConsumeAnyToken(); @@ -2188,6 +2390,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_parallel_for_simd: case OMPD_parallel_sections: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_atomic: case OMPD_target: case OMPD_teams: @@ -2204,6 +2407,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_master_taskloop_simd: case OMPD_parallel_master_taskloop: case OMPD_parallel_master_taskloop_simd: + case OMPD_masked_taskloop: + case OMPD_masked_taskloop_simd: + case OMPD_parallel_masked_taskloop: + case OMPD_parallel_masked_taskloop_simd: case OMPD_distribute: case OMPD_target_update: case OMPD_distribute_parallel_for: @@ -2211,6 +2418,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_distribute_simd: case OMPD_target_parallel_for_simd: case OMPD_target_simd: + case OMPD_scope: case OMPD_teams_distribute: case OMPD_teams_distribute_simd: case OMPD_teams_distribute_parallel_for_simd: @@ -2222,6 +2430,12 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_target_teams_distribute_simd: case OMPD_dispatch: case OMPD_masked: + case OMPD_metadirective: + case OMPD_loop: + case OMPD_teams_loop: + case OMPD_target_teams_loop: + case OMPD_parallel_loop: + case OMPD_target_parallel_loop: Diag(Tok, diag::err_omp_unexpected_directive) << 1 << getOpenMPDirectiveName(DKind); break; @@ -2259,8 +2473,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 @@ -2271,13 +2485,14 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( /// simd' | 'teams distribute parallel for simd' | 'teams distribute /// parallel for' | 'target teams' | 'target teams distribute' | 'target /// teams distribute parallel for' | 'target teams distribute parallel -/// for simd' | 'target teams distribute simd' | 'masked' {clause} -/// annot_pragma_openmp_end +/// for simd' | 'target teams distribute simd' | 'masked' | +/// 'parallel masked' {clause} annot_pragma_openmp_end /// -StmtResult -Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { - assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && - "Not an OpenMP directive!"); +StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( + ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) { + if (!ReadDirectiveWithinMetadirective) + assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && + "Not an OpenMP directive!"); ParsingOpenMPDirectiveRAII DirScope(*this); ParenBraceBracketBalancer BalancerRAIIObj(*this); SmallVector<OMPClause *, 5> Clauses; @@ -2286,8 +2501,15 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { FirstClauses(llvm::omp::Clause_enumSize + 1); unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; - SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; + SourceLocation Loc = ReadDirectiveWithinMetadirective + ? Tok.getLocation() + : ConsumeAnnotationToken(), + EndLoc; OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); + if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) { + Diag(Tok, diag::err_omp_unknown_directive); + return StmtError(); + } OpenMPDirectiveKind CancelRegion = OMPD_unknown; // Name of critical directive. DeclarationNameInfo DirName; @@ -2295,9 +2517,163 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { bool HasAssociatedStatement = true; switch (DKind) { + case OMPD_nothing: + ConsumeToken(); + // If we are parsing the directive within a metadirective, the directive + // ends with a ')'. + if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) + while (Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + else + skipUntilPragmaOpenMPEnd(DKind); + if (Tok.is(tok::annot_pragma_openmp_end)) + ConsumeAnnotationToken(); + // return an empty statement + return StmtEmpty(); + case OMPD_metadirective: { + ConsumeToken(); + SmallVector<VariantMatchInfo, 4> VMIs; + + // First iteration of parsing all clauses of metadirective. + // This iteration only parses and collects all context selector ignoring the + // associated directives. + TentativeParsingAction TPA(*this); + ASTContext &ASTContext = Actions.getASTContext(); + + BalancedDelimiterTracker T(*this, tok::l_paren, + tok::annot_pragma_openmp_end); + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + OpenMPClauseKind CKind = Tok.isAnnotation() + ? OMPC_unknown + : getOpenMPClauseKind(PP.getSpelling(Tok)); + SourceLocation Loc = ConsumeToken(); + + // Parse '('. + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPClauseName(CKind).data())) + return Directive; + + OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); + if (CKind == OMPC_when) { + // parse and get OMPTraitInfo to pass to the When clause + parseOMPContextSelectors(Loc, TI); + if (TI.Sets.size() == 0) { + Diag(Tok, diag::err_omp_expected_context_selector) << "when clause"; + TPA.Commit(); + return Directive; + } + + // Parse ':' + if (Tok.is(tok::colon)) + ConsumeAnyToken(); + else { + Diag(Tok, diag::err_omp_expected_colon) << "when clause"; + TPA.Commit(); + return Directive; + } + } + // Skip Directive for now. We will parse directive in the second iteration + int paren = 0; + while (Tok.isNot(tok::r_paren) || paren != 0) { + if (Tok.is(tok::l_paren)) + paren++; + if (Tok.is(tok::r_paren)) + paren--; + if (Tok.is(tok::annot_pragma_openmp_end)) { + Diag(Tok, diag::err_omp_expected_punc) + << getOpenMPClauseName(CKind) << 0; + TPA.Commit(); + return Directive; + } + ConsumeAnyToken(); + } + // Parse ')' + if (Tok.is(tok::r_paren)) + T.consumeClose(); + + VariantMatchInfo VMI; + TI.getAsVariantMatchInfo(ASTContext, VMI); + + VMIs.push_back(VMI); + } + + TPA.Revert(); + // End of the first iteration. Parser is reset to the start of metadirective + + std::function<void(StringRef)> DiagUnknownTrait = + [this, Loc](StringRef ISATrait) { + // TODO Track the selector locations in a way that is accessible here + // to improve the diagnostic location. + Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait; + }; + TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait), + /* CurrentFunctionDecl */ nullptr, + ArrayRef<llvm::omp::TraitProperty>()); + + // A single match is returned for OpenMP 5.0 + int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx); + + int Idx = 0; + // In OpenMP 5.0 metadirective is either replaced by another directive or + // ignored. + // TODO: In OpenMP 5.1 generate multiple directives based upon the matches + // found by getBestWhenMatchForContext. + while (Tok.isNot(tok::annot_pragma_openmp_end)) { + // OpenMP 5.0 implementation - Skip to the best index found. + if (Idx++ != BestIdx) { + ConsumeToken(); // Consume clause name + T.consumeOpen(); // Consume '(' + int paren = 0; + // Skip everything inside the clause + while (Tok.isNot(tok::r_paren) || paren != 0) { + if (Tok.is(tok::l_paren)) + paren++; + if (Tok.is(tok::r_paren)) + paren--; + ConsumeAnyToken(); + } + // Parse ')' + if (Tok.is(tok::r_paren)) + T.consumeClose(); + continue; + } + + OpenMPClauseKind CKind = Tok.isAnnotation() + ? OMPC_unknown + : getOpenMPClauseKind(PP.getSpelling(Tok)); + SourceLocation Loc = ConsumeToken(); + + // Parse '('. + T.consumeOpen(); + + // Skip ContextSelectors for when clause + if (CKind == OMPC_when) { + OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); + // parse and skip the ContextSelectors + parseOMPContextSelectors(Loc, TI); + + // Parse ':' + ConsumeAnyToken(); + } + + // If no directive is passed, skip in OpenMP 5.0. + // TODO: Generate nothing directive from OpenMP 5.1. + if (Tok.is(tok::r_paren)) { + SkipUntil(tok::annot_pragma_openmp_end); + break; + } + + // Parse Directive + Directive = ParseOpenMPDeclarativeOrExecutableDirective( + StmtCtx, + /*ReadDirectiveWithinMetadirective=*/true); + break; + } + break; + } case OMPD_threadprivate: { // FIXME: Should this be permitted in C++? - if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == + if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == ParsedStmtContext()) { Diag(Tok, diag::err_omp_immediate_directive) << getOpenMPDirectiveName(DKind) << 0; @@ -2316,7 +2692,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { } case OMPD_allocate: { // FIXME: Should this be permitted in C++? - if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == + if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == ParsedStmtContext()) { Diag(Tok, diag::err_omp_immediate_directive) << getOpenMPDirectiveName(DKind) << 0; @@ -2387,6 +2763,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { case OMPD_depobj: case OMPD_scan: case OMPD_taskyield: + case OMPD_error: case OMPD_barrier: case OMPD_taskwait: case OMPD_cancellation_point: @@ -2399,10 +2776,14 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { 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: @@ -2418,6 +2799,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { case OMPD_parallel_for_simd: case OMPD_parallel_sections: case OMPD_parallel_master: + case OMPD_parallel_masked: case OMPD_task: case OMPD_ordered: case OMPD_atomic: @@ -2427,12 +2809,22 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { case OMPD_target_data: case OMPD_target_parallel: case OMPD_target_parallel_for: + case OMPD_loop: + case OMPD_teams_loop: + case OMPD_target_teams_loop: + case OMPD_parallel_loop: + case OMPD_target_parallel_loop: + case OMPD_scope: case OMPD_taskloop: case OMPD_taskloop_simd: case OMPD_master_taskloop: + case OMPD_masked_taskloop: case OMPD_master_taskloop_simd: + case OMPD_masked_taskloop_simd: case OMPD_parallel_master_taskloop: + case OMPD_parallel_masked_taskloop: case OMPD_parallel_master_taskloop_simd: + case OMPD_parallel_masked_taskloop_simd: case OMPD_distribute: case OMPD_distribute_parallel_for: case OMPD_distribute_parallel_for_simd: @@ -2486,6 +2878,13 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); while (Tok.isNot(tok::annot_pragma_openmp_end)) { + // If we are parsing for a directive within a metadirective, the directive + // ends with a ')'. + if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) { + while (Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + break; + } bool HasImplicitClause = false; if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) { HasImplicitClause = true; @@ -2530,17 +2929,20 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { // Consume final annot_pragma_openmp_end. ConsumeAnnotationToken(); - // OpenMP [2.13.8, ordered Construct, Syntax] - // If the depend clause is specified, the ordered construct is a stand-alone - // directive. - if (DKind == OMPD_ordered && FirstClauses[unsigned(OMPC_depend)].getInt()) { - if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == - ParsedStmtContext()) { - Diag(Loc, diag::err_omp_immediate_directive) - << getOpenMPDirectiveName(DKind) << 1 - << getOpenMPClauseName(OMPC_depend); + if (DKind == OMPD_ordered) { + // If the depend or doacross clause is specified, the ordered construct + // is a stand-alone directive. + for (auto CK : {OMPC_depend, OMPC_doacross}) { + if (FirstClauses[unsigned(CK)].getInt()) { + if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == + ParsedStmtContext()) { + Diag(Loc, diag::err_omp_immediate_directive) + << getOpenMPDirectiveName(DKind) << 1 + << getOpenMPClauseName(CK); + } + HasAssociatedStatement = false; + } } - HasAssociatedStatement = false; } if (DKind == OMPD_tile && !FirstClauses[unsigned(OMPC_sizes)].getInt()) { @@ -2562,15 +2964,14 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) && getLangOpts().OpenMPIRBuilder) - AssociatedStmt = - Actions.ActOnOpenMPCanonicalLoop(AssociatedStmt.get()); + AssociatedStmt = Actions.ActOnOpenMPLoopnest(AssociatedStmt.get()); } AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 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); } @@ -2631,7 +3032,7 @@ bool Parser::ParseOpenMPSimpleVarList( if (AllowScopeSpecifier && getLangOpts().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, - /*ObjectHadErrors=*/false, false)) { + /*ObjectHasErrors=*/false, false)) { IsCorrect = false; SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); @@ -2710,8 +3111,13 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) { return nullptr; SmallVector<Sema::UsesAllocatorsData, 4> Data; do { + CXXScopeSpec SS; + Token Replacement; ExprResult Allocator = - getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression(); + getLangOpts().CPlusPlus + ? ParseCXXIdExpression() + : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false, + Replacement); if (Allocator.isInvalid()) { SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); @@ -2751,7 +3157,7 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) { /// clause: /// if-clause | final-clause | num_threads-clause | safelen-clause | /// default-clause | private-clause | firstprivate-clause | shared-clause -/// | linear-clause | aligned-clause | collapse-clause | +/// | linear-clause | aligned-clause | collapse-clause | bind-clause | /// lastprivate-clause | reduction-clause | proc_bind-clause | /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | /// mergeable-clause | flush-clause | read-clause | write-clause | @@ -2763,7 +3169,8 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) { /// in_reduction-clause | allocator-clause | allocate-clause | /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause | /// depobj-clause | destroy-clause | detach-clause | inclusive-clause | -/// exclusive-clause | uses_allocators-clause | use_device_addr-clause +/// exclusive-clause | uses_allocators-clause | use_device_addr-clause | +/// has_device_addr /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -2800,6 +3207,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_nocontext: 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] @@ -2825,6 +3235,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; @@ -2834,13 +3246,18 @@ 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_fail: 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 // teams directive. @@ -2849,7 +3266,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 - if (!FirstClause && CKind != OMPC_order) { + // 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) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; @@ -2861,19 +3283,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; @@ -2883,6 +3308,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_read: case OMPC_write: case OMPC_capture: + case OMPC_compare: case OMPC_seq_cst: case OMPC_acq_rel: case OMPC_acquire: @@ -2940,11 +3366,17 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_use_device_ptr: case OMPC_use_device_addr: case OMPC_is_device_ptr: + case OMPC_has_device_addr: case OMPC_allocate: case OMPC_nontemporal: case OMPC_inclusive: case OMPC_exclusive: case OMPC_affinity: + case OMPC_doacross: + case OMPC_enter: + if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered && + CKind == OMPC_depend) + Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated); Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); break; case OMPC_sizes: @@ -2969,7 +3401,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, Clause = ParseOpenMPClause(CKind, WrongDirective); break; } - LLVM_FALLTHROUGH; + [[fallthrough]]; case OMPC_init: case OMPC_use: Clause = ParseOpenMPInteropClause(CKind, WrongDirective); @@ -2986,6 +3418,20 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); break; + case OMPC_ompx_attribute: + Clause = ParseOpenMPOMPXAttributesClause(WrongDirective); + break; + case OMPC_ompx_bare: + if (WrongDirective) + Diag(Tok, diag::note_ompx_bare_clause) + << getOpenMPClauseName(CKind) << "target teams"; + if (!ErrorFound && !getLangOpts().OpenMPExtensions) { + Diag(Tok, diag::err_omp_unexpected_clause_extension_only) + << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); + ErrorFound = true; + } + Clause = ParseOpenMPClause(CKind, WrongDirective); + break; default: break; } @@ -3054,6 +3500,9 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, /// detach-clause: /// 'detach' '(' event-handler-expression ')' /// +/// align-clause +/// 'align' '(' positive-integer-constant ')' +/// OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, bool ParseOnly) { SourceLocation Loc = ConsumeToken(); @@ -3070,6 +3519,131 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); } +/// Parse indirect clause for '#pragma omp declare target' directive. +/// 'indirect' '[' '(' invoked-by-fptr ')' ']' +/// where invoked-by-fptr is a constant boolean expression that evaluates to +/// true or false at compile time. +bool Parser::ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI, + bool ParseOnly) { + SourceLocation Loc = ConsumeToken(); + SourceLocation RLoc; + + if (Tok.isNot(tok::l_paren)) { + if (ParseOnly) + return false; + DTCI.Indirect = nullptr; + return true; + } + + ExprResult Val = + ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc); + if (Val.isInvalid()) + return false; + + if (ParseOnly) + return false; + + if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() && + !Val.get()->isInstantiationDependent() && + !Val.get()->containsUnexpandedParameterPack()) { + ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get()); + if (Ret.isInvalid()) + return false; + llvm::APSInt Result; + Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result, + Sema::AllowFold); + if (Ret.isInvalid()) + return false; + DTCI.Indirect = Val.get(); + return true; + } + 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: @@ -3102,78 +3676,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. - bool HasError = false; - while (Tok.is(tok::identifier)) { - if (PP.getSpelling(Tok) == "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; - } else if (PP.getSpelling(Tok) == "targetsync") { - if (IsTargetSync) - Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync"; - IsTargetSync = true; - } 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); - - if (Tok.is(tok::colon)) - ConsumeToken(); - else if (IsTarget || IsTargetSync) - Diag(Tok, diag::warn_pragma_expected_colon) << "interop types"; - } + bool InteropError = false; + OMPInteropInfo InteropInfo; + if (Kind == OMPC_init) + InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init); // Parse the variable. SourceLocation VarLoc = Tok.getLocation(); @@ -3189,14 +3695,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); @@ -3208,33 +3712,98 @@ OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind, llvm_unreachable("Unexpected interop variable clause."); } +OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) { + SourceLocation Loc = ConsumeToken(); + // Parse '('. + BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); + if (T.expectAndConsume(diag::err_expected_lparen_after, + getOpenMPClauseName(OMPC_ompx_attribute).data())) + return nullptr; + + ParsedAttributes ParsedAttrs(AttrFactory); + ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs); + + // Parse ')'. + if (T.consumeClose()) + return nullptr; + + if (ParseOnly) + return nullptr; + + SmallVector<Attr *> Attrs; + for (const ParsedAttr &PA : ParsedAttrs) { + switch (PA.getKind()) { + case ParsedAttr::AT_AMDGPUFlatWorkGroupSize: + if (!PA.checkExactlyNumArgs(Actions, 2)) + continue; + if (auto *A = Actions.CreateAMDGPUFlatWorkGroupSizeAttr( + PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1))) + Attrs.push_back(A); + continue; + case ParsedAttr::AT_AMDGPUWavesPerEU: + if (!PA.checkAtLeastNumArgs(Actions, 1) || + !PA.checkAtMostNumArgs(Actions, 2)) + continue; + if (auto *A = Actions.CreateAMDGPUWavesPerEUAttr( + PA, PA.getArgAsExpr(0), + PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr)) + Attrs.push_back(A); + continue; + case ParsedAttr::AT_CUDALaunchBounds: + if (!PA.checkAtLeastNumArgs(Actions, 1) || + !PA.checkAtMostNumArgs(Actions, 2)) + continue; + if (auto *A = Actions.CreateLaunchBoundsAttr( + PA, PA.getArgAsExpr(0), + PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr, + PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr)) + Attrs.push_back(A); + continue; + default: + Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA; + continue; + }; + } + + return Actions.ActOnOpenMPXAttributeClause(Attrs, Loc, T.getOpenLocation(), + T.getCloseLocation()); +} + /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. /// /// default-clause: -/// 'default' '(' 'none' | 'shared' | 'firstprivate' ')' +/// 'default' '(' 'none' | 'shared' | 'private' | 'firstprivate' ')' /// /// proc_bind-clause: /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')' /// +/// bind-clause: +/// 'bind' '(' 'teams' | 'parallel' | 'thread' ')' +/// /// update-clause: -/// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')' +/// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' | +/// 'inoutset' ')' /// 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.getValue().Type) == - OMP_DEFAULT_firstprivate) { - Diag(Val.getValue().LOpen, diag::err_omp_invalid_dsa) - << getOpenMPClauseName(OMPC_firstprivate) + (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private || + static_cast<DefaultKind>(Val->Type) == + OMP_DEFAULT_firstprivate)) { + 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.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen, - Val.getValue().Loc, Val.getValue().RLoc); + return Actions.ActOnOpenMPSimpleClause(Kind, Val->Type, + Val->TypeLoc, Val->LOpen, + Val->Loc, Val->RLoc); } /// Parsing of OpenMP clauses like 'ordered'. @@ -3310,8 +3879,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; unsigned KindModifier = getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), - getLangOpts().OpenMP); + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); if (KindModifier > OMPC_SCHEDULE_unknown) { // Parse 'modifier' Arg[Modifier1] = KindModifier; @@ -3323,8 +3891,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, // Parse ',' 'modifier' ConsumeAnyToken(); KindModifier = getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), - getLangOpts().OpenMP); + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown ? KindModifier : (unsigned)OMPC_SCHEDULE_unknown; @@ -3339,8 +3906,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, else Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; KindModifier = getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), - getLangOpts().OpenMP); + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); } Arg[ScheduleKind] = KindModifier; KLoc[ScheduleKind] = Tok.getLocation(); @@ -3354,8 +3920,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, DelimLoc = ConsumeAnyToken(); } else if (Kind == OMPC_dist_schedule) { Arg.push_back(getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), - getLangOpts().OpenMP)); + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); KLoc.push_back(Tok.getLocation()); if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && Tok.isNot(tok::annot_pragma_openmp_end)) @@ -3365,8 +3930,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, } else if (Kind == OMPC_defaultmap) { // Get a defaultmap modifier unsigned Modifier = getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), - getLangOpts().OpenMP); + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); // Set defaultmap modifier to unknown if it is either scalar, aggregate, or // pointer if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) @@ -3384,8 +3948,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; // Get a defaultmap kind Arg.push_back(getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), - getLangOpts().OpenMP)); + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); KLoc.push_back(Tok.getLocation()); if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && Tok.isNot(tok::annot_pragma_openmp_end)) @@ -3394,14 +3957,41 @@ 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 && NextToken().is(tok::colon)) { // Parse optional <device modifier> ':' Arg.push_back(getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), - getLangOpts().OpenMP)); + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); KLoc.push_back(Tok.getLocation()); ConsumeAnyToken(); // Parse ':' @@ -3410,6 +4000,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()); @@ -3432,7 +4076,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)); @@ -3512,12 +4157,12 @@ static OpenMPMapModifierKind isMapModifier(Parser &P) { Preprocessor &PP = P.getPreprocessor(); OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType( - OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP)); + OMPC_map, PP.getSpelling(Tok), P.getLangOpts())); return TypeModifier; } /// Parse the mapper modifier in map, to, and from clauses. -bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { +bool Parser::parseMapperModifier(Sema::OpenMPVarListDataTy &Data) { // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { @@ -3529,7 +4174,7 @@ bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { if (getLangOpts().CPlusPlus) ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, /*ObjectType=*/nullptr, - /*ObjectHadErrors=*/false, + /*ObjectHasErrors=*/false, /*EnteringContext=*/false); if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); @@ -3549,14 +4194,19 @@ bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) | /// present -bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) { +bool Parser::parseMapTypeModifiers(Sema::OpenMPVarListDataTy &Data) { while (getCurToken().isNot(tok::colon)) { OpenMPMapModifierKind TypeModifier = isMapModifier(*this); if (TypeModifier == OMPC_MAP_MODIFIER_always || TypeModifier == OMPC_MAP_MODIFIER_close || - TypeModifier == OMPC_MAP_MODIFIER_present) { + TypeModifier == OMPC_MAP_MODIFIER_present || + TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) { Data.MapTypeModifiers.push_back(TypeModifier); Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); + if (PP.LookAhead(0).isNot(tok::comma) && + PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52) + Diag(Tok.getLocation(), diag::err_omp_missing_comma) + << "map type modifier"; ConsumeToken(); } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { Data.MapTypeModifiers.push_back(TypeModifier); @@ -3564,6 +4214,11 @@ bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) { ConsumeToken(); if (parseMapperModifier(Data)) return true; + if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) && + getLangOpts().OpenMP >= 52) + Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma) + << "map type modifier"; + } else { // For the case of unknown map-type-modifier or a map-type. // Map-type is followed by a colon; the function returns when it @@ -3577,7 +4232,9 @@ bool Parser::parseMapTypeModifiers(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(); } if (getCurToken().is(tok::comma)) @@ -3596,14 +4253,14 @@ static OpenMPMapClauseKind isMapType(Parser &P) { Preprocessor &PP = P.getPreprocessor(); OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( - OMPC_map, PP.getSpelling(Tok), P.getLangOpts().OpenMP)); + OMPC_map, PP.getSpelling(Tok), P.getLangOpts())); return MapType; } /// Parse map-type in map clause. /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) /// where, map-type ::= to | from | tofrom | alloc | release | delete -static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { +static void parseMapType(Parser &P, Sema::OpenMPVarListDataTy &Data) { Token Tok = P.getCurToken(); if (Tok.is(tok::colon)) { P.Diag(Tok, diag::err_omp_map_type_missing); @@ -3722,11 +4379,57 @@ ExprResult Parser::ParseOpenMPIteratorsExpr() { Data); } +bool Parser::ParseOpenMPReservedLocator(OpenMPClauseKind Kind, + Sema::OpenMPVarListDataTy &Data, + const LangOptions &LangOpts) { + // Currently the only reserved locator is 'omp_all_memory' which is only + // allowed on a depend clause. + if (Kind != OMPC_depend || LangOpts.OpenMP < 51) + return false; + + if (Tok.is(tok::identifier) && + Tok.getIdentifierInfo()->isStr("omp_all_memory")) { + + if (Data.ExtraModifier == OMPC_DEPEND_outallmemory || + Data.ExtraModifier == OMPC_DEPEND_inoutallmemory) + Diag(Tok, diag::warn_omp_more_one_omp_all_memory); + else if (Data.ExtraModifier != OMPC_DEPEND_out && + Data.ExtraModifier != OMPC_DEPEND_inout) + Diag(Tok, diag::err_omp_requires_out_inout_depend_type); + else + Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out + ? OMPC_DEPEND_outallmemory + : OMPC_DEPEND_inoutallmemory; + ConsumeToken(); + return true; + } + return false; +} + +/// Parse step size expression. Returns true if parsing is successfull, +/// otherwise returns false. +static bool parseStepSize(Parser &P, Sema::OpenMPVarListDataTy &Data, + OpenMPClauseKind CKind, SourceLocation ELoc) { + ExprResult Tail = P.ParseAssignmentExpression(); + Sema &Actions = P.getActions(); + Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc, + /*DiscardedValue*/ false); + if (Tail.isUsable()) { + Data.DepModOrTailExpr = Tail.get(); + Token CurTok = P.getCurToken(); + if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) { + P.Diag(CurTok, diag::err_expected_punc) << "step expression"; + } + return true; + } + return false; +} + /// Parses clauses with list. bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl<Expr *> &Vars, - OpenMPVarListDataTy &Data) { + Sema::OpenMPVarListDataTy &Data) { UnqualifiedId UnqualifiedReductionId; bool InvalidReductionId = false; bool IsInvalidMapperModifier = false; @@ -3738,6 +4441,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); @@ -3749,8 +4453,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) && NextToken().is(tok::comma)) { // Parse optional reduction modifier. - Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), - getLangOpts().OpenMP); + Data.ExtraModifier = + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); Data.ExtraModifierLoc = Tok.getLocation(); ConsumeToken(); assert(Tok.is(tok::comma) && "Expected comma."); @@ -3760,7 +4464,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, if (getLangOpts().CPlusPlus) ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, /*ObjectType=*/nullptr, - /*ObjectHadErrors=*/false, + /*ObjectHasErrors=*/false, /*EnteringContext=*/false); InvalidReductionId = ParseReductionId( *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); @@ -3775,7 +4479,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, if (!InvalidReductionId) Data.ReductionOrMapperId = Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); - } else if (Kind == OMPC_depend) { + } else if (Kind == OMPC_depend || Kind == OMPC_doacross) { if (getLangOpts().OpenMP >= 50) { if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") { // Handle optional dependence modifier. @@ -3796,15 +4500,18 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, ColonProtectionRAIIObject ColonRAII(*this); Data.ExtraModifier = getOpenMPSimpleClauseType( Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "", - getLangOpts().OpenMP); + getLangOpts()); Data.ExtraModifierLoc = Tok.getLocation(); - if (Data.ExtraModifier == OMPC_DEPEND_unknown) { + if ((Kind == OMPC_depend && Data.ExtraModifier == OMPC_DEPEND_unknown) || + (Kind == OMPC_doacross && + Data.ExtraModifier == OMPC_DOACROSS_unknown)) { SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else { ConsumeToken(); // Special processing for depend(source) clause. - if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) { + if (DKind == OMPD_ordered && Kind == OMPC_depend && + Data.ExtraModifier == OMPC_DEPEND_source) { // Parse ')'. T.consumeClose(); return false; @@ -3812,20 +4519,69 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, } if (Tok.is(tok::colon)) { Data.ColonLoc = ConsumeToken(); - } else { + } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) { Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren : diag::warn_pragma_expected_colon) - << "dependency type"; + << (Kind == OMPC_depend ? "dependency type" : "dependence-type"); + } + if (Kind == OMPC_doacross) { + if (Tok.is(tok::identifier) && + Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) { + Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source + ? OMPC_DOACROSS_source_omp_cur_iteration + : OMPC_DOACROSS_sink_omp_cur_iteration; + ConsumeToken(); + } + if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) { + if (Tok.isNot(tok::minus)) { + Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd) + << getOpenMPClauseName(Kind) << 0 << 0; + SkipUntil(tok::r_paren); + return false; + } else { + ConsumeToken(); + SourceLocation Loc = Tok.getLocation(); + uint64_t Value = 0; + if (Tok.isNot(tok::numeric_constant) || + (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) { + Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd) + << getOpenMPClauseName(Kind) << 0 << 0; + SkipUntil(tok::r_paren); + return false; + } + } + } + if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) { + if (Tok.isNot(tok::r_paren)) { + Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd) + << getOpenMPClauseName(Kind) << 1 << 1; + SkipUntil(tok::r_paren); + return false; + } + } + // Only the 'sink' case has the expression list. + if (Kind == OMPC_doacross && + (Data.ExtraModifier == OMPC_DOACROSS_source || + Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration || + Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) { + // Parse ')'. + T.consumeClose(); + return false; + } } } else if (Kind == OMPC_linear) { // Try to parse modifier if any. Data.ExtraModifier = OMPC_LINEAR_val; if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { - Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), - getLangOpts().OpenMP); + Data.ExtraModifier = + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); Data.ExtraModifierLoc = ConsumeToken(); LinearT.consumeOpen(); NeedRParenForLinear = true; + if (getLangOpts().OpenMP >= 52) + Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax) + << "linear-modifier(list)" << getOpenMPClauseName(Kind) + << "linear(list: [linear-modifier,] step(step-size))"; } } else if (Kind == OMPC_lastprivate) { // Try to parse modifier if any. @@ -3835,14 +4591,31 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) && !isOpenMPTaskLoopDirective(DKind)) && Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) { - Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), - getLangOpts().OpenMP); + Data.ExtraModifier = + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); Data.ExtraModifierLoc = Tok.getLocation(); ConsumeToken(); assert(Tok.is(tok::colon) && "Expected colon."); 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); @@ -3872,6 +4645,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; } @@ -3879,9 +4658,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.ColonLoc = ConsumeToken(); } else if (Kind == OMPC_to || Kind == OMPC_from) { while (Tok.is(tok::identifier)) { - auto Modifier = - static_cast<OpenMPMotionModifierKind>(getOpenMPSimpleClauseType( - Kind, PP.getSpelling(Tok), getLangOpts().OpenMP)); + auto Modifier = static_cast<OpenMPMotionModifierKind>( + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts())); if (Modifier == OMPC_MOTION_MODIFIER_unknown) break; Data.MotionModifiers.push_back(Modifier); @@ -3951,27 +4729,50 @@ 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 = (Kind != OMPC_reduction && Kind != OMPC_task_reduction && - Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || + Kind != OMPC_in_reduction && Kind != OMPC_depend && + Kind != OMPC_doacross && 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_doacross && Data.ExtraModifier != OMPC_DOACROSS_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))) { ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope); ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); - // Parse variable - ExprResult VarExpr = - Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); - if (VarExpr.isUsable()) { - Vars.push_back(VarExpr.get()); - } else { - SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, - StopBeforeMatch); + if (!ParseOpenMPReservedLocator(Kind, Data, getLangOpts())) { + // Parse variable + ExprResult VarExpr = + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + if (VarExpr.isUsable()) { + Vars.push_back(VarExpr.get()); + } else { + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); + } } // Skip ',' if any IsComma = Tok.is(tok::comma); @@ -3990,19 +4791,76 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, if (NeedRParenForLinear) LinearT.consumeClose(); - // Parse ':' linear-step (or ':' alignment). + // Parse ':' linear modifiers (val, uval, ref or step(step-size)) + // or parse ':' alignment. const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); + bool StepFound = false; + bool ModifierFound = false; if (MustHaveTail) { Data.ColonLoc = Tok.getLocation(); SourceLocation ELoc = ConsumeToken(); - ExprResult Tail = ParseAssignmentExpression(); - Tail = - Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); - if (Tail.isUsable()) - Data.DepModOrTailExpr = Tail.get(); - else - SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, - StopBeforeMatch); + + if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) { + while (Tok.isNot(tok::r_paren)) { + if (Tok.is(tok::identifier)) { + // identifier could be a linear kind (val, uval, ref) or step + // modifier or step size + OpenMPLinearClauseKind LinKind = + static_cast<OpenMPLinearClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), + getLangOpts())); + + if (LinKind == OMPC_LINEAR_step) { + if (StepFound) + Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0; + + BalancedDelimiterTracker StepT(*this, tok::l_paren, + tok::annot_pragma_openmp_end); + SourceLocation StepModifierLoc = ConsumeToken(); + // parse '(' + if (StepT.consumeOpen()) + Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step"; + + // parse step size expression + StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation()); + if (StepFound) + Data.StepModifierLoc = StepModifierLoc; + + // parse ')' + StepT.consumeClose(); + } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) { + if (ModifierFound) + Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1; + + Data.ExtraModifier = LinKind; + Data.ExtraModifierLoc = ConsumeToken(); + ModifierFound = true; + } else { + StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation()); + } + } else { + // parse an integer expression as step size + StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation()); + } + + if (Tok.is(tok::comma)) + ConsumeToken(); + if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end)) + break; + } + if (!StepFound && !ModifierFound) + Diag(ELoc, diag::err_expected_expression); + } else { + // for OMPC_aligned and OMPC_linear (with OpenMP <= 5.1) + ExprResult Tail = ParseAssignmentExpression(); + Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc, + /*DiscardedValue*/ false); + if (Tail.isUsable()) + Data.DepModOrTailExpr = Tail.get(); + else + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); + } } // Parse ')'. @@ -4012,9 +4870,10 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, // Exit from scope when the iterator is used in depend clause. if (HasIterator) ExitScope(); - return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || - (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId || - IsInvalidMapperModifier; + return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map && + Vars.empty()) || + (MustHaveTail && !Data.DepModOrTailExpr && StepFound) || + InvalidReductionId || IsInvalidMapperModifier || InvalidIterator; } /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', @@ -4059,6 +4918,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, /// 'use_device_addr' '(' list ')' /// is_device_ptr-clause: /// 'is_device_ptr' '(' list ')' +/// has_device_addr-clause: +/// 'has_device_addr' '(' list ')' /// allocate-clause: /// 'allocate' '(' [ allocator ':' ] list ')' /// nontemporal-clause: @@ -4078,7 +4939,7 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); SmallVector<Expr *, 4> Vars; - OpenMPVarListDataTy Data; + Sema::OpenMPVarListDataTy Data; if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) return nullptr; @@ -4086,10 +4947,5 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, if (ParseOnly) return nullptr; OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); - return Actions.ActOnOpenMPVarListClause( - Kind, Vars, Data.DepModOrTailExpr, Locs, Data.ColonLoc, - Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, - Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, - Data.IsMapTypeImplicit, Data.ExtraModifierLoc, Data.MotionModifiers, - Data.MotionModifiersLoc); + return Actions.ActOnOpenMPVarListClause(Kind, Vars, Locs, Data); } |