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