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