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