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