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