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