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