clang API Documentation

ParseOpenMP.cpp
Go to the documentation of this file.
00001 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 /// \file
00010 /// \brief This file implements parsing of all OpenMP directives and clauses.
00011 ///
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "RAIIObjectsForParser.h"
00015 #include "clang/AST/ASTConsumer.h"
00016 #include "clang/AST/ASTContext.h"
00017 #include "clang/AST/StmtOpenMP.h"
00018 #include "clang/Parse/ParseDiagnostic.h"
00019 #include "clang/Parse/Parser.h"
00020 #include "clang/Sema/Scope.h"
00021 #include "llvm/ADT/PointerIntPair.h"
00022 using namespace clang;
00023 
00024 //===----------------------------------------------------------------------===//
00025 // OpenMP declarative directives.
00026 //===----------------------------------------------------------------------===//
00027 
00028 static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) {
00029   // Array of foldings: F[i][0] F[i][1] ===> F[i][2].
00030   // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
00031   // TODO: add other combined directives in topological order.
00032   const OpenMPDirectiveKind F[][3] = {
00033     { OMPD_for, OMPD_simd, OMPD_for_simd },
00034     { OMPD_parallel, OMPD_for, OMPD_parallel_for },
00035     { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
00036     { OMPD_parallel, OMPD_sections, OMPD_parallel_sections }
00037   };
00038   auto Tok = P.getCurToken();
00039   auto DKind =
00040       Tok.isAnnotation()
00041           ? OMPD_unknown
00042           : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
00043   for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
00044     if (DKind == F[i][0]) {
00045       Tok = P.getPreprocessor().LookAhead(0);
00046       auto SDKind =
00047           Tok.isAnnotation()
00048               ? OMPD_unknown
00049               : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok));
00050       if (SDKind == F[i][1]) {
00051         P.ConsumeToken();
00052         DKind = F[i][2];
00053       }
00054     }
00055   }
00056   return DKind;
00057 }
00058 
00059 /// \brief Parsing of declarative OpenMP directives.
00060 ///
00061 ///       threadprivate-directive:
00062 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
00063 ///
00064 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() {
00065   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
00066   ParenBraceBracketBalancer BalancerRAIIObj(*this);
00067 
00068   SourceLocation Loc = ConsumeToken();
00069   SmallVector<Expr *, 5> Identifiers;
00070   auto DKind = ParseOpenMPDirectiveKind(*this);
00071 
00072   switch (DKind) {
00073   case OMPD_threadprivate:
00074     ConsumeToken();
00075     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) {
00076       // The last seen token is annot_pragma_openmp_end - need to check for
00077       // extra tokens.
00078       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
00079         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
00080             << getOpenMPDirectiveName(OMPD_threadprivate);
00081         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
00082       }
00083       // Skip the last annot_pragma_openmp_end.
00084       ConsumeToken();
00085       return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
00086     }
00087     break;
00088   case OMPD_unknown:
00089     Diag(Tok, diag::err_omp_unknown_directive);
00090     break;
00091   case OMPD_parallel:
00092   case OMPD_simd:
00093   case OMPD_task:
00094   case OMPD_taskyield:
00095   case OMPD_barrier:
00096   case OMPD_taskwait:
00097   case OMPD_flush:
00098   case OMPD_for:
00099   case OMPD_for_simd:
00100   case OMPD_sections:
00101   case OMPD_section:
00102   case OMPD_single:
00103   case OMPD_master:
00104   case OMPD_ordered:
00105   case OMPD_critical:
00106   case OMPD_parallel_for:
00107   case OMPD_parallel_for_simd:
00108   case OMPD_parallel_sections:
00109   case OMPD_atomic:
00110   case OMPD_target:
00111   case OMPD_teams:
00112     Diag(Tok, diag::err_omp_unexpected_directive)
00113         << getOpenMPDirectiveName(DKind);
00114     break;
00115   }
00116   SkipUntil(tok::annot_pragma_openmp_end);
00117   return DeclGroupPtrTy();
00118 }
00119 
00120 /// \brief Parsing of declarative or executable OpenMP directives.
00121 ///
00122 ///       threadprivate-directive:
00123 ///         annot_pragma_openmp 'threadprivate' simple-variable-list
00124 ///         annot_pragma_openmp_end
00125 ///
00126 ///       executable-directive:
00127 ///         annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
00128 ///         'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
00129 ///         'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
00130 ///         'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
00131 ///         'for simd' | 'parallel for simd' | 'target' | 'teams' {clause}
00132 ///         annot_pragma_openmp_end
00133 ///
00134 StmtResult
00135 Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) {
00136   assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
00137   ParenBraceBracketBalancer BalancerRAIIObj(*this);
00138   SmallVector<Expr *, 5> Identifiers;
00139   SmallVector<OMPClause *, 5> Clauses;
00140   SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
00141   FirstClauses(OMPC_unknown + 1);
00142   unsigned ScopeFlags =
00143       Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope;
00144   SourceLocation Loc = ConsumeToken(), EndLoc;
00145   auto DKind = ParseOpenMPDirectiveKind(*this);
00146   // Name of critical directive.
00147   DeclarationNameInfo DirName;
00148   StmtResult Directive = StmtError();
00149   bool HasAssociatedStatement = true;
00150   bool FlushHasClause = false;
00151 
00152   switch (DKind) {
00153   case OMPD_threadprivate:
00154     ConsumeToken();
00155     if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) {
00156       // The last seen token is annot_pragma_openmp_end - need to check for
00157       // extra tokens.
00158       if (Tok.isNot(tok::annot_pragma_openmp_end)) {
00159         Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
00160             << getOpenMPDirectiveName(OMPD_threadprivate);
00161         SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
00162       }
00163       DeclGroupPtrTy Res =
00164           Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers);
00165       Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
00166     }
00167     SkipUntil(tok::annot_pragma_openmp_end);
00168     break;
00169   case OMPD_flush:
00170     if (PP.LookAhead(0).is(tok::l_paren)) {
00171       FlushHasClause = true;
00172       // Push copy of the current token back to stream to properly parse
00173       // pseudo-clause OMPFlushClause.
00174       PP.EnterToken(Tok);
00175     }
00176   case OMPD_taskyield:
00177   case OMPD_barrier:
00178   case OMPD_taskwait:
00179     if (!StandAloneAllowed) {
00180       Diag(Tok, diag::err_omp_immediate_directive)
00181           << getOpenMPDirectiveName(DKind);
00182     }
00183     HasAssociatedStatement = false;
00184     // Fall through for further analysis.
00185   case OMPD_parallel:
00186   case OMPD_simd:
00187   case OMPD_for:
00188   case OMPD_for_simd:
00189   case OMPD_sections:
00190   case OMPD_single:
00191   case OMPD_section:
00192   case OMPD_master:
00193   case OMPD_critical:
00194   case OMPD_parallel_for:
00195   case OMPD_parallel_for_simd:
00196   case OMPD_parallel_sections:
00197   case OMPD_task:
00198   case OMPD_ordered:
00199   case OMPD_atomic:
00200   case OMPD_target:
00201   case OMPD_teams: {
00202     ConsumeToken();
00203     // Parse directive name of the 'critical' directive if any.
00204     if (DKind == OMPD_critical) {
00205       BalancedDelimiterTracker T(*this, tok::l_paren,
00206                                  tok::annot_pragma_openmp_end);
00207       if (!T.consumeOpen()) {
00208         if (Tok.isAnyIdentifier()) {
00209           DirName =
00210               DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
00211           ConsumeAnyToken();
00212         } else {
00213           Diag(Tok, diag::err_omp_expected_identifier_for_critical);
00214         }
00215         T.consumeClose();
00216       }
00217     }
00218 
00219     if (isOpenMPLoopDirective(DKind))
00220       ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
00221     if (isOpenMPSimdDirective(DKind))
00222       ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
00223     ParseScope OMPDirectiveScope(this, ScopeFlags);
00224     Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
00225 
00226     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
00227       OpenMPClauseKind CKind =
00228           Tok.isAnnotation()
00229               ? OMPC_unknown
00230               : FlushHasClause ? OMPC_flush
00231                                : getOpenMPClauseKind(PP.getSpelling(Tok));
00232       FlushHasClause = false;
00233       OMPClause *Clause =
00234           ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
00235       FirstClauses[CKind].setInt(true);
00236       if (Clause) {
00237         FirstClauses[CKind].setPointer(Clause);
00238         Clauses.push_back(Clause);
00239       }
00240 
00241       // Skip ',' if any.
00242       if (Tok.is(tok::comma))
00243         ConsumeToken();
00244     }
00245     // End location of the directive.
00246     EndLoc = Tok.getLocation();
00247     // Consume final annot_pragma_openmp_end.
00248     ConsumeToken();
00249 
00250     StmtResult AssociatedStmt;
00251     bool CreateDirective = true;
00252     if (HasAssociatedStatement) {
00253       // The body is a block scope like in Lambdas and Blocks.
00254       Sema::CompoundScopeRAII CompoundScope(Actions);
00255       Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
00256       Actions.ActOnStartOfCompoundStmt();
00257       // Parse statement
00258       AssociatedStmt = ParseStatement();
00259       Actions.ActOnFinishOfCompoundStmt();
00260       if (!AssociatedStmt.isUsable()) {
00261         Actions.ActOnCapturedRegionError();
00262         CreateDirective = false;
00263       } else {
00264         AssociatedStmt = Actions.ActOnCapturedRegionEnd(AssociatedStmt.get());
00265         CreateDirective = AssociatedStmt.isUsable();
00266       }
00267     }
00268     if (CreateDirective)
00269       Directive = Actions.ActOnOpenMPExecutableDirective(
00270           DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
00271 
00272     // Exit scope.
00273     Actions.EndOpenMPDSABlock(Directive.get());
00274     OMPDirectiveScope.Exit();
00275     break;
00276   }
00277   case OMPD_unknown:
00278     Diag(Tok, diag::err_omp_unknown_directive);
00279     SkipUntil(tok::annot_pragma_openmp_end);
00280     break;
00281   }
00282   return Directive;
00283 }
00284 
00285 /// \brief Parses list of simple variables for '#pragma omp threadprivate'
00286 /// directive.
00287 ///
00288 ///   simple-variable-list:
00289 ///         '(' id-expression {, id-expression} ')'
00290 ///
00291 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind,
00292                                       SmallVectorImpl<Expr *> &VarList,
00293                                       bool AllowScopeSpecifier) {
00294   VarList.clear();
00295   // Parse '('.
00296   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
00297   if (T.expectAndConsume(diag::err_expected_lparen_after,
00298                          getOpenMPDirectiveName(Kind)))
00299     return true;
00300   bool IsCorrect = true;
00301   bool NoIdentIsFound = true;
00302 
00303   // Read tokens while ')' or annot_pragma_openmp_end is not found.
00304   while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
00305     CXXScopeSpec SS;
00306     SourceLocation TemplateKWLoc;
00307     UnqualifiedId Name;
00308     // Read var name.
00309     Token PrevTok = Tok;
00310     NoIdentIsFound = false;
00311 
00312     if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
00313         ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false)) {
00314       IsCorrect = false;
00315       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
00316                 StopBeforeMatch);
00317     } else if (ParseUnqualifiedId(SS, false, false, false, ParsedType(),
00318                                   TemplateKWLoc, Name)) {
00319       IsCorrect = false;
00320       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
00321                 StopBeforeMatch);
00322     } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
00323                Tok.isNot(tok::annot_pragma_openmp_end)) {
00324       IsCorrect = false;
00325       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
00326                 StopBeforeMatch);
00327       Diag(PrevTok.getLocation(), diag::err_expected)
00328           << tok::identifier
00329           << SourceRange(PrevTok.getLocation(), PrevTokLocation);
00330     } else {
00331       DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name);
00332       ExprResult Res =
00333           Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo);
00334       if (Res.isUsable())
00335         VarList.push_back(Res.get());
00336     }
00337     // Consume ','.
00338     if (Tok.is(tok::comma)) {
00339       ConsumeToken();
00340     }
00341   }
00342 
00343   if (NoIdentIsFound) {
00344     Diag(Tok, diag::err_expected) << tok::identifier;
00345     IsCorrect = false;
00346   }
00347 
00348   // Parse ')'.
00349   IsCorrect = !T.consumeClose() && IsCorrect;
00350 
00351   return !IsCorrect && VarList.empty();
00352 }
00353 
00354 /// \brief Parsing of OpenMP clauses.
00355 ///
00356 ///    clause:
00357 ///       if-clause | final-clause | num_threads-clause | safelen-clause |
00358 ///       default-clause | private-clause | firstprivate-clause | shared-clause
00359 ///       | linear-clause | aligned-clause | collapse-clause |
00360 ///       lastprivate-clause | reduction-clause | proc_bind-clause |
00361 ///       schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
00362 ///       mergeable-clause | flush-clause | read-clause | write-clause |
00363 ///       update-clause | capture-clause | seq_cst-clause
00364 ///
00365 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
00366                                      OpenMPClauseKind CKind, bool FirstClause) {
00367   OMPClause *Clause = nullptr;
00368   bool ErrorFound = false;
00369   // Check if clause is allowed for the given directive.
00370   if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
00371     Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
00372                                                << getOpenMPDirectiveName(DKind);
00373     ErrorFound = true;
00374   }
00375 
00376   switch (CKind) {
00377   case OMPC_if:
00378   case OMPC_final:
00379   case OMPC_num_threads:
00380   case OMPC_safelen:
00381   case OMPC_collapse:
00382     // OpenMP [2.5, Restrictions]
00383     //  At most one if clause can appear on the directive.
00384     //  At most one num_threads clause can appear on the directive.
00385     // OpenMP [2.8.1, simd construct, Restrictions]
00386     //  Only one safelen  clause can appear on a simd directive.
00387     //  Only one collapse clause can appear on a simd directive.
00388     // OpenMP [2.11.1, task Construct, Restrictions]
00389     //  At most one if clause can appear on the directive.
00390     //  At most one final clause can appear on the directive.
00391     if (!FirstClause) {
00392       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
00393                                                << getOpenMPClauseName(CKind);
00394       ErrorFound = true;
00395     }
00396 
00397     Clause = ParseOpenMPSingleExprClause(CKind);
00398     break;
00399   case OMPC_default:
00400   case OMPC_proc_bind:
00401     // OpenMP [2.14.3.1, Restrictions]
00402     //  Only a single default clause may be specified on a parallel, task or
00403     //  teams directive.
00404     // OpenMP [2.5, parallel Construct, Restrictions]
00405     //  At most one proc_bind clause can appear on the directive.
00406     if (!FirstClause) {
00407       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
00408                                                << getOpenMPClauseName(CKind);
00409       ErrorFound = true;
00410     }
00411 
00412     Clause = ParseOpenMPSimpleClause(CKind);
00413     break;
00414   case OMPC_schedule:
00415     // OpenMP [2.7.1, Restrictions, p. 3]
00416     //  Only one schedule clause can appear on a loop directive.
00417     if (!FirstClause) {
00418       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
00419                                                << getOpenMPClauseName(CKind);
00420       ErrorFound = true;
00421     }
00422 
00423     Clause = ParseOpenMPSingleExprWithArgClause(CKind);
00424     break;
00425   case OMPC_ordered:
00426   case OMPC_nowait:
00427   case OMPC_untied:
00428   case OMPC_mergeable:
00429   case OMPC_read:
00430   case OMPC_write:
00431   case OMPC_update:
00432   case OMPC_capture:
00433   case OMPC_seq_cst:
00434     // OpenMP [2.7.1, Restrictions, p. 9]
00435     //  Only one ordered clause can appear on a loop directive.
00436     // OpenMP [2.7.1, Restrictions, C/C++, p. 4]
00437     //  Only one nowait clause can appear on a for directive.
00438     if (!FirstClause) {
00439       Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind)
00440                                                << getOpenMPClauseName(CKind);
00441       ErrorFound = true;
00442     }
00443 
00444     Clause = ParseOpenMPClause(CKind);
00445     break;
00446   case OMPC_private:
00447   case OMPC_firstprivate:
00448   case OMPC_lastprivate:
00449   case OMPC_shared:
00450   case OMPC_reduction:
00451   case OMPC_linear:
00452   case OMPC_aligned:
00453   case OMPC_copyin:
00454   case OMPC_copyprivate:
00455   case OMPC_flush:
00456     Clause = ParseOpenMPVarListClause(CKind);
00457     break;
00458   case OMPC_unknown:
00459     Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
00460         << getOpenMPDirectiveName(DKind);
00461     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
00462     break;
00463   case OMPC_threadprivate:
00464     Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
00465                                                << getOpenMPDirectiveName(DKind);
00466     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
00467     break;
00468   }
00469   return ErrorFound ? nullptr : Clause;
00470 }
00471 
00472 /// \brief Parsing of OpenMP clauses with single expressions like 'if',
00473 /// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or
00474 /// 'thread_limit'.
00475 ///
00476 ///    if-clause:
00477 ///      'if' '(' expression ')'
00478 ///
00479 ///    final-clause:
00480 ///      'final' '(' expression ')'
00481 ///
00482 ///    num_threads-clause:
00483 ///      'num_threads' '(' expression ')'
00484 ///
00485 ///    safelen-clause:
00486 ///      'safelen' '(' expression ')'
00487 ///
00488 ///    collapse-clause:
00489 ///      'collapse' '(' expression ')'
00490 ///
00491 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) {
00492   SourceLocation Loc = ConsumeToken();
00493 
00494   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
00495   if (T.expectAndConsume(diag::err_expected_lparen_after,
00496                          getOpenMPClauseName(Kind)))
00497     return nullptr;
00498 
00499   ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
00500   ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
00501 
00502   // Parse ')'.
00503   T.consumeClose();
00504 
00505   if (Val.isInvalid())
00506     return nullptr;
00507 
00508   return Actions.ActOnOpenMPSingleExprClause(
00509       Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation());
00510 }
00511 
00512 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
00513 ///
00514 ///    default-clause:
00515 ///         'default' '(' 'none' | 'shared' ')
00516 ///
00517 ///    proc_bind-clause:
00518 ///         'proc_bind' '(' 'master' | 'close' | 'spread' ')
00519 ///
00520 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) {
00521   SourceLocation Loc = Tok.getLocation();
00522   SourceLocation LOpen = ConsumeToken();
00523   // Parse '('.
00524   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
00525   if (T.expectAndConsume(diag::err_expected_lparen_after,
00526                          getOpenMPClauseName(Kind)))
00527     return nullptr;
00528 
00529   unsigned Type = getOpenMPSimpleClauseType(
00530       Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
00531   SourceLocation TypeLoc = Tok.getLocation();
00532   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
00533       Tok.isNot(tok::annot_pragma_openmp_end))
00534     ConsumeAnyToken();
00535 
00536   // Parse ')'.
00537   T.consumeClose();
00538 
00539   return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
00540                                          Tok.getLocation());
00541 }
00542 
00543 /// \brief Parsing of OpenMP clauses like 'ordered'.
00544 ///
00545 ///    ordered-clause:
00546 ///         'ordered'
00547 ///
00548 ///    nowait-clause:
00549 ///         'nowait'
00550 ///
00551 ///    untied-clause:
00552 ///         'untied'
00553 ///
00554 ///    mergeable-clause:
00555 ///         'mergeable'
00556 ///
00557 ///    read-clause:
00558 ///         'read'
00559 ///
00560 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) {
00561   SourceLocation Loc = Tok.getLocation();
00562   ConsumeAnyToken();
00563 
00564   return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
00565 }
00566 
00567 
00568 /// \brief Parsing of OpenMP clauses with single expressions and some additional
00569 /// argument like 'schedule' or 'dist_schedule'.
00570 ///
00571 ///    schedule-clause:
00572 ///      'schedule' '(' kind [',' expression ] ')'
00573 ///
00574 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) {
00575   SourceLocation Loc = ConsumeToken();
00576   SourceLocation CommaLoc;
00577   // Parse '('.
00578   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
00579   if (T.expectAndConsume(diag::err_expected_lparen_after,
00580                          getOpenMPClauseName(Kind)))
00581     return nullptr;
00582 
00583   ExprResult Val;
00584   unsigned Type = getOpenMPSimpleClauseType(
00585       Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
00586   SourceLocation KLoc = Tok.getLocation();
00587   if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
00588       Tok.isNot(tok::annot_pragma_openmp_end))
00589     ConsumeAnyToken();
00590 
00591   if (Kind == OMPC_schedule &&
00592       (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic ||
00593        Type == OMPC_SCHEDULE_guided) &&
00594       Tok.is(tok::comma)) {
00595     CommaLoc = ConsumeAnyToken();
00596     ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
00597     Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
00598     if (Val.isInvalid())
00599       return nullptr;
00600   }
00601 
00602   // Parse ')'.
00603   T.consumeClose();
00604 
00605   return Actions.ActOnOpenMPSingleExprWithArgClause(
00606       Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc,
00607       T.getCloseLocation());
00608 }
00609 
00610 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
00611                              UnqualifiedId &ReductionId) {
00612   SourceLocation TemplateKWLoc;
00613   if (ReductionIdScopeSpec.isEmpty()) {
00614     auto OOK = OO_None;
00615     switch (P.getCurToken().getKind()) {
00616     case tok::plus:
00617       OOK = OO_Plus;
00618       break;
00619     case tok::minus:
00620       OOK = OO_Minus;
00621       break;
00622     case tok::star:
00623       OOK = OO_Star;
00624       break;
00625     case tok::amp:
00626       OOK = OO_Amp;
00627       break;
00628     case tok::pipe:
00629       OOK = OO_Pipe;
00630       break;
00631     case tok::caret:
00632       OOK = OO_Caret;
00633       break;
00634     case tok::ampamp:
00635       OOK = OO_AmpAmp;
00636       break;
00637     case tok::pipepipe:
00638       OOK = OO_PipePipe;
00639       break;
00640     default:
00641       break;
00642     }
00643     if (OOK != OO_None) {
00644       SourceLocation OpLoc = P.ConsumeToken();
00645       SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
00646       ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
00647       return false;
00648     }
00649   }
00650   return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
00651                               /*AllowDestructorName*/ false,
00652                               /*AllowConstructorName*/ false, ParsedType(),
00653                               TemplateKWLoc, ReductionId);
00654 }
00655 
00656 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
00657 /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'.
00658 ///
00659 ///    private-clause:
00660 ///       'private' '(' list ')'
00661 ///    firstprivate-clause:
00662 ///       'firstprivate' '(' list ')'
00663 ///    lastprivate-clause:
00664 ///       'lastprivate' '(' list ')'
00665 ///    shared-clause:
00666 ///       'shared' '(' list ')'
00667 ///    linear-clause:
00668 ///       'linear' '(' list [ ':' linear-step ] ')'
00669 ///    aligned-clause:
00670 ///       'aligned' '(' list [ ':' alignment ] ')'
00671 ///    reduction-clause:
00672 ///       'reduction' '(' reduction-identifier ':' list ')'
00673 ///    copyprivate-clause:
00674 ///       'copyprivate' '(' list ')'
00675 ///    flush-clause:
00676 ///       'flush' '(' list ')'
00677 ///
00678 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) {
00679   SourceLocation Loc = Tok.getLocation();
00680   SourceLocation LOpen = ConsumeToken();
00681   SourceLocation ColonLoc = SourceLocation();
00682   // Optional scope specifier and unqualified id for reduction identifier.
00683   CXXScopeSpec ReductionIdScopeSpec;
00684   UnqualifiedId ReductionId;
00685   bool InvalidReductionId = false;
00686   // Parse '('.
00687   BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
00688   if (T.expectAndConsume(diag::err_expected_lparen_after,
00689                          getOpenMPClauseName(Kind)))
00690     return nullptr;
00691 
00692   // Handle reduction-identifier for reduction clause.
00693   if (Kind == OMPC_reduction) {
00694     ColonProtectionRAIIObject ColonRAII(*this);
00695     if (getLangOpts().CPlusPlus) {
00696       ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, ParsedType(), false);
00697     }
00698     InvalidReductionId =
00699         ParseReductionId(*this, ReductionIdScopeSpec, ReductionId);
00700     if (InvalidReductionId) {
00701       SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
00702                 StopBeforeMatch);
00703     }
00704     if (Tok.is(tok::colon)) {
00705       ColonLoc = ConsumeToken();
00706     } else {
00707       Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
00708     }
00709   }
00710 
00711   SmallVector<Expr *, 5> Vars;
00712   bool IsComma = !InvalidReductionId;
00713   const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
00714   while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
00715                      Tok.isNot(tok::annot_pragma_openmp_end))) {
00716     ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
00717     // Parse variable
00718     ExprResult VarExpr = ParseAssignmentExpression();
00719     if (VarExpr.isUsable()) {
00720       Vars.push_back(VarExpr.get());
00721     } else {
00722       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
00723                 StopBeforeMatch);
00724     }
00725     // Skip ',' if any
00726     IsComma = Tok.is(tok::comma);
00727     if (IsComma)
00728       ConsumeToken();
00729     else if (Tok.isNot(tok::r_paren) &&
00730              Tok.isNot(tok::annot_pragma_openmp_end) &&
00731              (!MayHaveTail || Tok.isNot(tok::colon)))
00732       Diag(Tok, diag::err_omp_expected_punc)
00733           << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
00734                                    : getOpenMPClauseName(Kind))
00735           << (Kind == OMPC_flush);
00736   }
00737 
00738   // Parse ':' linear-step (or ':' alignment).
00739   Expr *TailExpr = nullptr;
00740   const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
00741   if (MustHaveTail) {
00742     ColonLoc = Tok.getLocation();
00743     ConsumeToken();
00744     ExprResult Tail = ParseAssignmentExpression();
00745     if (Tail.isUsable())
00746       TailExpr = Tail.get();
00747     else
00748       SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
00749                 StopBeforeMatch);
00750   }
00751 
00752   // Parse ')'.
00753   T.consumeClose();
00754   if (Vars.empty() || (MustHaveTail && !TailExpr) || InvalidReductionId)
00755     return nullptr;
00756 
00757   return Actions.ActOnOpenMPVarListClause(
00758       Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(),
00759       ReductionIdScopeSpec,
00760       ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId)
00761                             : DeclarationNameInfo());
00762 }
00763