1 //===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// This file implements parsing of all OpenMP directives and clauses. 10 /// 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/ASTContext.h" 14 #include "clang/AST/StmtOpenMP.h" 15 #include "clang/Parse/ParseDiagnostic.h" 16 #include "clang/Parse/Parser.h" 17 #include "clang/Parse/RAIIObjectsForParser.h" 18 #include "clang/Sema/Scope.h" 19 #include "llvm/ADT/PointerIntPair.h" 20 21 using namespace clang; 22 23 //===----------------------------------------------------------------------===// 24 // OpenMP declarative directives. 25 //===----------------------------------------------------------------------===// 26 27 namespace { 28 enum OpenMPDirectiveKindEx { 29 OMPD_cancellation = OMPD_unknown + 1, 30 OMPD_data, 31 OMPD_declare, 32 OMPD_end, 33 OMPD_end_declare, 34 OMPD_enter, 35 OMPD_exit, 36 OMPD_point, 37 OMPD_reduction, 38 OMPD_target_enter, 39 OMPD_target_exit, 40 OMPD_update, 41 OMPD_distribute_parallel, 42 OMPD_teams_distribute_parallel, 43 OMPD_target_teams_distribute_parallel, 44 OMPD_mapper, 45 }; 46 47 class DeclDirectiveListParserHelper final { 48 SmallVector<Expr *, 4> Identifiers; 49 Parser *P; 50 OpenMPDirectiveKind Kind; 51 52 public: 53 DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind) 54 : P(P), Kind(Kind) {} 55 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 56 ExprResult Res = P->getActions().ActOnOpenMPIdExpression( 57 P->getCurScope(), SS, NameInfo, Kind); 58 if (Res.isUsable()) 59 Identifiers.push_back(Res.get()); 60 } 61 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; } 62 }; 63 } // namespace 64 65 // Map token string to extended OMP token kind that are 66 // OpenMPDirectiveKind + OpenMPDirectiveKindEx. 67 static unsigned getOpenMPDirectiveKindEx(StringRef S) { 68 auto DKind = getOpenMPDirectiveKind(S); 69 if (DKind != OMPD_unknown) 70 return DKind; 71 72 return llvm::StringSwitch<unsigned>(S) 73 .Case("cancellation", OMPD_cancellation) 74 .Case("data", OMPD_data) 75 .Case("declare", OMPD_declare) 76 .Case("end", OMPD_end) 77 .Case("enter", OMPD_enter) 78 .Case("exit", OMPD_exit) 79 .Case("point", OMPD_point) 80 .Case("reduction", OMPD_reduction) 81 .Case("update", OMPD_update) 82 .Case("mapper", OMPD_mapper) 83 .Default(OMPD_unknown); 84 } 85 86 static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) { 87 // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. 88 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd 89 // TODO: add other combined directives in topological order. 90 static const unsigned F[][3] = { 91 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point}, 92 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction}, 93 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper}, 94 {OMPD_declare, OMPD_simd, OMPD_declare_simd}, 95 {OMPD_declare, OMPD_target, OMPD_declare_target}, 96 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel}, 97 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for}, 98 {OMPD_distribute_parallel_for, OMPD_simd, 99 OMPD_distribute_parallel_for_simd}, 100 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd}, 101 {OMPD_end, OMPD_declare, OMPD_end_declare}, 102 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target}, 103 {OMPD_target, OMPD_data, OMPD_target_data}, 104 {OMPD_target, OMPD_enter, OMPD_target_enter}, 105 {OMPD_target, OMPD_exit, OMPD_target_exit}, 106 {OMPD_target, OMPD_update, OMPD_target_update}, 107 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data}, 108 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data}, 109 {OMPD_for, OMPD_simd, OMPD_for_simd}, 110 {OMPD_parallel, OMPD_for, OMPD_parallel_for}, 111 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, 112 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, 113 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}, 114 {OMPD_target, OMPD_parallel, OMPD_target_parallel}, 115 {OMPD_target, OMPD_simd, OMPD_target_simd}, 116 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for}, 117 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd}, 118 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute}, 119 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd}, 120 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel}, 121 {OMPD_teams_distribute_parallel, OMPD_for, 122 OMPD_teams_distribute_parallel_for}, 123 {OMPD_teams_distribute_parallel_for, OMPD_simd, 124 OMPD_teams_distribute_parallel_for_simd}, 125 {OMPD_target, OMPD_teams, OMPD_target_teams}, 126 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute}, 127 {OMPD_target_teams_distribute, OMPD_parallel, 128 OMPD_target_teams_distribute_parallel}, 129 {OMPD_target_teams_distribute, OMPD_simd, 130 OMPD_target_teams_distribute_simd}, 131 {OMPD_target_teams_distribute_parallel, OMPD_for, 132 OMPD_target_teams_distribute_parallel_for}, 133 {OMPD_target_teams_distribute_parallel_for, OMPD_simd, 134 OMPD_target_teams_distribute_parallel_for_simd}}; 135 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; 136 Token Tok = P.getCurToken(); 137 unsigned DKind = 138 Tok.isAnnotation() 139 ? static_cast<unsigned>(OMPD_unknown) 140 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 141 if (DKind == OMPD_unknown) 142 return OMPD_unknown; 143 144 for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) { 145 if (DKind != F[I][0]) 146 continue; 147 148 Tok = P.getPreprocessor().LookAhead(0); 149 unsigned SDKind = 150 Tok.isAnnotation() 151 ? static_cast<unsigned>(OMPD_unknown) 152 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 153 if (SDKind == OMPD_unknown) 154 continue; 155 156 if (SDKind == F[I][1]) { 157 P.ConsumeToken(); 158 DKind = F[I][2]; 159 } 160 } 161 return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind) 162 : OMPD_unknown; 163 } 164 165 static DeclarationName parseOpenMPReductionId(Parser &P) { 166 Token Tok = P.getCurToken(); 167 Sema &Actions = P.getActions(); 168 OverloadedOperatorKind OOK = OO_None; 169 // Allow to use 'operator' keyword for C++ operators 170 bool WithOperator = false; 171 if (Tok.is(tok::kw_operator)) { 172 P.ConsumeToken(); 173 Tok = P.getCurToken(); 174 WithOperator = true; 175 } 176 switch (Tok.getKind()) { 177 case tok::plus: // '+' 178 OOK = OO_Plus; 179 break; 180 case tok::minus: // '-' 181 OOK = OO_Minus; 182 break; 183 case tok::star: // '*' 184 OOK = OO_Star; 185 break; 186 case tok::amp: // '&' 187 OOK = OO_Amp; 188 break; 189 case tok::pipe: // '|' 190 OOK = OO_Pipe; 191 break; 192 case tok::caret: // '^' 193 OOK = OO_Caret; 194 break; 195 case tok::ampamp: // '&&' 196 OOK = OO_AmpAmp; 197 break; 198 case tok::pipepipe: // '||' 199 OOK = OO_PipePipe; 200 break; 201 case tok::identifier: // identifier 202 if (!WithOperator) 203 break; 204 LLVM_FALLTHROUGH; 205 default: 206 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); 207 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 208 Parser::StopBeforeMatch); 209 return DeclarationName(); 210 } 211 P.ConsumeToken(); 212 auto &DeclNames = Actions.getASTContext().DeclarationNames; 213 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo()) 214 : DeclNames.getCXXOperatorName(OOK); 215 } 216 217 /// Parse 'omp declare reduction' construct. 218 /// 219 /// declare-reduction-directive: 220 /// annot_pragma_openmp 'declare' 'reduction' 221 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')' 222 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')'] 223 /// annot_pragma_openmp_end 224 /// <reduction_id> is either a base language identifier or one of the following 225 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'. 226 /// 227 Parser::DeclGroupPtrTy 228 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { 229 // Parse '('. 230 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 231 if (T.expectAndConsume(diag::err_expected_lparen_after, 232 getOpenMPDirectiveName(OMPD_declare_reduction))) { 233 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 234 return DeclGroupPtrTy(); 235 } 236 237 DeclarationName Name = parseOpenMPReductionId(*this); 238 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end)) 239 return DeclGroupPtrTy(); 240 241 // Consume ':'. 242 bool IsCorrect = !ExpectAndConsume(tok::colon); 243 244 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 245 return DeclGroupPtrTy(); 246 247 IsCorrect = IsCorrect && !Name.isEmpty(); 248 249 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) { 250 Diag(Tok.getLocation(), diag::err_expected_type); 251 IsCorrect = false; 252 } 253 254 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 255 return DeclGroupPtrTy(); 256 257 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes; 258 // Parse list of types until ':' token. 259 do { 260 ColonProtectionRAIIObject ColonRAII(*this); 261 SourceRange Range; 262 TypeResult TR = 263 ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS); 264 if (TR.isUsable()) { 265 QualType ReductionType = 266 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR); 267 if (!ReductionType.isNull()) { 268 ReductionTypes.push_back( 269 std::make_pair(ReductionType, Range.getBegin())); 270 } 271 } else { 272 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end, 273 StopBeforeMatch); 274 } 275 276 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) 277 break; 278 279 // Consume ','. 280 if (ExpectAndConsume(tok::comma)) { 281 IsCorrect = false; 282 if (Tok.is(tok::annot_pragma_openmp_end)) { 283 Diag(Tok.getLocation(), diag::err_expected_type); 284 return DeclGroupPtrTy(); 285 } 286 } 287 } while (Tok.isNot(tok::annot_pragma_openmp_end)); 288 289 if (ReductionTypes.empty()) { 290 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 291 return DeclGroupPtrTy(); 292 } 293 294 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 295 return DeclGroupPtrTy(); 296 297 // Consume ':'. 298 if (ExpectAndConsume(tok::colon)) 299 IsCorrect = false; 300 301 if (Tok.is(tok::annot_pragma_openmp_end)) { 302 Diag(Tok.getLocation(), diag::err_expected_expression); 303 return DeclGroupPtrTy(); 304 } 305 306 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart( 307 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS); 308 309 // Parse <combiner> expression and then parse initializer if any for each 310 // correct type. 311 unsigned I = 0, E = ReductionTypes.size(); 312 for (Decl *D : DRD.get()) { 313 TentativeParsingAction TPA(*this); 314 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 315 Scope::CompoundStmtScope | 316 Scope::OpenMPDirectiveScope); 317 // Parse <combiner> expression. 318 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); 319 ExprResult CombinerResult = 320 Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(), 321 D->getLocation(), /*DiscardedValue*/ false); 322 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); 323 324 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && 325 Tok.isNot(tok::annot_pragma_openmp_end)) { 326 TPA.Commit(); 327 IsCorrect = false; 328 break; 329 } 330 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable(); 331 ExprResult InitializerResult; 332 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 333 // Parse <initializer> expression. 334 if (Tok.is(tok::identifier) && 335 Tok.getIdentifierInfo()->isStr("initializer")) { 336 ConsumeToken(); 337 } else { 338 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'"; 339 TPA.Commit(); 340 IsCorrect = false; 341 break; 342 } 343 // Parse '('. 344 BalancedDelimiterTracker T(*this, tok::l_paren, 345 tok::annot_pragma_openmp_end); 346 IsCorrect = 347 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") && 348 IsCorrect; 349 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 350 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 351 Scope::CompoundStmtScope | 352 Scope::OpenMPDirectiveScope); 353 // Parse expression. 354 VarDecl *OmpPrivParm = 355 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), 356 D); 357 // Check if initializer is omp_priv <init_expr> or something else. 358 if (Tok.is(tok::identifier) && 359 Tok.getIdentifierInfo()->isStr("omp_priv")) { 360 if (Actions.getLangOpts().CPlusPlus) { 361 InitializerResult = Actions.ActOnFinishFullExpr( 362 ParseAssignmentExpression().get(), D->getLocation(), 363 /*DiscardedValue*/ false); 364 } else { 365 ConsumeToken(); 366 ParseOpenMPReductionInitializerForDecl(OmpPrivParm); 367 } 368 } else { 369 InitializerResult = Actions.ActOnFinishFullExpr( 370 ParseAssignmentExpression().get(), D->getLocation(), 371 /*DiscardedValue*/ false); 372 } 373 Actions.ActOnOpenMPDeclareReductionInitializerEnd( 374 D, InitializerResult.get(), OmpPrivParm); 375 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) && 376 Tok.isNot(tok::annot_pragma_openmp_end)) { 377 TPA.Commit(); 378 IsCorrect = false; 379 break; 380 } 381 IsCorrect = 382 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid(); 383 } 384 } 385 386 ++I; 387 // Revert parsing if not the last type, otherwise accept it, we're done with 388 // parsing. 389 if (I != E) 390 TPA.Revert(); 391 else 392 TPA.Commit(); 393 } 394 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD, 395 IsCorrect); 396 } 397 398 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { 399 // Parse declarator '=' initializer. 400 // If a '==' or '+=' is found, suggest a fixit to '='. 401 if (isTokenEqualOrEqualTypo()) { 402 ConsumeToken(); 403 404 if (Tok.is(tok::code_completion)) { 405 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm); 406 Actions.FinalizeDeclaration(OmpPrivParm); 407 cutOffParsing(); 408 return; 409 } 410 411 ExprResult Init(ParseInitializer()); 412 413 if (Init.isInvalid()) { 414 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 415 Actions.ActOnInitializerError(OmpPrivParm); 416 } else { 417 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 418 /*DirectInit=*/false); 419 } 420 } else if (Tok.is(tok::l_paren)) { 421 // Parse C++ direct initializer: '(' expression-list ')' 422 BalancedDelimiterTracker T(*this, tok::l_paren); 423 T.consumeOpen(); 424 425 ExprVector Exprs; 426 CommaLocsTy CommaLocs; 427 428 SourceLocation LParLoc = T.getOpenLocation(); 429 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() { 430 QualType PreferredType = Actions.ProduceConstructorSignatureHelp( 431 getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(), 432 OmpPrivParm->getLocation(), Exprs, LParLoc); 433 CalledSignatureHelp = true; 434 return PreferredType; 435 }; 436 if (ParseExpressionList(Exprs, CommaLocs, [&] { 437 PreferredType.enterFunctionArgument(Tok.getLocation(), 438 RunSignatureHelp); 439 })) { 440 if (PP.isCodeCompletionReached() && !CalledSignatureHelp) 441 RunSignatureHelp(); 442 Actions.ActOnInitializerError(OmpPrivParm); 443 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 444 } else { 445 // Match the ')'. 446 SourceLocation RLoc = Tok.getLocation(); 447 if (!T.consumeClose()) 448 RLoc = T.getCloseLocation(); 449 450 assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() && 451 "Unexpected number of commas!"); 452 453 ExprResult Initializer = 454 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs); 455 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(), 456 /*DirectInit=*/true); 457 } 458 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 459 // Parse C++0x braced-init-list. 460 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 461 462 ExprResult Init(ParseBraceInitializer()); 463 464 if (Init.isInvalid()) { 465 Actions.ActOnInitializerError(OmpPrivParm); 466 } else { 467 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 468 /*DirectInit=*/true); 469 } 470 } else { 471 Actions.ActOnUninitializedDecl(OmpPrivParm); 472 } 473 } 474 475 /// Parses 'omp declare mapper' directive. 476 /// 477 /// declare-mapper-directive: 478 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':'] 479 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 480 /// annot_pragma_openmp_end 481 /// <mapper-identifier> and <var> are base language identifiers. 482 /// 483 Parser::DeclGroupPtrTy 484 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) { 485 bool IsCorrect = true; 486 // Parse '(' 487 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 488 if (T.expectAndConsume(diag::err_expected_lparen_after, 489 getOpenMPDirectiveName(OMPD_declare_mapper))) { 490 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 491 return DeclGroupPtrTy(); 492 } 493 494 // Parse <mapper-identifier> 495 auto &DeclNames = Actions.getASTContext().DeclarationNames; 496 DeclarationName MapperId; 497 if (PP.LookAhead(0).is(tok::colon)) { 498 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 499 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 500 IsCorrect = false; 501 } else { 502 MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo()); 503 } 504 ConsumeToken(); 505 // Consume ':'. 506 ExpectAndConsume(tok::colon); 507 } else { 508 // If no mapper identifier is provided, its name is "default" by default 509 MapperId = 510 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default")); 511 } 512 513 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 514 return DeclGroupPtrTy(); 515 516 // Parse <type> <var> 517 DeclarationName VName; 518 QualType MapperType; 519 SourceRange Range; 520 TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS); 521 if (ParsedType.isUsable()) 522 MapperType = 523 Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType); 524 if (MapperType.isNull()) 525 IsCorrect = false; 526 if (!IsCorrect) { 527 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 528 return DeclGroupPtrTy(); 529 } 530 531 // Consume ')'. 532 IsCorrect &= !T.consumeClose(); 533 if (!IsCorrect) { 534 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 535 return DeclGroupPtrTy(); 536 } 537 538 // Enter scope. 539 OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart( 540 getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType, 541 Range.getBegin(), VName, AS); 542 DeclarationNameInfo DirName; 543 SourceLocation Loc = Tok.getLocation(); 544 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 545 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 546 ParseScope OMPDirectiveScope(this, ScopeFlags); 547 Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc); 548 549 // Add the mapper variable declaration. 550 Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl( 551 DMD, getCurScope(), MapperType, Range.getBegin(), VName); 552 553 // Parse map clauses. 554 SmallVector<OMPClause *, 6> Clauses; 555 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 556 OpenMPClauseKind CKind = Tok.isAnnotation() 557 ? OMPC_unknown 558 : getOpenMPClauseKind(PP.getSpelling(Tok)); 559 Actions.StartOpenMPClause(CKind); 560 OMPClause *Clause = 561 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0); 562 if (Clause) 563 Clauses.push_back(Clause); 564 else 565 IsCorrect = false; 566 // Skip ',' if any. 567 if (Tok.is(tok::comma)) 568 ConsumeToken(); 569 Actions.EndOpenMPClause(); 570 } 571 if (Clauses.empty()) { 572 Diag(Tok, diag::err_omp_expected_clause) 573 << getOpenMPDirectiveName(OMPD_declare_mapper); 574 IsCorrect = false; 575 } 576 577 // Exit scope. 578 Actions.EndOpenMPDSABlock(nullptr); 579 OMPDirectiveScope.Exit(); 580 581 DeclGroupPtrTy DGP = 582 Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses); 583 if (!IsCorrect) 584 return DeclGroupPtrTy(); 585 return DGP; 586 } 587 588 TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range, 589 DeclarationName &Name, 590 AccessSpecifier AS) { 591 // Parse the common declaration-specifiers piece. 592 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier; 593 DeclSpec DS(AttrFactory); 594 ParseSpecifierQualifierList(DS, AS, DSC); 595 596 // Parse the declarator. 597 DeclaratorContext Context = DeclaratorContext::PrototypeContext; 598 Declarator DeclaratorInfo(DS, Context); 599 ParseDeclarator(DeclaratorInfo); 600 Range = DeclaratorInfo.getSourceRange(); 601 if (DeclaratorInfo.getIdentifier() == nullptr) { 602 Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator); 603 return true; 604 } 605 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName(); 606 607 return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo); 608 } 609 610 namespace { 611 /// RAII that recreates function context for correct parsing of clauses of 612 /// 'declare simd' construct. 613 /// OpenMP, 2.8.2 declare simd Construct 614 /// The expressions appearing in the clauses of this directive are evaluated in 615 /// the scope of the arguments of the function declaration or definition. 616 class FNContextRAII final { 617 Parser &P; 618 Sema::CXXThisScopeRAII *ThisScope; 619 Parser::ParseScope *TempScope; 620 Parser::ParseScope *FnScope; 621 bool HasTemplateScope = false; 622 bool HasFunScope = false; 623 FNContextRAII() = delete; 624 FNContextRAII(const FNContextRAII &) = delete; 625 FNContextRAII &operator=(const FNContextRAII &) = delete; 626 627 public: 628 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) { 629 Decl *D = *Ptr.get().begin(); 630 NamedDecl *ND = dyn_cast<NamedDecl>(D); 631 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); 632 Sema &Actions = P.getActions(); 633 634 // Allow 'this' within late-parsed attributes. 635 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(), 636 ND && ND->isCXXInstanceMember()); 637 638 // If the Decl is templatized, add template parameters to scope. 639 HasTemplateScope = D->isTemplateDecl(); 640 TempScope = 641 new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope); 642 if (HasTemplateScope) 643 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D); 644 645 // If the Decl is on a function, add function parameters to the scope. 646 HasFunScope = D->isFunctionOrFunctionTemplate(); 647 FnScope = new Parser::ParseScope( 648 &P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope, 649 HasFunScope); 650 if (HasFunScope) 651 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D); 652 } 653 ~FNContextRAII() { 654 if (HasFunScope) { 655 P.getActions().ActOnExitFunctionContext(); 656 FnScope->Exit(); // Pop scope, and remove Decls from IdResolver 657 } 658 if (HasTemplateScope) 659 TempScope->Exit(); 660 delete FnScope; 661 delete TempScope; 662 delete ThisScope; 663 } 664 }; 665 } // namespace 666 667 /// Parses clauses for 'declare simd' directive. 668 /// clause: 669 /// 'inbranch' | 'notinbranch' 670 /// 'simdlen' '(' <expr> ')' 671 /// { 'uniform' '(' <argument_list> ')' } 672 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' } 673 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' } 674 static bool parseDeclareSimdClauses( 675 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, 676 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds, 677 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears, 678 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) { 679 SourceRange BSRange; 680 const Token &Tok = P.getCurToken(); 681 bool IsError = false; 682 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 683 if (Tok.isNot(tok::identifier)) 684 break; 685 OMPDeclareSimdDeclAttr::BranchStateTy Out; 686 IdentifierInfo *II = Tok.getIdentifierInfo(); 687 StringRef ClauseName = II->getName(); 688 // Parse 'inranch|notinbranch' clauses. 689 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { 690 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { 691 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) 692 << ClauseName 693 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; 694 IsError = true; 695 } 696 BS = Out; 697 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); 698 P.ConsumeToken(); 699 } else if (ClauseName.equals("simdlen")) { 700 if (SimdLen.isUsable()) { 701 P.Diag(Tok, diag::err_omp_more_one_clause) 702 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; 703 IsError = true; 704 } 705 P.ConsumeToken(); 706 SourceLocation RLoc; 707 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); 708 if (SimdLen.isInvalid()) 709 IsError = true; 710 } else { 711 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); 712 if (CKind == OMPC_uniform || CKind == OMPC_aligned || 713 CKind == OMPC_linear) { 714 Parser::OpenMPVarListDataTy Data; 715 SmallVectorImpl<Expr *> *Vars = &Uniforms; 716 if (CKind == OMPC_aligned) 717 Vars = &Aligneds; 718 else if (CKind == OMPC_linear) 719 Vars = &Linears; 720 721 P.ConsumeToken(); 722 if (P.ParseOpenMPVarList(OMPD_declare_simd, 723 getOpenMPClauseKind(ClauseName), *Vars, Data)) 724 IsError = true; 725 if (CKind == OMPC_aligned) { 726 Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr); 727 } else if (CKind == OMPC_linear) { 728 if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind, 729 Data.DepLinMapLoc)) 730 Data.LinKind = OMPC_LINEAR_val; 731 LinModifiers.append(Linears.size() - LinModifiers.size(), 732 Data.LinKind); 733 Steps.append(Linears.size() - Steps.size(), Data.TailExpr); 734 } 735 } else 736 // TODO: add parsing of other clauses. 737 break; 738 } 739 // Skip ',' if any. 740 if (Tok.is(tok::comma)) 741 P.ConsumeToken(); 742 } 743 return IsError; 744 } 745 746 /// Parse clauses for '#pragma omp declare simd'. 747 Parser::DeclGroupPtrTy 748 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, 749 CachedTokens &Toks, SourceLocation Loc) { 750 PP.EnterToken(Tok); 751 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true); 752 // Consume the previously pushed token. 753 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 754 755 FNContextRAII FnContext(*this, Ptr); 756 OMPDeclareSimdDeclAttr::BranchStateTy BS = 757 OMPDeclareSimdDeclAttr::BS_Undefined; 758 ExprResult Simdlen; 759 SmallVector<Expr *, 4> Uniforms; 760 SmallVector<Expr *, 4> Aligneds; 761 SmallVector<Expr *, 4> Alignments; 762 SmallVector<Expr *, 4> Linears; 763 SmallVector<unsigned, 4> LinModifiers; 764 SmallVector<Expr *, 4> Steps; 765 bool IsError = 766 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds, 767 Alignments, Linears, LinModifiers, Steps); 768 // Need to check for extra tokens. 769 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 770 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 771 << getOpenMPDirectiveName(OMPD_declare_simd); 772 while (Tok.isNot(tok::annot_pragma_openmp_end)) 773 ConsumeAnyToken(); 774 } 775 // Skip the last annot_pragma_openmp_end. 776 SourceLocation EndLoc = ConsumeAnnotationToken(); 777 if (IsError) 778 return Ptr; 779 return Actions.ActOnOpenMPDeclareSimdDirective( 780 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, 781 LinModifiers, Steps, SourceRange(Loc, EndLoc)); 782 } 783 784 Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() { 785 // OpenMP 4.5 syntax with list of entities. 786 Sema::NamedDeclSetType SameDirectiveDecls; 787 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 788 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; 789 if (Tok.is(tok::identifier)) { 790 IdentifierInfo *II = Tok.getIdentifierInfo(); 791 StringRef ClauseName = II->getName(); 792 // Parse 'to|link' clauses. 793 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT)) { 794 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) << ClauseName; 795 break; 796 } 797 ConsumeToken(); 798 } 799 auto &&Callback = [this, MT, &SameDirectiveDecls]( 800 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 801 Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT, 802 SameDirectiveDecls); 803 }; 804 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, 805 /*AllowScopeSpecifier=*/true)) 806 break; 807 808 // Consume optional ','. 809 if (Tok.is(tok::comma)) 810 ConsumeToken(); 811 } 812 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 813 ConsumeAnyToken(); 814 SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), 815 SameDirectiveDecls.end()); 816 if (Decls.empty()) 817 return DeclGroupPtrTy(); 818 return Actions.BuildDeclaratorGroup(Decls); 819 } 820 821 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind, 822 SourceLocation DTLoc) { 823 if (DKind != OMPD_end_declare_target) { 824 Diag(Tok, diag::err_expected_end_declare_target); 825 Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'"; 826 return; 827 } 828 ConsumeAnyToken(); 829 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 830 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 831 << getOpenMPDirectiveName(OMPD_end_declare_target); 832 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 833 } 834 // Skip the last annot_pragma_openmp_end. 835 ConsumeAnyToken(); 836 } 837 838 /// Parsing of declarative OpenMP directives. 839 /// 840 /// threadprivate-directive: 841 /// annot_pragma_openmp 'threadprivate' simple-variable-list 842 /// annot_pragma_openmp_end 843 /// 844 /// allocate-directive: 845 /// annot_pragma_openmp 'allocate' simple-variable-list 846 /// annot_pragma_openmp_end 847 /// 848 /// declare-reduction-directive: 849 /// annot_pragma_openmp 'declare' 'reduction' [...] 850 /// annot_pragma_openmp_end 851 /// 852 /// declare-mapper-directive: 853 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 854 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 855 /// annot_pragma_openmp_end 856 /// 857 /// declare-simd-directive: 858 /// annot_pragma_openmp 'declare simd' {<clause> [,]} 859 /// annot_pragma_openmp_end 860 /// <function declaration/definition> 861 /// 862 /// requires directive: 863 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] 864 /// annot_pragma_openmp_end 865 /// 866 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 867 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, 868 DeclSpec::TST TagType, Decl *Tag) { 869 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 870 ParenBraceBracketBalancer BalancerRAIIObj(*this); 871 872 SourceLocation Loc = ConsumeAnnotationToken(); 873 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 874 875 switch (DKind) { 876 case OMPD_threadprivate: { 877 ConsumeToken(); 878 DeclDirectiveListParserHelper Helper(this, DKind); 879 if (!ParseOpenMPSimpleVarList(DKind, Helper, 880 /*AllowScopeSpecifier=*/true)) { 881 // The last seen token is annot_pragma_openmp_end - need to check for 882 // extra tokens. 883 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 884 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 885 << getOpenMPDirectiveName(DKind); 886 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 887 } 888 // Skip the last annot_pragma_openmp_end. 889 ConsumeAnnotationToken(); 890 return Actions.ActOnOpenMPThreadprivateDirective(Loc, 891 Helper.getIdentifiers()); 892 } 893 break; 894 } 895 case OMPD_allocate: { 896 ConsumeToken(); 897 DeclDirectiveListParserHelper Helper(this, DKind); 898 if (!ParseOpenMPSimpleVarList(DKind, Helper, 899 /*AllowScopeSpecifier=*/true)) { 900 // The last seen token is annot_pragma_openmp_end - need to check for 901 // extra tokens. 902 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 903 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 904 << getOpenMPDirectiveName(DKind); 905 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 906 } 907 // Skip the last annot_pragma_openmp_end. 908 ConsumeAnnotationToken(); 909 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers()); 910 } 911 break; 912 } 913 case OMPD_requires: { 914 SourceLocation StartLoc = ConsumeToken(); 915 SmallVector<OMPClause *, 5> Clauses; 916 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> 917 FirstClauses(OMPC_unknown + 1); 918 if (Tok.is(tok::annot_pragma_openmp_end)) { 919 Diag(Tok, diag::err_omp_expected_clause) 920 << getOpenMPDirectiveName(OMPD_requires); 921 break; 922 } 923 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 924 OpenMPClauseKind CKind = Tok.isAnnotation() 925 ? OMPC_unknown 926 : getOpenMPClauseKind(PP.getSpelling(Tok)); 927 Actions.StartOpenMPClause(CKind); 928 OMPClause *Clause = 929 ParseOpenMPClause(OMPD_requires, CKind, !FirstClauses[CKind].getInt()); 930 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, StopBeforeMatch); 931 FirstClauses[CKind].setInt(true); 932 if (Clause != nullptr) 933 Clauses.push_back(Clause); 934 if (Tok.is(tok::annot_pragma_openmp_end)) { 935 Actions.EndOpenMPClause(); 936 break; 937 } 938 // Skip ',' if any. 939 if (Tok.is(tok::comma)) 940 ConsumeToken(); 941 Actions.EndOpenMPClause(); 942 } 943 // Consume final annot_pragma_openmp_end 944 if (Clauses.size() == 0) { 945 Diag(Tok, diag::err_omp_expected_clause) 946 << getOpenMPDirectiveName(OMPD_requires); 947 ConsumeAnnotationToken(); 948 return nullptr; 949 } 950 ConsumeAnnotationToken(); 951 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); 952 } 953 case OMPD_declare_reduction: 954 ConsumeToken(); 955 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { 956 // The last seen token is annot_pragma_openmp_end - need to check for 957 // extra tokens. 958 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 959 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 960 << getOpenMPDirectiveName(OMPD_declare_reduction); 961 while (Tok.isNot(tok::annot_pragma_openmp_end)) 962 ConsumeAnyToken(); 963 } 964 // Skip the last annot_pragma_openmp_end. 965 ConsumeAnnotationToken(); 966 return Res; 967 } 968 break; 969 case OMPD_declare_mapper: { 970 ConsumeToken(); 971 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) { 972 // Skip the last annot_pragma_openmp_end. 973 ConsumeAnnotationToken(); 974 return Res; 975 } 976 break; 977 } 978 case OMPD_declare_simd: { 979 // The syntax is: 980 // { #pragma omp declare simd } 981 // <function-declaration-or-definition> 982 // 983 ConsumeToken(); 984 CachedTokens Toks; 985 while(Tok.isNot(tok::annot_pragma_openmp_end)) { 986 Toks.push_back(Tok); 987 ConsumeAnyToken(); 988 } 989 Toks.push_back(Tok); 990 ConsumeAnyToken(); 991 992 DeclGroupPtrTy Ptr; 993 if (Tok.is(tok::annot_pragma_openmp)) { 994 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag); 995 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 996 // Here we expect to see some function declaration. 997 if (AS == AS_none) { 998 assert(TagType == DeclSpec::TST_unspecified); 999 MaybeParseCXX11Attributes(Attrs); 1000 ParsingDeclSpec PDS(*this); 1001 Ptr = ParseExternalDeclaration(Attrs, &PDS); 1002 } else { 1003 Ptr = 1004 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1005 } 1006 } 1007 if (!Ptr) { 1008 Diag(Loc, diag::err_omp_decl_in_declare_simd); 1009 return DeclGroupPtrTy(); 1010 } 1011 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 1012 } 1013 case OMPD_declare_target: { 1014 SourceLocation DTLoc = ConsumeAnyToken(); 1015 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1016 return ParseOMPDeclareTargetClauses(); 1017 } 1018 1019 // Skip the last annot_pragma_openmp_end. 1020 ConsumeAnyToken(); 1021 1022 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc)) 1023 return DeclGroupPtrTy(); 1024 1025 llvm::SmallVector<Decl *, 4> Decls; 1026 DKind = parseOpenMPDirectiveKind(*this); 1027 while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) && 1028 Tok.isNot(tok::r_brace)) { 1029 DeclGroupPtrTy Ptr; 1030 // Here we expect to see some function declaration. 1031 if (AS == AS_none) { 1032 assert(TagType == DeclSpec::TST_unspecified); 1033 MaybeParseCXX11Attributes(Attrs); 1034 ParsingDeclSpec PDS(*this); 1035 Ptr = ParseExternalDeclaration(Attrs, &PDS); 1036 } else { 1037 Ptr = 1038 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1039 } 1040 if (Ptr) { 1041 DeclGroupRef Ref = Ptr.get(); 1042 Decls.append(Ref.begin(), Ref.end()); 1043 } 1044 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { 1045 TentativeParsingAction TPA(*this); 1046 ConsumeAnnotationToken(); 1047 DKind = parseOpenMPDirectiveKind(*this); 1048 if (DKind != OMPD_end_declare_target) 1049 TPA.Revert(); 1050 else 1051 TPA.Commit(); 1052 } 1053 } 1054 1055 ParseOMPEndDeclareTargetDirective(DKind, DTLoc); 1056 Actions.ActOnFinishOpenMPDeclareTargetDirective(); 1057 return Actions.BuildDeclaratorGroup(Decls); 1058 } 1059 case OMPD_unknown: 1060 Diag(Tok, diag::err_omp_unknown_directive); 1061 break; 1062 case OMPD_parallel: 1063 case OMPD_simd: 1064 case OMPD_task: 1065 case OMPD_taskyield: 1066 case OMPD_barrier: 1067 case OMPD_taskwait: 1068 case OMPD_taskgroup: 1069 case OMPD_flush: 1070 case OMPD_for: 1071 case OMPD_for_simd: 1072 case OMPD_sections: 1073 case OMPD_section: 1074 case OMPD_single: 1075 case OMPD_master: 1076 case OMPD_ordered: 1077 case OMPD_critical: 1078 case OMPD_parallel_for: 1079 case OMPD_parallel_for_simd: 1080 case OMPD_parallel_sections: 1081 case OMPD_atomic: 1082 case OMPD_target: 1083 case OMPD_teams: 1084 case OMPD_cancellation_point: 1085 case OMPD_cancel: 1086 case OMPD_target_data: 1087 case OMPD_target_enter_data: 1088 case OMPD_target_exit_data: 1089 case OMPD_target_parallel: 1090 case OMPD_target_parallel_for: 1091 case OMPD_taskloop: 1092 case OMPD_taskloop_simd: 1093 case OMPD_distribute: 1094 case OMPD_end_declare_target: 1095 case OMPD_target_update: 1096 case OMPD_distribute_parallel_for: 1097 case OMPD_distribute_parallel_for_simd: 1098 case OMPD_distribute_simd: 1099 case OMPD_target_parallel_for_simd: 1100 case OMPD_target_simd: 1101 case OMPD_teams_distribute: 1102 case OMPD_teams_distribute_simd: 1103 case OMPD_teams_distribute_parallel_for_simd: 1104 case OMPD_teams_distribute_parallel_for: 1105 case OMPD_target_teams: 1106 case OMPD_target_teams_distribute: 1107 case OMPD_target_teams_distribute_parallel_for: 1108 case OMPD_target_teams_distribute_parallel_for_simd: 1109 case OMPD_target_teams_distribute_simd: 1110 Diag(Tok, diag::err_omp_unexpected_directive) 1111 << 1 << getOpenMPDirectiveName(DKind); 1112 break; 1113 } 1114 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1115 ConsumeAnyToken(); 1116 ConsumeAnyToken(); 1117 return nullptr; 1118 } 1119 1120 /// Parsing of declarative or executable OpenMP directives. 1121 /// 1122 /// threadprivate-directive: 1123 /// annot_pragma_openmp 'threadprivate' simple-variable-list 1124 /// annot_pragma_openmp_end 1125 /// 1126 /// allocate-directive: 1127 /// annot_pragma_openmp 'allocate' simple-variable-list 1128 /// annot_pragma_openmp_end 1129 /// 1130 /// declare-reduction-directive: 1131 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 1132 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 1133 /// ('omp_priv' '=' <expression>|<function_call>) ')'] 1134 /// annot_pragma_openmp_end 1135 /// 1136 /// declare-mapper-directive: 1137 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 1138 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 1139 /// annot_pragma_openmp_end 1140 /// 1141 /// executable-directive: 1142 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 1143 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 1144 /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | 1145 /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | 1146 /// 'for simd' | 'parallel for simd' | 'target' | 'target data' | 1147 /// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 1148 /// 'distribute' | 'target enter data' | 'target exit data' | 1149 /// 'target parallel' | 'target parallel for' | 1150 /// 'target update' | 'distribute parallel for' | 1151 /// 'distribute paralle for simd' | 'distribute simd' | 1152 /// 'target parallel for simd' | 'target simd' | 1153 /// 'teams distribute' | 'teams distribute simd' | 1154 /// 'teams distribute parallel for simd' | 1155 /// 'teams distribute parallel for' | 'target teams' | 1156 /// 'target teams distribute' | 1157 /// 'target teams distribute parallel for' | 1158 /// 'target teams distribute parallel for simd' | 1159 /// 'target teams distribute simd' {clause} 1160 /// annot_pragma_openmp_end 1161 /// 1162 StmtResult 1163 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { 1164 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 1165 ParenBraceBracketBalancer BalancerRAIIObj(*this); 1166 SmallVector<OMPClause *, 5> Clauses; 1167 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1> 1168 FirstClauses(OMPC_unknown + 1); 1169 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 1170 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 1171 SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; 1172 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 1173 OpenMPDirectiveKind CancelRegion = OMPD_unknown; 1174 // Name of critical directive. 1175 DeclarationNameInfo DirName; 1176 StmtResult Directive = StmtError(); 1177 bool HasAssociatedStatement = true; 1178 bool FlushHasClause = false; 1179 1180 switch (DKind) { 1181 case OMPD_threadprivate: { 1182 // FIXME: Should this be permitted in C++? 1183 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 1184 ParsedStmtContext()) { 1185 Diag(Tok, diag::err_omp_immediate_directive) 1186 << getOpenMPDirectiveName(DKind) << 0; 1187 } 1188 ConsumeToken(); 1189 DeclDirectiveListParserHelper Helper(this, DKind); 1190 if (!ParseOpenMPSimpleVarList(DKind, Helper, 1191 /*AllowScopeSpecifier=*/false)) { 1192 // The last seen token is annot_pragma_openmp_end - need to check for 1193 // extra tokens. 1194 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1195 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1196 << getOpenMPDirectiveName(DKind); 1197 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1198 } 1199 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 1200 Loc, Helper.getIdentifiers()); 1201 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1202 } 1203 SkipUntil(tok::annot_pragma_openmp_end); 1204 break; 1205 } 1206 case OMPD_allocate: { 1207 // FIXME: Should this be permitted in C++? 1208 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 1209 ParsedStmtContext()) { 1210 Diag(Tok, diag::err_omp_immediate_directive) 1211 << getOpenMPDirectiveName(DKind) << 0; 1212 } 1213 ConsumeToken(); 1214 DeclDirectiveListParserHelper Helper(this, DKind); 1215 if (!ParseOpenMPSimpleVarList(DKind, Helper, 1216 /*AllowScopeSpecifier=*/false)) { 1217 // The last seen token is annot_pragma_openmp_end - need to check for 1218 // extra tokens. 1219 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1220 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1221 << getOpenMPDirectiveName(DKind); 1222 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1223 } 1224 DeclGroupPtrTy Res = 1225 Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers()); 1226 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1227 } 1228 SkipUntil(tok::annot_pragma_openmp_end); 1229 break; 1230 } 1231 case OMPD_declare_reduction: 1232 ConsumeToken(); 1233 if (DeclGroupPtrTy Res = 1234 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 1235 // The last seen token is annot_pragma_openmp_end - need to check for 1236 // extra tokens. 1237 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1238 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1239 << getOpenMPDirectiveName(OMPD_declare_reduction); 1240 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1241 ConsumeAnyToken(); 1242 } 1243 ConsumeAnyToken(); 1244 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1245 } else { 1246 SkipUntil(tok::annot_pragma_openmp_end); 1247 } 1248 break; 1249 case OMPD_declare_mapper: { 1250 ConsumeToken(); 1251 if (DeclGroupPtrTy Res = 1252 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) { 1253 // Skip the last annot_pragma_openmp_end. 1254 ConsumeAnnotationToken(); 1255 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1256 } else { 1257 SkipUntil(tok::annot_pragma_openmp_end); 1258 } 1259 break; 1260 } 1261 case OMPD_flush: 1262 if (PP.LookAhead(0).is(tok::l_paren)) { 1263 FlushHasClause = true; 1264 // Push copy of the current token back to stream to properly parse 1265 // pseudo-clause OMPFlushClause. 1266 PP.EnterToken(Tok); 1267 } 1268 LLVM_FALLTHROUGH; 1269 case OMPD_taskyield: 1270 case OMPD_barrier: 1271 case OMPD_taskwait: 1272 case OMPD_cancellation_point: 1273 case OMPD_cancel: 1274 case OMPD_target_enter_data: 1275 case OMPD_target_exit_data: 1276 case OMPD_target_update: 1277 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 1278 ParsedStmtContext()) { 1279 Diag(Tok, diag::err_omp_immediate_directive) 1280 << getOpenMPDirectiveName(DKind) << 0; 1281 } 1282 HasAssociatedStatement = false; 1283 // Fall through for further analysis. 1284 LLVM_FALLTHROUGH; 1285 case OMPD_parallel: 1286 case OMPD_simd: 1287 case OMPD_for: 1288 case OMPD_for_simd: 1289 case OMPD_sections: 1290 case OMPD_single: 1291 case OMPD_section: 1292 case OMPD_master: 1293 case OMPD_critical: 1294 case OMPD_parallel_for: 1295 case OMPD_parallel_for_simd: 1296 case OMPD_parallel_sections: 1297 case OMPD_task: 1298 case OMPD_ordered: 1299 case OMPD_atomic: 1300 case OMPD_target: 1301 case OMPD_teams: 1302 case OMPD_taskgroup: 1303 case OMPD_target_data: 1304 case OMPD_target_parallel: 1305 case OMPD_target_parallel_for: 1306 case OMPD_taskloop: 1307 case OMPD_taskloop_simd: 1308 case OMPD_distribute: 1309 case OMPD_distribute_parallel_for: 1310 case OMPD_distribute_parallel_for_simd: 1311 case OMPD_distribute_simd: 1312 case OMPD_target_parallel_for_simd: 1313 case OMPD_target_simd: 1314 case OMPD_teams_distribute: 1315 case OMPD_teams_distribute_simd: 1316 case OMPD_teams_distribute_parallel_for_simd: 1317 case OMPD_teams_distribute_parallel_for: 1318 case OMPD_target_teams: 1319 case OMPD_target_teams_distribute: 1320 case OMPD_target_teams_distribute_parallel_for: 1321 case OMPD_target_teams_distribute_parallel_for_simd: 1322 case OMPD_target_teams_distribute_simd: { 1323 ConsumeToken(); 1324 // Parse directive name of the 'critical' directive if any. 1325 if (DKind == OMPD_critical) { 1326 BalancedDelimiterTracker T(*this, tok::l_paren, 1327 tok::annot_pragma_openmp_end); 1328 if (!T.consumeOpen()) { 1329 if (Tok.isAnyIdentifier()) { 1330 DirName = 1331 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 1332 ConsumeAnyToken(); 1333 } else { 1334 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 1335 } 1336 T.consumeClose(); 1337 } 1338 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 1339 CancelRegion = parseOpenMPDirectiveKind(*this); 1340 if (Tok.isNot(tok::annot_pragma_openmp_end)) 1341 ConsumeToken(); 1342 } 1343 1344 if (isOpenMPLoopDirective(DKind)) 1345 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 1346 if (isOpenMPSimdDirective(DKind)) 1347 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 1348 ParseScope OMPDirectiveScope(this, ScopeFlags); 1349 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 1350 1351 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1352 OpenMPClauseKind CKind = 1353 Tok.isAnnotation() 1354 ? OMPC_unknown 1355 : FlushHasClause ? OMPC_flush 1356 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1357 Actions.StartOpenMPClause(CKind); 1358 FlushHasClause = false; 1359 OMPClause *Clause = 1360 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); 1361 FirstClauses[CKind].setInt(true); 1362 if (Clause) { 1363 FirstClauses[CKind].setPointer(Clause); 1364 Clauses.push_back(Clause); 1365 } 1366 1367 // Skip ',' if any. 1368 if (Tok.is(tok::comma)) 1369 ConsumeToken(); 1370 Actions.EndOpenMPClause(); 1371 } 1372 // End location of the directive. 1373 EndLoc = Tok.getLocation(); 1374 // Consume final annot_pragma_openmp_end. 1375 ConsumeAnnotationToken(); 1376 1377 // OpenMP [2.13.8, ordered Construct, Syntax] 1378 // If the depend clause is specified, the ordered construct is a stand-alone 1379 // directive. 1380 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) { 1381 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 1382 ParsedStmtContext()) { 1383 Diag(Loc, diag::err_omp_immediate_directive) 1384 << getOpenMPDirectiveName(DKind) << 1 1385 << getOpenMPClauseName(OMPC_depend); 1386 } 1387 HasAssociatedStatement = false; 1388 } 1389 1390 StmtResult AssociatedStmt; 1391 if (HasAssociatedStatement) { 1392 // The body is a block scope like in Lambdas and Blocks. 1393 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 1394 // FIXME: We create a bogus CompoundStmt scope to hold the contents of 1395 // the captured region. Code elsewhere assumes that any FunctionScopeInfo 1396 // should have at least one compound statement scope within it. 1397 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement()); 1398 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1399 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 1400 DKind == OMPD_target_exit_data) { 1401 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 1402 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 1403 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, 1404 /*isStmtExpr=*/false)); 1405 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1406 } 1407 Directive = Actions.ActOnOpenMPExecutableDirective( 1408 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 1409 EndLoc); 1410 1411 // Exit scope. 1412 Actions.EndOpenMPDSABlock(Directive.get()); 1413 OMPDirectiveScope.Exit(); 1414 break; 1415 } 1416 case OMPD_declare_simd: 1417 case OMPD_declare_target: 1418 case OMPD_end_declare_target: 1419 case OMPD_requires: 1420 Diag(Tok, diag::err_omp_unexpected_directive) 1421 << 1 << getOpenMPDirectiveName(DKind); 1422 SkipUntil(tok::annot_pragma_openmp_end); 1423 break; 1424 case OMPD_unknown: 1425 Diag(Tok, diag::err_omp_unknown_directive); 1426 SkipUntil(tok::annot_pragma_openmp_end); 1427 break; 1428 } 1429 return Directive; 1430 } 1431 1432 // Parses simple list: 1433 // simple-variable-list: 1434 // '(' id-expression {, id-expression} ')' 1435 // 1436 bool Parser::ParseOpenMPSimpleVarList( 1437 OpenMPDirectiveKind Kind, 1438 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & 1439 Callback, 1440 bool AllowScopeSpecifier) { 1441 // Parse '('. 1442 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1443 if (T.expectAndConsume(diag::err_expected_lparen_after, 1444 getOpenMPDirectiveName(Kind))) 1445 return true; 1446 bool IsCorrect = true; 1447 bool NoIdentIsFound = true; 1448 1449 // Read tokens while ')' or annot_pragma_openmp_end is not found. 1450 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 1451 CXXScopeSpec SS; 1452 UnqualifiedId Name; 1453 // Read var name. 1454 Token PrevTok = Tok; 1455 NoIdentIsFound = false; 1456 1457 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 1458 ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) { 1459 IsCorrect = false; 1460 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1461 StopBeforeMatch); 1462 } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr, 1463 nullptr, Name)) { 1464 IsCorrect = false; 1465 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1466 StopBeforeMatch); 1467 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 1468 Tok.isNot(tok::annot_pragma_openmp_end)) { 1469 IsCorrect = false; 1470 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1471 StopBeforeMatch); 1472 Diag(PrevTok.getLocation(), diag::err_expected) 1473 << tok::identifier 1474 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 1475 } else { 1476 Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 1477 } 1478 // Consume ','. 1479 if (Tok.is(tok::comma)) { 1480 ConsumeToken(); 1481 } 1482 } 1483 1484 if (NoIdentIsFound) { 1485 Diag(Tok, diag::err_expected) << tok::identifier; 1486 IsCorrect = false; 1487 } 1488 1489 // Parse ')'. 1490 IsCorrect = !T.consumeClose() && IsCorrect; 1491 1492 return !IsCorrect; 1493 } 1494 1495 /// Parsing of OpenMP clauses. 1496 /// 1497 /// clause: 1498 /// if-clause | final-clause | num_threads-clause | safelen-clause | 1499 /// default-clause | private-clause | firstprivate-clause | shared-clause 1500 /// | linear-clause | aligned-clause | collapse-clause | 1501 /// lastprivate-clause | reduction-clause | proc_bind-clause | 1502 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 1503 /// mergeable-clause | flush-clause | read-clause | write-clause | 1504 /// update-clause | capture-clause | seq_cst-clause | device-clause | 1505 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 1506 /// thread_limit-clause | priority-clause | grainsize-clause | 1507 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 1508 /// from-clause | is_device_ptr-clause | task_reduction-clause | 1509 /// in_reduction-clause 1510 /// 1511 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 1512 OpenMPClauseKind CKind, bool FirstClause) { 1513 OMPClause *Clause = nullptr; 1514 bool ErrorFound = false; 1515 bool WrongDirective = false; 1516 // Check if clause is allowed for the given directive. 1517 if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { 1518 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 1519 << getOpenMPDirectiveName(DKind); 1520 ErrorFound = true; 1521 WrongDirective = true; 1522 } 1523 1524 switch (CKind) { 1525 case OMPC_final: 1526 case OMPC_num_threads: 1527 case OMPC_safelen: 1528 case OMPC_simdlen: 1529 case OMPC_collapse: 1530 case OMPC_ordered: 1531 case OMPC_device: 1532 case OMPC_num_teams: 1533 case OMPC_thread_limit: 1534 case OMPC_priority: 1535 case OMPC_grainsize: 1536 case OMPC_num_tasks: 1537 case OMPC_hint: 1538 // OpenMP [2.5, Restrictions] 1539 // At most one num_threads clause can appear on the directive. 1540 // OpenMP [2.8.1, simd construct, Restrictions] 1541 // Only one safelen clause can appear on a simd directive. 1542 // Only one simdlen clause can appear on a simd directive. 1543 // Only one collapse clause can appear on a simd directive. 1544 // OpenMP [2.9.1, target data construct, Restrictions] 1545 // At most one device clause can appear on the directive. 1546 // OpenMP [2.11.1, task Construct, Restrictions] 1547 // At most one if clause can appear on the directive. 1548 // At most one final clause can appear on the directive. 1549 // OpenMP [teams Construct, Restrictions] 1550 // At most one num_teams clause can appear on the directive. 1551 // At most one thread_limit clause can appear on the directive. 1552 // OpenMP [2.9.1, task Construct, Restrictions] 1553 // At most one priority clause can appear on the directive. 1554 // OpenMP [2.9.2, taskloop Construct, Restrictions] 1555 // At most one grainsize clause can appear on the directive. 1556 // OpenMP [2.9.2, taskloop Construct, Restrictions] 1557 // At most one num_tasks clause can appear on the directive. 1558 if (!FirstClause) { 1559 Diag(Tok, diag::err_omp_more_one_clause) 1560 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1561 ErrorFound = true; 1562 } 1563 1564 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 1565 Clause = ParseOpenMPClause(CKind, WrongDirective); 1566 else 1567 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 1568 break; 1569 case OMPC_default: 1570 case OMPC_proc_bind: 1571 case OMPC_atomic_default_mem_order: 1572 // OpenMP [2.14.3.1, Restrictions] 1573 // Only a single default clause may be specified on a parallel, task or 1574 // teams directive. 1575 // OpenMP [2.5, parallel Construct, Restrictions] 1576 // At most one proc_bind clause can appear on the directive. 1577 // OpenMP [5.0, Requires directive, Restrictions] 1578 // At most one atomic_default_mem_order clause can appear 1579 // on the directive 1580 if (!FirstClause) { 1581 Diag(Tok, diag::err_omp_more_one_clause) 1582 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1583 ErrorFound = true; 1584 } 1585 1586 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 1587 break; 1588 case OMPC_schedule: 1589 case OMPC_dist_schedule: 1590 case OMPC_defaultmap: 1591 // OpenMP [2.7.1, Restrictions, p. 3] 1592 // Only one schedule clause can appear on a loop directive. 1593 // OpenMP [2.10.4, Restrictions, p. 106] 1594 // At most one defaultmap clause can appear on the directive. 1595 if (!FirstClause) { 1596 Diag(Tok, diag::err_omp_more_one_clause) 1597 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1598 ErrorFound = true; 1599 } 1600 LLVM_FALLTHROUGH; 1601 1602 case OMPC_if: 1603 Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective); 1604 break; 1605 case OMPC_nowait: 1606 case OMPC_untied: 1607 case OMPC_mergeable: 1608 case OMPC_read: 1609 case OMPC_write: 1610 case OMPC_update: 1611 case OMPC_capture: 1612 case OMPC_seq_cst: 1613 case OMPC_threads: 1614 case OMPC_simd: 1615 case OMPC_nogroup: 1616 case OMPC_unified_address: 1617 case OMPC_unified_shared_memory: 1618 case OMPC_reverse_offload: 1619 case OMPC_dynamic_allocators: 1620 // OpenMP [2.7.1, Restrictions, p. 9] 1621 // Only one ordered clause can appear on a loop directive. 1622 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 1623 // Only one nowait clause can appear on a for directive. 1624 // OpenMP [5.0, Requires directive, Restrictions] 1625 // Each of the requires clauses can appear at most once on the directive. 1626 if (!FirstClause) { 1627 Diag(Tok, diag::err_omp_more_one_clause) 1628 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 1629 ErrorFound = true; 1630 } 1631 1632 Clause = ParseOpenMPClause(CKind, WrongDirective); 1633 break; 1634 case OMPC_private: 1635 case OMPC_firstprivate: 1636 case OMPC_lastprivate: 1637 case OMPC_shared: 1638 case OMPC_reduction: 1639 case OMPC_task_reduction: 1640 case OMPC_in_reduction: 1641 case OMPC_linear: 1642 case OMPC_aligned: 1643 case OMPC_copyin: 1644 case OMPC_copyprivate: 1645 case OMPC_flush: 1646 case OMPC_depend: 1647 case OMPC_map: 1648 case OMPC_to: 1649 case OMPC_from: 1650 case OMPC_use_device_ptr: 1651 case OMPC_is_device_ptr: 1652 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 1653 break; 1654 case OMPC_unknown: 1655 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1656 << getOpenMPDirectiveName(DKind); 1657 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1658 break; 1659 case OMPC_threadprivate: 1660 case OMPC_allocate: 1661 case OMPC_uniform: 1662 if (!WrongDirective) 1663 Diag(Tok, diag::err_omp_unexpected_clause) 1664 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 1665 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 1666 break; 1667 } 1668 return ErrorFound ? nullptr : Clause; 1669 } 1670 1671 /// Parses simple expression in parens for single-expression clauses of OpenMP 1672 /// constructs. 1673 /// \param RLoc Returned location of right paren. 1674 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 1675 SourceLocation &RLoc) { 1676 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1677 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 1678 return ExprError(); 1679 1680 SourceLocation ELoc = Tok.getLocation(); 1681 ExprResult LHS(ParseCastExpression( 1682 /*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, NotTypeCast)); 1683 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 1684 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 1685 1686 // Parse ')'. 1687 RLoc = Tok.getLocation(); 1688 if (!T.consumeClose()) 1689 RLoc = T.getCloseLocation(); 1690 1691 return Val; 1692 } 1693 1694 /// Parsing of OpenMP clauses with single expressions like 'final', 1695 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 1696 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'. 1697 /// 1698 /// final-clause: 1699 /// 'final' '(' expression ')' 1700 /// 1701 /// num_threads-clause: 1702 /// 'num_threads' '(' expression ')' 1703 /// 1704 /// safelen-clause: 1705 /// 'safelen' '(' expression ')' 1706 /// 1707 /// simdlen-clause: 1708 /// 'simdlen' '(' expression ')' 1709 /// 1710 /// collapse-clause: 1711 /// 'collapse' '(' expression ')' 1712 /// 1713 /// priority-clause: 1714 /// 'priority' '(' expression ')' 1715 /// 1716 /// grainsize-clause: 1717 /// 'grainsize' '(' expression ')' 1718 /// 1719 /// num_tasks-clause: 1720 /// 'num_tasks' '(' expression ')' 1721 /// 1722 /// hint-clause: 1723 /// 'hint' '(' expression ')' 1724 /// 1725 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 1726 bool ParseOnly) { 1727 SourceLocation Loc = ConsumeToken(); 1728 SourceLocation LLoc = Tok.getLocation(); 1729 SourceLocation RLoc; 1730 1731 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 1732 1733 if (Val.isInvalid()) 1734 return nullptr; 1735 1736 if (ParseOnly) 1737 return nullptr; 1738 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 1739 } 1740 1741 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1742 /// 1743 /// default-clause: 1744 /// 'default' '(' 'none' | 'shared' ') 1745 /// 1746 /// proc_bind-clause: 1747 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1748 /// 1749 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 1750 bool ParseOnly) { 1751 SourceLocation Loc = Tok.getLocation(); 1752 SourceLocation LOpen = ConsumeToken(); 1753 // Parse '('. 1754 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1755 if (T.expectAndConsume(diag::err_expected_lparen_after, 1756 getOpenMPClauseName(Kind))) 1757 return nullptr; 1758 1759 unsigned Type = getOpenMPSimpleClauseType( 1760 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1761 SourceLocation TypeLoc = Tok.getLocation(); 1762 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1763 Tok.isNot(tok::annot_pragma_openmp_end)) 1764 ConsumeAnyToken(); 1765 1766 // Parse ')'. 1767 SourceLocation RLoc = Tok.getLocation(); 1768 if (!T.consumeClose()) 1769 RLoc = T.getCloseLocation(); 1770 1771 if (ParseOnly) 1772 return nullptr; 1773 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc); 1774 } 1775 1776 /// Parsing of OpenMP clauses like 'ordered'. 1777 /// 1778 /// ordered-clause: 1779 /// 'ordered' 1780 /// 1781 /// nowait-clause: 1782 /// 'nowait' 1783 /// 1784 /// untied-clause: 1785 /// 'untied' 1786 /// 1787 /// mergeable-clause: 1788 /// 'mergeable' 1789 /// 1790 /// read-clause: 1791 /// 'read' 1792 /// 1793 /// threads-clause: 1794 /// 'threads' 1795 /// 1796 /// simd-clause: 1797 /// 'simd' 1798 /// 1799 /// nogroup-clause: 1800 /// 'nogroup' 1801 /// 1802 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 1803 SourceLocation Loc = Tok.getLocation(); 1804 ConsumeAnyToken(); 1805 1806 if (ParseOnly) 1807 return nullptr; 1808 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 1809 } 1810 1811 1812 /// Parsing of OpenMP clauses with single expressions and some additional 1813 /// argument like 'schedule' or 'dist_schedule'. 1814 /// 1815 /// schedule-clause: 1816 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 1817 /// ')' 1818 /// 1819 /// if-clause: 1820 /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 1821 /// 1822 /// defaultmap: 1823 /// 'defaultmap' '(' modifier ':' kind ')' 1824 /// 1825 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, 1826 bool ParseOnly) { 1827 SourceLocation Loc = ConsumeToken(); 1828 SourceLocation DelimLoc; 1829 // Parse '('. 1830 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1831 if (T.expectAndConsume(diag::err_expected_lparen_after, 1832 getOpenMPClauseName(Kind))) 1833 return nullptr; 1834 1835 ExprResult Val; 1836 SmallVector<unsigned, 4> Arg; 1837 SmallVector<SourceLocation, 4> KLoc; 1838 if (Kind == OMPC_schedule) { 1839 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 1840 Arg.resize(NumberOfElements); 1841 KLoc.resize(NumberOfElements); 1842 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 1843 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 1844 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 1845 unsigned KindModifier = getOpenMPSimpleClauseType( 1846 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1847 if (KindModifier > OMPC_SCHEDULE_unknown) { 1848 // Parse 'modifier' 1849 Arg[Modifier1] = KindModifier; 1850 KLoc[Modifier1] = Tok.getLocation(); 1851 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1852 Tok.isNot(tok::annot_pragma_openmp_end)) 1853 ConsumeAnyToken(); 1854 if (Tok.is(tok::comma)) { 1855 // Parse ',' 'modifier' 1856 ConsumeAnyToken(); 1857 KindModifier = getOpenMPSimpleClauseType( 1858 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1859 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 1860 ? KindModifier 1861 : (unsigned)OMPC_SCHEDULE_unknown; 1862 KLoc[Modifier2] = Tok.getLocation(); 1863 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1864 Tok.isNot(tok::annot_pragma_openmp_end)) 1865 ConsumeAnyToken(); 1866 } 1867 // Parse ':' 1868 if (Tok.is(tok::colon)) 1869 ConsumeAnyToken(); 1870 else 1871 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 1872 KindModifier = getOpenMPSimpleClauseType( 1873 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 1874 } 1875 Arg[ScheduleKind] = KindModifier; 1876 KLoc[ScheduleKind] = Tok.getLocation(); 1877 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1878 Tok.isNot(tok::annot_pragma_openmp_end)) 1879 ConsumeAnyToken(); 1880 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 1881 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 1882 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 1883 Tok.is(tok::comma)) 1884 DelimLoc = ConsumeAnyToken(); 1885 } else if (Kind == OMPC_dist_schedule) { 1886 Arg.push_back(getOpenMPSimpleClauseType( 1887 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1888 KLoc.push_back(Tok.getLocation()); 1889 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1890 Tok.isNot(tok::annot_pragma_openmp_end)) 1891 ConsumeAnyToken(); 1892 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 1893 DelimLoc = ConsumeAnyToken(); 1894 } else if (Kind == OMPC_defaultmap) { 1895 // Get a defaultmap modifier 1896 Arg.push_back(getOpenMPSimpleClauseType( 1897 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1898 KLoc.push_back(Tok.getLocation()); 1899 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1900 Tok.isNot(tok::annot_pragma_openmp_end)) 1901 ConsumeAnyToken(); 1902 // Parse ':' 1903 if (Tok.is(tok::colon)) 1904 ConsumeAnyToken(); 1905 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 1906 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 1907 // Get a defaultmap kind 1908 Arg.push_back(getOpenMPSimpleClauseType( 1909 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 1910 KLoc.push_back(Tok.getLocation()); 1911 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1912 Tok.isNot(tok::annot_pragma_openmp_end)) 1913 ConsumeAnyToken(); 1914 } else { 1915 assert(Kind == OMPC_if); 1916 KLoc.push_back(Tok.getLocation()); 1917 TentativeParsingAction TPA(*this); 1918 Arg.push_back(parseOpenMPDirectiveKind(*this)); 1919 if (Arg.back() != OMPD_unknown) { 1920 ConsumeToken(); 1921 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 1922 TPA.Commit(); 1923 DelimLoc = ConsumeToken(); 1924 } else { 1925 TPA.Revert(); 1926 Arg.back() = OMPD_unknown; 1927 } 1928 } else { 1929 TPA.Revert(); 1930 } 1931 } 1932 1933 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 1934 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 1935 Kind == OMPC_if; 1936 if (NeedAnExpression) { 1937 SourceLocation ELoc = Tok.getLocation(); 1938 ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); 1939 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 1940 Val = 1941 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 1942 } 1943 1944 // Parse ')'. 1945 SourceLocation RLoc = Tok.getLocation(); 1946 if (!T.consumeClose()) 1947 RLoc = T.getCloseLocation(); 1948 1949 if (NeedAnExpression && Val.isInvalid()) 1950 return nullptr; 1951 1952 if (ParseOnly) 1953 return nullptr; 1954 return Actions.ActOnOpenMPSingleExprWithArgClause( 1955 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 1956 } 1957 1958 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 1959 UnqualifiedId &ReductionId) { 1960 if (ReductionIdScopeSpec.isEmpty()) { 1961 auto OOK = OO_None; 1962 switch (P.getCurToken().getKind()) { 1963 case tok::plus: 1964 OOK = OO_Plus; 1965 break; 1966 case tok::minus: 1967 OOK = OO_Minus; 1968 break; 1969 case tok::star: 1970 OOK = OO_Star; 1971 break; 1972 case tok::amp: 1973 OOK = OO_Amp; 1974 break; 1975 case tok::pipe: 1976 OOK = OO_Pipe; 1977 break; 1978 case tok::caret: 1979 OOK = OO_Caret; 1980 break; 1981 case tok::ampamp: 1982 OOK = OO_AmpAmp; 1983 break; 1984 case tok::pipepipe: 1985 OOK = OO_PipePipe; 1986 break; 1987 default: 1988 break; 1989 } 1990 if (OOK != OO_None) { 1991 SourceLocation OpLoc = P.ConsumeToken(); 1992 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 1993 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 1994 return false; 1995 } 1996 } 1997 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false, 1998 /*AllowDestructorName*/ false, 1999 /*AllowConstructorName*/ false, 2000 /*AllowDeductionGuide*/ false, 2001 nullptr, nullptr, ReductionId); 2002 } 2003 2004 /// Checks if the token is a valid map-type-modifier. 2005 static OpenMPMapModifierKind isMapModifier(Parser &P) { 2006 Token Tok = P.getCurToken(); 2007 if (!Tok.is(tok::identifier)) 2008 return OMPC_MAP_MODIFIER_unknown; 2009 2010 Preprocessor &PP = P.getPreprocessor(); 2011 OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>( 2012 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); 2013 return TypeModifier; 2014 } 2015 2016 /// Parse the mapper modifier in map, to, and from clauses. 2017 bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { 2018 // Parse '('. 2019 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); 2020 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { 2021 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2022 StopBeforeMatch); 2023 return true; 2024 } 2025 // Parse mapper-identifier 2026 if (getLangOpts().CPlusPlus) 2027 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 2028 /*ObjectType=*/nullptr, 2029 /*EnteringContext=*/false); 2030 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 2031 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 2032 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2033 StopBeforeMatch); 2034 return true; 2035 } 2036 auto &DeclNames = Actions.getASTContext().DeclarationNames; 2037 Data.ReductionOrMapperId = DeclarationNameInfo( 2038 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation()); 2039 ConsumeToken(); 2040 // Parse ')'. 2041 return T.consumeClose(); 2042 } 2043 2044 /// Parse map-type-modifiers in map clause. 2045 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 2046 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) 2047 bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) { 2048 while (getCurToken().isNot(tok::colon)) { 2049 OpenMPMapModifierKind TypeModifier = isMapModifier(*this); 2050 if (TypeModifier == OMPC_MAP_MODIFIER_always || 2051 TypeModifier == OMPC_MAP_MODIFIER_close) { 2052 Data.MapTypeModifiers.push_back(TypeModifier); 2053 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 2054 ConsumeToken(); 2055 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { 2056 Data.MapTypeModifiers.push_back(TypeModifier); 2057 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 2058 ConsumeToken(); 2059 if (parseMapperModifier(Data)) 2060 return true; 2061 } else { 2062 // For the case of unknown map-type-modifier or a map-type. 2063 // Map-type is followed by a colon; the function returns when it 2064 // encounters a token followed by a colon. 2065 if (Tok.is(tok::comma)) { 2066 Diag(Tok, diag::err_omp_map_type_modifier_missing); 2067 ConsumeToken(); 2068 continue; 2069 } 2070 // Potential map-type token as it is followed by a colon. 2071 if (PP.LookAhead(0).is(tok::colon)) 2072 return false; 2073 Diag(Tok, diag::err_omp_unknown_map_type_modifier); 2074 ConsumeToken(); 2075 } 2076 if (getCurToken().is(tok::comma)) 2077 ConsumeToken(); 2078 } 2079 return false; 2080 } 2081 2082 /// Checks if the token is a valid map-type. 2083 static OpenMPMapClauseKind isMapType(Parser &P) { 2084 Token Tok = P.getCurToken(); 2085 // The map-type token can be either an identifier or the C++ delete keyword. 2086 if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) 2087 return OMPC_MAP_unknown; 2088 Preprocessor &PP = P.getPreprocessor(); 2089 OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>( 2090 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); 2091 return MapType; 2092 } 2093 2094 /// Parse map-type in map clause. 2095 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 2096 /// where, map-type ::= to | from | tofrom | alloc | release | delete 2097 static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { 2098 Token Tok = P.getCurToken(); 2099 if (Tok.is(tok::colon)) { 2100 P.Diag(Tok, diag::err_omp_map_type_missing); 2101 return; 2102 } 2103 Data.MapType = isMapType(P); 2104 if (Data.MapType == OMPC_MAP_unknown) 2105 P.Diag(Tok, diag::err_omp_unknown_map_type); 2106 P.ConsumeToken(); 2107 } 2108 2109 /// Parses clauses with list. 2110 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 2111 OpenMPClauseKind Kind, 2112 SmallVectorImpl<Expr *> &Vars, 2113 OpenMPVarListDataTy &Data) { 2114 UnqualifiedId UnqualifiedReductionId; 2115 bool InvalidReductionId = false; 2116 bool IsInvalidMapperModifier = false; 2117 2118 // Parse '('. 2119 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2120 if (T.expectAndConsume(diag::err_expected_lparen_after, 2121 getOpenMPClauseName(Kind))) 2122 return true; 2123 2124 bool NeedRParenForLinear = false; 2125 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 2126 tok::annot_pragma_openmp_end); 2127 // Handle reduction-identifier for reduction clause. 2128 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 2129 Kind == OMPC_in_reduction) { 2130 ColonProtectionRAIIObject ColonRAII(*this); 2131 if (getLangOpts().CPlusPlus) 2132 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 2133 /*ObjectType=*/nullptr, 2134 /*EnteringContext=*/false); 2135 InvalidReductionId = ParseReductionId( 2136 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); 2137 if (InvalidReductionId) { 2138 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2139 StopBeforeMatch); 2140 } 2141 if (Tok.is(tok::colon)) 2142 Data.ColonLoc = ConsumeToken(); 2143 else 2144 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 2145 if (!InvalidReductionId) 2146 Data.ReductionOrMapperId = 2147 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 2148 } else if (Kind == OMPC_depend) { 2149 // Handle dependency type for depend clause. 2150 ColonProtectionRAIIObject ColonRAII(*this); 2151 Data.DepKind = 2152 static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( 2153 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); 2154 Data.DepLinMapLoc = Tok.getLocation(); 2155 2156 if (Data.DepKind == OMPC_DEPEND_unknown) { 2157 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2158 StopBeforeMatch); 2159 } else { 2160 ConsumeToken(); 2161 // Special processing for depend(source) clause. 2162 if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) { 2163 // Parse ')'. 2164 T.consumeClose(); 2165 return false; 2166 } 2167 } 2168 if (Tok.is(tok::colon)) { 2169 Data.ColonLoc = ConsumeToken(); 2170 } else { 2171 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 2172 : diag::warn_pragma_expected_colon) 2173 << "dependency type"; 2174 } 2175 } else if (Kind == OMPC_linear) { 2176 // Try to parse modifier if any. 2177 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 2178 Data.LinKind = static_cast<OpenMPLinearClauseKind>( 2179 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 2180 Data.DepLinMapLoc = ConsumeToken(); 2181 LinearT.consumeOpen(); 2182 NeedRParenForLinear = true; 2183 } 2184 } else if (Kind == OMPC_map) { 2185 // Handle map type for map clause. 2186 ColonProtectionRAIIObject ColonRAII(*this); 2187 2188 // The first identifier may be a list item, a map-type or a 2189 // map-type-modifier. The map-type can also be delete which has the same 2190 // spelling of the C++ delete keyword. 2191 Data.DepLinMapLoc = Tok.getLocation(); 2192 2193 // Check for presence of a colon in the map clause. 2194 TentativeParsingAction TPA(*this); 2195 bool ColonPresent = false; 2196 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2197 StopBeforeMatch)) { 2198 if (Tok.is(tok::colon)) 2199 ColonPresent = true; 2200 } 2201 TPA.Revert(); 2202 // Only parse map-type-modifier[s] and map-type if a colon is present in 2203 // the map clause. 2204 if (ColonPresent) { 2205 IsInvalidMapperModifier = parseMapTypeModifiers(Data); 2206 if (!IsInvalidMapperModifier) 2207 parseMapType(*this, Data); 2208 else 2209 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); 2210 } 2211 if (Data.MapType == OMPC_MAP_unknown) { 2212 Data.MapType = OMPC_MAP_tofrom; 2213 Data.IsMapTypeImplicit = true; 2214 } 2215 2216 if (Tok.is(tok::colon)) 2217 Data.ColonLoc = ConsumeToken(); 2218 } else if (Kind == OMPC_to || Kind == OMPC_from) { 2219 if (Tok.is(tok::identifier)) { 2220 bool IsMapperModifier = false; 2221 if (Kind == OMPC_to) { 2222 auto Modifier = static_cast<OpenMPToModifierKind>( 2223 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 2224 if (Modifier == OMPC_TO_MODIFIER_mapper) 2225 IsMapperModifier = true; 2226 } else { 2227 auto Modifier = static_cast<OpenMPFromModifierKind>( 2228 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 2229 if (Modifier == OMPC_FROM_MODIFIER_mapper) 2230 IsMapperModifier = true; 2231 } 2232 if (IsMapperModifier) { 2233 // Parse the mapper modifier. 2234 ConsumeToken(); 2235 IsInvalidMapperModifier = parseMapperModifier(Data); 2236 if (Tok.isNot(tok::colon)) { 2237 if (!IsInvalidMapperModifier) 2238 Diag(Tok, diag::warn_pragma_expected_colon) << ")"; 2239 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2240 StopBeforeMatch); 2241 } 2242 // Consume ':'. 2243 if (Tok.is(tok::colon)) 2244 ConsumeToken(); 2245 } 2246 } 2247 } 2248 2249 bool IsComma = 2250 (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 2251 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 2252 (Kind == OMPC_reduction && !InvalidReductionId) || 2253 (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) || 2254 (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown); 2255 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 2256 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 2257 Tok.isNot(tok::annot_pragma_openmp_end))) { 2258 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 2259 // Parse variable 2260 ExprResult VarExpr = 2261 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 2262 if (VarExpr.isUsable()) { 2263 Vars.push_back(VarExpr.get()); 2264 } else { 2265 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2266 StopBeforeMatch); 2267 } 2268 // Skip ',' if any 2269 IsComma = Tok.is(tok::comma); 2270 if (IsComma) 2271 ConsumeToken(); 2272 else if (Tok.isNot(tok::r_paren) && 2273 Tok.isNot(tok::annot_pragma_openmp_end) && 2274 (!MayHaveTail || Tok.isNot(tok::colon))) 2275 Diag(Tok, diag::err_omp_expected_punc) 2276 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 2277 : getOpenMPClauseName(Kind)) 2278 << (Kind == OMPC_flush); 2279 } 2280 2281 // Parse ')' for linear clause with modifier. 2282 if (NeedRParenForLinear) 2283 LinearT.consumeClose(); 2284 2285 // Parse ':' linear-step (or ':' alignment). 2286 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 2287 if (MustHaveTail) { 2288 Data.ColonLoc = Tok.getLocation(); 2289 SourceLocation ELoc = ConsumeToken(); 2290 ExprResult Tail = ParseAssignmentExpression(); 2291 Tail = 2292 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); 2293 if (Tail.isUsable()) 2294 Data.TailExpr = Tail.get(); 2295 else 2296 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2297 StopBeforeMatch); 2298 } 2299 2300 // Parse ')'. 2301 Data.RLoc = Tok.getLocation(); 2302 if (!T.consumeClose()) 2303 Data.RLoc = T.getCloseLocation(); 2304 return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown && 2305 Vars.empty()) || 2306 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 2307 (MustHaveTail && !Data.TailExpr) || InvalidReductionId || 2308 IsInvalidMapperModifier; 2309 } 2310 2311 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 2312 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or 2313 /// 'in_reduction'. 2314 /// 2315 /// private-clause: 2316 /// 'private' '(' list ')' 2317 /// firstprivate-clause: 2318 /// 'firstprivate' '(' list ')' 2319 /// lastprivate-clause: 2320 /// 'lastprivate' '(' list ')' 2321 /// shared-clause: 2322 /// 'shared' '(' list ')' 2323 /// linear-clause: 2324 /// 'linear' '(' linear-list [ ':' linear-step ] ')' 2325 /// aligned-clause: 2326 /// 'aligned' '(' list [ ':' alignment ] ')' 2327 /// reduction-clause: 2328 /// 'reduction' '(' reduction-identifier ':' list ')' 2329 /// task_reduction-clause: 2330 /// 'task_reduction' '(' reduction-identifier ':' list ')' 2331 /// in_reduction-clause: 2332 /// 'in_reduction' '(' reduction-identifier ':' list ')' 2333 /// copyprivate-clause: 2334 /// 'copyprivate' '(' list ')' 2335 /// flush-clause: 2336 /// 'flush' '(' list ')' 2337 /// depend-clause: 2338 /// 'depend' '(' in | out | inout : list | source ')' 2339 /// map-clause: 2340 /// 'map' '(' [ [ always [,] ] [ close [,] ] 2341 /// [ mapper '(' mapper-identifier ')' [,] ] 2342 /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 2343 /// to-clause: 2344 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 2345 /// from-clause: 2346 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 2347 /// use_device_ptr-clause: 2348 /// 'use_device_ptr' '(' list ')' 2349 /// is_device_ptr-clause: 2350 /// 'is_device_ptr' '(' list ')' 2351 /// 2352 /// For 'linear' clause linear-list may have the following forms: 2353 /// list 2354 /// modifier(list) 2355 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 2356 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 2357 OpenMPClauseKind Kind, 2358 bool ParseOnly) { 2359 SourceLocation Loc = Tok.getLocation(); 2360 SourceLocation LOpen = ConsumeToken(); 2361 SmallVector<Expr *, 4> Vars; 2362 OpenMPVarListDataTy Data; 2363 2364 if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 2365 return nullptr; 2366 2367 if (ParseOnly) 2368 return nullptr; 2369 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); 2370 return Actions.ActOnOpenMPVarListClause( 2371 Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc, 2372 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, Data.DepKind, 2373 Data.LinKind, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, 2374 Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc); 2375 } 2376 2377