diff options
Diffstat (limited to 'clang/lib/Parse/ParseOpenMP.cpp')
-rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 429 |
1 files changed, 292 insertions, 137 deletions
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 91fe10e667db..1095919baa7d 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -12,6 +12,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/StmtOpenMP.h" +#include "clang/Basic/OpenMPKinds.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" @@ -20,6 +21,7 @@ #include "llvm/ADT/UniqueVector.h" using namespace clang; +using namespace llvm::omp; //===----------------------------------------------------------------------===// // OpenMP declarative directives. @@ -27,7 +29,7 @@ using namespace clang; namespace { enum OpenMPDirectiveKindEx { - OMPD_cancellation = OMPD_unknown + 1, + OMPD_cancellation = unsigned(OMPD_unknown) + 1, OMPD_data, OMPD_declare, OMPD_end, @@ -44,7 +46,20 @@ enum OpenMPDirectiveKindEx { OMPD_target_teams_distribute_parallel, OMPD_mapper, OMPD_variant, - OMPD_parallel_master, +}; + +// Helper to unify the enum class OpenMPDirectiveKind with its extension +// the OpenMPDirectiveKindEx enum which allows to use them together as if they +// are unsigned values. +struct OpenMPDirectiveKindExWrapper { + OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {} + OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {} + bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); } + bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); } + bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); } + operator unsigned() const { return Value; } + operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); } + unsigned Value; }; class DeclDirectiveListParserHelper final { @@ -68,11 +83,11 @@ public: // Map token string to extended OMP token kind that are // OpenMPDirectiveKind + OpenMPDirectiveKindEx. static unsigned getOpenMPDirectiveKindEx(StringRef S) { - auto DKind = getOpenMPDirectiveKind(S); + OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S); if (DKind != OMPD_unknown) return DKind; - return llvm::StringSwitch<unsigned>(S) + return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S) .Case("cancellation", OMPD_cancellation) .Case("data", OMPD_data) .Case("declare", OMPD_declare) @@ -87,11 +102,11 @@ static unsigned getOpenMPDirectiveKindEx(StringRef S) { .Default(OMPD_unknown); } -static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) { +static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) { // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd // TODO: add other combined directives in topological order. - static const unsigned F[][3] = { + static const OpenMPDirectiveKindExWrapper F[][3] = { {OMPD_cancellation, OMPD_point, OMPD_cancellation_point}, {OMPD_declare, OMPD_reduction, OMPD_declare_reduction}, {OMPD_declare, OMPD_mapper, OMPD_declare_mapper}, @@ -140,10 +155,12 @@ static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) { {OMPD_master, OMPD_taskloop, OMPD_master_taskloop}, {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd}, {OMPD_parallel, OMPD_master, OMPD_parallel_master}, - {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}}; + {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}, + {OMPD_parallel_master_taskloop, OMPD_simd, + OMPD_parallel_master_taskloop_simd}}; enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; Token Tok = P.getCurToken(); - unsigned DKind = + OpenMPDirectiveKindExWrapper DKind = Tok.isAnnotation() ? static_cast<unsigned>(OMPD_unknown) : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); @@ -155,7 +172,7 @@ static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) { continue; Tok = P.getPreprocessor().LookAhead(0); - unsigned SDKind = + OpenMPDirectiveKindExWrapper SDKind = Tok.isAnnotation() ? static_cast<unsigned>(OMPD_unknown) : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); @@ -237,8 +254,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); - if (T.expectAndConsume(diag::err_expected_lparen_after, - getOpenMPDirectiveName(OMPD_declare_reduction))) { + if (T.expectAndConsume( + diag::err_expected_lparen_after, + getOpenMPDirectiveName(OMPD_declare_reduction).data())) { SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); return DeclGroupPtrTy(); } @@ -325,9 +343,8 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { Scope::OpenMPDirectiveScope); // Parse <combiner> expression. Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); - ExprResult CombinerResult = - Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), - D->getLocation(), /*DiscardedValue*/ false); + ExprResult CombinerResult = Actions.ActOnFinishFullExpr( + ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false); Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && @@ -366,14 +383,8 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { // Check if initializer is omp_priv <init_expr> or something else. if (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("omp_priv")) { - if (Actions.getLangOpts().CPlusPlus) { - InitializerResult = Actions.ActOnFinishFullExpr( - ParseAssignmentExpression().get(), D->getLocation(), - /*DiscardedValue*/ false); - } else { - ConsumeToken(); - ParseOpenMPReductionInitializerForDecl(OmpPrivParm); - } + ConsumeToken(); + ParseOpenMPReductionInitializerForDecl(OmpPrivParm); } else { InitializerResult = Actions.ActOnFinishFullExpr( ParseAssignmentExpression().get(), D->getLocation(), @@ -417,7 +428,8 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { return; } - ExprResult Init(ParseInitializer()); + PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm); + ExprResult Init = ParseInitializer(); if (Init.isInvalid()) { SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); @@ -495,7 +507,7 @@ Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) { // Parse '(' BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, - getOpenMPDirectiveName(OMPD_declare_mapper))) { + getOpenMPDirectiveName(OMPD_declare_mapper).data())) { SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); return DeclGroupPtrTy(); } @@ -722,10 +734,12 @@ static bool parseDeclareSimdClauses( CKind == OMPC_linear) { Parser::OpenMPVarListDataTy Data; SmallVectorImpl<Expr *> *Vars = &Uniforms; - if (CKind == OMPC_aligned) + if (CKind == OMPC_aligned) { Vars = &Aligneds; - else if (CKind == OMPC_linear) + } else if (CKind == OMPC_linear) { + Data.ExtraModifier = OMPC_LINEAR_val; Vars = &Linears; + } P.ConsumeToken(); if (P.ParseOpenMPVarList(OMPD_declare_simd, @@ -734,11 +748,15 @@ static bool parseDeclareSimdClauses( if (CKind == OMPC_aligned) { Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr); } else if (CKind == OMPC_linear) { - if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind, - Data.DepLinMapLoc)) - Data.LinKind = OMPC_LINEAR_val; + assert(0 <= Data.ExtraModifier && + Data.ExtraModifier <= OMPC_LINEAR_unknown && + "Unexpected linear modifier."); + if (P.getActions().CheckOpenMPLinearModifier( + static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier), + Data.DepLinMapLastLoc)) + Data.ExtraModifier = OMPC_LINEAR_val; LinModifiers.append(Linears.size() - LinModifiers.size(), - Data.LinKind); + Data.ExtraModifier); Steps.append(Linears.size() - Steps.size(), Data.TailExpr); } } else @@ -795,16 +813,11 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, /// Parse optional 'score' '(' <expr> ')' ':'. static ExprResult parseContextScore(Parser &P) { ExprResult ScoreExpr; - SmallString<16> Buffer; + Sema::OMPCtxStringType Buffer; StringRef SelectorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); - OMPDeclareVariantAttr::ScoreType ScoreKind = - OMPDeclareVariantAttr::ScoreUnknown; - (void)OMPDeclareVariantAttr::ConvertStrToScoreType(SelectorName, ScoreKind); - if (ScoreKind == OMPDeclareVariantAttr::ScoreUnknown) + if (!SelectorName.equals("score")) return ScoreExpr; - assert(ScoreKind == OMPDeclareVariantAttr::ScoreSpecified && - "Expected \"score\" clause."); (void)P.ConsumeToken(); SourceLocation RLoc; ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc); @@ -820,11 +833,10 @@ static ExprResult parseContextScore(Parser &P) { /// Parse context selector for 'implementation' selector set: /// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> } /// ')' -static void parseImplementationSelector( - Parser &P, SourceLocation Loc, llvm::StringMap<SourceLocation> &UsedCtx, - llvm::function_ref<void(SourceRange, - const Sema::OpenMPDeclareVariantCtsSelectorData &)> - Callback) { +static void +parseImplementationSelector(Parser &P, SourceLocation Loc, + llvm::StringMap<SourceLocation> &UsedCtx, + SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) { const Token &Tok = P.getCurToken(); // Parse inner context selector set name, if any. if (!Tok.is(tok::identifier)) { @@ -836,7 +848,7 @@ static void parseImplementationSelector( ; return; } - SmallString<16> Buffer; + Sema::OMPCtxStringType Buffer; StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer); auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation()); if (!Res.second) { @@ -847,19 +859,16 @@ static void parseImplementationSelector( P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) << CtxSelectorName; } - OMPDeclareVariantAttr::CtxSelectorType CSKind = - OMPDeclareVariantAttr::CtxUnknown; - (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorType(CtxSelectorName, - CSKind); + OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName); (void)P.ConsumeToken(); switch (CSKind) { - case OMPDeclareVariantAttr::CtxVendor: { + case OMP_CTX_vendor: { // Parse '('. BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); (void)T.expectAndConsume(diag::err_expected_lparen_after, CtxSelectorName.data()); - const ExprResult Score = parseContextScore(P); - llvm::UniqueVector<llvm::SmallString<16>> Vendors; + ExprResult Score = parseContextScore(P); + llvm::UniqueVector<Sema::OMPCtxStringType> Vendors; do { // Parse <vendor>. StringRef VendorName; @@ -882,18 +891,12 @@ static void parseImplementationSelector( } while (Tok.is(tok::identifier)); // Parse ')'. (void)T.consumeClose(); - if (!Vendors.empty()) { - SmallVector<StringRef, 4> ImplVendors(Vendors.size()); - llvm::copy(Vendors, ImplVendors.begin()); - Sema::OpenMPDeclareVariantCtsSelectorData Data( - OMPDeclareVariantAttr::CtxSetImplementation, CSKind, - llvm::makeMutableArrayRef(ImplVendors.begin(), ImplVendors.size()), - Score); - Callback(SourceRange(Loc, Tok.getLocation()), Data); - } + if (!Vendors.empty()) + Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors); break; } - case OMPDeclareVariantAttr::CtxUnknown: + case OMP_CTX_kind: + case OMP_CTX_unknown: P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) << "implementation"; // Skip until either '}', ')', or end of directive. @@ -904,15 +907,97 @@ static void parseImplementationSelector( } } +/// Parse context selector for 'device' selector set: +/// 'kind' '(' <kind> { ',' <kind> } ')' +static void +parseDeviceSelector(Parser &P, SourceLocation Loc, + llvm::StringMap<SourceLocation> &UsedCtx, + SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) { + const Token &Tok = P.getCurToken(); + // Parse inner context selector set name, if any. + if (!Tok.is(tok::identifier)) { + P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) + << "device"; + // Skip until either '}', ')', or end of directive. + while (!P.SkipUntil(tok::r_brace, tok::r_paren, + tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) + ; + return; + } + Sema::OMPCtxStringType Buffer; + StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer); + auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation()); + if (!Res.second) { + // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions. + // Each trait-selector-name can only be specified once. + P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use) + << CtxSelectorName << "device"; + P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) + << CtxSelectorName; + } + OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName); + (void)P.ConsumeToken(); + switch (CSKind) { + case OMP_CTX_kind: { + // Parse '('. + BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); + (void)T.expectAndConsume(diag::err_expected_lparen_after, + CtxSelectorName.data()); + llvm::UniqueVector<Sema::OMPCtxStringType> Kinds; + do { + // Parse <kind>. + StringRef KindName; + if (Tok.is(tok::identifier)) { + Buffer.clear(); + KindName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); + SourceLocation SLoc = P.getCurToken().getLocation(); + (void)P.ConsumeToken(); + if (llvm::StringSwitch<bool>(KindName) + .Case("host", false) + .Case("nohost", false) + .Case("cpu", false) + .Case("gpu", false) + .Case("fpga", false) + .Default(true)) { + P.Diag(SLoc, diag::err_omp_wrong_device_kind_trait) << KindName; + } else { + Kinds.insert(KindName); + } + } else { + P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected) + << "'host', 'nohost', 'cpu', 'gpu', or 'fpga'" + << "kind" + << "device"; + } + if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) { + P.Diag(Tok, diag::err_expected_punc) + << (KindName.empty() ? "kind of device" : KindName); + } + } while (Tok.is(tok::identifier)); + // Parse ')'. + (void)T.consumeClose(); + if (!Kinds.empty()) + Data.emplace_back(OMP_CTX_SET_device, CSKind, ExprResult(), Kinds); + break; + } + case OMP_CTX_vendor: + case OMP_CTX_unknown: + P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected) + << "device"; + // Skip until either '}', ')', or end of directive. + while (!P.SkipUntil(tok::r_brace, tok::r_paren, + tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) + ; + return; + } +} + /// Parses clauses for 'declare variant' directive. /// clause: /// <selector_set_name> '=' '{' <context_selectors> '}' /// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ] bool Parser::parseOpenMPContextSelectors( - SourceLocation Loc, - llvm::function_ref<void(SourceRange, - const Sema::OpenMPDeclareVariantCtsSelectorData &)> - Callback) { + SourceLocation Loc, SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) { llvm::StringMap<SourceLocation> UsedCtxSets; do { // Parse inner context selector set name. @@ -921,7 +1006,7 @@ bool Parser::parseOpenMPContextSelectors( << getOpenMPClauseName(OMPC_match); return true; } - SmallString<16> Buffer; + Sema::OMPCtxStringType Buffer; StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer); auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation()); if (!Res.second) { @@ -949,17 +1034,18 @@ bool Parser::parseOpenMPContextSelectors( tok::annot_pragma_openmp_end); if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "=")) return true; - OMPDeclareVariantAttr::CtxSelectorSetType CSSKind = - OMPDeclareVariantAttr::CtxSetUnknown; - (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorSetType( - CtxSelectorSetName, CSSKind); + OpenMPContextSelectorSetKind CSSKind = + getOpenMPContextSelectorSet(CtxSelectorSetName); llvm::StringMap<SourceLocation> UsedCtx; do { switch (CSSKind) { - case OMPDeclareVariantAttr::CtxSetImplementation: - parseImplementationSelector(*this, Loc, UsedCtx, Callback); + case OMP_CTX_SET_implementation: + parseImplementationSelector(*this, Loc, UsedCtx, Data); break; - case OMPDeclareVariantAttr::CtxSetUnknown: + case OMP_CTX_SET_device: + parseDeviceSelector(*this, Loc, UsedCtx, Data); + break; + case OMP_CTX_SET_unknown: // Skip until either '}', ')', or end of directive. while (!SkipUntil(tok::r_brace, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch)) @@ -998,9 +1084,16 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, SourceLocation RLoc; // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs // instead of MemberExprs. - ExprResult AssociatedFunction = - ParseOpenMPParensExpr(getOpenMPDirectiveName(OMPD_declare_variant), RLoc, - /*IsAddressOfOperand=*/true); + ExprResult AssociatedFunction; + { + // Do not mark function as is used to prevent its emission if this is the + // only place where it is used. + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::Unevaluated); + AssociatedFunction = ParseOpenMPParensExpr( + getOpenMPDirectiveName(OMPD_declare_variant), RLoc, + /*IsAddressOfOperand=*/true); + } if (!AssociatedFunction.isUsable()) { if (!Tok.is(tok::annot_pragma_openmp_end)) while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) @@ -1039,15 +1132,8 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, } // Parse inner context selectors. - if (!parseOpenMPContextSelectors( - Loc, [this, &DeclVarData]( - SourceRange SR, - const Sema::OpenMPDeclareVariantCtsSelectorData &Data) { - if (DeclVarData.hasValue()) - Actions.ActOnOpenMPDeclareVariantDirective( - DeclVarData.getValue().first, DeclVarData.getValue().second, - SR, Data); - })) { + SmallVector<Sema::OMPCtxSelectorData, 4> Data; + if (!parseOpenMPContextSelectors(Loc, Data)) { // Parse ')'. (void)T.consumeClose(); // Need to check for extra tokens. @@ -1060,6 +1146,10 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, // Skip last tokens. while (Tok.isNot(tok::annot_pragma_openmp_end)) ConsumeAnyToken(); + if (DeclVarData.hasValue()) + Actions.ActOnOpenMPDeclareVariantDirective( + DeclVarData.getValue().first, DeclVarData.getValue().second, + SourceRange(Loc, Tok.getLocation()), Data); // Skip the last annot_pragma_openmp_end. (void)ConsumeAnnotationToken(); } @@ -1245,13 +1335,45 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind, /// annot_pragma_openmp_end /// Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( - AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, + AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed, DeclSpec::TST TagType, Decl *Tag) { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); + ParsingOpenMPDirectiveRAII DirScope(*this); ParenBraceBracketBalancer BalancerRAIIObj(*this); - SourceLocation Loc = ConsumeAnnotationToken(); - OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); + SourceLocation Loc; + OpenMPDirectiveKind DKind; + if (Delayed) { + TentativeParsingAction TPA(*this); + Loc = ConsumeAnnotationToken(); + DKind = parseOpenMPDirectiveKind(*this); + if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) { + // Need to delay parsing until completion of the parent class. + TPA.Revert(); + CachedTokens Toks; + unsigned Cnt = 1; + Toks.push_back(Tok); + while (Cnt && Tok.isNot(tok::eof)) { + (void)ConsumeAnyToken(); + if (Tok.is(tok::annot_pragma_openmp)) + ++Cnt; + else if (Tok.is(tok::annot_pragma_openmp_end)) + --Cnt; + Toks.push_back(Tok); + } + // Skip last annot_pragma_openmp_end. + if (Cnt == 0) + (void)ConsumeAnyToken(); + auto *LP = new LateParsedPragma(this, AS); + LP->takeToks(Toks); + getCurrentClass().LateParsedDeclarations.push_back(LP); + return nullptr; + } + TPA.Commit(); + } else { + Loc = ConsumeAnnotationToken(); + DKind = parseOpenMPDirectiveKind(*this); + } switch (DKind) { case OMPD_threadprivate: { @@ -1403,7 +1525,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( DeclGroupPtrTy Ptr; if (Tok.is(tok::annot_pragma_openmp)) { - Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag); + Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed, + TagType, Tag); } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // Here we expect to see some function declaration. if (AS == AS_none) { @@ -1496,6 +1619,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_parallel_for: case OMPD_parallel_for_simd: case OMPD_parallel_sections: + case OMPD_parallel_master: case OMPD_atomic: case OMPD_target: case OMPD_teams: @@ -1511,6 +1635,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_master_taskloop: case OMPD_master_taskloop_simd: case OMPD_parallel_master_taskloop: + case OMPD_parallel_master_taskloop_simd: case OMPD_distribute: case OMPD_end_declare_target: case OMPD_target_update: @@ -1562,24 +1687,26 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( /// executable-directive: /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | -/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | -/// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | -/// 'for simd' | 'parallel for simd' | 'target' | 'target data' | -/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 'master -/// taskloop' | 'master taskloop simd' | 'parallel master taskloop' | -/// 'distribute' | 'target enter data' | 'target exit data' | 'target -/// parallel' | 'target parallel for' | 'target update' | 'distribute -/// parallel for' | 'distribute paralle for simd' | 'distribute simd' | -/// 'target parallel for simd' | 'target simd' | 'teams distribute' | -/// 'teams distribute 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' -/// {clause} annot_pragma_openmp_end +/// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' | +/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | +/// '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 +/// enter data' | 'target exit data' | 'target parallel' | 'target +/// parallel for' | 'target update' | 'distribute parallel for' | +/// 'distribute paralle for simd' | 'distribute simd' | 'target parallel +/// for simd' | 'target simd' | 'teams distribute' | 'teams distribute +/// 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' {clause} +/// annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); + ParsingOpenMPDirectiveRAII DirScope(*this); ParenBraceBracketBalancer BalancerRAIIObj(*this); SmallVector<OMPClause *, 5> Clauses; SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> @@ -1739,6 +1866,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { case OMPD_parallel_for: case OMPD_parallel_for_simd: case OMPD_parallel_sections: + case OMPD_parallel_master: case OMPD_task: case OMPD_ordered: case OMPD_atomic: @@ -1753,6 +1881,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { case OMPD_master_taskloop: case OMPD_master_taskloop_simd: case OMPD_parallel_master_taskloop: + case OMPD_parallel_master_taskloop_simd: case OMPD_distribute: case OMPD_distribute_parallel_for: case OMPD_distribute_parallel_for_simd: @@ -1890,7 +2019,7 @@ bool Parser::ParseOpenMPSimpleVarList( // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, - getOpenMPDirectiveName(Kind))) + getOpenMPDirectiveName(Kind).data())) return true; bool IsCorrect = true; bool NoIdentIsFound = true; @@ -1963,7 +2092,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, bool ErrorFound = false; bool WrongDirective = false; // Check if clause is allowed for the given directive. - if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { + if (CKind != OMPC_unknown && + !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) { Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); ErrorFound = true; @@ -2042,15 +2172,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_defaultmap: // OpenMP [2.7.1, Restrictions, p. 3] // Only one schedule clause can appear on a loop directive. - // OpenMP [2.10.4, Restrictions, p. 106] + // OpenMP 4.5 [2.10.4, Restrictions, p. 106] // At most one defaultmap clause can appear on the directive. - if (!FirstClause) { + if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && + !FirstClause) { Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } LLVM_FALLTHROUGH; - case OMPC_if: Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective); break; @@ -2102,6 +2232,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_use_device_ptr: case OMPC_is_device_ptr: case OMPC_allocate: + case OMPC_nontemporal: Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); break; case OMPC_device_type: @@ -2133,8 +2264,8 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, return ExprError(); SourceLocation ELoc = Tok.getLocation(); - ExprResult LHS(ParseCastExpression( - /*isUnaryExpression=*/false, IsAddressOfOperand, NotTypeCast)); + ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand, + NotTypeCast)); ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); @@ -2334,8 +2465,13 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, DelimLoc = ConsumeAnyToken(); } else if (Kind == OMPC_defaultmap) { // Get a defaultmap modifier - Arg.push_back(getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); + unsigned Modifier = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); + // Set defaultmap modifier to unknown if it is either scalar, aggregate, or + // pointer + if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) + Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; + Arg.push_back(Modifier); KLoc.push_back(Tok.getLocation()); if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && Tok.isNot(tok::annot_pragma_openmp_end)) @@ -2356,15 +2492,16 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, assert(Kind == OMPC_if); KLoc.push_back(Tok.getLocation()); TentativeParsingAction TPA(*this); - Arg.push_back(parseOpenMPDirectiveKind(*this)); - if (Arg.back() != OMPD_unknown) { + auto DK = parseOpenMPDirectiveKind(*this); + Arg.push_back(DK); + if (DK != OMPD_unknown) { ConsumeToken(); if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { TPA.Commit(); DelimLoc = ConsumeToken(); } else { TPA.Revert(); - Arg.back() = OMPD_unknown; + Arg.back() = unsigned(OMPD_unknown); } } else { TPA.Revert(); @@ -2376,7 +2513,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, Kind == OMPC_if; if (NeedAnExpression) { SourceLocation ELoc = Tok.getLocation(); - ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); + ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); @@ -2541,8 +2678,8 @@ static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { P.Diag(Tok, diag::err_omp_map_type_missing); return; } - Data.MapType = isMapType(P); - if (Data.MapType == OMPC_MAP_unknown) + Data.ExtraModifier = isMapType(P); + if (Data.ExtraModifier == OMPC_MAP_unknown) P.Diag(Tok, diag::err_omp_unknown_map_type); P.ConsumeToken(); } @@ -2587,20 +2724,18 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.ReductionOrMapperId = Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); } else if (Kind == OMPC_depend) { - // Handle dependency type for depend clause. + // Handle dependency type for depend clause. ColonProtectionRAIIObject ColonRAII(*this); - Data.DepKind = - static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( - Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); - Data.DepLinMapLoc = Tok.getLocation(); - - if (Data.DepKind == OMPC_DEPEND_unknown) { + Data.ExtraModifier = getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""); + Data.DepLinMapLastLoc = Tok.getLocation(); + if (Data.ExtraModifier == OMPC_DEPEND_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.DepKind == OMPC_DEPEND_source) { + if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) { // Parse ')'. T.consumeClose(); return false; @@ -2615,13 +2750,32 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, } } 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.LinKind = static_cast<OpenMPLinearClauseKind>( - getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); - Data.DepLinMapLoc = ConsumeToken(); + Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); + Data.DepLinMapLastLoc = ConsumeToken(); LinearT.consumeOpen(); NeedRParenForLinear = true; } + } else if (Kind == OMPC_lastprivate) { + // Try to parse modifier if any. + Data.ExtraModifier = OMPC_LASTPRIVATE_unknown; + // Conditional modifier allowed only in OpenMP 5.0 and not supported in + // distribute and taskloop based directives. + 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)); + Data.DepLinMapLastLoc = Tok.getLocation(); + if (Data.ExtraModifier == OMPC_LASTPRIVATE_unknown) { + SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); + } else { + ConsumeToken(); + } + assert(Tok.is(tok::colon) && "Expected colon."); + Data.ColonLoc = ConsumeToken(); + } } else if (Kind == OMPC_map) { // Handle map type for map clause. ColonProtectionRAIIObject ColonRAII(*this); @@ -2629,7 +2783,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, // The first identifier may be a list item, a map-type or a // map-type-modifier. The map-type can also be delete which has the same // spelling of the C++ delete keyword. - Data.DepLinMapLoc = Tok.getLocation(); + Data.ExtraModifier = OMPC_MAP_unknown; + Data.DepLinMapLastLoc = Tok.getLocation(); // Check for presence of a colon in the map clause. TentativeParsingAction TPA(*this); @@ -2649,8 +2804,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, else SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); } - if (Data.MapType == OMPC_MAP_unknown) { - Data.MapType = OMPC_MAP_tofrom; + if (Data.ExtraModifier == OMPC_MAP_unknown) { + Data.ExtraModifier = OMPC_MAP_tofrom; Data.IsMapTypeImplicit = true; } @@ -2716,8 +2871,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, (Kind != OMPC_reduction && Kind != OMPC_task_reduction && Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || (Kind == OMPC_reduction && !InvalidReductionId) || - (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) || - (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); + (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) || + (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_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))) { @@ -2767,7 +2922,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.RLoc = Tok.getLocation(); if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); - return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown && + return (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown && Vars.empty()) || (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || (MustHaveTail && !Data.TailExpr) || InvalidReductionId || @@ -2837,8 +2992,8 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); return Actions.ActOnOpenMPVarListClause( Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc, - Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, Data.DepKind, - Data.LinKind, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, - Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc); + Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, + Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, + Data.IsMapTypeImplicit, Data.DepLinMapLastLoc); } |