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