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