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