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