Home | History | Annotate | Download | only in Parse
      1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 /// \file
     10 /// \brief This file implements parsing of all OpenMP directives and clauses.
     11 ///
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "RAIIObjectsForParser.h"
     15 #include "clang/AST/ASTConsumer.h"
     16 #include "clang/AST/ASTContext.h"
     17 #include "clang/AST/StmtOpenMP.h"
     18 #include "clang/Parse/ParseDiagnostic.h"
     19 #include "clang/Parse/Parser.h"
     20 #include "clang/Sema/Scope.h"
     21 #include "llvm/ADT/PointerIntPair.h"
     22 using namespace clang;
     23 
     24 //===----------------------------------------------------------------------===//
     25 // OpenMP declarative directives.
     26 //===----------------------------------------------------------------------===//
     27 
     28 static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
     29   auto Tok = P.getCurToken();
     30   auto DKind =
     31       Tok.isAnnotation()
     32           ? OMPD_unknown
     33           : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
     34   if (DKind == OMPD_parallel) {
     35     Tok = P.getPreprocessor().LookAhead(0);
     36     auto SDKind =
     37         Tok.isAnnotation()
     38             ? OMPD_unknown
     39             : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
     40     if (SDKind == OMPD_for) {
     41       P.ConsumeToken();
     42       DKind = OMPD_parallel_for;
     43     } else if (SDKind == OMPD_sections) {
     44       P.ConsumeToken();
     45       DKind = OMPD_parallel_sections;
     46     }
     47   }
     48   return DKind;
     49 }
     50 
     51 /// \brief Parsing of declarative OpenMP directives.
     52 ///
     53 ///       threadprivate-directive:
     54 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
     55 ///
     56 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
     57   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
     58   ParenBraceBracketBalancer BalancerRAIIObj(*this);
     59 
     60   SourceLocation Loc = ConsumeToken();
     61   SmallVector<Expr *, 5> Identifiers;
     62   auto DKind = ParseOpenMPDirectiveKind(*this);
     63 
     64   switch (DKind) {
     65   case OMPD_threadprivate:
     66     ConsumeToken();
     67     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
     68       // The last seen token is annot_pragma_openmp_end - need to check for
     69       // extra tokens.
     70       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
     71         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
     72             << getOpenMPDirectiveName(OMPD_threadprivate);
     73         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
     74       }
     75       // Skip the last annot_pragma_openmp_end.
     76       ConsumeToken();
     77       return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
     78     }
     79     break;
     80   case OMPD_unknown:
     81     Diag(Tok, diag::err_omp_unknown_directive);
     82     break;
     83   case OMPD_parallel:
     84   case OMPD_simd:
     85   case OMPD_task:
     86   case OMPD_for:
     87   case OMPD_sections:
     88   case OMPD_section:
     89   case OMPD_single:
     90   case OMPD_parallel_for:
     91   case OMPD_parallel_sections:
     92     Diag(Tok, diag::err_omp_unexpected_directive)
     93         << getOpenMPDirectiveName(DKind);
     94     break;
     95   }
     96   SkipUntil(tok::annot_pragma_openmp_end);
     97   return DeclGroupPtrTy();
     98 }
     99 
    100 /// \brief Parsing of declarative or executable OpenMP directives.
    101 ///
    102 ///       threadprivate-directive:
    103 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
    104 ///         annot_pragma_openmp_end
    105 ///
    106 ///       executable-directive:
    107 ///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
    108 ///         'section' | 'single' | 'parallel for' | 'parallel sections' {clause}
    109 ///         annot_pragma_openmp_end
    110 ///
    111 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() {
    112   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
    113   ParenBraceBracketBalancer BalancerRAIIObj(*this);
    114   SmallVector<Expr *, 5> Identifiers;
    115   SmallVector<OMPClause *, 5> Clauses;
    116   SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
    117   FirstClauses(OMPC_unknown + 1);
    118   unsigned ScopeFlags =
    119       Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
    120   SourceLocation Loc = ConsumeToken(), EndLoc;
    121   auto DKind = ParseOpenMPDirectiveKind(*this);
    122   // Name of critical directive.
    123   DeclarationNameInfo DirName;
    124   StmtResult Directive = StmtError();
    125 
    126   switch (DKind) {
    127   case OMPD_threadprivate:
    128     ConsumeToken();
    129     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
    130       // The last seen token is annot_pragma_openmp_end - need to check for
    131       // extra tokens.
    132       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
    133         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
    134             << getOpenMPDirectiveName(OMPD_threadprivate);
    135         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    136       }
    137       DeclGroupPtrTy Res =
    138           Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
    139       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
    140     }
    141     SkipUntil(tok::annot_pragma_openmp_end);
    142     break;
    143   case OMPD_parallel:
    144   case OMPD_simd:
    145   case OMPD_for:
    146   case OMPD_sections:
    147   case OMPD_single:
    148   case OMPD_section:
    149   case OMPD_parallel_for:
    150   case OMPD_parallel_sections: {
    151     ConsumeToken();
    152 
    153     if (isOpenMPLoopDirective(DKind))
    154       ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
    155     if (isOpenMPSimdDirective(DKind))
    156       ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
    157     ParseScope OMPDirectiveScope(this, ScopeFlags);
    158     Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
    159 
    160     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
    161       OpenMPClauseKind CKind = Tok.isAnnotation()
    162                                    ? OMPC_unknown
    163                                    : getOpenMPClauseKind(PP.getSpelling(Tok));
    164       OMPClause *Clause =
    165           ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
    166       FirstClauses[CKind].setInt(true);
    167       if (Clause) {
    168         FirstClauses[CKind].setPointer(Clause);
    169         Clauses.push_back(Clause);
    170       }
    171 
    172       // Skip ',' if any.
    173       if (Tok.is(tok::comma))
    174         ConsumeToken();
    175     }
    176     // End location of the directive.
    177     EndLoc = Tok.getLocation();
    178     // Consume final annot_pragma_openmp_end.
    179     ConsumeToken();
    180 
    181     StmtResult AssociatedStmt;
    182     bool CreateDirective = true;
    183     {
    184       // The body is a block scope like in Lambdas and Blocks.
    185       Sema::CompoundScopeRAII CompoundScope(Actions);
    186       Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
    187       Actions.ActOnStartOfCompoundStmt();
    188       // Parse statement
    189       AssociatedStmt = ParseStatement();
    190       Actions.ActOnFinishOfCompoundStmt();
    191       if (!AssociatedStmt.isUsable()) {
    192         Actions.ActOnCapturedRegionError();
    193         CreateDirective = false;
    194       } else {
    195         AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
    196         CreateDirective = AssociatedStmt.isUsable();
    197       }
    198     }
    199     if (CreateDirective)
    200       Directive = Actions.ActOnOpenMPExecutableDirective(
    201           DKind, Clauses, AssociatedStmt.get(), Loc, EndLoc);
    202 
    203     // Exit scope.
    204     Actions.EndOpenMPDSABlock(Directive.get());
    205     OMPDirectiveScope.Exit();
    206     break;
    207   }
    208   case OMPD_unknown:
    209     Diag(Tok, diag::err_omp_unknown_directive);
    210     SkipUntil(tok::annot_pragma_openmp_end);
    211     break;
    212   case OMPD_task:
    213     Diag(Tok, diag::err_omp_unexpected_directive)
    214         << getOpenMPDirectiveName(DKind);
    215     SkipUntil(tok::annot_pragma_openmp_end);
    216     break;
    217   }
    218   return Directive;
    219 }
    220 
    221 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
    222 /// directive.
    223 ///
    224 ///   simple-variable-list:
    225 ///         '(' id-expression {, id-expression} ')'
    226 ///
    227 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
    228                                       SmallVectorImpl<Expr *> &VarList,
    229                                       bool AllowScopeSpecifier) {
    230   VarList.clear();
    231   // Parse '('.
    232   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
    233   if (T.expectAndConsume(diag::err_expected_lparen_after,
    234                          getOpenMPDirectiveName(Kind)))
    235     return true;
    236   bool IsCorrect = true;
    237   bool NoIdentIsFound = true;
    238 
    239   // Read tokens while ')' or annot_pragma_openmp_end is not found.
    240   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
    241     CXXScopeSpec SS;
    242     SourceLocation TemplateKWLoc;
    243     UnqualifiedId Name;
    244     // Read var name.
    245     Token PrevTok = Tok;
    246     NoIdentIsFound = false;
    247 
    248     if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
    249         ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
    250       IsCorrect = false;
    251       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
    252                 StopBeforeMatch);
    253     } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
    254                                   TemplateKWLoc, Name)) {
    255       IsCorrect = false;
    256       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
    257                 StopBeforeMatch);
    258     } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
    259                Tok.isNot(tok::annot_pragma_openmp_end)) {
    260       IsCorrect = false;
    261       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
    262                 StopBeforeMatch);
    263       Diag(PrevTok.getLocation(), diag::err_expected)
    264           << tok::identifier
    265           << SourceRange(PrevTok.getLocation(), PrevTokLocation);
    266     } else {
    267       DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
    268       ExprResult Res =
    269           Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
    270       if (Res.isUsable())
    271         VarList.push_back(Res.get());
    272     }
    273     // Consume ','.
    274     if (Tok.is(tok::comma)) {
    275       ConsumeToken();
    276     }
    277   }
    278 
    279   if (NoIdentIsFound) {
    280     Diag(Tok, diag::err_expected) << tok::identifier;
    281     IsCorrect = false;
    282   }
    283 
    284   // Parse ')'.
    285   IsCorrect = !T.consumeClose() && IsCorrect;
    286 
    287   return !IsCorrect && VarList.empty();
    288 }
    289 
    290 /// \brief Parsing of OpenMP clauses.
    291 ///
    292 ///    clause:
    293 ///       if-clause | num_threads-clause | safelen-clause | default-clause |
    294 ///       private-clause | firstprivate-clause | shared-clause | linear-clause |
    295 ///       aligned-clause | collapse-clause | lastprivate-clause |
    296 ///       reduction-clause | proc_bind-clause | schedule-clause |
    297 ///       copyin-clause | copyprivate-clause
    298 ///
    299 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
    300                                      OpenMPClauseKind CKind, bool FirstClause) {
    301   OMPClause *Clause = nullptr;
    302   bool ErrorFound = false;
    303   // Check if clause is allowed for the given directive.
    304   if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
    305     Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
    306                                                << getOpenMPDirectiveName(DKind);
    307     ErrorFound = true;
    308   }
    309 
    310   switch (CKind) {
    311   case OMPC_if:
    312   case OMPC_num_threads:
    313   case OMPC_safelen:
    314   case OMPC_collapse:
    315     // OpenMP [2.5, Restrictions]
    316     //  At most one if clause can appear on the directive.
    317     //  At most one num_threads clause can appear on the directive.
    318     // OpenMP [2.8.1, simd construct, Restrictions]
    319     //  Only one safelen  clause can appear on a simd directive.
    320     //  Only one collapse clause can appear on a simd directive.
    321     if (!FirstClause) {
    322       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
    323                                                << getOpenMPClauseName(CKind);
    324     }
    325 
    326     Clause = ParseOpenMPSingleExprClause(CKind);
    327     break;
    328   case OMPC_default:
    329   case OMPC_proc_bind:
    330     // OpenMP [2.14.3.1, Restrictions]
    331     //  Only a single default clause may be specified on a parallel, task or
    332     //  teams directive.
    333     // OpenMP [2.5, parallel Construct, Restrictions]
    334     //  At most one proc_bind clause can appear on the directive.
    335     if (!FirstClause) {
    336       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
    337                                                << getOpenMPClauseName(CKind);
    338     }
    339 
    340     Clause = ParseOpenMPSimpleClause(CKind);
    341     break;
    342   case OMPC_schedule:
    343     // OpenMP [2.7.1, Restrictions, p. 3]
    344     //  Only one schedule clause can appear on a loop directive.
    345     if (!FirstClause) {
    346       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
    347                                                << getOpenMPClauseName(CKind);
    348     }
    349 
    350     Clause = ParseOpenMPSingleExprWithArgClause(CKind);
    351     break;
    352   case OMPC_ordered:
    353   case OMPC_nowait:
    354     // OpenMP [2.7.1, Restrictions, p. 9]
    355     //  Only one ordered clause can appear on a loop directive.
    356     // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
    357     //  Only one nowait clause can appear on a for directive.
    358     if (!FirstClause) {
    359       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
    360                                                << getOpenMPClauseName(CKind);
    361     }
    362 
    363     Clause = ParseOpenMPClause(CKind);
    364     break;
    365   case OMPC_private:
    366   case OMPC_firstprivate:
    367   case OMPC_lastprivate:
    368   case OMPC_shared:
    369   case OMPC_reduction:
    370   case OMPC_linear:
    371   case OMPC_aligned:
    372   case OMPC_copyin:
    373   case OMPC_copyprivate:
    374     Clause = ParseOpenMPVarListClause(CKind);
    375     break;
    376   case OMPC_unknown:
    377     Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
    378         << getOpenMPDirectiveName(DKind);
    379     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
    380     break;
    381   case OMPC_threadprivate:
    382     Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
    383                                                << getOpenMPDirectiveName(DKind);
    384     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
    385     break;
    386   }
    387   return ErrorFound ? nullptr : Clause;
    388 }
    389 
    390 /// \brief Parsing of OpenMP clauses with single expressions like 'if',
    391 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
    392 /// 'thread_limit'.
    393 ///
    394 ///    if-clause:
    395 ///      'if' '(' expression ')'
    396 ///
    397 ///    num_threads-clause:
    398 ///      'num_threads' '(' expression ')'
    399 ///
    400 ///    safelen-clause:
    401 ///      'safelen' '(' expression ')'
    402 ///
    403 ///    collapse-clause:
    404 ///      'collapse' '(' expression ')'
    405 ///
    406 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
    407   SourceLocation Loc = ConsumeToken();
    408 
    409   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
    410   if (T.expectAndConsume(diag::err_expected_lparen_after,
    411                          getOpenMPClauseName(Kind)))
    412     return nullptr;
    413 
    414   ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
    415   ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
    416 
    417   // Parse ')'.
    418   T.consumeClose();
    419 
    420   if (Val.isInvalid())
    421     return nullptr;
    422 
    423   return Actions.ActOnOpenMPSingleExprClause(
    424       Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
    425 }
    426 
    427 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
    428 ///
    429 ///    default-clause:
    430 ///         'default' '(' 'none' | 'shared' ')
    431 ///
    432 ///    proc_bind-clause:
    433 ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
    434 ///
    435 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
    436   SourceLocation Loc = Tok.getLocation();
    437   SourceLocation LOpen = ConsumeToken();
    438   // Parse '('.
    439   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
    440   if (T.expectAndConsume(diag::err_expected_lparen_after,
    441                          getOpenMPClauseName(Kind)))
    442     return nullptr;
    443 
    444   unsigned Type = getOpenMPSimpleClauseType(
    445       Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
    446   SourceLocation TypeLoc = Tok.getLocation();
    447   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
    448       Tok.isNot(tok::annot_pragma_openmp_end))
    449     ConsumeAnyToken();
    450 
    451   // Parse ')'.
    452   T.consumeClose();
    453 
    454   return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
    455                                          Tok.getLocation());
    456 }
    457 
    458 /// \brief Parsing of OpenMP clauses like 'ordered'.
    459 ///
    460 ///    ordered-clause:
    461 ///         'ordered'
    462 ///
    463 ///    nowait-clause:
    464 ///         'nowait'
    465 ///
    466 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
    467   SourceLocation Loc = Tok.getLocation();
    468   ConsumeAnyToken();
    469 
    470   return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
    471 }
    472 
    473 
    474 /// \brief Parsing of OpenMP clauses with single expressions and some additional
    475 /// argument like 'schedule' or 'dist_schedule'.
    476 ///
    477 ///    schedule-clause:
    478 ///      'schedule' '(' kind [',' expression ] ')'
    479 ///
    480 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
    481   SourceLocation Loc = ConsumeToken();
    482   SourceLocation CommaLoc;
    483   // Parse '('.
    484   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
    485   if (T.expectAndConsume(diag::err_expected_lparen_after,
    486                          getOpenMPClauseName(Kind)))
    487     return nullptr;
    488 
    489   ExprResult Val;
    490   unsigned Type = getOpenMPSimpleClauseType(
    491       Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
    492   SourceLocation KLoc = Tok.getLocation();
    493   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
    494       Tok.isNot(tok::annot_pragma_openmp_end))
    495     ConsumeAnyToken();
    496 
    497   if (Kind == OMPC_schedule &&
    498       (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
    499        Type == OMPC_SCHEDULE_guided) &&
    500       Tok.is(tok::comma)) {
    501     CommaLoc = ConsumeAnyToken();
    502     ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
    503     Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
    504     if (Val.isInvalid())
    505       return nullptr;
    506   }
    507 
    508   // Parse ')'.
    509   T.consumeClose();
    510 
    511   return Actions.ActOnOpenMPSingleExprWithArgClause(
    512       Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
    513       T.getCloseLocation());
    514 }
    515 
    516 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
    517                              UnqualifiedId &ReductionId) {
    518   SourceLocation TemplateKWLoc;
    519   if (ReductionIdScopeSpec.isEmpty()) {
    520     auto OOK = OO_None;
    521     switch (P.getCurToken().getKind()) {
    522     case tok::plus:
    523       OOK = OO_Plus;
    524       break;
    525     case tok::minus:
    526       OOK = OO_Minus;
    527       break;
    528     case tok::star:
    529       OOK = OO_Star;
    530       break;
    531     case tok::amp:
    532       OOK = OO_Amp;
    533       break;
    534     case tok::pipe:
    535       OOK = OO_Pipe;
    536       break;
    537     case tok::caret:
    538       OOK = OO_Caret;
    539       break;
    540     case tok::ampamp:
    541       OOK = OO_AmpAmp;
    542       break;
    543     case tok::pipepipe:
    544       OOK = OO_PipePipe;
    545       break;
    546     default:
    547       break;
    548     }
    549     if (OOK != OO_None) {
    550       SourceLocation OpLoc = P.ConsumeToken();
    551       SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
    552       ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
    553       return false;
    554     }
    555   }
    556   return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
    557                               /*AllowDestructorName*/ false,
    558                               /*AllowConstructorName*/ false, ParsedType(),
    559                               TemplateKWLoc, ReductionId);
    560 }
    561 
    562 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
    563 /// 'shared', 'copyin', or 'reduction'.
    564 ///
    565 ///    private-clause:
    566 ///       'private' '(' list ')'
    567 ///    firstprivate-clause:
    568 ///       'firstprivate' '(' list ')'
    569 ///    lastprivate-clause:
    570 ///       'lastprivate' '(' list ')'
    571 ///    shared-clause:
    572 ///       'shared' '(' list ')'
    573 ///    linear-clause:
    574 ///       'linear' '(' list [ ':' linear-step ] ')'
    575 ///    aligned-clause:
    576 ///       'aligned' '(' list [ ':' alignment ] ')'
    577 ///    reduction-clause:
    578 ///       'reduction' '(' reduction-identifier ':' list ')'
    579 ///
    580 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
    581   SourceLocation Loc = Tok.getLocation();
    582   SourceLocation LOpen = ConsumeToken();
    583   SourceLocation ColonLoc = SourceLocation();
    584   // Optional scope specifier and unqualified id for reduction identifier.
    585   CXXScopeSpec ReductionIdScopeSpec;
    586   UnqualifiedId ReductionId;
    587   bool InvalidReductionId = false;
    588   // Parse '('.
    589   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
    590   if (T.expectAndConsume(diag::err_expected_lparen_after,
    591                          getOpenMPClauseName(Kind)))
    592     return nullptr;
    593 
    594   // Handle reduction-identifier for reduction clause.
    595   if (Kind == OMPC_reduction) {
    596     ColonProtectionRAIIObject ColonRAII(*this);
    597     if (getLangOpts().CPlusPlus) {
    598       ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
    599     }
    600     InvalidReductionId =
    601         ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
    602     if (InvalidReductionId) {
    603       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
    604                 StopBeforeMatch);
    605     }
    606     if (Tok.is(tok::colon)) {
    607       ColonLoc = ConsumeToken();
    608     } else {
    609       Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
    610     }
    611   }
    612 
    613   SmallVector<Expr *, 5> Vars;
    614   bool IsComma = !InvalidReductionId;
    615   const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
    616   while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
    617                      Tok.isNot(tok::annot_pragma_openmp_end))) {
    618     ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
    619     // Parse variable
    620     ExprResult VarExpr = ParseAssignmentExpression();
    621     if (VarExpr.isUsable()) {
    622       Vars.push_back(VarExpr.get());
    623     } else {
    624       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
    625                 StopBeforeMatch);
    626     }
    627     // Skip ',' if any
    628     IsComma = Tok.is(tok::comma);
    629     if (IsComma)
    630       ConsumeToken();
    631     else if (Tok.isNot(tok::r_paren) &&
    632              Tok.isNot(tok::annot_pragma_openmp_end) &&
    633              (!MayHaveTail || Tok.isNot(tok::colon)))
    634       Diag(Tok, diag::err_omp_expected_punc) << getOpenMPClauseName(Kind);
    635   }
    636 
    637   // Parse ':' linear-step (or ':' alignment).
    638   Expr *TailExpr = nullptr;
    639   const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
    640   if (MustHaveTail) {
    641     ColonLoc = Tok.getLocation();
    642     ConsumeToken();
    643     ExprResult Tail = ParseAssignmentExpression();
    644     if (Tail.isUsable())
    645       TailExpr = Tail.get();
    646     else
    647       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
    648                 StopBeforeMatch);
    649   }
    650 
    651   // Parse ')'.
    652   T.consumeClose();
    653   if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
    654     return nullptr;
    655 
    656   return Actions.ActOnOpenMPVarListClause(
    657       Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
    658       ReductionIdScopeSpec,
    659       ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
    660                             : DeclarationNameInfo());
    661 }
    662 
    663