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