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