clang API Documentation
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