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