diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp | 377 |
1 files changed, 313 insertions, 64 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp index 0113a31..078f4c3 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseOpenMP.cpp @@ -19,6 +19,7 @@ #include "clang/Parse/Parser.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/PointerIntPair.h" + using namespace clang; //===----------------------------------------------------------------------===// @@ -32,15 +33,18 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { const OpenMPDirectiveKind F[][3] = { {OMPD_unknown /*cancellation*/, OMPD_unknown /*point*/, OMPD_cancellation_point}, + {OMPD_target, OMPD_unknown /*data*/, OMPD_target_data}, {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_sections, OMPD_parallel_sections}}; + {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, + {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}}; auto Tok = P.getCurToken(); auto DKind = Tok.isAnnotation() ? OMPD_unknown : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); + bool TokenMatched = false; for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) { if (!Tok.isAnnotation() && DKind == OMPD_unknown) { @@ -50,18 +54,24 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { } else { TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown; } + if (TokenMatched) { Tok = P.getPreprocessor().LookAhead(0); + auto TokenIsAnnotation = Tok.isAnnotation(); auto SDKind = - Tok.isAnnotation() + TokenIsAnnotation ? OMPD_unknown : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); - if (!Tok.isAnnotation() && DKind == OMPD_unknown) { + + if (!TokenIsAnnotation && SDKind == OMPD_unknown) { TokenMatched = - (i == 0) && !P.getPreprocessor().getSpelling(Tok).compare("point"); + ((i == 0) && + !P.getPreprocessor().getSpelling(Tok).compare("point")) || + ((i == 1) && !P.getPreprocessor().getSpelling(Tok).compare("data")); } else { TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown; } + if (TokenMatched) { P.ConsumeToken(); DKind = F[i][2]; @@ -127,6 +137,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_teams: case OMPD_cancellation_point: case OMPD_cancel: + case OMPD_target_data: + case OMPD_taskloop: + case OMPD_taskloop_simd: + case OMPD_distribute: Diag(Tok, diag::err_omp_unexpected_directive) << getOpenMPDirectiveName(DKind); break; @@ -146,8 +160,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | -/// 'for simd' | 'parallel for simd' | 'target' | 'teams' | 'taskgroup' -/// {clause} +/// 'for simd' | 'parallel for simd' | 'target' | 'target data' | +/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' {clause} | +/// 'distribute' /// annot_pragma_openmp_end /// StmtResult @@ -200,7 +215,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_cancel: if (!StandAloneAllowed) { Diag(Tok, diag::err_omp_immediate_directive) - << getOpenMPDirectiveName(DKind); + << getOpenMPDirectiveName(DKind) << 0; } HasAssociatedStatement = false; // Fall through for further analysis. @@ -221,7 +236,11 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_atomic: case OMPD_target: case OMPD_teams: - case OMPD_taskgroup: { + case OMPD_taskgroup: + case OMPD_target_data: + case OMPD_taskloop: + case OMPD_taskloop_simd: + case OMPD_distribute: { ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { @@ -276,8 +295,19 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { // Consume final annot_pragma_openmp_end. ConsumeToken(); + // 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[OMPC_depend].getInt()) { + if (!StandAloneAllowed) { + Diag(Loc, diag::err_omp_immediate_directive) + << getOpenMPDirectiveName(DKind) << 1 + << getOpenMPClauseName(OMPC_depend); + } + HasAssociatedStatement = false; + } + StmtResult AssociatedStmt; - bool CreateDirective = true; if (HasAssociatedStatement) { // The body is a block scope like in Lambdas and Blocks. Sema::CompoundScopeRAII CompoundScope(Actions); @@ -287,12 +317,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { AssociatedStmt = ParseStatement(); Actions.ActOnFinishOfCompoundStmt(); AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); - CreateDirective = AssociatedStmt.isUsable(); } - if (CreateDirective) - Directive = Actions.ActOnOpenMPExecutableDirective( - DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, - EndLoc); + Directive = Actions.ActOnOpenMPExecutableDirective( + DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, + EndLoc); // Exit scope. Actions.EndOpenMPDSABlock(Directive.get()); @@ -385,7 +413,10 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, /// lastprivate-clause | reduction-clause | proc_bind-clause | /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | /// mergeable-clause | flush-clause | read-clause | write-clause | -/// update-clause | capture-clause | seq_cst-clause +/// update-clause | capture-clause | seq_cst-clause | device-clause | +/// simdlen-clause | threads-clause | simd-clause | num_teams-clause | +/// thread_limit-clause | priority-clause | grainsize-clause | +/// nogroup-clause | num_tasks-clause | hint-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -399,27 +430,49 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, } switch (CKind) { - case OMPC_if: case OMPC_final: case OMPC_num_threads: case OMPC_safelen: + case OMPC_simdlen: case OMPC_collapse: + case OMPC_ordered: + case OMPC_device: + case OMPC_num_teams: + case OMPC_thread_limit: + case OMPC_priority: + case OMPC_grainsize: + case OMPC_num_tasks: + case OMPC_hint: // OpenMP [2.5, Restrictions] - // At most one if clause can appear on the directive. // At most one num_threads clause can appear on the directive. // OpenMP [2.8.1, simd construct, Restrictions] // Only one safelen clause can appear on a simd directive. + // Only one simdlen clause can appear on a simd directive. // Only one collapse clause can appear on a simd directive. + // OpenMP [2.9.1, target data construct, Restrictions] + // At most one device clause can appear on the directive. // OpenMP [2.11.1, task Construct, Restrictions] // At most one if clause can appear on the directive. // At most one final clause can appear on the directive. + // OpenMP [teams Construct, Restrictions] + // At most one num_teams clause can appear on the directive. + // At most one thread_limit clause can appear on the directive. + // OpenMP [2.9.1, task Construct, Restrictions] + // At most one priority clause can appear on the directive. + // OpenMP [2.9.2, taskloop Construct, Restrictions] + // At most one grainsize clause can appear on the directive. + // OpenMP [2.9.2, taskloop Construct, Restrictions] + // At most one num_tasks clause can appear on the directive. if (!FirstClause) { - Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) - << getOpenMPClauseName(CKind); + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } - Clause = ParseOpenMPSingleExprClause(CKind); + if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) + Clause = ParseOpenMPClause(CKind); + else + Clause = ParseOpenMPSingleExprClause(CKind); break; case OMPC_default: case OMPC_proc_bind: @@ -429,8 +482,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, // OpenMP [2.5, parallel Construct, Restrictions] // At most one proc_bind clause can appear on the directive. if (!FirstClause) { - Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) - << getOpenMPClauseName(CKind); + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } @@ -440,14 +493,14 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, // OpenMP [2.7.1, Restrictions, p. 3] // Only one schedule clause can appear on a loop directive. if (!FirstClause) { - Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) - << getOpenMPClauseName(CKind); + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } + case OMPC_if: Clause = ParseOpenMPSingleExprWithArgClause(CKind); break; - case OMPC_ordered: case OMPC_nowait: case OMPC_untied: case OMPC_mergeable: @@ -456,13 +509,16 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_threads: + case OMPC_simd: + case OMPC_nogroup: // OpenMP [2.7.1, Restrictions, p. 9] // Only one ordered clause can appear on a loop directive. // OpenMP [2.7.1, Restrictions, C/C++, p. 4] // Only one nowait clause can appear on a for directive. if (!FirstClause) { - Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) - << getOpenMPClauseName(CKind); + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } @@ -479,7 +535,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_copyprivate: case OMPC_flush: case OMPC_depend: - Clause = ParseOpenMPVarListClause(CKind); + case OMPC_map: + Clause = ParseOpenMPVarListClause(DKind, CKind); break; case OMPC_unknown: Diag(Tok, diag::warn_omp_extra_tokens_at_eol) @@ -495,12 +552,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, return ErrorFound ? nullptr : Clause; } -/// \brief Parsing of OpenMP clauses with single expressions like 'if', -/// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or -/// 'thread_limit'. -/// -/// if-clause: -/// 'if' '(' expression ')' +/// \brief Parsing of OpenMP clauses with single expressions like 'final', +/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', +/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'. /// /// final-clause: /// 'final' '(' expression ')' @@ -511,9 +565,24 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, /// safelen-clause: /// 'safelen' '(' expression ')' /// +/// simdlen-clause: +/// 'simdlen' '(' expression ')' +/// /// collapse-clause: /// 'collapse' '(' expression ')' /// +/// priority-clause: +/// 'priority' '(' expression ')' +/// +/// grainsize-clause: +/// 'grainsize' '(' expression ')' +/// +/// num_tasks-clause: +/// 'num_tasks' '(' expression ')' +/// +/// hint-clause: +/// 'hint' '(' expression ')' +/// OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { SourceLocation Loc = ConsumeToken(); @@ -522,8 +591,10 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { getOpenMPClauseName(Kind))) return nullptr; + SourceLocation ELoc = Tok.getLocation(); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); // Parse ')'. T.consumeClose(); @@ -583,6 +654,15 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { /// read-clause: /// 'read' /// +/// threads-clause: +/// 'threads' +/// +/// simd-clause: +/// 'simd' +/// +/// nogroup-clause: +/// 'nogroup' +/// OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); ConsumeAnyToken(); @@ -595,11 +675,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) { /// argument like 'schedule' or 'dist_schedule'. /// /// schedule-clause: -/// 'schedule' '(' kind [',' expression ] ')' +/// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] +/// ')' +/// +/// if-clause: +/// 'if' '(' [ directive-name-modifier ':' ] expression ')' /// OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { SourceLocation Loc = ConsumeToken(); - SourceLocation CommaLoc; + SourceLocation DelimLoc; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, @@ -607,29 +691,86 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { return nullptr; ExprResult Val; - unsigned Type = getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); - SourceLocation KLoc = Tok.getLocation(); - if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && - Tok.isNot(tok::annot_pragma_openmp_end)) - ConsumeAnyToken(); + SmallVector<unsigned, 4> Arg; + SmallVector<SourceLocation, 4> KLoc; + if (Kind == OMPC_schedule) { + enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; + Arg.resize(NumberOfElements); + KLoc.resize(NumberOfElements); + Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; + Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; + Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; + auto KindModifier = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); + if (KindModifier > OMPC_SCHEDULE_unknown) { + // Parse 'modifier' + Arg[Modifier1] = KindModifier; + KLoc[Modifier1] = Tok.getLocation(); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + if (Tok.is(tok::comma)) { + // Parse ',' 'modifier' + ConsumeAnyToken(); + KindModifier = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); + Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown + ? KindModifier + : (unsigned)OMPC_SCHEDULE_unknown; + KLoc[Modifier2] = 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) << "schedule modifier"; + KindModifier = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); + } + Arg[ScheduleKind] = KindModifier; + KLoc[ScheduleKind] = Tok.getLocation(); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || + Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || + Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && + Tok.is(tok::comma)) + DelimLoc = ConsumeAnyToken(); + } else { + assert(Kind == OMPC_if); + KLoc.push_back(Tok.getLocation()); + Arg.push_back(ParseOpenMPDirectiveKind(*this)); + if (Arg.back() != OMPD_unknown) { + ConsumeToken(); + if (Tok.is(tok::colon)) + DelimLoc = ConsumeToken(); + else + Diag(Tok, diag::warn_pragma_expected_colon) + << "directive name modifier"; + } + } - if (Kind == OMPC_schedule && - (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic || - Type == OMPC_SCHEDULE_guided) && - Tok.is(tok::comma)) { - CommaLoc = ConsumeAnyToken(); + bool NeedAnExpression = + (Kind == OMPC_schedule && DelimLoc.isValid()) || Kind == OMPC_if; + if (NeedAnExpression) { + SourceLocation ELoc = Tok.getLocation(); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); - if (Val.isInvalid()) - return nullptr; + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); } // Parse ')'. T.consumeClose(); + if (NeedAnExpression && Val.isInvalid()) + return nullptr; + return Actions.ActOnOpenMPSingleExprWithArgClause( - Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc, + Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, T.getCloseLocation()); } @@ -691,7 +832,7 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, /// shared-clause: /// 'shared' '(' list ')' /// linear-clause: -/// 'linear' '(' list [ ':' linear-step ] ')' +/// 'linear' '(' linear-list [ ':' linear-step ] ')' /// aligned-clause: /// 'aligned' '(' list [ ':' alignment ] ')' /// reduction-clause: @@ -701,9 +842,17 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, /// flush-clause: /// 'flush' '(' list ')' /// depend-clause: -/// 'depend' '(' in | out | inout : list ')' +/// 'depend' '(' in | out | inout : list | source ')' +/// map-clause: +/// 'map' '(' [ [ always , ] +/// to | from | tofrom | alloc | release | delete ':' ] list ')'; /// -OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { +/// For 'linear' clause linear-list may have the following forms: +/// list +/// modifier(list) +/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). +OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, + OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); SourceLocation ColonLoc = SourceLocation(); @@ -712,7 +861,14 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { UnqualifiedId ReductionId; bool InvalidReductionId = false; OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; - SourceLocation DepLoc; + // OpenMP 4.1 [2.15.3.7, linear Clause] + // If no modifier is specified it is assumed to be val. + OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val; + OpenMPMapClauseKind MapType = OMPC_MAP_unknown; + OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; + bool MapTypeModifierSpecified = false; + bool UnexpectedId = false; + SourceLocation DepLinMapLoc; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); @@ -720,6 +876,9 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { getOpenMPClauseName(Kind))) return nullptr; + bool NeedRParenForLinear = false; + BalancedDelimiterTracker LinearT(*this, tok::l_paren, + tok::annot_pragma_openmp_end); // Handle reduction-identifier for reduction clause. if (Kind == OMPC_reduction) { ColonProtectionRAIIObject ColonRAII(*this); @@ -742,25 +901,109 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { ColonProtectionRAIIObject ColonRAII(*this); DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); - DepLoc = Tok.getLocation(); + DepLinMapLoc = Tok.getLocation(); if (DepKind == 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 && DepKind == OMPC_DEPEND_source) { + // Parse ')'. + T.consumeClose(); + return Actions.ActOnOpenMPVarListClause( + Kind, llvm::None, /*TailExpr=*/nullptr, Loc, LOpen, + /*ColonLoc=*/SourceLocation(), Tok.getLocation(), + ReductionIdScopeSpec, DeclarationNameInfo(), DepKind, + LinearModifier, MapTypeModifier, MapType, DepLinMapLoc); + } } if (Tok.is(tok::colon)) { ColonLoc = ConsumeToken(); } else { - Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type"; + Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren + : diag::warn_pragma_expected_colon) + << "dependency type"; + } + } else if (Kind == OMPC_linear) { + // Try to parse modifier if any. + if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { + LinearModifier = static_cast<OpenMPLinearClauseKind>( + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); + DepLinMapLoc = ConsumeToken(); + LinearT.consumeOpen(); + NeedRParenForLinear = true; + } + } else if (Kind == OMPC_map) { + // Handle map type for map clause. + ColonProtectionRAIIObject ColonRAII(*this); + + // the first identifier may be a list item, a map-type or + // a map-type-modifier + MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); + DepLinMapLoc = Tok.getLocation(); + bool ColonExpected = false; + + if (Tok.is(tok::identifier)) { + if (PP.LookAhead(0).is(tok::colon)) { + MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); + if (MapType == OMPC_MAP_unknown) { + Diag(Tok, diag::err_omp_unknown_map_type); + } else if (MapType == OMPC_MAP_always) { + Diag(Tok, diag::err_omp_map_type_missing); + } + ConsumeToken(); + } else if (PP.LookAhead(0).is(tok::comma)) { + if (PP.LookAhead(1).is(tok::identifier) && + PP.LookAhead(2).is(tok::colon)) { + MapTypeModifier = + static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); + if (MapTypeModifier != OMPC_MAP_always) { + Diag(Tok, diag::err_omp_unknown_map_type_modifier); + MapTypeModifier = OMPC_MAP_unknown; + } else { + MapTypeModifierSpecified = true; + } + + ConsumeToken(); + ConsumeToken(); + + MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); + if (MapType == OMPC_MAP_unknown || MapType == OMPC_MAP_always) { + Diag(Tok, diag::err_omp_unknown_map_type); + } + ConsumeToken(); + } else { + MapType = OMPC_MAP_tofrom; + } + } else { + MapType = OMPC_MAP_tofrom; + } + } else { + UnexpectedId = true; + } + + if (Tok.is(tok::colon)) { + ColonLoc = ConsumeToken(); + } else if (ColonExpected) { + Diag(Tok, diag::warn_pragma_expected_colon) << "map type"; } } SmallVector<Expr *, 5> Vars; - bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) || - ((Kind == OMPC_reduction) && !InvalidReductionId) || - ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown); + bool IsComma = + ((Kind != OMPC_reduction) && (Kind != OMPC_depend) && + (Kind != OMPC_map)) || + ((Kind == OMPC_reduction) && !InvalidReductionId) || + ((Kind == OMPC_map) && (UnexpectedId || MapType != OMPC_MAP_unknown) && + (!MapTypeModifierSpecified || + (MapTypeModifierSpecified && MapTypeModifier == OMPC_MAP_always))) || + ((Kind == OMPC_depend) && DepKind != 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))) { @@ -787,14 +1030,18 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { << (Kind == OMPC_flush); } + // Parse ')' for linear clause with modifier. + if (NeedRParenForLinear) + LinearT.consumeClose(); + // Parse ':' linear-step (or ':' alignment). Expr *TailExpr = nullptr; const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); if (MustHaveTail) { ColonLoc = Tok.getLocation(); - ConsumeToken(); - ExprResult Tail = - Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + SourceLocation ELoc = ConsumeToken(); + ExprResult Tail = ParseAssignmentExpression(); + Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc); if (Tail.isUsable()) TailExpr = Tail.get(); else @@ -806,14 +1053,16 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { T.consumeClose(); if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) || (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) || - InvalidReductionId) + (Kind == OMPC_map && MapType == OMPC_MAP_unknown) || + InvalidReductionId) { return nullptr; + } return Actions.ActOnOpenMPVarListClause( Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(), ReductionIdScopeSpec, ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId) : DeclarationNameInfo(), - DepKind, DepLoc); + DepKind, LinearModifier, MapTypeModifier, MapType, DepLinMapLoc); } |