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 23 using namespace clang; 24 25 //===----------------------------------------------------------------------===// 26 // OpenMP declarative directives. 27 //===----------------------------------------------------------------------===// 28 29 namespace { 30 enum OpenMPDirectiveKindEx { 31 OMPD_cancellation = OMPD_unknown + 1, 32 OMPD_data, 33 OMPD_enter, 34 OMPD_exit, 35 OMPD_point, 36 OMPD_target_enter, 37 OMPD_target_exit 38 }; 39 } // namespace 40 41 // Map token string to extended OMP token kind that are 42 // OpenMPDirectiveKind + OpenMPDirectiveKindEx. 43 static unsigned getOpenMPDirectiveKindEx(StringRef S) { 44 auto DKind = getOpenMPDirectiveKind(S); 45 if (DKind != OMPD_unknown) 46 return DKind; 47 48 return llvm::StringSwitch<unsigned>(S) 49 .Case("cancellation", OMPD_cancellation) 50 .Case("data", OMPD_data) 51 .Case("enter", OMPD_enter) 52 .Case("exit", OMPD_exit) 53 .Case("point", OMPD_point) 54 .Default(OMPD_unknown); 55 } 56 57 static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { 58 // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. 59 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd 60 // TODO: add other combined directives in topological order. 61 static const unsigned F[][3] = { 62 { OMPD_cancellation, OMPD_point, OMPD_cancellation_point }, 63 { OMPD_target, OMPD_data, OMPD_target_data }, 64 { OMPD_target, OMPD_enter, OMPD_target_enter }, 65 { OMPD_target, OMPD_exit, OMPD_target_exit }, 66 { OMPD_target_enter, OMPD_data, OMPD_target_enter_data }, 67 { OMPD_target_exit, OMPD_data, OMPD_target_exit_data }, 68 { OMPD_for, OMPD_simd, OMPD_for_simd }, 69 { OMPD_parallel, OMPD_for, OMPD_parallel_for }, 70 { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd }, 71 { OMPD_parallel, OMPD_sections, OMPD_parallel_sections }, 72 { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd }, 73 { OMPD_target, OMPD_parallel, OMPD_target_parallel }, 74 { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for } 75 }; 76 auto Tok = P.getCurToken(); 77 unsigned DKind = 78 Tok.isAnnotation() 79 ? static_cast<unsigned>(OMPD_unknown) 80 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 81 if (DKind == OMPD_unknown) 82 return OMPD_unknown; 83 84 for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) { 85 if (DKind != F[i][0]) 86 continue; 87 88 Tok = P.getPreprocessor().LookAhead(0); 89 unsigned SDKind = 90 Tok.isAnnotation() 91 ? static_cast<unsigned>(OMPD_unknown) 92 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 93 if (SDKind == OMPD_unknown) 94 continue; 95 96 if (SDKind == F[i][1]) { 97 P.ConsumeToken(); 98 DKind = F[i][2]; 99 } 100 } 101 return DKind <= OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind) 102 : OMPD_unknown; 103 } 104 105 /// \brief Parsing of declarative OpenMP directives. 106 /// 107 /// threadprivate-directive: 108 /// annot_pragma_openmp 'threadprivate' simple-variable-list 109 /// 110 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { 111 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 112 ParenBraceBracketBalancer BalancerRAIIObj(*this); 113 114 SourceLocation Loc = ConsumeToken(); 115 SmallVector<Expr *, 5> Identifiers; 116 auto DKind = ParseOpenMPDirectiveKind(*this); 117 118 switch (DKind) { 119 case OMPD_threadprivate: 120 ConsumeToken(); 121 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, true)) { 122 // The last seen token is annot_pragma_openmp_end - need to check for 123 // extra tokens. 124 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 125 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 126 << getOpenMPDirectiveName(OMPD_threadprivate); 127 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 128 } 129 // Skip the last annot_pragma_openmp_end. 130 ConsumeToken(); 131 return Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers); 132 } 133 break; 134 case OMPD_unknown: 135 Diag(Tok, diag::err_omp_unknown_directive); 136 break; 137 case OMPD_parallel: 138 case OMPD_simd: 139 case OMPD_task: 140 case OMPD_taskyield: 141 case OMPD_barrier: 142 case OMPD_taskwait: 143 case OMPD_taskgroup: 144 case OMPD_flush: 145 case OMPD_for: 146 case OMPD_for_simd: 147 case OMPD_sections: 148 case OMPD_section: 149 case OMPD_single: 150 case OMPD_master: 151 case OMPD_ordered: 152 case OMPD_critical: 153 case OMPD_parallel_for: 154 case OMPD_parallel_for_simd: 155 case OMPD_parallel_sections: 156 case OMPD_atomic: 157 case OMPD_target: 158 case OMPD_teams: 159 case OMPD_cancellation_point: 160 case OMPD_cancel: 161 case OMPD_target_data: 162 case OMPD_target_enter_data: 163 case OMPD_target_exit_data: 164 case OMPD_target_parallel: 165 case OMPD_target_parallel_for: 166 case OMPD_taskloop: 167 case OMPD_taskloop_simd: 168 case OMPD_distribute: 169 Diag(Tok, diag::err_omp_unexpected_directive) 170 << getOpenMPDirectiveName(DKind); 171 break; 172 } 173 SkipUntil(tok::annot_pragma_openmp_end); 174 return nullptr; 175 } 176 177 /// \brief Parsing of declarative or executable OpenMP directives. 178 /// 179 /// threadprivate-directive: 180 /// annot_pragma_openmp 'threadprivate' simple-variable-list 181 /// annot_pragma_openmp_end 182 /// 183 /// executable-directive: 184 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 185 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 186 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | 187 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | 188 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' | 189 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 190 /// 'distribute' | 'target enter data' | 'target exit data' | 191 /// 'target parallel' | 'target parallel for' {clause} 192 /// annot_pragma_openmp_end 193 /// 194 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( 195 AllowedContsructsKind Allowed) { 196 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 197 ParenBraceBracketBalancer BalancerRAIIObj(*this); 198 SmallVector<Expr *, 5> Identifiers; 199 SmallVector<OMPClause *, 5> Clauses; 200 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> 201 FirstClauses(OMPC_unknown + 1); 202 unsigned ScopeFlags = 203 Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope; 204 SourceLocation Loc = ConsumeToken(), EndLoc; 205 auto DKind = ParseOpenMPDirectiveKind(*this); 206 OpenMPDirectiveKind CancelRegion = OMPD_unknown; 207 // Name of critical directive. 208 DeclarationNameInfo DirName; 209 StmtResult Directive = StmtError(); 210 bool HasAssociatedStatement = true; 211 bool FlushHasClause = false; 212 213 switch (DKind) { 214 case OMPD_threadprivate: 215 if (Allowed != ACK_Any) { 216 Diag(Tok, diag::err_omp_immediate_directive) 217 << getOpenMPDirectiveName(DKind) << 0; 218 } 219 ConsumeToken(); 220 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Identifiers, false)) { 221 // The last seen token is annot_pragma_openmp_end - need to check for 222 // extra tokens. 223 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 224 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 225 << getOpenMPDirectiveName(OMPD_threadprivate); 226 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 227 } 228 DeclGroupPtrTy Res = 229 Actions.ActOnOpenMPThreadprivateDirective(Loc, Identifiers); 230 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 231 } 232 SkipUntil(tok::annot_pragma_openmp_end); 233 break; 234 case OMPD_flush: 235 if (PP.LookAhead(0).is(tok::l_paren)) { 236 FlushHasClause = true; 237 // Push copy of the current token back to stream to properly parse 238 // pseudo-clause OMPFlushClause. 239 PP.EnterToken(Tok); 240 } 241 case OMPD_taskyield: 242 case OMPD_barrier: 243 case OMPD_taskwait: 244 case OMPD_cancellation_point: 245 case OMPD_cancel: 246 case OMPD_target_enter_data: 247 case OMPD_target_exit_data: 248 if (Allowed == ACK_StatementsOpenMPNonStandalone) { 249 Diag(Tok, diag::err_omp_immediate_directive) 250 << getOpenMPDirectiveName(DKind) << 0; 251 } 252 HasAssociatedStatement = false; 253 // Fall through for further analysis. 254 case OMPD_parallel: 255 case OMPD_simd: 256 case OMPD_for: 257 case OMPD_for_simd: 258 case OMPD_sections: 259 case OMPD_single: 260 case OMPD_section: 261 case OMPD_master: 262 case OMPD_critical: 263 case OMPD_parallel_for: 264 case OMPD_parallel_for_simd: 265 case OMPD_parallel_sections: 266 case OMPD_task: 267 case OMPD_ordered: 268 case OMPD_atomic: 269 case OMPD_target: 270 case OMPD_teams: 271 case OMPD_taskgroup: 272 case OMPD_target_data: 273 case OMPD_target_parallel: 274 case OMPD_target_parallel_for: 275 case OMPD_taskloop: 276 case OMPD_taskloop_simd: 277 case OMPD_distribute: { 278 ConsumeToken(); 279 // Parse directive name of the 'critical' directive if any. 280 if (DKind == OMPD_critical) { 281 BalancedDelimiterTracker T(*this, tok::l_paren, 282 tok::annot_pragma_openmp_end); 283 if (!T.consumeOpen()) { 284 if (Tok.isAnyIdentifier()) { 285 DirName = 286 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 287 ConsumeAnyToken(); 288 } else { 289 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 290 } 291 T.consumeClose(); 292 } 293 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 294 CancelRegion = ParseOpenMPDirectiveKind(*this); 295 if (Tok.isNot(tok::annot_pragma_openmp_end)) 296 ConsumeToken(); 297 } 298 299 if (isOpenMPLoopDirective(DKind)) 300 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 301 if (isOpenMPSimdDirective(DKind)) 302 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 303 ParseScope OMPDirectiveScope(this, ScopeFlags); 304 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 305 306 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 307 OpenMPClauseKind CKind = 308 Tok.isAnnotation() 309 ? OMPC_unknown 310 : FlushHasClause ? OMPC_flush 311 : getOpenMPClauseKind(PP.getSpelling(Tok)); 312 Actions.StartOpenMPClause(CKind); 313 FlushHasClause = false; 314 OMPClause *Clause = 315 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); 316 FirstClauses[CKind].setInt(true); 317 if (Clause) { 318 FirstClauses[CKind].setPointer(Clause); 319 Clauses.push_back(Clause); 320 } 321 322 // Skip ',' if any. 323 if (Tok.is(tok::comma)) 324 ConsumeToken(); 325 Actions.EndOpenMPClause(); 326 } 327 // End location of the directive. 328 EndLoc = Tok.getLocation(); 329 // Consume final annot_pragma_openmp_end. 330 ConsumeToken(); 331 332 // OpenMP [2.13.8, ordered Construct, Syntax] 333 // If the depend clause is specified, the ordered construct is a stand-alone 334 // directive. 335 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) { 336 if (Allowed == ACK_StatementsOpenMPNonStandalone) { 337 Diag(Loc, diag::err_omp_immediate_directive) 338 << getOpenMPDirectiveName(DKind) << 1 339 << getOpenMPClauseName(OMPC_depend); 340 } 341 HasAssociatedStatement = false; 342 } 343 344 StmtResult AssociatedStmt; 345 if (HasAssociatedStatement) { 346 // The body is a block scope like in Lambdas and Blocks. 347 Sema::CompoundScopeRAII CompoundScope(Actions); 348 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 349 Actions.ActOnStartOfCompoundStmt(); 350 // Parse statement 351 AssociatedStmt = ParseStatement(); 352 Actions.ActOnFinishOfCompoundStmt(); 353 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 354 } 355 Directive = Actions.ActOnOpenMPExecutableDirective( 356 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 357 EndLoc); 358 359 // Exit scope. 360 Actions.EndOpenMPDSABlock(Directive.get()); 361 OMPDirectiveScope.Exit(); 362 break; 363 } 364 case OMPD_unknown: 365 Diag(Tok, diag::err_omp_unknown_directive); 366 SkipUntil(tok::annot_pragma_openmp_end); 367 break; 368 } 369 return Directive; 370 } 371 372 /// \brief Parses list of simple variables for '#pragma omp threadprivate' 373 /// directive. 374 /// 375 /// simple-variable-list: 376 /// '(' id-expression {, id-expression} ')' 377 /// 378 bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, 379 SmallVectorImpl<Expr *> &VarList, 380 bool AllowScopeSpecifier) { 381 VarList.clear(); 382 // Parse '('. 383 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 384 if (T.expectAndConsume(diag::err_expected_lparen_after, 385 getOpenMPDirectiveName(Kind))) 386 return true; 387 bool IsCorrect = true; 388 bool NoIdentIsFound = true; 389 390 // Read tokens while ')' or annot_pragma_openmp_end is not found. 391 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 392 CXXScopeSpec SS; 393 SourceLocation TemplateKWLoc; 394 UnqualifiedId Name; 395 // Read var name. 396 Token PrevTok = Tok; 397 NoIdentIsFound = false; 398 399 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 400 ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) { 401 IsCorrect = false; 402 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 403 StopBeforeMatch); 404 } else if (ParseUnqualifiedId(SS, false, false, false, nullptr, 405 TemplateKWLoc, Name)) { 406 IsCorrect = false; 407 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 408 StopBeforeMatch); 409 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 410 Tok.isNot(tok::annot_pragma_openmp_end)) { 411 IsCorrect = false; 412 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 413 StopBeforeMatch); 414 Diag(PrevTok.getLocation(), diag::err_expected) 415 << tok::identifier 416 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 417 } else { 418 DeclarationNameInfo NameInfo = Actions.GetNameFromUnqualifiedId(Name); 419 ExprResult Res = 420 Actions.ActOnOpenMPIdExpression(getCurScope(), SS, NameInfo); 421 if (Res.isUsable()) 422 VarList.push_back(Res.get()); 423 } 424 // Consume ','. 425 if (Tok.is(tok::comma)) { 426 ConsumeToken(); 427 } 428 } 429 430 if (NoIdentIsFound) { 431 Diag(Tok, diag::err_expected) << tok::identifier; 432 IsCorrect = false; 433 } 434 435 // Parse ')'. 436 IsCorrect = !T.consumeClose() && IsCorrect; 437 438 return !IsCorrect && VarList.empty(); 439 } 440 441 /// \brief Parsing of OpenMP clauses. 442 /// 443 /// clause: 444 /// if-clause | final-clause | num_threads-clause | safelen-clause | 445 /// default-clause | private-clause | firstprivate-clause | shared-clause 446 /// | linear-clause | aligned-clause | collapse-clause | 447 /// lastprivate-clause | reduction-clause | proc_bind-clause | 448 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 449 /// mergeable-clause | flush-clause | read-clause | write-clause | 450 /// update-clause | capture-clause | seq_cst-clause | device-clause | 451 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 452 /// thread_limit-clause | priority-clause | grainsize-clause | 453 /// nogroup-clause | num_tasks-clause | hint-clause 454 /// 455 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 456 OpenMPClauseKind CKind, bool FirstClause) { 457 OMPClause *Clause = nullptr; 458 bool ErrorFound = false; 459 // Check if clause is allowed for the given directive. 460 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { 461 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 462 << getOpenMPDirectiveName(DKind); 463 ErrorFound = true; 464 } 465 466 switch (CKind) { 467 case OMPC_final: 468 case OMPC_num_threads: 469 case OMPC_safelen: 470 case OMPC_simdlen: 471 case OMPC_collapse: 472 case OMPC_ordered: 473 case OMPC_device: 474 case OMPC_num_teams: 475 case OMPC_thread_limit: 476 case OMPC_priority: 477 case OMPC_grainsize: 478 case OMPC_num_tasks: 479 case OMPC_hint: 480 // OpenMP [2.5, Restrictions] 481 // At most one num_threads clause can appear on the directive. 482 // OpenMP [2.8.1, simd construct, Restrictions] 483 // Only one safelen clause can appear on a simd directive. 484 // Only one simdlen clause can appear on a simd directive. 485 // Only one collapse clause can appear on a simd directive. 486 // OpenMP [2.9.1, target data construct, Restrictions] 487 // At most one device clause can appear on the directive. 488 // OpenMP [2.11.1, task Construct, Restrictions] 489 // At most one if clause can appear on the directive. 490 // At most one final clause can appear on the directive. 491 // OpenMP [teams Construct, Restrictions] 492 // At most one num_teams clause can appear on the directive. 493 // At most one thread_limit clause can appear on the directive. 494 // OpenMP [2.9.1, task Construct, Restrictions] 495 // At most one priority clause can appear on the directive. 496 // OpenMP [2.9.2, taskloop Construct, Restrictions] 497 // At most one grainsize clause can appear on the directive. 498 // OpenMP [2.9.2, taskloop Construct, Restrictions] 499 // At most one num_tasks clause can appear on the directive. 500 if (!FirstClause) { 501 Diag(Tok, diag::err_omp_more_one_clause) 502 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 503 ErrorFound = true; 504 } 505 506 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 507 Clause = ParseOpenMPClause(CKind); 508 else 509 Clause = ParseOpenMPSingleExprClause(CKind); 510 break; 511 case OMPC_default: 512 case OMPC_proc_bind: 513 // OpenMP [2.14.3.1, Restrictions] 514 // Only a single default clause may be specified on a parallel, task or 515 // teams directive. 516 // OpenMP [2.5, parallel Construct, Restrictions] 517 // At most one proc_bind clause can appear on the directive. 518 if (!FirstClause) { 519 Diag(Tok, diag::err_omp_more_one_clause) 520 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 521 ErrorFound = true; 522 } 523 524 Clause = ParseOpenMPSimpleClause(CKind); 525 break; 526 case OMPC_schedule: 527 case OMPC_dist_schedule: 528 case OMPC_defaultmap: 529 // OpenMP [2.7.1, Restrictions, p. 3] 530 // Only one schedule clause can appear on a loop directive. 531 // OpenMP [2.10.4, Restrictions, p. 106] 532 // At most one defaultmap clause can appear on the directive. 533 if (!FirstClause) { 534 Diag(Tok, diag::err_omp_more_one_clause) 535 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 536 ErrorFound = true; 537 } 538 539 case OMPC_if: 540 Clause = ParseOpenMPSingleExprWithArgClause(CKind); 541 break; 542 case OMPC_nowait: 543 case OMPC_untied: 544 case OMPC_mergeable: 545 case OMPC_read: 546 case OMPC_write: 547 case OMPC_update: 548 case OMPC_capture: 549 case OMPC_seq_cst: 550 case OMPC_threads: 551 case OMPC_simd: 552 case OMPC_nogroup: 553 // OpenMP [2.7.1, Restrictions, p. 9] 554 // Only one ordered clause can appear on a loop directive. 555 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 556 // Only one nowait clause can appear on a for directive. 557 if (!FirstClause) { 558 Diag(Tok, diag::err_omp_more_one_clause) 559 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 560 ErrorFound = true; 561 } 562 563 Clause = ParseOpenMPClause(CKind); 564 break; 565 case OMPC_private: 566 case OMPC_firstprivate: 567 case OMPC_lastprivate: 568 case OMPC_shared: 569 case OMPC_reduction: 570 case OMPC_linear: 571 case OMPC_aligned: 572 case OMPC_copyin: 573 case OMPC_copyprivate: 574 case OMPC_flush: 575 case OMPC_depend: 576 case OMPC_map: 577 Clause = ParseOpenMPVarListClause(DKind, CKind); 578 break; 579 case OMPC_unknown: 580 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 581 << getOpenMPDirectiveName(DKind); 582 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 583 break; 584 case OMPC_threadprivate: 585 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 586 << getOpenMPDirectiveName(DKind); 587 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 588 break; 589 } 590 return ErrorFound ? nullptr : Clause; 591 } 592 593 /// \brief Parsing of OpenMP clauses with single expressions like 'final', 594 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 595 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'. 596 /// 597 /// final-clause: 598 /// 'final' '(' expression ')' 599 /// 600 /// num_threads-clause: 601 /// 'num_threads' '(' expression ')' 602 /// 603 /// safelen-clause: 604 /// 'safelen' '(' expression ')' 605 /// 606 /// simdlen-clause: 607 /// 'simdlen' '(' expression ')' 608 /// 609 /// collapse-clause: 610 /// 'collapse' '(' expression ')' 611 /// 612 /// priority-clause: 613 /// 'priority' '(' expression ')' 614 /// 615 /// grainsize-clause: 616 /// 'grainsize' '(' expression ')' 617 /// 618 /// num_tasks-clause: 619 /// 'num_tasks' '(' expression ')' 620 /// 621 /// hint-clause: 622 /// 'hint' '(' expression ')' 623 /// 624 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { 625 SourceLocation Loc = ConsumeToken(); 626 627 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 628 if (T.expectAndConsume(diag::err_expected_lparen_after, 629 getOpenMPClauseName(Kind))) 630 return nullptr; 631 632 SourceLocation ELoc = Tok.getLocation(); 633 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); 634 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 635 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); 636 637 // Parse ')'. 638 T.consumeClose(); 639 640 if (Val.isInvalid()) 641 return nullptr; 642 643 return Actions.ActOnOpenMPSingleExprClause( 644 Kind, Val.get(), Loc, T.getOpenLocation(), T.getCloseLocation()); 645 } 646 647 /// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 648 /// 649 /// default-clause: 650 /// 'default' '(' 'none' | 'shared' ') 651 /// 652 /// proc_bind-clause: 653 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 654 /// 655 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { 656 SourceLocation Loc = Tok.getLocation(); 657 SourceLocation LOpen = ConsumeToken(); 658 // Parse '('. 659 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 660 if (T.expectAndConsume(diag::err_expected_lparen_after, 661 getOpenMPClauseName(Kind))) 662 return nullptr; 663 664 unsigned Type = getOpenMPSimpleClauseType( 665 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 666 SourceLocation TypeLoc = Tok.getLocation(); 667 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 668 Tok.isNot(tok::annot_pragma_openmp_end)) 669 ConsumeAnyToken(); 670 671 // Parse ')'. 672 T.consumeClose(); 673 674 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, 675 Tok.getLocation()); 676 } 677 678 /// \brief Parsing of OpenMP clauses like 'ordered'. 679 /// 680 /// ordered-clause: 681 /// 'ordered' 682 /// 683 /// nowait-clause: 684 /// 'nowait' 685 /// 686 /// untied-clause: 687 /// 'untied' 688 /// 689 /// mergeable-clause: 690 /// 'mergeable' 691 /// 692 /// read-clause: 693 /// 'read' 694 /// 695 /// threads-clause: 696 /// 'threads' 697 /// 698 /// simd-clause: 699 /// 'simd' 700 /// 701 /// nogroup-clause: 702 /// 'nogroup' 703 /// 704 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) { 705 SourceLocation Loc = Tok.getLocation(); 706 ConsumeAnyToken(); 707 708 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 709 } 710 711 712 /// \brief Parsing of OpenMP clauses with single expressions and some additional 713 /// argument like 'schedule' or 'dist_schedule'. 714 /// 715 /// schedule-clause: 716 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 717 /// ')' 718 /// 719 /// if-clause: 720 /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 721 /// 722 /// defaultmap: 723 /// 'defaultmap' '(' modifier ':' kind ')' 724 /// 725 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { 726 SourceLocation Loc = ConsumeToken(); 727 SourceLocation DelimLoc; 728 // Parse '('. 729 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 730 if (T.expectAndConsume(diag::err_expected_lparen_after, 731 getOpenMPClauseName(Kind))) 732 return nullptr; 733 734 ExprResult Val; 735 SmallVector<unsigned, 4> Arg; 736 SmallVector<SourceLocation, 4> KLoc; 737 if (Kind == OMPC_schedule) { 738 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 739 Arg.resize(NumberOfElements); 740 KLoc.resize(NumberOfElements); 741 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 742 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 743 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 744 auto KindModifier = getOpenMPSimpleClauseType( 745 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 746 if (KindModifier > OMPC_SCHEDULE_unknown) { 747 // Parse 'modifier' 748 Arg[Modifier1] = KindModifier; 749 KLoc[Modifier1] = Tok.getLocation(); 750 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 751 Tok.isNot(tok::annot_pragma_openmp_end)) 752 ConsumeAnyToken(); 753 if (Tok.is(tok::comma)) { 754 // Parse ',' 'modifier' 755 ConsumeAnyToken(); 756 KindModifier = getOpenMPSimpleClauseType( 757 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 758 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 759 ? KindModifier 760 : (unsigned)OMPC_SCHEDULE_unknown; 761 KLoc[Modifier2] = Tok.getLocation(); 762 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 763 Tok.isNot(tok::annot_pragma_openmp_end)) 764 ConsumeAnyToken(); 765 } 766 // Parse ':' 767 if (Tok.is(tok::colon)) 768 ConsumeAnyToken(); 769 else 770 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 771 KindModifier = getOpenMPSimpleClauseType( 772 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 773 } 774 Arg[ScheduleKind] = KindModifier; 775 KLoc[ScheduleKind] = Tok.getLocation(); 776 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 777 Tok.isNot(tok::annot_pragma_openmp_end)) 778 ConsumeAnyToken(); 779 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 780 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 781 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 782 Tok.is(tok::comma)) 783 DelimLoc = ConsumeAnyToken(); 784 } else if (Kind == OMPC_dist_schedule) { 785 Arg.push_back(getOpenMPSimpleClauseType( 786 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 787 KLoc.push_back(Tok.getLocation()); 788 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 789 Tok.isNot(tok::annot_pragma_openmp_end)) 790 ConsumeAnyToken(); 791 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 792 DelimLoc = ConsumeAnyToken(); 793 } else if (Kind == OMPC_defaultmap) { 794 // Get a defaultmap modifier 795 Arg.push_back(getOpenMPSimpleClauseType( 796 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 797 KLoc.push_back(Tok.getLocation()); 798 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 799 Tok.isNot(tok::annot_pragma_openmp_end)) 800 ConsumeAnyToken(); 801 // Parse ':' 802 if (Tok.is(tok::colon)) 803 ConsumeAnyToken(); 804 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 805 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 806 // Get a defaultmap kind 807 Arg.push_back(getOpenMPSimpleClauseType( 808 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 809 KLoc.push_back(Tok.getLocation()); 810 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 811 Tok.isNot(tok::annot_pragma_openmp_end)) 812 ConsumeAnyToken(); 813 } else { 814 assert(Kind == OMPC_if); 815 KLoc.push_back(Tok.getLocation()); 816 Arg.push_back(ParseOpenMPDirectiveKind(*this)); 817 if (Arg.back() != OMPD_unknown) { 818 ConsumeToken(); 819 if (Tok.is(tok::colon)) 820 DelimLoc = ConsumeToken(); 821 else 822 Diag(Tok, diag::warn_pragma_expected_colon) 823 << "directive name modifier"; 824 } 825 } 826 827 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 828 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 829 Kind == OMPC_if; 830 if (NeedAnExpression) { 831 SourceLocation ELoc = Tok.getLocation(); 832 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); 833 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 834 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); 835 } 836 837 // Parse ')'. 838 T.consumeClose(); 839 840 if (NeedAnExpression && Val.isInvalid()) 841 return nullptr; 842 843 return Actions.ActOnOpenMPSingleExprWithArgClause( 844 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, 845 T.getCloseLocation()); 846 } 847 848 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 849 UnqualifiedId &ReductionId) { 850 SourceLocation TemplateKWLoc; 851 if (ReductionIdScopeSpec.isEmpty()) { 852 auto OOK = OO_None; 853 switch (P.getCurToken().getKind()) { 854 case tok::plus: 855 OOK = OO_Plus; 856 break; 857 case tok::minus: 858 OOK = OO_Minus; 859 break; 860 case tok::star: 861 OOK = OO_Star; 862 break; 863 case tok::amp: 864 OOK = OO_Amp; 865 break; 866 case tok::pipe: 867 OOK = OO_Pipe; 868 break; 869 case tok::caret: 870 OOK = OO_Caret; 871 break; 872 case tok::ampamp: 873 OOK = OO_AmpAmp; 874 break; 875 case tok::pipepipe: 876 OOK = OO_PipePipe; 877 break; 878 default: 879 break; 880 } 881 if (OOK != OO_None) { 882 SourceLocation OpLoc = P.ConsumeToken(); 883 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 884 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 885 return false; 886 } 887 } 888 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false, 889 /*AllowDestructorName*/ false, 890 /*AllowConstructorName*/ false, nullptr, 891 TemplateKWLoc, ReductionId); 892 } 893 894 /// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 895 /// 'shared', 'copyin', 'copyprivate', 'flush' or 'reduction'. 896 /// 897 /// private-clause: 898 /// 'private' '(' list ')' 899 /// firstprivate-clause: 900 /// 'firstprivate' '(' list ')' 901 /// lastprivate-clause: 902 /// 'lastprivate' '(' list ')' 903 /// shared-clause: 904 /// 'shared' '(' list ')' 905 /// linear-clause: 906 /// 'linear' '(' linear-list [ ':' linear-step ] ')' 907 /// aligned-clause: 908 /// 'aligned' '(' list [ ':' alignment ] ')' 909 /// reduction-clause: 910 /// 'reduction' '(' reduction-identifier ':' list ')' 911 /// copyprivate-clause: 912 /// 'copyprivate' '(' list ')' 913 /// flush-clause: 914 /// 'flush' '(' list ')' 915 /// depend-clause: 916 /// 'depend' '(' in | out | inout : list | source ')' 917 /// map-clause: 918 /// 'map' '(' [ [ always , ] 919 /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 920 /// 921 /// For 'linear' clause linear-list may have the following forms: 922 /// list 923 /// modifier(list) 924 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 925 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 926 OpenMPClauseKind Kind) { 927 SourceLocation Loc = Tok.getLocation(); 928 SourceLocation LOpen = ConsumeToken(); 929 SourceLocation ColonLoc = SourceLocation(); 930 // Optional scope specifier and unqualified id for reduction identifier. 931 CXXScopeSpec ReductionIdScopeSpec; 932 UnqualifiedId ReductionId; 933 bool InvalidReductionId = false; 934 OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; 935 // OpenMP 4.1 [2.15.3.7, linear Clause] 936 // If no modifier is specified it is assumed to be val. 937 OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val; 938 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 939 OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; 940 bool MapTypeIsImplicit = false; 941 bool MapTypeModifierSpecified = false; 942 SourceLocation DepLinMapLoc; 943 944 // Parse '('. 945 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 946 if (T.expectAndConsume(diag::err_expected_lparen_after, 947 getOpenMPClauseName(Kind))) 948 return nullptr; 949 950 bool NeedRParenForLinear = false; 951 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 952 tok::annot_pragma_openmp_end); 953 // Handle reduction-identifier for reduction clause. 954 if (Kind == OMPC_reduction) { 955 ColonProtectionRAIIObject ColonRAII(*this); 956 if (getLangOpts().CPlusPlus) { 957 ParseOptionalCXXScopeSpecifier(ReductionIdScopeSpec, nullptr, false); 958 } 959 InvalidReductionId = 960 ParseReductionId(*this, ReductionIdScopeSpec, ReductionId); 961 if (InvalidReductionId) { 962 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 963 StopBeforeMatch); 964 } 965 if (Tok.is(tok::colon)) { 966 ColonLoc = ConsumeToken(); 967 } else { 968 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 969 } 970 } else if (Kind == OMPC_depend) { 971 // Handle dependency type for depend clause. 972 ColonProtectionRAIIObject ColonRAII(*this); 973 DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( 974 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); 975 DepLinMapLoc = Tok.getLocation(); 976 977 if (DepKind == OMPC_DEPEND_unknown) { 978 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 979 StopBeforeMatch); 980 } else { 981 ConsumeToken(); 982 // Special processing for depend(source) clause. 983 if (DKind == OMPD_ordered && DepKind == OMPC_DEPEND_source) { 984 // Parse ')'. 985 T.consumeClose(); 986 return Actions.ActOnOpenMPVarListClause( 987 Kind, llvm::None, /*TailExpr=*/nullptr, Loc, LOpen, 988 /*ColonLoc=*/SourceLocation(), Tok.getLocation(), 989 ReductionIdScopeSpec, DeclarationNameInfo(), DepKind, 990 LinearModifier, MapTypeModifier, MapType, MapTypeIsImplicit, 991 DepLinMapLoc); 992 } 993 } 994 if (Tok.is(tok::colon)) { 995 ColonLoc = ConsumeToken(); 996 } else { 997 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 998 : diag::warn_pragma_expected_colon) 999 << "dependency type"; 1000 } 1001 } else if (Kind == OMPC_linear) { 1002 // Try to parse modifier if any. 1003 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 1004 LinearModifier = static_cast<OpenMPLinearClauseKind>( 1005 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 1006 DepLinMapLoc = ConsumeToken(); 1007 LinearT.consumeOpen(); 1008 NeedRParenForLinear = true; 1009 } 1010 } else if (Kind == OMPC_map) { 1011 // Handle map type for map clause. 1012 ColonProtectionRAIIObject ColonRAII(*this); 1013 1014 /// The map clause modifier token can be either a identifier or the C++ 1015 /// delete keyword. 1016 auto IsMapClauseModifierToken = [](const Token &Tok) { 1017 return Tok.isOneOf(tok::identifier, tok::kw_delete); 1018 }; 1019 1020 // The first identifier may be a list item, a map-type or a 1021 // map-type-modifier. The map modifier can also be delete which has the same 1022 // spelling of the C++ delete keyword. 1023 MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( 1024 Kind, IsMapClauseModifierToken(Tok) ? PP.getSpelling(Tok) : "")); 1025 DepLinMapLoc = Tok.getLocation(); 1026 bool ColonExpected = false; 1027 1028 if (IsMapClauseModifierToken(Tok)) { 1029 if (PP.LookAhead(0).is(tok::colon)) { 1030 MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( 1031 Kind, IsMapClauseModifierToken(Tok) ? PP.getSpelling(Tok) : "")); 1032 if (MapType == OMPC_MAP_unknown) { 1033 Diag(Tok, diag::err_omp_unknown_map_type); 1034 } else if (MapType == OMPC_MAP_always) { 1035 Diag(Tok, diag::err_omp_map_type_missing); 1036 } 1037 ConsumeToken(); 1038 } else if (PP.LookAhead(0).is(tok::comma)) { 1039 if (IsMapClauseModifierToken(PP.LookAhead(1)) && 1040 PP.LookAhead(2).is(tok::colon)) { 1041 MapTypeModifier = 1042 static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( 1043 Kind, 1044 IsMapClauseModifierToken(Tok) ? PP.getSpelling(Tok) : "")); 1045 if (MapTypeModifier != OMPC_MAP_always) { 1046 Diag(Tok, diag::err_omp_unknown_map_type_modifier); 1047 MapTypeModifier = OMPC_MAP_unknown; 1048 } else { 1049 MapTypeModifierSpecified = true; 1050 } 1051 1052 ConsumeToken(); 1053 ConsumeToken(); 1054 1055 MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( 1056 Kind, IsMapClauseModifierToken(Tok) ? PP.getSpelling(Tok) : "")); 1057 if (MapType == OMPC_MAP_unknown || MapType == OMPC_MAP_always) { 1058 Diag(Tok, diag::err_omp_unknown_map_type); 1059 } 1060 ConsumeToken(); 1061 } else { 1062 MapType = OMPC_MAP_tofrom; 1063 MapTypeIsImplicit = true; 1064 } 1065 } else { 1066 MapType = OMPC_MAP_tofrom; 1067 MapTypeIsImplicit = true; 1068 } 1069 } else { 1070 MapType = OMPC_MAP_tofrom; 1071 MapTypeIsImplicit = true; 1072 } 1073 1074 if (Tok.is(tok::colon)) { 1075 ColonLoc = ConsumeToken(); 1076 } else if (ColonExpected) { 1077 Diag(Tok, diag::warn_pragma_expected_colon) << "map type"; 1078 } 1079 } 1080 1081 SmallVector<Expr *, 5> Vars; 1082 bool IsComma = 1083 ((Kind != OMPC_reduction) && (Kind != OMPC_depend) && 1084 (Kind != OMPC_map)) || 1085 ((Kind == OMPC_reduction) && !InvalidReductionId) || 1086 ((Kind == OMPC_map) && (MapType != OMPC_MAP_unknown) && 1087 (!MapTypeModifierSpecified || 1088 (MapTypeModifierSpecified && MapTypeModifier == OMPC_MAP_always))) || 1089 ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown); 1090 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 1091 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 1092 Tok.isNot(tok::annot_pragma_openmp_end))) { 1093 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 1094 // Parse variable 1095 ExprResult VarExpr = 1096 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 1097 if (VarExpr.isUsable()) { 1098 Vars.push_back(VarExpr.get()); 1099 } else { 1100 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1101 StopBeforeMatch); 1102 } 1103 // Skip ',' if any 1104 IsComma = Tok.is(tok::comma); 1105 if (IsComma) 1106 ConsumeToken(); 1107 else if (Tok.isNot(tok::r_paren) && 1108 Tok.isNot(tok::annot_pragma_openmp_end) && 1109 (!MayHaveTail || Tok.isNot(tok::colon))) 1110 Diag(Tok, diag::err_omp_expected_punc) 1111 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 1112 : getOpenMPClauseName(Kind)) 1113 << (Kind == OMPC_flush); 1114 } 1115 1116 // Parse ')' for linear clause with modifier. 1117 if (NeedRParenForLinear) 1118 LinearT.consumeClose(); 1119 1120 // Parse ':' linear-step (or ':' alignment). 1121 Expr *TailExpr = nullptr; 1122 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 1123 if (MustHaveTail) { 1124 ColonLoc = Tok.getLocation(); 1125 SourceLocation ELoc = ConsumeToken(); 1126 ExprResult Tail = ParseAssignmentExpression(); 1127 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc); 1128 if (Tail.isUsable()) 1129 TailExpr = Tail.get(); 1130 else 1131 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1132 StopBeforeMatch); 1133 } 1134 1135 // Parse ')'. 1136 T.consumeClose(); 1137 if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) || 1138 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 1139 (MustHaveTail && !TailExpr) || InvalidReductionId) { 1140 return nullptr; 1141 } 1142 1143 return Actions.ActOnOpenMPVarListClause( 1144 Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(), 1145 ReductionIdScopeSpec, 1146 ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId) 1147 : DeclarationNameInfo(), 1148 DepKind, LinearModifier, MapTypeModifier, MapType, MapTypeIsImplicit, 1149 DepLinMapLoc); 1150 } 1151 1152