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