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