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 1724 switch (DKind) { 1725 case OMPD_threadprivate: { 1726 // FIXME: Should this be permitted in C++? 1727 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 1728 ParsedStmtContext()) { 1729 Diag(Tok, diag::err_omp_immediate_directive) 1730 << getOpenMPDirectiveName(DKind) << 0; 1731 } 1732 ConsumeToken(); 1733 DeclDirectiveListParserHelper Helper(this, DKind); 1734 if (!ParseOpenMPSimpleVarList(DKind, Helper, 1735 /*AllowScopeSpecifier=*/false)) { 1736 // The last seen token is annot_pragma_openmp_end - need to check for 1737 // extra tokens. 1738 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1739 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1740 << getOpenMPDirectiveName(DKind); 1741 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1742 } 1743 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 1744 Loc, Helper.getIdentifiers()); 1745 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1746 } 1747 SkipUntil(tok::annot_pragma_openmp_end); 1748 break; 1749 } 1750 case OMPD_allocate: { 1751 // FIXME: Should this be permitted in C++? 1752 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 1753 ParsedStmtContext()) { 1754 Diag(Tok, diag::err_omp_immediate_directive) 1755 << getOpenMPDirectiveName(DKind) << 0; 1756 } 1757 ConsumeToken(); 1758 DeclDirectiveListParserHelper Helper(this, DKind); 1759 if (!ParseOpenMPSimpleVarList(DKind, Helper, 1760 /*AllowScopeSpecifier=*/false)) { 1761 SmallVector<OMPClause *, 1> Clauses; 1762 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1763 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1764 OMPC_unknown + 1> 1765 FirstClauses(OMPC_unknown + 1); 1766 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1767 OpenMPClauseKind CKind = 1768 Tok.isAnnotation() ? OMPC_unknown 1769 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1770 Actions.StartOpenMPClause(CKind); 1771 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind, 1772 !FirstClauses[CKind].getInt()); 1773 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1774 StopBeforeMatch); 1775 FirstClauses[CKind].setInt(true); 1776 if (Clause != nullptr) 1777 Clauses.push_back(Clause); 1778 if (Tok.is(tok::annot_pragma_openmp_end)) { 1779 Actions.EndOpenMPClause(); 1780 break; 1781 } 1782 // Skip ',' if any. 1783 if (Tok.is(tok::comma)) 1784 ConsumeToken(); 1785 Actions.EndOpenMPClause(); 1786 } 1787 // The last seen token is annot_pragma_openmp_end - need to check for 1788 // extra tokens. 1789 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1790 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1791 << getOpenMPDirectiveName(DKind); 1792 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1793 } 1794 } 1795 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective( 1796 Loc, Helper.getIdentifiers(), Clauses); 1797 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1798 } 1799 SkipUntil(tok::annot_pragma_openmp_end); 1800 break; 1801 } 1802 case OMPD_declare_reduction: 1803 ConsumeToken(); 1804 if (DeclGroupPtrTy Res = 1805 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 1806 // The last seen token is annot_pragma_openmp_end - need to check for 1807 // extra tokens. 1808 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1809 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1810 << getOpenMPDirectiveName(OMPD_declare_reduction); 1811 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1812 ConsumeAnyToken(); 1813 } 1814 ConsumeAnyToken(); 1815 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1816 } else { 1817 SkipUntil(tok::annot_pragma_openmp_end); 1818 } 1819 break; 1820 case OMPD_declare_mapper: { 1821 ConsumeToken(); 1822 if (DeclGroupPtrTy Res = 1823 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) { 1824 // Skip the last annot_pragma_openmp_end. 1825 ConsumeAnnotationToken(); 1826 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 1827 } else { 1828 SkipUntil(tok::annot_pragma_openmp_end); 1829 } 1830 break; 1831 } 1832 case OMPD_flush: 1833 case OMPD_taskyield: 1834 case OMPD_barrier: 1835 case OMPD_taskwait: 1836 case OMPD_cancellation_point: 1837 case OMPD_cancel: 1838 case OMPD_target_enter_data: 1839 case OMPD_target_exit_data: 1840 case OMPD_target_update: 1841 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 1842 ParsedStmtContext()) { 1843 Diag(Tok, diag::err_omp_immediate_directive) 1844 << getOpenMPDirectiveName(DKind) << 0; 1845 } 1846 HasAssociatedStatement = false; 1847 // Fall through for further analysis. 1848 LLVM_FALLTHROUGH; 1849 case OMPD_parallel: 1850 case OMPD_simd: 1851 case OMPD_for: 1852 case OMPD_for_simd: 1853 case OMPD_sections: 1854 case OMPD_single: 1855 case OMPD_section: 1856 case OMPD_master: 1857 case OMPD_critical: 1858 case OMPD_parallel_for: 1859 case OMPD_parallel_for_simd: 1860 case OMPD_parallel_sections: 1861 case OMPD_parallel_master: 1862 case OMPD_task: 1863 case OMPD_ordered: 1864 case OMPD_atomic: 1865 case OMPD_target: 1866 case OMPD_teams: 1867 case OMPD_taskgroup: 1868 case OMPD_target_data: 1869 case OMPD_target_parallel: 1870 case OMPD_target_parallel_for: 1871 case OMPD_taskloop: 1872 case OMPD_taskloop_simd: 1873 case OMPD_master_taskloop: 1874 case OMPD_master_taskloop_simd: 1875 case OMPD_parallel_master_taskloop: 1876 case OMPD_parallel_master_taskloop_simd: 1877 case OMPD_distribute: 1878 case OMPD_distribute_parallel_for: 1879 case OMPD_distribute_parallel_for_simd: 1880 case OMPD_distribute_simd: 1881 case OMPD_target_parallel_for_simd: 1882 case OMPD_target_simd: 1883 case OMPD_teams_distribute: 1884 case OMPD_teams_distribute_simd: 1885 case OMPD_teams_distribute_parallel_for_simd: 1886 case OMPD_teams_distribute_parallel_for: 1887 case OMPD_target_teams: 1888 case OMPD_target_teams_distribute: 1889 case OMPD_target_teams_distribute_parallel_for: 1890 case OMPD_target_teams_distribute_parallel_for_simd: 1891 case OMPD_target_teams_distribute_simd: { 1892 // Special processing for flush clause. 1893 Token FlushTok; 1894 if (DKind == OMPD_flush) 1895 FlushTok = Tok; 1896 ConsumeToken(); 1897 // Parse directive name of the 'critical' directive if any. 1898 if (DKind == OMPD_critical) { 1899 BalancedDelimiterTracker T(*this, tok::l_paren, 1900 tok::annot_pragma_openmp_end); 1901 if (!T.consumeOpen()) { 1902 if (Tok.isAnyIdentifier()) { 1903 DirName = 1904 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 1905 ConsumeAnyToken(); 1906 } else { 1907 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 1908 } 1909 T.consumeClose(); 1910 } 1911 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 1912 CancelRegion = parseOpenMPDirectiveKind(*this); 1913 if (Tok.isNot(tok::annot_pragma_openmp_end)) 1914 ConsumeToken(); 1915 } 1916 1917 if (isOpenMPLoopDirective(DKind)) 1918 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 1919 if (isOpenMPSimdDirective(DKind)) 1920 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 1921 ParseScope OMPDirectiveScope(this, ScopeFlags); 1922 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 1923 1924 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1925 bool FlushHasClause = false; 1926 if (DKind == OMPD_flush && Tok.is(tok::l_paren)) { 1927 FlushHasClause = true; 1928 // Push copy of the current token back to stream to properly parse 1929 // pseudo-clause OMPFlushClause. 1930 PP.EnterToken(Tok, /*IsReinject*/ true); 1931 PP.EnterToken(FlushTok, /*IsReinject*/ true); 1932 ConsumeAnyToken(); 1933 } 1934 OpenMPClauseKind CKind = 1935 Tok.isAnnotation() 1936 ? OMPC_unknown 1937 : FlushHasClause ? OMPC_flush 1938 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1939 Actions.StartOpenMPClause(CKind); 1940 FlushHasClause = false; 1941 OMPClause *Clause = 1942 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt()); 1943 FirstClauses[CKind].setInt(true); 1944 if (Clause) { 1945 FirstClauses[CKind].setPointer(Clause); 1946 Clauses.push_back(Clause); 1947 } 1948 1949 // Skip ',' if any. 1950 if (Tok.is(tok::comma)) 1951 ConsumeToken(); 1952 Actions.EndOpenMPClause(); 1953 } 1954 // End location of the directive. 1955 EndLoc = Tok.getLocation(); 1956 // Consume final annot_pragma_openmp_end. 1957 ConsumeAnnotationToken(); 1958 1959 // OpenMP [2.13.8, ordered Construct, Syntax] 1960 // If the depend clause is specified, the ordered construct is a stand-alone 1961 // directive. 1962 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) { 1963 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 1964 ParsedStmtContext()) { 1965 Diag(Loc, diag::err_omp_immediate_directive) 1966 << getOpenMPDirectiveName(DKind) << 1 1967 << getOpenMPClauseName(OMPC_depend); 1968 } 1969 HasAssociatedStatement = false; 1970 } 1971 1972 StmtResult AssociatedStmt; 1973 if (HasAssociatedStatement) { 1974 // The body is a block scope like in Lambdas and Blocks. 1975 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 1976 // FIXME: We create a bogus CompoundStmt scope to hold the contents of 1977 // the captured region. Code elsewhere assumes that any FunctionScopeInfo 1978 // should have at least one compound statement scope within it. 1979 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement()); 1980 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1981 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 1982 DKind == OMPD_target_exit_data) { 1983 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 1984 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 1985 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, 1986 /*isStmtExpr=*/false)); 1987 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 1988 } 1989 Directive = Actions.ActOnOpenMPExecutableDirective( 1990 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 1991 EndLoc); 1992 1993 // Exit scope. 1994 Actions.EndOpenMPDSABlock(Directive.get()); 1995 OMPDirectiveScope.Exit(); 1996 break; 1997 } 1998 case OMPD_declare_simd: 1999 case OMPD_declare_target: 2000 case OMPD_end_declare_target: 2001 case OMPD_requires: 2002 case OMPD_declare_variant: 2003 Diag(Tok, diag::err_omp_unexpected_directive) 2004 << 1 << getOpenMPDirectiveName(DKind); 2005 SkipUntil(tok::annot_pragma_openmp_end); 2006 break; 2007 case OMPD_unknown: 2008 Diag(Tok, diag::err_omp_unknown_directive); 2009 SkipUntil(tok::annot_pragma_openmp_end); 2010 break; 2011 } 2012 return Directive; 2013 } 2014 2015 // Parses simple list: 2016 // simple-variable-list: 2017 // '(' id-expression {, id-expression} ')' 2018 // 2019 bool Parser::ParseOpenMPSimpleVarList( 2020 OpenMPDirectiveKind Kind, 2021 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & 2022 Callback, 2023 bool AllowScopeSpecifier) { 2024 // Parse '('. 2025 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2026 if (T.expectAndConsume(diag::err_expected_lparen_after, 2027 getOpenMPDirectiveName(Kind).data())) 2028 return true; 2029 bool IsCorrect = true; 2030 bool NoIdentIsFound = true; 2031 2032 // Read tokens while ')' or annot_pragma_openmp_end is not found. 2033 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 2034 CXXScopeSpec SS; 2035 UnqualifiedId Name; 2036 // Read var name. 2037 Token PrevTok = Tok; 2038 NoIdentIsFound = false; 2039 2040 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 2041 ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) { 2042 IsCorrect = false; 2043 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2044 StopBeforeMatch); 2045 } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr, 2046 nullptr, Name)) { 2047 IsCorrect = false; 2048 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2049 StopBeforeMatch); 2050 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 2051 Tok.isNot(tok::annot_pragma_openmp_end)) { 2052 IsCorrect = false; 2053 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2054 StopBeforeMatch); 2055 Diag(PrevTok.getLocation(), diag::err_expected) 2056 << tok::identifier 2057 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 2058 } else { 2059 Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 2060 } 2061 // Consume ','. 2062 if (Tok.is(tok::comma)) { 2063 ConsumeToken(); 2064 } 2065 } 2066 2067 if (NoIdentIsFound) { 2068 Diag(Tok, diag::err_expected) << tok::identifier; 2069 IsCorrect = false; 2070 } 2071 2072 // Parse ')'. 2073 IsCorrect = !T.consumeClose() && IsCorrect; 2074 2075 return !IsCorrect; 2076 } 2077 2078 /// Parsing of OpenMP clauses. 2079 /// 2080 /// clause: 2081 /// if-clause | final-clause | num_threads-clause | safelen-clause | 2082 /// default-clause | private-clause | firstprivate-clause | shared-clause 2083 /// | linear-clause | aligned-clause | collapse-clause | 2084 /// lastprivate-clause | reduction-clause | proc_bind-clause | 2085 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 2086 /// mergeable-clause | flush-clause | read-clause | write-clause | 2087 /// update-clause | capture-clause | seq_cst-clause | device-clause | 2088 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 2089 /// thread_limit-clause | priority-clause | grainsize-clause | 2090 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 2091 /// from-clause | is_device_ptr-clause | task_reduction-clause | 2092 /// in_reduction-clause | allocator-clause | allocate-clause | 2093 /// acq_rel-clause 2094 /// 2095 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 2096 OpenMPClauseKind CKind, bool FirstClause) { 2097 OMPClause *Clause = nullptr; 2098 bool ErrorFound = false; 2099 bool WrongDirective = false; 2100 // Check if clause is allowed for the given directive. 2101 if (CKind != OMPC_unknown && 2102 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) { 2103 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 2104 << getOpenMPDirectiveName(DKind); 2105 ErrorFound = true; 2106 WrongDirective = true; 2107 } 2108 2109 switch (CKind) { 2110 case OMPC_final: 2111 case OMPC_num_threads: 2112 case OMPC_safelen: 2113 case OMPC_simdlen: 2114 case OMPC_collapse: 2115 case OMPC_ordered: 2116 case OMPC_device: 2117 case OMPC_num_teams: 2118 case OMPC_thread_limit: 2119 case OMPC_priority: 2120 case OMPC_grainsize: 2121 case OMPC_num_tasks: 2122 case OMPC_hint: 2123 case OMPC_allocator: 2124 // OpenMP [2.5, Restrictions] 2125 // At most one num_threads clause can appear on the directive. 2126 // OpenMP [2.8.1, simd construct, Restrictions] 2127 // Only one safelen clause can appear on a simd directive. 2128 // Only one simdlen clause can appear on a simd directive. 2129 // Only one collapse clause can appear on a simd directive. 2130 // OpenMP [2.9.1, target data construct, Restrictions] 2131 // At most one device clause can appear on the directive. 2132 // OpenMP [2.11.1, task Construct, Restrictions] 2133 // At most one if clause can appear on the directive. 2134 // At most one final clause can appear on the directive. 2135 // OpenMP [teams Construct, Restrictions] 2136 // At most one num_teams clause can appear on the directive. 2137 // At most one thread_limit clause can appear on the directive. 2138 // OpenMP [2.9.1, task Construct, Restrictions] 2139 // At most one priority clause can appear on the directive. 2140 // OpenMP [2.9.2, taskloop Construct, Restrictions] 2141 // At most one grainsize clause can appear on the directive. 2142 // OpenMP [2.9.2, taskloop Construct, Restrictions] 2143 // At most one num_tasks clause can appear on the directive. 2144 // OpenMP [2.11.3, allocate Directive, Restrictions] 2145 // At most one allocator clause can appear on the directive. 2146 if (!FirstClause) { 2147 Diag(Tok, diag::err_omp_more_one_clause) 2148 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2149 ErrorFound = true; 2150 } 2151 2152 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 2153 Clause = ParseOpenMPClause(CKind, WrongDirective); 2154 else 2155 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 2156 break; 2157 case OMPC_default: 2158 case OMPC_proc_bind: 2159 case OMPC_atomic_default_mem_order: 2160 case OMPC_order: 2161 // OpenMP [2.14.3.1, Restrictions] 2162 // Only a single default clause may be specified on a parallel, task or 2163 // teams directive. 2164 // OpenMP [2.5, parallel Construct, Restrictions] 2165 // At most one proc_bind clause can appear on the directive. 2166 // OpenMP [5.0, Requires directive, Restrictions] 2167 // At most one atomic_default_mem_order clause can appear 2168 // on the directive 2169 if (!FirstClause && CKind != OMPC_order) { 2170 Diag(Tok, diag::err_omp_more_one_clause) 2171 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2172 ErrorFound = true; 2173 } 2174 2175 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 2176 break; 2177 case OMPC_schedule: 2178 case OMPC_dist_schedule: 2179 case OMPC_defaultmap: 2180 // OpenMP [2.7.1, Restrictions, p. 3] 2181 // Only one schedule clause can appear on a loop directive. 2182 // OpenMP 4.5 [2.10.4, Restrictions, p. 106] 2183 // At most one defaultmap clause can appear on the directive. 2184 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && 2185 !FirstClause) { 2186 Diag(Tok, diag::err_omp_more_one_clause) 2187 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2188 ErrorFound = true; 2189 } 2190 LLVM_FALLTHROUGH; 2191 case OMPC_if: 2192 Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective); 2193 break; 2194 case OMPC_nowait: 2195 case OMPC_untied: 2196 case OMPC_mergeable: 2197 case OMPC_read: 2198 case OMPC_write: 2199 case OMPC_update: 2200 case OMPC_capture: 2201 case OMPC_seq_cst: 2202 case OMPC_acq_rel: 2203 case OMPC_threads: 2204 case OMPC_simd: 2205 case OMPC_nogroup: 2206 case OMPC_unified_address: 2207 case OMPC_unified_shared_memory: 2208 case OMPC_reverse_offload: 2209 case OMPC_dynamic_allocators: 2210 // OpenMP [2.7.1, Restrictions, p. 9] 2211 // Only one ordered clause can appear on a loop directive. 2212 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 2213 // Only one nowait clause can appear on a for directive. 2214 // OpenMP [5.0, Requires directive, Restrictions] 2215 // Each of the requires clauses can appear at most once on the directive. 2216 if (!FirstClause) { 2217 Diag(Tok, diag::err_omp_more_one_clause) 2218 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2219 ErrorFound = true; 2220 } 2221 2222 Clause = ParseOpenMPClause(CKind, WrongDirective); 2223 break; 2224 case OMPC_private: 2225 case OMPC_firstprivate: 2226 case OMPC_lastprivate: 2227 case OMPC_shared: 2228 case OMPC_reduction: 2229 case OMPC_task_reduction: 2230 case OMPC_in_reduction: 2231 case OMPC_linear: 2232 case OMPC_aligned: 2233 case OMPC_copyin: 2234 case OMPC_copyprivate: 2235 case OMPC_flush: 2236 case OMPC_depend: 2237 case OMPC_map: 2238 case OMPC_to: 2239 case OMPC_from: 2240 case OMPC_use_device_ptr: 2241 case OMPC_is_device_ptr: 2242 case OMPC_allocate: 2243 case OMPC_nontemporal: 2244 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 2245 break; 2246 case OMPC_device_type: 2247 case OMPC_unknown: 2248 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 2249 << getOpenMPDirectiveName(DKind); 2250 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 2251 break; 2252 case OMPC_threadprivate: 2253 case OMPC_uniform: 2254 case OMPC_match: 2255 if (!WrongDirective) 2256 Diag(Tok, diag::err_omp_unexpected_clause) 2257 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 2258 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 2259 break; 2260 } 2261 return ErrorFound ? nullptr : Clause; 2262 } 2263 2264 /// Parses simple expression in parens for single-expression clauses of OpenMP 2265 /// constructs. 2266 /// \param RLoc Returned location of right paren. 2267 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 2268 SourceLocation &RLoc, 2269 bool IsAddressOfOperand) { 2270 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2271 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 2272 return ExprError(); 2273 2274 SourceLocation ELoc = Tok.getLocation(); 2275 ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand, 2276 NotTypeCast)); 2277 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 2278 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 2279 2280 // Parse ')'. 2281 RLoc = Tok.getLocation(); 2282 if (!T.consumeClose()) 2283 RLoc = T.getCloseLocation(); 2284 2285 return Val; 2286 } 2287 2288 /// Parsing of OpenMP clauses with single expressions like 'final', 2289 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 2290 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'. 2291 /// 2292 /// final-clause: 2293 /// 'final' '(' expression ')' 2294 /// 2295 /// num_threads-clause: 2296 /// 'num_threads' '(' expression ')' 2297 /// 2298 /// safelen-clause: 2299 /// 'safelen' '(' expression ')' 2300 /// 2301 /// simdlen-clause: 2302 /// 'simdlen' '(' expression ')' 2303 /// 2304 /// collapse-clause: 2305 /// 'collapse' '(' expression ')' 2306 /// 2307 /// priority-clause: 2308 /// 'priority' '(' expression ')' 2309 /// 2310 /// grainsize-clause: 2311 /// 'grainsize' '(' expression ')' 2312 /// 2313 /// num_tasks-clause: 2314 /// 'num_tasks' '(' expression ')' 2315 /// 2316 /// hint-clause: 2317 /// 'hint' '(' expression ')' 2318 /// 2319 /// allocator-clause: 2320 /// 'allocator' '(' expression ')' 2321 /// 2322 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 2323 bool ParseOnly) { 2324 SourceLocation Loc = ConsumeToken(); 2325 SourceLocation LLoc = Tok.getLocation(); 2326 SourceLocation RLoc; 2327 2328 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 2329 2330 if (Val.isInvalid()) 2331 return nullptr; 2332 2333 if (ParseOnly) 2334 return nullptr; 2335 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 2336 } 2337 2338 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 2339 /// 2340 /// default-clause: 2341 /// 'default' '(' 'none' | 'shared' ') 2342 /// 2343 /// proc_bind-clause: 2344 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 2345 /// 2346 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 2347 bool ParseOnly) { 2348 llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind); 2349 if (!Val || ParseOnly) 2350 return nullptr; 2351 return Actions.ActOnOpenMPSimpleClause( 2352 Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen, 2353 Val.getValue().Loc, Val.getValue().RLoc); 2354 } 2355 2356 /// Parsing of OpenMP clauses like 'ordered'. 2357 /// 2358 /// ordered-clause: 2359 /// 'ordered' 2360 /// 2361 /// nowait-clause: 2362 /// 'nowait' 2363 /// 2364 /// untied-clause: 2365 /// 'untied' 2366 /// 2367 /// mergeable-clause: 2368 /// 'mergeable' 2369 /// 2370 /// read-clause: 2371 /// 'read' 2372 /// 2373 /// threads-clause: 2374 /// 'threads' 2375 /// 2376 /// simd-clause: 2377 /// 'simd' 2378 /// 2379 /// nogroup-clause: 2380 /// 'nogroup' 2381 /// 2382 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 2383 SourceLocation Loc = Tok.getLocation(); 2384 ConsumeAnyToken(); 2385 2386 if (ParseOnly) 2387 return nullptr; 2388 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 2389 } 2390 2391 2392 /// Parsing of OpenMP clauses with single expressions and some additional 2393 /// argument like 'schedule' or 'dist_schedule'. 2394 /// 2395 /// schedule-clause: 2396 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 2397 /// ')' 2398 /// 2399 /// if-clause: 2400 /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 2401 /// 2402 /// defaultmap: 2403 /// 'defaultmap' '(' modifier ':' kind ')' 2404 /// 2405 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, 2406 bool ParseOnly) { 2407 SourceLocation Loc = ConsumeToken(); 2408 SourceLocation DelimLoc; 2409 // Parse '('. 2410 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2411 if (T.expectAndConsume(diag::err_expected_lparen_after, 2412 getOpenMPClauseName(Kind))) 2413 return nullptr; 2414 2415 ExprResult Val; 2416 SmallVector<unsigned, 4> Arg; 2417 SmallVector<SourceLocation, 4> KLoc; 2418 if (Kind == OMPC_schedule) { 2419 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 2420 Arg.resize(NumberOfElements); 2421 KLoc.resize(NumberOfElements); 2422 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 2423 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 2424 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 2425 unsigned KindModifier = getOpenMPSimpleClauseType( 2426 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2427 if (KindModifier > OMPC_SCHEDULE_unknown) { 2428 // Parse 'modifier' 2429 Arg[Modifier1] = KindModifier; 2430 KLoc[Modifier1] = Tok.getLocation(); 2431 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2432 Tok.isNot(tok::annot_pragma_openmp_end)) 2433 ConsumeAnyToken(); 2434 if (Tok.is(tok::comma)) { 2435 // Parse ',' 'modifier' 2436 ConsumeAnyToken(); 2437 KindModifier = getOpenMPSimpleClauseType( 2438 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2439 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 2440 ? KindModifier 2441 : (unsigned)OMPC_SCHEDULE_unknown; 2442 KLoc[Modifier2] = Tok.getLocation(); 2443 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2444 Tok.isNot(tok::annot_pragma_openmp_end)) 2445 ConsumeAnyToken(); 2446 } 2447 // Parse ':' 2448 if (Tok.is(tok::colon)) 2449 ConsumeAnyToken(); 2450 else 2451 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 2452 KindModifier = getOpenMPSimpleClauseType( 2453 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2454 } 2455 Arg[ScheduleKind] = KindModifier; 2456 KLoc[ScheduleKind] = Tok.getLocation(); 2457 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2458 Tok.isNot(tok::annot_pragma_openmp_end)) 2459 ConsumeAnyToken(); 2460 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 2461 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 2462 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 2463 Tok.is(tok::comma)) 2464 DelimLoc = ConsumeAnyToken(); 2465 } else if (Kind == OMPC_dist_schedule) { 2466 Arg.push_back(getOpenMPSimpleClauseType( 2467 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 2468 KLoc.push_back(Tok.getLocation()); 2469 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2470 Tok.isNot(tok::annot_pragma_openmp_end)) 2471 ConsumeAnyToken(); 2472 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 2473 DelimLoc = ConsumeAnyToken(); 2474 } else if (Kind == OMPC_defaultmap) { 2475 // Get a defaultmap modifier 2476 unsigned Modifier = getOpenMPSimpleClauseType( 2477 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2478 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or 2479 // pointer 2480 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) 2481 Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; 2482 Arg.push_back(Modifier); 2483 KLoc.push_back(Tok.getLocation()); 2484 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2485 Tok.isNot(tok::annot_pragma_openmp_end)) 2486 ConsumeAnyToken(); 2487 // Parse ':' 2488 if (Tok.is(tok::colon)) 2489 ConsumeAnyToken(); 2490 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 2491 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 2492 // Get a defaultmap kind 2493 Arg.push_back(getOpenMPSimpleClauseType( 2494 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 2495 KLoc.push_back(Tok.getLocation()); 2496 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2497 Tok.isNot(tok::annot_pragma_openmp_end)) 2498 ConsumeAnyToken(); 2499 } else { 2500 assert(Kind == OMPC_if); 2501 KLoc.push_back(Tok.getLocation()); 2502 TentativeParsingAction TPA(*this); 2503 auto DK = parseOpenMPDirectiveKind(*this); 2504 Arg.push_back(DK); 2505 if (DK != OMPD_unknown) { 2506 ConsumeToken(); 2507 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 2508 TPA.Commit(); 2509 DelimLoc = ConsumeToken(); 2510 } else { 2511 TPA.Revert(); 2512 Arg.back() = unsigned(OMPD_unknown); 2513 } 2514 } else { 2515 TPA.Revert(); 2516 } 2517 } 2518 2519 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 2520 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 2521 Kind == OMPC_if; 2522 if (NeedAnExpression) { 2523 SourceLocation ELoc = Tok.getLocation(); 2524 ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); 2525 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 2526 Val = 2527 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 2528 } 2529 2530 // Parse ')'. 2531 SourceLocation RLoc = Tok.getLocation(); 2532 if (!T.consumeClose()) 2533 RLoc = T.getCloseLocation(); 2534 2535 if (NeedAnExpression && Val.isInvalid()) 2536 return nullptr; 2537 2538 if (ParseOnly) 2539 return nullptr; 2540 return Actions.ActOnOpenMPSingleExprWithArgClause( 2541 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 2542 } 2543 2544 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 2545 UnqualifiedId &ReductionId) { 2546 if (ReductionIdScopeSpec.isEmpty()) { 2547 auto OOK = OO_None; 2548 switch (P.getCurToken().getKind()) { 2549 case tok::plus: 2550 OOK = OO_Plus; 2551 break; 2552 case tok::minus: 2553 OOK = OO_Minus; 2554 break; 2555 case tok::star: 2556 OOK = OO_Star; 2557 break; 2558 case tok::amp: 2559 OOK = OO_Amp; 2560 break; 2561 case tok::pipe: 2562 OOK = OO_Pipe; 2563 break; 2564 case tok::caret: 2565 OOK = OO_Caret; 2566 break; 2567 case tok::ampamp: 2568 OOK = OO_AmpAmp; 2569 break; 2570 case tok::pipepipe: 2571 OOK = OO_PipePipe; 2572 break; 2573 default: 2574 break; 2575 } 2576 if (OOK != OO_None) { 2577 SourceLocation OpLoc = P.ConsumeToken(); 2578 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 2579 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 2580 return false; 2581 } 2582 } 2583 return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false, 2584 /*AllowDestructorName*/ false, 2585 /*AllowConstructorName*/ false, 2586 /*AllowDeductionGuide*/ false, 2587 nullptr, nullptr, ReductionId); 2588 } 2589 2590 /// Checks if the token is a valid map-type-modifier. 2591 static OpenMPMapModifierKind isMapModifier(Parser &P) { 2592 Token Tok = P.getCurToken(); 2593 if (!Tok.is(tok::identifier)) 2594 return OMPC_MAP_MODIFIER_unknown; 2595 2596 Preprocessor &PP = P.getPreprocessor(); 2597 OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>( 2598 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); 2599 return TypeModifier; 2600 } 2601 2602 /// Parse the mapper modifier in map, to, and from clauses. 2603 bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { 2604 // Parse '('. 2605 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); 2606 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { 2607 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2608 StopBeforeMatch); 2609 return true; 2610 } 2611 // Parse mapper-identifier 2612 if (getLangOpts().CPlusPlus) 2613 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 2614 /*ObjectType=*/nullptr, 2615 /*EnteringContext=*/false); 2616 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 2617 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 2618 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2619 StopBeforeMatch); 2620 return true; 2621 } 2622 auto &DeclNames = Actions.getASTContext().DeclarationNames; 2623 Data.ReductionOrMapperId = DeclarationNameInfo( 2624 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation()); 2625 ConsumeToken(); 2626 // Parse ')'. 2627 return T.consumeClose(); 2628 } 2629 2630 /// Parse map-type-modifiers in map clause. 2631 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 2632 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) 2633 bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) { 2634 while (getCurToken().isNot(tok::colon)) { 2635 OpenMPMapModifierKind TypeModifier = isMapModifier(*this); 2636 if (TypeModifier == OMPC_MAP_MODIFIER_always || 2637 TypeModifier == OMPC_MAP_MODIFIER_close) { 2638 Data.MapTypeModifiers.push_back(TypeModifier); 2639 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 2640 ConsumeToken(); 2641 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { 2642 Data.MapTypeModifiers.push_back(TypeModifier); 2643 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 2644 ConsumeToken(); 2645 if (parseMapperModifier(Data)) 2646 return true; 2647 } else { 2648 // For the case of unknown map-type-modifier or a map-type. 2649 // Map-type is followed by a colon; the function returns when it 2650 // encounters a token followed by a colon. 2651 if (Tok.is(tok::comma)) { 2652 Diag(Tok, diag::err_omp_map_type_modifier_missing); 2653 ConsumeToken(); 2654 continue; 2655 } 2656 // Potential map-type token as it is followed by a colon. 2657 if (PP.LookAhead(0).is(tok::colon)) 2658 return false; 2659 Diag(Tok, diag::err_omp_unknown_map_type_modifier); 2660 ConsumeToken(); 2661 } 2662 if (getCurToken().is(tok::comma)) 2663 ConsumeToken(); 2664 } 2665 return false; 2666 } 2667 2668 /// Checks if the token is a valid map-type. 2669 static OpenMPMapClauseKind isMapType(Parser &P) { 2670 Token Tok = P.getCurToken(); 2671 // The map-type token can be either an identifier or the C++ delete keyword. 2672 if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) 2673 return OMPC_MAP_unknown; 2674 Preprocessor &PP = P.getPreprocessor(); 2675 OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>( 2676 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); 2677 return MapType; 2678 } 2679 2680 /// Parse map-type in map clause. 2681 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 2682 /// where, map-type ::= to | from | tofrom | alloc | release | delete 2683 static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { 2684 Token Tok = P.getCurToken(); 2685 if (Tok.is(tok::colon)) { 2686 P.Diag(Tok, diag::err_omp_map_type_missing); 2687 return; 2688 } 2689 Data.ExtraModifier = isMapType(P); 2690 if (Data.ExtraModifier == OMPC_MAP_unknown) 2691 P.Diag(Tok, diag::err_omp_unknown_map_type); 2692 P.ConsumeToken(); 2693 } 2694 2695 /// Parses clauses with list. 2696 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 2697 OpenMPClauseKind Kind, 2698 SmallVectorImpl<Expr *> &Vars, 2699 OpenMPVarListDataTy &Data) { 2700 UnqualifiedId UnqualifiedReductionId; 2701 bool InvalidReductionId = false; 2702 bool IsInvalidMapperModifier = false; 2703 2704 // Parse '('. 2705 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2706 if (T.expectAndConsume(diag::err_expected_lparen_after, 2707 getOpenMPClauseName(Kind))) 2708 return true; 2709 2710 bool NeedRParenForLinear = false; 2711 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 2712 tok::annot_pragma_openmp_end); 2713 // Handle reduction-identifier for reduction clause. 2714 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 2715 Kind == OMPC_in_reduction) { 2716 ColonProtectionRAIIObject ColonRAII(*this); 2717 if (getLangOpts().CPlusPlus) 2718 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 2719 /*ObjectType=*/nullptr, 2720 /*EnteringContext=*/false); 2721 InvalidReductionId = ParseReductionId( 2722 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); 2723 if (InvalidReductionId) { 2724 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2725 StopBeforeMatch); 2726 } 2727 if (Tok.is(tok::colon)) 2728 Data.ColonLoc = ConsumeToken(); 2729 else 2730 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 2731 if (!InvalidReductionId) 2732 Data.ReductionOrMapperId = 2733 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 2734 } else if (Kind == OMPC_depend) { 2735 // Handle dependency type for depend clause. 2736 ColonProtectionRAIIObject ColonRAII(*this); 2737 Data.ExtraModifier = getOpenMPSimpleClauseType( 2738 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""); 2739 Data.DepLinMapLastLoc = Tok.getLocation(); 2740 if (Data.ExtraModifier == OMPC_DEPEND_unknown) { 2741 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2742 StopBeforeMatch); 2743 } else { 2744 ConsumeToken(); 2745 // Special processing for depend(source) clause. 2746 if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) { 2747 // Parse ')'. 2748 T.consumeClose(); 2749 return false; 2750 } 2751 } 2752 if (Tok.is(tok::colon)) { 2753 Data.ColonLoc = ConsumeToken(); 2754 } else { 2755 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 2756 : diag::warn_pragma_expected_colon) 2757 << "dependency type"; 2758 } 2759 } else if (Kind == OMPC_linear) { 2760 // Try to parse modifier if any. 2761 Data.ExtraModifier = OMPC_LINEAR_val; 2762 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 2763 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); 2764 Data.DepLinMapLastLoc = ConsumeToken(); 2765 LinearT.consumeOpen(); 2766 NeedRParenForLinear = true; 2767 } 2768 } else if (Kind == OMPC_lastprivate) { 2769 // Try to parse modifier if any. 2770 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown; 2771 // Conditional modifier allowed only in OpenMP 5.0 and not supported in 2772 // distribute and taskloop based directives. 2773 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) && 2774 !isOpenMPTaskLoopDirective(DKind)) && 2775 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) { 2776 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); 2777 Data.DepLinMapLastLoc = Tok.getLocation(); 2778 if (Data.ExtraModifier == OMPC_LASTPRIVATE_unknown) { 2779 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2780 StopBeforeMatch); 2781 } else { 2782 ConsumeToken(); 2783 } 2784 assert(Tok.is(tok::colon) && "Expected colon."); 2785 Data.ColonLoc = ConsumeToken(); 2786 } 2787 } else if (Kind == OMPC_map) { 2788 // Handle map type for map clause. 2789 ColonProtectionRAIIObject ColonRAII(*this); 2790 2791 // The first identifier may be a list item, a map-type or a 2792 // map-type-modifier. The map-type can also be delete which has the same 2793 // spelling of the C++ delete keyword. 2794 Data.ExtraModifier = OMPC_MAP_unknown; 2795 Data.DepLinMapLastLoc = Tok.getLocation(); 2796 2797 // Check for presence of a colon in the map clause. 2798 TentativeParsingAction TPA(*this); 2799 bool ColonPresent = false; 2800 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2801 StopBeforeMatch)) { 2802 if (Tok.is(tok::colon)) 2803 ColonPresent = true; 2804 } 2805 TPA.Revert(); 2806 // Only parse map-type-modifier[s] and map-type if a colon is present in 2807 // the map clause. 2808 if (ColonPresent) { 2809 IsInvalidMapperModifier = parseMapTypeModifiers(Data); 2810 if (!IsInvalidMapperModifier) 2811 parseMapType(*this, Data); 2812 else 2813 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); 2814 } 2815 if (Data.ExtraModifier == OMPC_MAP_unknown) { 2816 Data.ExtraModifier = OMPC_MAP_tofrom; 2817 Data.IsMapTypeImplicit = true; 2818 } 2819 2820 if (Tok.is(tok::colon)) 2821 Data.ColonLoc = ConsumeToken(); 2822 } else if (Kind == OMPC_to || Kind == OMPC_from) { 2823 if (Tok.is(tok::identifier)) { 2824 bool IsMapperModifier = false; 2825 if (Kind == OMPC_to) { 2826 auto Modifier = static_cast<OpenMPToModifierKind>( 2827 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 2828 if (Modifier == OMPC_TO_MODIFIER_mapper) 2829 IsMapperModifier = true; 2830 } else { 2831 auto Modifier = static_cast<OpenMPFromModifierKind>( 2832 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 2833 if (Modifier == OMPC_FROM_MODIFIER_mapper) 2834 IsMapperModifier = true; 2835 } 2836 if (IsMapperModifier) { 2837 // Parse the mapper modifier. 2838 ConsumeToken(); 2839 IsInvalidMapperModifier = parseMapperModifier(Data); 2840 if (Tok.isNot(tok::colon)) { 2841 if (!IsInvalidMapperModifier) 2842 Diag(Tok, diag::warn_pragma_expected_colon) << ")"; 2843 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 2844 StopBeforeMatch); 2845 } 2846 // Consume ':'. 2847 if (Tok.is(tok::colon)) 2848 ConsumeToken(); 2849 } 2850 } 2851 } else if (Kind == OMPC_allocate) { 2852 // Handle optional allocator expression followed by colon delimiter. 2853 ColonProtectionRAIIObject ColonRAII(*this); 2854 TentativeParsingAction TPA(*this); 2855 ExprResult Tail = 2856 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 2857 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), 2858 /*DiscardedValue=*/false); 2859 if (Tail.isUsable()) { 2860 if (Tok.is(tok::colon)) { 2861 Data.TailExpr = Tail.get(); 2862 Data.ColonLoc = ConsumeToken(); 2863 TPA.Commit(); 2864 } else { 2865 // colon not found, no allocator specified, parse only list of 2866 // variables. 2867 TPA.Revert(); 2868 } 2869 } else { 2870 // Parsing was unsuccessfull, revert and skip to the end of clause or 2871 // directive. 2872 TPA.Revert(); 2873 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2874 StopBeforeMatch); 2875 } 2876 } 2877 2878 bool IsComma = 2879 (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 2880 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 2881 (Kind == OMPC_reduction && !InvalidReductionId) || 2882 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) || 2883 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown); 2884 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 2885 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 2886 Tok.isNot(tok::annot_pragma_openmp_end))) { 2887 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 2888 // Parse variable 2889 ExprResult VarExpr = 2890 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 2891 if (VarExpr.isUsable()) { 2892 Vars.push_back(VarExpr.get()); 2893 } else { 2894 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2895 StopBeforeMatch); 2896 } 2897 // Skip ',' if any 2898 IsComma = Tok.is(tok::comma); 2899 if (IsComma) 2900 ConsumeToken(); 2901 else if (Tok.isNot(tok::r_paren) && 2902 Tok.isNot(tok::annot_pragma_openmp_end) && 2903 (!MayHaveTail || Tok.isNot(tok::colon))) 2904 Diag(Tok, diag::err_omp_expected_punc) 2905 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 2906 : getOpenMPClauseName(Kind)) 2907 << (Kind == OMPC_flush); 2908 } 2909 2910 // Parse ')' for linear clause with modifier. 2911 if (NeedRParenForLinear) 2912 LinearT.consumeClose(); 2913 2914 // Parse ':' linear-step (or ':' alignment). 2915 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 2916 if (MustHaveTail) { 2917 Data.ColonLoc = Tok.getLocation(); 2918 SourceLocation ELoc = ConsumeToken(); 2919 ExprResult Tail = ParseAssignmentExpression(); 2920 Tail = 2921 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); 2922 if (Tail.isUsable()) 2923 Data.TailExpr = Tail.get(); 2924 else 2925 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2926 StopBeforeMatch); 2927 } 2928 2929 // Parse ')'. 2930 Data.RLoc = Tok.getLocation(); 2931 if (!T.consumeClose()) 2932 Data.RLoc = T.getCloseLocation(); 2933 return (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown && 2934 Vars.empty()) || 2935 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 2936 (MustHaveTail && !Data.TailExpr) || InvalidReductionId || 2937 IsInvalidMapperModifier; 2938 } 2939 2940 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 2941 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or 2942 /// 'in_reduction'. 2943 /// 2944 /// private-clause: 2945 /// 'private' '(' list ')' 2946 /// firstprivate-clause: 2947 /// 'firstprivate' '(' list ')' 2948 /// lastprivate-clause: 2949 /// 'lastprivate' '(' list ')' 2950 /// shared-clause: 2951 /// 'shared' '(' list ')' 2952 /// linear-clause: 2953 /// 'linear' '(' linear-list [ ':' linear-step ] ')' 2954 /// aligned-clause: 2955 /// 'aligned' '(' list [ ':' alignment ] ')' 2956 /// reduction-clause: 2957 /// 'reduction' '(' reduction-identifier ':' list ')' 2958 /// task_reduction-clause: 2959 /// 'task_reduction' '(' reduction-identifier ':' list ')' 2960 /// in_reduction-clause: 2961 /// 'in_reduction' '(' reduction-identifier ':' list ')' 2962 /// copyprivate-clause: 2963 /// 'copyprivate' '(' list ')' 2964 /// flush-clause: 2965 /// 'flush' '(' list ')' 2966 /// depend-clause: 2967 /// 'depend' '(' in | out | inout : list | source ')' 2968 /// map-clause: 2969 /// 'map' '(' [ [ always [,] ] [ close [,] ] 2970 /// [ mapper '(' mapper-identifier ')' [,] ] 2971 /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 2972 /// to-clause: 2973 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 2974 /// from-clause: 2975 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 2976 /// use_device_ptr-clause: 2977 /// 'use_device_ptr' '(' list ')' 2978 /// is_device_ptr-clause: 2979 /// 'is_device_ptr' '(' list ')' 2980 /// allocate-clause: 2981 /// 'allocate' '(' [ allocator ':' ] list ')' 2982 /// 2983 /// For 'linear' clause linear-list may have the following forms: 2984 /// list 2985 /// modifier(list) 2986 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 2987 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 2988 OpenMPClauseKind Kind, 2989 bool ParseOnly) { 2990 SourceLocation Loc = Tok.getLocation(); 2991 SourceLocation LOpen = ConsumeToken(); 2992 SmallVector<Expr *, 4> Vars; 2993 OpenMPVarListDataTy Data; 2994 2995 if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 2996 return nullptr; 2997 2998 if (ParseOnly) 2999 return nullptr; 3000 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); 3001 return Actions.ActOnOpenMPVarListClause( 3002 Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc, 3003 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, 3004 Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, 3005 Data.IsMapTypeImplicit, Data.DepLinMapLastLoc); 3006 } 3007 3008