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