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