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