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 static bool checkExtensionProperty(Parser &P, SourceLocation Loc, 939 OMPTraitProperty &TIProperty, 940 OMPTraitSelector &TISelector, 941 llvm::StringMap<SourceLocation> &Seen) { 942 assert(TISelector.Kind == 943 llvm::omp::TraitSelector::implementation_extension && 944 "Only for extension properties, e.g., " 945 "`implementation={extension(PROPERTY)}`"); 946 if (TIProperty.Kind == TraitProperty::invalid) 947 return false; 948 949 auto IsMatchExtension = [](OMPTraitProperty &TP) { 950 return (TP.Kind == 951 llvm::omp::TraitProperty::implementation_extension_match_all || 952 TP.Kind == 953 llvm::omp::TraitProperty::implementation_extension_match_any || 954 TP.Kind == 955 llvm::omp::TraitProperty::implementation_extension_match_none); 956 }; 957 958 if (IsMatchExtension(TIProperty)) { 959 for (OMPTraitProperty &SeenProp : TISelector.Properties) 960 if (IsMatchExtension(SeenProp)) { 961 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension); 962 StringRef SeenName = 963 llvm::omp::getOpenMPContextTraitPropertyName(SeenProp.Kind); 964 SourceLocation SeenLoc = Seen[SeenName]; 965 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here) 966 << CONTEXT_TRAIT_LVL << SeenName; 967 return false; 968 } 969 return true; 970 } 971 972 llvm_unreachable("Unknown extension property!"); 973 } 974 975 void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector, 976 llvm::omp::TraitSet Set, 977 llvm::StringMap<SourceLocation> &Seen) { 978 assert(TISelector.Kind != TraitSelector::user_condition && 979 "User conditions are special properties not handled here!"); 980 981 SourceLocation PropertyLoc = Tok.getLocation(); 982 OMPTraitProperty TIProperty; 983 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen); 984 985 if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension) 986 if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty, 987 TISelector, Seen)) 988 TIProperty.Kind = TraitProperty::invalid; 989 990 // If we have an invalid property here we already issued a warning. 991 if (TIProperty.Kind == TraitProperty::invalid) { 992 if (PropertyLoc != Tok.getLocation()) 993 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 994 << CONTEXT_TRAIT_LVL; 995 return; 996 } 997 998 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind, 999 TISelector.Kind, Set)) { 1000 1001 // If we make it here the property, selector, set, score, condition, ... are 1002 // all valid (or have been corrected). Thus we can record the property. 1003 TISelector.Properties.push_back(TIProperty); 1004 return; 1005 } 1006 1007 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector) 1008 << getOpenMPContextTraitPropertyName(TIProperty.Kind) 1009 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1010 << getOpenMPContextTraitSetName(Set); 1011 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property) 1012 << getOpenMPContextTraitPropertyName(TIProperty.Kind) 1013 << getOpenMPContextTraitSelectorName( 1014 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind)) 1015 << getOpenMPContextTraitSetName( 1016 getOpenMPContextTraitSetForProperty(TIProperty.Kind)); 1017 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1018 << CONTEXT_TRAIT_LVL; 1019 } 1020 1021 void Parser::parseOMPTraitSelectorKind( 1022 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set, 1023 llvm::StringMap<SourceLocation> &Seen) { 1024 TISelector.Kind = TraitSelector::invalid; 1025 1026 SourceLocation NameLoc = Tok.getLocation(); 1027 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL 1028 ); 1029 if (Name.empty()) { 1030 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 1031 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set); 1032 return; 1033 } 1034 1035 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name); 1036 if (TISelector.Kind != TraitSelector::invalid) { 1037 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL)) 1038 TISelector.Kind = TraitSelector::invalid; 1039 return; 1040 } 1041 1042 // It follows diagnosis and helping notes. 1043 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector) 1044 << Name << getOpenMPContextTraitSetName(Set); 1045 1046 TraitSet SetForName = getOpenMPContextTraitSetKind(Name); 1047 if (SetForName != TraitSet::invalid) { 1048 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1049 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL; 1050 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1051 << Name << "<selector-name>" 1052 << "<property-name>"; 1053 return; 1054 } 1055 for (const auto &PotentialSet : 1056 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 1057 TraitSet::device}) { 1058 TraitProperty PropertyForName = 1059 getOpenMPContextTraitPropertyKind(PotentialSet, Name); 1060 if (PropertyForName == TraitProperty::invalid) 1061 continue; 1062 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1063 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL; 1064 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1065 << getOpenMPContextTraitSetName( 1066 getOpenMPContextTraitSetForProperty(PropertyForName)) 1067 << getOpenMPContextTraitSelectorName( 1068 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 1069 << ("(" + Name + ")").str(); 1070 return; 1071 } 1072 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 1073 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set); 1074 } 1075 1076 /// Parse optional 'score' '(' <expr> ')' ':'. 1077 static ExprResult parseContextScore(Parser &P) { 1078 ExprResult ScoreExpr; 1079 llvm::SmallString<16> Buffer; 1080 StringRef SelectorName = 1081 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); 1082 if (!SelectorName.equals("score")) 1083 return ScoreExpr; 1084 (void)P.ConsumeToken(); 1085 SourceLocation RLoc; 1086 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc); 1087 // Parse ':' 1088 if (P.getCurToken().is(tok::colon)) 1089 (void)P.ConsumeAnyToken(); 1090 else 1091 P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected) 1092 << "':'" 1093 << "score expression"; 1094 return ScoreExpr; 1095 } 1096 1097 /// Parses an OpenMP context selector. 1098 /// 1099 /// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')'] 1100 void Parser::parseOMPContextSelector( 1101 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set, 1102 llvm::StringMap<SourceLocation> &SeenSelectors) { 1103 unsigned short OuterPC = ParenCount; 1104 1105 // If anything went wrong we issue an error or warning and then skip the rest 1106 // of the selector. However, commas are ambiguous so we look for the nesting 1107 // of parentheses here as well. 1108 auto FinishSelector = [OuterPC, this]() -> void { 1109 bool Done = false; 1110 while (!Done) { 1111 while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma, 1112 tok::annot_pragma_openmp_end}, 1113 StopBeforeMatch)) 1114 ; 1115 if (Tok.is(tok::r_paren) && OuterPC > ParenCount) 1116 (void)ConsumeParen(); 1117 if (OuterPC <= ParenCount) { 1118 Done = true; 1119 break; 1120 } 1121 if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) { 1122 Done = true; 1123 break; 1124 } 1125 (void)ConsumeAnyToken(); 1126 } 1127 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1128 << CONTEXT_SELECTOR_LVL; 1129 }; 1130 1131 SourceLocation SelectorLoc = Tok.getLocation(); 1132 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors); 1133 if (TISelector.Kind == TraitSelector::invalid) 1134 return FinishSelector(); 1135 1136 bool AllowsTraitScore = false; 1137 bool RequiresProperty = false; 1138 if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore, 1139 RequiresProperty)) { 1140 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set) 1141 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1142 << getOpenMPContextTraitSetName(Set); 1143 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector) 1144 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1145 << getOpenMPContextTraitSetName( 1146 getOpenMPContextTraitSetForSelector(TISelector.Kind)) 1147 << RequiresProperty; 1148 return FinishSelector(); 1149 } 1150 1151 if (!RequiresProperty) { 1152 TISelector.Properties.push_back( 1153 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind)}); 1154 return; 1155 } 1156 1157 if (!Tok.is(tok::l_paren)) { 1158 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties) 1159 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1160 << getOpenMPContextTraitSetName(Set); 1161 return FinishSelector(); 1162 } 1163 1164 if (TISelector.Kind == TraitSelector::user_condition) { 1165 SourceLocation RLoc; 1166 ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc); 1167 if (!Condition.isUsable()) 1168 return FinishSelector(); 1169 TISelector.ScoreOrCondition = Condition.get(); 1170 TISelector.Properties.push_back({TraitProperty::user_condition_unknown}); 1171 return; 1172 } 1173 1174 BalancedDelimiterTracker BDT(*this, tok::l_paren, 1175 tok::annot_pragma_openmp_end); 1176 // Parse '('. 1177 (void)BDT.consumeOpen(); 1178 1179 SourceLocation ScoreLoc = Tok.getLocation(); 1180 ExprResult Score = parseContextScore(*this); 1181 1182 if (!AllowsTraitScore && !Score.isUnset()) { 1183 if (Score.isUsable()) { 1184 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property) 1185 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1186 << getOpenMPContextTraitSetName(Set) << Score.get(); 1187 } else { 1188 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property) 1189 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1190 << getOpenMPContextTraitSetName(Set) << "<invalid>"; 1191 } 1192 Score = ExprResult(); 1193 } 1194 1195 if (Score.isUsable()) 1196 TISelector.ScoreOrCondition = Score.get(); 1197 1198 llvm::StringMap<SourceLocation> SeenProperties; 1199 do { 1200 parseOMPContextProperty(TISelector, Set, SeenProperties); 1201 } while (TryConsumeToken(tok::comma)); 1202 1203 // Parse ')'. 1204 BDT.consumeClose(); 1205 } 1206 1207 void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet, 1208 llvm::StringMap<SourceLocation> &Seen) { 1209 TISet.Kind = TraitSet::invalid; 1210 1211 SourceLocation NameLoc = Tok.getLocation(); 1212 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL 1213 ); 1214 if (Name.empty()) { 1215 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 1216 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets(); 1217 return; 1218 } 1219 1220 TISet.Kind = getOpenMPContextTraitSetKind(Name); 1221 if (TISet.Kind != TraitSet::invalid) { 1222 if (checkForDuplicates(*this, Name, NameLoc, Seen, 1223 CONTEXT_SELECTOR_SET_LVL)) 1224 TISet.Kind = TraitSet::invalid; 1225 return; 1226 } 1227 1228 // It follows diagnosis and helping notes. 1229 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name; 1230 1231 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name); 1232 if (SelectorForName != TraitSelector::invalid) { 1233 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1234 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL; 1235 bool AllowsTraitScore = false; 1236 bool RequiresProperty = false; 1237 isValidTraitSelectorForTraitSet( 1238 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName), 1239 AllowsTraitScore, RequiresProperty); 1240 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1241 << getOpenMPContextTraitSetName( 1242 getOpenMPContextTraitSetForSelector(SelectorForName)) 1243 << Name << (RequiresProperty ? "(<property-name>)" : ""); 1244 return; 1245 } 1246 for (const auto &PotentialSet : 1247 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 1248 TraitSet::device}) { 1249 TraitProperty PropertyForName = 1250 getOpenMPContextTraitPropertyKind(PotentialSet, Name); 1251 if (PropertyForName == TraitProperty::invalid) 1252 continue; 1253 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1254 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL; 1255 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1256 << getOpenMPContextTraitSetName( 1257 getOpenMPContextTraitSetForProperty(PropertyForName)) 1258 << getOpenMPContextTraitSelectorName( 1259 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 1260 << ("(" + Name + ")").str(); 1261 return; 1262 } 1263 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 1264 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets(); 1265 } 1266 1267 /// Parses an OpenMP context selector set. 1268 /// 1269 /// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}' 1270 void Parser::parseOMPContextSelectorSet( 1271 OMPTraitSet &TISet, 1272 llvm::StringMap<SourceLocation> &SeenSets) { 1273 auto OuterBC = BraceCount; 1274 1275 // If anything went wrong we issue an error or warning and then skip the rest 1276 // of the set. However, commas are ambiguous so we look for the nesting 1277 // of braces here as well. 1278 auto FinishSelectorSet = [this, OuterBC]() -> void { 1279 bool Done = false; 1280 while (!Done) { 1281 while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren, 1282 tok::annot_pragma_openmp_end}, 1283 StopBeforeMatch)) 1284 ; 1285 if (Tok.is(tok::r_brace) && OuterBC > BraceCount) 1286 (void)ConsumeBrace(); 1287 if (OuterBC <= BraceCount) { 1288 Done = true; 1289 break; 1290 } 1291 if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) { 1292 Done = true; 1293 break; 1294 } 1295 (void)ConsumeAnyToken(); 1296 } 1297 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1298 << CONTEXT_SELECTOR_SET_LVL; 1299 }; 1300 1301 parseOMPTraitSetKind(TISet, SeenSets); 1302 if (TISet.Kind == TraitSet::invalid) 1303 return FinishSelectorSet(); 1304 1305 // Parse '='. 1306 if (!TryConsumeToken(tok::equal)) 1307 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1308 << "=" 1309 << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) + 1310 "\"") 1311 .str(); 1312 1313 // Parse '{'. 1314 if (Tok.is(tok::l_brace)) { 1315 (void)ConsumeBrace(); 1316 } else { 1317 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1318 << "{" 1319 << ("'=' that follows the context set name \"" + 1320 getOpenMPContextTraitSetName(TISet.Kind) + "\"") 1321 .str(); 1322 } 1323 1324 llvm::StringMap<SourceLocation> SeenSelectors; 1325 do { 1326 OMPTraitSelector TISelector; 1327 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors); 1328 if (TISelector.Kind != TraitSelector::invalid && 1329 !TISelector.Properties.empty()) 1330 TISet.Selectors.push_back(TISelector); 1331 } while (TryConsumeToken(tok::comma)); 1332 1333 // Parse '}'. 1334 if (Tok.is(tok::r_brace)) { 1335 (void)ConsumeBrace(); 1336 } else { 1337 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1338 << "}" 1339 << ("context selectors for the context set \"" + 1340 getOpenMPContextTraitSetName(TISet.Kind) + "\"") 1341 .str(); 1342 } 1343 } 1344 1345 /// Parse OpenMP context selectors: 1346 /// 1347 /// <trait-set-selector> [, <trait-set-selector>]* 1348 bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo& TI) { 1349 llvm::StringMap<SourceLocation> SeenSets; 1350 do { 1351 OMPTraitSet TISet; 1352 parseOMPContextSelectorSet(TISet, SeenSets); 1353 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty()) 1354 TI.Sets.push_back(TISet); 1355 } while (TryConsumeToken(tok::comma)); 1356 1357 return false; 1358 } 1359 1360 /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'. 1361 void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, 1362 CachedTokens &Toks, 1363 SourceLocation Loc) { 1364 PP.EnterToken(Tok, /*IsReinject*/ true); 1365 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 1366 /*IsReinject*/ true); 1367 // Consume the previously pushed token. 1368 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1369 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1370 1371 FNContextRAII FnContext(*this, Ptr); 1372 // Parse function declaration id. 1373 SourceLocation RLoc; 1374 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs 1375 // instead of MemberExprs. 1376 ExprResult AssociatedFunction; 1377 { 1378 // Do not mark function as is used to prevent its emission if this is the 1379 // only place where it is used. 1380 EnterExpressionEvaluationContext Unevaluated( 1381 Actions, Sema::ExpressionEvaluationContext::Unevaluated); 1382 AssociatedFunction = ParseOpenMPParensExpr( 1383 getOpenMPDirectiveName(OMPD_declare_variant), RLoc, 1384 /*IsAddressOfOperand=*/true); 1385 } 1386 if (!AssociatedFunction.isUsable()) { 1387 if (!Tok.is(tok::annot_pragma_openmp_end)) 1388 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1389 ; 1390 // Skip the last annot_pragma_openmp_end. 1391 (void)ConsumeAnnotationToken(); 1392 return; 1393 } 1394 1395 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); 1396 if (parseOMPDeclareVariantMatchClause(Loc, TI)) 1397 return; 1398 1399 Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = 1400 Actions.checkOpenMPDeclareVariantFunction( 1401 Ptr, AssociatedFunction.get(), TI, 1402 SourceRange(Loc, Tok.getLocation())); 1403 1404 // Skip last tokens. 1405 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1406 ConsumeAnyToken(); 1407 if (DeclVarData && !TI.Sets.empty()) 1408 Actions.ActOnOpenMPDeclareVariantDirective( 1409 DeclVarData->first, DeclVarData->second, TI, 1410 SourceRange(Loc, Tok.getLocation())); 1411 1412 // Skip the last annot_pragma_openmp_end. 1413 (void)ConsumeAnnotationToken(); 1414 } 1415 1416 bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc, 1417 OMPTraitInfo &TI) { 1418 // Parse 'match'. 1419 OpenMPClauseKind CKind = Tok.isAnnotation() 1420 ? OMPC_unknown 1421 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1422 if (CKind != OMPC_match) { 1423 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1424 << getOpenMPClauseName(OMPC_match); 1425 while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 1426 ; 1427 // Skip the last annot_pragma_openmp_end. 1428 (void)ConsumeAnnotationToken(); 1429 return true; 1430 } 1431 (void)ConsumeToken(); 1432 // Parse '('. 1433 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1434 if (T.expectAndConsume(diag::err_expected_lparen_after, 1435 getOpenMPClauseName(OMPC_match).data())) { 1436 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1437 ; 1438 // Skip the last annot_pragma_openmp_end. 1439 (void)ConsumeAnnotationToken(); 1440 return true; 1441 } 1442 1443 // Parse inner context selectors. 1444 parseOMPContextSelectors(Loc, TI); 1445 1446 // Parse ')' 1447 (void)T.consumeClose(); 1448 return false; 1449 } 1450 1451 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1452 /// 1453 /// default-clause: 1454 /// 'default' '(' 'none' | 'shared' ') 1455 /// 1456 /// proc_bind-clause: 1457 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1458 /// 1459 /// device_type-clause: 1460 /// 'device_type' '(' 'host' | 'nohost' | 'any' )' 1461 namespace { 1462 struct SimpleClauseData { 1463 unsigned Type; 1464 SourceLocation Loc; 1465 SourceLocation LOpen; 1466 SourceLocation TypeLoc; 1467 SourceLocation RLoc; 1468 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen, 1469 SourceLocation TypeLoc, SourceLocation RLoc) 1470 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {} 1471 }; 1472 } // anonymous namespace 1473 1474 static Optional<SimpleClauseData> 1475 parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) { 1476 const Token &Tok = P.getCurToken(); 1477 SourceLocation Loc = Tok.getLocation(); 1478 SourceLocation LOpen = P.ConsumeToken(); 1479 // Parse '('. 1480 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); 1481 if (T.expectAndConsume(diag::err_expected_lparen_after, 1482 getOpenMPClauseName(Kind).data())) 1483 return llvm::None; 1484 1485 unsigned Type = getOpenMPSimpleClauseType( 1486 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok)); 1487 SourceLocation TypeLoc = Tok.getLocation(); 1488 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1489 Tok.isNot(tok::annot_pragma_openmp_end)) 1490 P.ConsumeAnyToken(); 1491 1492 // Parse ')'. 1493 SourceLocation RLoc = Tok.getLocation(); 1494 if (!T.consumeClose()) 1495 RLoc = T.getCloseLocation(); 1496 1497 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc); 1498 } 1499 1500 Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() { 1501 // OpenMP 4.5 syntax with list of entities. 1502 Sema::NamedDeclSetType SameDirectiveDecls; 1503 SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation, 1504 NamedDecl *>, 1505 4> 1506 DeclareTargetDecls; 1507 OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any; 1508 SourceLocation DeviceTypeLoc; 1509 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1510 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; 1511 if (Tok.is(tok::identifier)) { 1512 IdentifierInfo *II = Tok.getIdentifierInfo(); 1513 StringRef ClauseName = II->getName(); 1514 bool IsDeviceTypeClause = 1515 getLangOpts().OpenMP >= 50 && 1516 getOpenMPClauseKind(ClauseName) == OMPC_device_type; 1517 // Parse 'to|link|device_type' clauses. 1518 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) && 1519 !IsDeviceTypeClause) { 1520 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 1521 << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0); 1522 break; 1523 } 1524 // Parse 'device_type' clause and go to next clause if any. 1525 if (IsDeviceTypeClause) { 1526 Optional<SimpleClauseData> DevTypeData = 1527 parseOpenMPSimpleClause(*this, OMPC_device_type); 1528 if (DevTypeData.hasValue()) { 1529 if (DeviceTypeLoc.isValid()) { 1530 // We already saw another device_type clause, diagnose it. 1531 Diag(DevTypeData.getValue().Loc, 1532 diag::warn_omp_more_one_device_type_clause); 1533 } 1534 switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) { 1535 case OMPC_DEVICE_TYPE_any: 1536 DT = OMPDeclareTargetDeclAttr::DT_Any; 1537 break; 1538 case OMPC_DEVICE_TYPE_host: 1539 DT = OMPDeclareTargetDeclAttr::DT_Host; 1540 break; 1541 case OMPC_DEVICE_TYPE_nohost: 1542 DT = OMPDeclareTargetDeclAttr::DT_NoHost; 1543 break; 1544 case OMPC_DEVICE_TYPE_unknown: 1545 llvm_unreachable("Unexpected device_type"); 1546 } 1547 DeviceTypeLoc = DevTypeData.getValue().Loc; 1548 } 1549 continue; 1550 } 1551 ConsumeToken(); 1552 } 1553 auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls]( 1554 CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 1555 NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName( 1556 getCurScope(), SS, NameInfo, SameDirectiveDecls); 1557 if (ND) 1558 DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND); 1559 }; 1560 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, 1561 /*AllowScopeSpecifier=*/true)) 1562 break; 1563 1564 // Consume optional ','. 1565 if (Tok.is(tok::comma)) 1566 ConsumeToken(); 1567 } 1568 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1569 ConsumeAnyToken(); 1570 for (auto &MTLocDecl : DeclareTargetDecls) { 1571 OMPDeclareTargetDeclAttr::MapTypeTy MT; 1572 SourceLocation Loc; 1573 NamedDecl *ND; 1574 std::tie(MT, Loc, ND) = MTLocDecl; 1575 // device_type clause is applied only to functions. 1576 Actions.ActOnOpenMPDeclareTargetName( 1577 ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT); 1578 } 1579 SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), 1580 SameDirectiveDecls.end()); 1581 if (Decls.empty()) 1582 return DeclGroupPtrTy(); 1583 return Actions.BuildDeclaratorGroup(Decls); 1584 } 1585 1586 void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) { 1587 // The last seen token is annot_pragma_openmp_end - need to check for 1588 // extra tokens. 1589 if (Tok.is(tok::annot_pragma_openmp_end)) 1590 return; 1591 1592 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1593 << getOpenMPDirectiveName(DKind); 1594 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1595 ConsumeAnyToken(); 1596 } 1597 1598 void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind, 1599 OpenMPDirectiveKind ExpectedKind, 1600 OpenMPDirectiveKind FoundKind, 1601 SourceLocation BeginLoc, 1602 SourceLocation FoundLoc, 1603 bool SkipUntilOpenMPEnd) { 1604 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1; 1605 1606 if (FoundKind == ExpectedKind) { 1607 ConsumeAnyToken(); 1608 skipUntilPragmaOpenMPEnd(ExpectedKind); 1609 return; 1610 } 1611 1612 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant) 1613 << DiagSelection; 1614 Diag(BeginLoc, diag::note_matching) 1615 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str(); 1616 if (SkipUntilOpenMPEnd) 1617 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1618 } 1619 1620 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind, 1621 SourceLocation DKLoc) { 1622 parseOMPEndDirective(OMPD_declare_target, OMPD_end_declare_target, DKind, 1623 DKLoc, Tok.getLocation(), 1624 /* SkipUntilOpenMPEnd */ false); 1625 // Skip the last annot_pragma_openmp_end. 1626 if (Tok.is(tok::annot_pragma_openmp_end)) 1627 ConsumeAnnotationToken(); 1628 } 1629 1630 /// Parsing of declarative OpenMP directives. 1631 /// 1632 /// threadprivate-directive: 1633 /// annot_pragma_openmp 'threadprivate' simple-variable-list 1634 /// annot_pragma_openmp_end 1635 /// 1636 /// allocate-directive: 1637 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>] 1638 /// annot_pragma_openmp_end 1639 /// 1640 /// declare-reduction-directive: 1641 /// annot_pragma_openmp 'declare' 'reduction' [...] 1642 /// annot_pragma_openmp_end 1643 /// 1644 /// declare-mapper-directive: 1645 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 1646 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 1647 /// annot_pragma_openmp_end 1648 /// 1649 /// declare-simd-directive: 1650 /// annot_pragma_openmp 'declare simd' {<clause> [,]} 1651 /// annot_pragma_openmp_end 1652 /// <function declaration/definition> 1653 /// 1654 /// requires directive: 1655 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] 1656 /// annot_pragma_openmp_end 1657 /// 1658 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 1659 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed, 1660 DeclSpec::TST TagType, Decl *Tag) { 1661 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 1662 ParsingOpenMPDirectiveRAII DirScope(*this); 1663 ParenBraceBracketBalancer BalancerRAIIObj(*this); 1664 1665 SourceLocation Loc; 1666 OpenMPDirectiveKind DKind; 1667 if (Delayed) { 1668 TentativeParsingAction TPA(*this); 1669 Loc = ConsumeAnnotationToken(); 1670 DKind = parseOpenMPDirectiveKind(*this); 1671 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) { 1672 // Need to delay parsing until completion of the parent class. 1673 TPA.Revert(); 1674 CachedTokens Toks; 1675 unsigned Cnt = 1; 1676 Toks.push_back(Tok); 1677 while (Cnt && Tok.isNot(tok::eof)) { 1678 (void)ConsumeAnyToken(); 1679 if (Tok.is(tok::annot_pragma_openmp)) 1680 ++Cnt; 1681 else if (Tok.is(tok::annot_pragma_openmp_end)) 1682 --Cnt; 1683 Toks.push_back(Tok); 1684 } 1685 // Skip last annot_pragma_openmp_end. 1686 if (Cnt == 0) 1687 (void)ConsumeAnyToken(); 1688 auto *LP = new LateParsedPragma(this, AS); 1689 LP->takeToks(Toks); 1690 getCurrentClass().LateParsedDeclarations.push_back(LP); 1691 return nullptr; 1692 } 1693 TPA.Commit(); 1694 } else { 1695 Loc = ConsumeAnnotationToken(); 1696 DKind = parseOpenMPDirectiveKind(*this); 1697 } 1698 1699 switch (DKind) { 1700 case OMPD_threadprivate: { 1701 ConsumeToken(); 1702 DeclDirectiveListParserHelper Helper(this, DKind); 1703 if (!ParseOpenMPSimpleVarList(DKind, Helper, 1704 /*AllowScopeSpecifier=*/true)) { 1705 skipUntilPragmaOpenMPEnd(DKind); 1706 // Skip the last annot_pragma_openmp_end. 1707 ConsumeAnnotationToken(); 1708 return Actions.ActOnOpenMPThreadprivateDirective(Loc, 1709 Helper.getIdentifiers()); 1710 } 1711 break; 1712 } 1713 case OMPD_allocate: { 1714 ConsumeToken(); 1715 DeclDirectiveListParserHelper Helper(this, DKind); 1716 if (!ParseOpenMPSimpleVarList(DKind, Helper, 1717 /*AllowScopeSpecifier=*/true)) { 1718 SmallVector<OMPClause *, 1> Clauses; 1719 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1720 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1721 unsigned(OMPC_unknown) + 1> 1722 FirstClauses(unsigned(OMPC_unknown) + 1); 1723 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1724 OpenMPClauseKind CKind = 1725 Tok.isAnnotation() ? OMPC_unknown 1726 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1727 Actions.StartOpenMPClause(CKind); 1728 OMPClause *Clause = ParseOpenMPClause( 1729 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 1730 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1731 StopBeforeMatch); 1732 FirstClauses[unsigned(CKind)].setInt(true); 1733 if (Clause != nullptr) 1734 Clauses.push_back(Clause); 1735 if (Tok.is(tok::annot_pragma_openmp_end)) { 1736 Actions.EndOpenMPClause(); 1737 break; 1738 } 1739 // Skip ',' if any. 1740 if (Tok.is(tok::comma)) 1741 ConsumeToken(); 1742 Actions.EndOpenMPClause(); 1743 } 1744 skipUntilPragmaOpenMPEnd(DKind); 1745 } 1746 // Skip the last annot_pragma_openmp_end. 1747 ConsumeAnnotationToken(); 1748 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(), 1749 Clauses); 1750 } 1751 break; 1752 } 1753 case OMPD_requires: { 1754 SourceLocation StartLoc = ConsumeToken(); 1755 SmallVector<OMPClause *, 5> Clauses; 1756 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 1757 unsigned(OMPC_unknown) + 1> 1758 FirstClauses(unsigned(OMPC_unknown) + 1); 1759 if (Tok.is(tok::annot_pragma_openmp_end)) { 1760 Diag(Tok, diag::err_omp_expected_clause) 1761 << getOpenMPDirectiveName(OMPD_requires); 1762 break; 1763 } 1764 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1765 OpenMPClauseKind CKind = Tok.isAnnotation() 1766 ? OMPC_unknown 1767 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1768 Actions.StartOpenMPClause(CKind); 1769 OMPClause *Clause = ParseOpenMPClause( 1770 OMPD_requires, CKind, !FirstClauses[unsigned(CKind)].getInt()); 1771 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 1772 StopBeforeMatch); 1773 FirstClauses[unsigned(CKind)].setInt(true); 1774 if (Clause != nullptr) 1775 Clauses.push_back(Clause); 1776 if (Tok.is(tok::annot_pragma_openmp_end)) { 1777 Actions.EndOpenMPClause(); 1778 break; 1779 } 1780 // Skip ',' if any. 1781 if (Tok.is(tok::comma)) 1782 ConsumeToken(); 1783 Actions.EndOpenMPClause(); 1784 } 1785 // Consume final annot_pragma_openmp_end 1786 if (Clauses.empty()) { 1787 Diag(Tok, diag::err_omp_expected_clause) 1788 << getOpenMPDirectiveName(OMPD_requires); 1789 ConsumeAnnotationToken(); 1790 return nullptr; 1791 } 1792 ConsumeAnnotationToken(); 1793 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); 1794 } 1795 case OMPD_declare_reduction: 1796 ConsumeToken(); 1797 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { 1798 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 1799 // Skip the last annot_pragma_openmp_end. 1800 ConsumeAnnotationToken(); 1801 return Res; 1802 } 1803 break; 1804 case OMPD_declare_mapper: { 1805 ConsumeToken(); 1806 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) { 1807 // Skip the last annot_pragma_openmp_end. 1808 ConsumeAnnotationToken(); 1809 return Res; 1810 } 1811 break; 1812 } 1813 case OMPD_begin_declare_variant: { 1814 // The syntax is: 1815 // { #pragma omp begin declare variant clause } 1816 // <function-declaration-or-definition-sequence> 1817 // { #pragma omp end declare variant } 1818 // 1819 ConsumeToken(); 1820 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); 1821 if (parseOMPDeclareVariantMatchClause(Loc, TI)) 1822 break; 1823 1824 // Skip last tokens. 1825 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant); 1826 1827 VariantMatchInfo VMI; 1828 ASTContext &ASTCtx = Actions.getASTContext(); 1829 TI.getAsVariantMatchInfo(ASTCtx, VMI); 1830 OMPContext OMPCtx(ASTCtx.getLangOpts().OpenMPIsDevice, 1831 ASTCtx.getTargetInfo().getTriple()); 1832 1833 if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) { 1834 Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI); 1835 break; 1836 } 1837 1838 // Elide all the code till the matching end declare variant was found. 1839 unsigned Nesting = 1; 1840 SourceLocation DKLoc; 1841 OpenMPDirectiveKind DK = OMPD_unknown; 1842 do { 1843 DKLoc = Tok.getLocation(); 1844 DK = parseOpenMPDirectiveKind(*this); 1845 if (DK == OMPD_end_declare_variant) 1846 --Nesting; 1847 else if (DK == OMPD_begin_declare_variant) 1848 ++Nesting; 1849 if (!Nesting || isEofOrEom()) 1850 break; 1851 ConsumeAnyToken(); 1852 } while (true); 1853 1854 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, 1855 DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true); 1856 if (isEofOrEom()) 1857 return nullptr; 1858 break; 1859 } 1860 case OMPD_end_declare_variant: { 1861 if (Actions.isInOpenMPDeclareVariantScope()) 1862 Actions.ActOnOpenMPEndDeclareVariant(); 1863 else 1864 Diag(Loc, diag::err_expected_begin_declare_variant); 1865 ConsumeToken(); 1866 break; 1867 } 1868 case OMPD_declare_variant: 1869 case OMPD_declare_simd: { 1870 // The syntax is: 1871 // { #pragma omp declare {simd|variant} } 1872 // <function-declaration-or-definition> 1873 // 1874 CachedTokens Toks; 1875 Toks.push_back(Tok); 1876 ConsumeToken(); 1877 while(Tok.isNot(tok::annot_pragma_openmp_end)) { 1878 Toks.push_back(Tok); 1879 ConsumeAnyToken(); 1880 } 1881 Toks.push_back(Tok); 1882 ConsumeAnyToken(); 1883 1884 DeclGroupPtrTy Ptr; 1885 if (Tok.is(tok::annot_pragma_openmp)) { 1886 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed, 1887 TagType, Tag); 1888 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 1889 // Here we expect to see some function declaration. 1890 if (AS == AS_none) { 1891 assert(TagType == DeclSpec::TST_unspecified); 1892 MaybeParseCXX11Attributes(Attrs); 1893 ParsingDeclSpec PDS(*this); 1894 Ptr = ParseExternalDeclaration(Attrs, &PDS); 1895 } else { 1896 Ptr = 1897 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1898 } 1899 } 1900 if (!Ptr) { 1901 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant) 1902 << (DKind == OMPD_declare_simd ? 0 : 1); 1903 return DeclGroupPtrTy(); 1904 } 1905 if (DKind == OMPD_declare_simd) 1906 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 1907 assert(DKind == OMPD_declare_variant && 1908 "Expected declare variant directive only"); 1909 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc); 1910 return Ptr; 1911 } 1912 case OMPD_declare_target: { 1913 SourceLocation DTLoc = ConsumeAnyToken(); 1914 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 1915 return ParseOMPDeclareTargetClauses(); 1916 } 1917 1918 // Skip the last annot_pragma_openmp_end. 1919 ConsumeAnyToken(); 1920 1921 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc)) 1922 return DeclGroupPtrTy(); 1923 1924 llvm::SmallVector<Decl *, 4> Decls; 1925 DKind = parseOpenMPDirectiveKind(*this); 1926 while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) && 1927 Tok.isNot(tok::r_brace)) { 1928 DeclGroupPtrTy Ptr; 1929 // Here we expect to see some function declaration. 1930 if (AS == AS_none) { 1931 assert(TagType == DeclSpec::TST_unspecified); 1932 MaybeParseCXX11Attributes(Attrs); 1933 ParsingDeclSpec PDS(*this); 1934 Ptr = ParseExternalDeclaration(Attrs, &PDS); 1935 } else { 1936 Ptr = 1937 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 1938 } 1939 if (Ptr) { 1940 DeclGroupRef Ref = Ptr.get(); 1941 Decls.append(Ref.begin(), Ref.end()); 1942 } 1943 if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { 1944 TentativeParsingAction TPA(*this); 1945 ConsumeAnnotationToken(); 1946 DKind = parseOpenMPDirectiveKind(*this); 1947 if (DKind != OMPD_end_declare_target) 1948 TPA.Revert(); 1949 else 1950 TPA.Commit(); 1951 } 1952 } 1953 1954 ParseOMPEndDeclareTargetDirective(DKind, DTLoc); 1955 Actions.ActOnFinishOpenMPDeclareTargetDirective(); 1956 return Actions.BuildDeclaratorGroup(Decls); 1957 } 1958 case OMPD_unknown: 1959 Diag(Tok, diag::err_omp_unknown_directive); 1960 break; 1961 case OMPD_parallel: 1962 case OMPD_simd: 1963 case OMPD_task: 1964 case OMPD_taskyield: 1965 case OMPD_barrier: 1966 case OMPD_taskwait: 1967 case OMPD_taskgroup: 1968 case OMPD_flush: 1969 case OMPD_depobj: 1970 case OMPD_scan: 1971 case OMPD_for: 1972 case OMPD_for_simd: 1973 case OMPD_sections: 1974 case OMPD_section: 1975 case OMPD_single: 1976 case OMPD_master: 1977 case OMPD_ordered: 1978 case OMPD_critical: 1979 case OMPD_parallel_for: 1980 case OMPD_parallel_for_simd: 1981 case OMPD_parallel_sections: 1982 case OMPD_parallel_master: 1983 case OMPD_atomic: 1984 case OMPD_target: 1985 case OMPD_teams: 1986 case OMPD_cancellation_point: 1987 case OMPD_cancel: 1988 case OMPD_target_data: 1989 case OMPD_target_enter_data: 1990 case OMPD_target_exit_data: 1991 case OMPD_target_parallel: 1992 case OMPD_target_parallel_for: 1993 case OMPD_taskloop: 1994 case OMPD_taskloop_simd: 1995 case OMPD_master_taskloop: 1996 case OMPD_master_taskloop_simd: 1997 case OMPD_parallel_master_taskloop: 1998 case OMPD_parallel_master_taskloop_simd: 1999 case OMPD_distribute: 2000 case OMPD_end_declare_target: 2001 case OMPD_target_update: 2002 case OMPD_distribute_parallel_for: 2003 case OMPD_distribute_parallel_for_simd: 2004 case OMPD_distribute_simd: 2005 case OMPD_target_parallel_for_simd: 2006 case OMPD_target_simd: 2007 case OMPD_teams_distribute: 2008 case OMPD_teams_distribute_simd: 2009 case OMPD_teams_distribute_parallel_for_simd: 2010 case OMPD_teams_distribute_parallel_for: 2011 case OMPD_target_teams: 2012 case OMPD_target_teams_distribute: 2013 case OMPD_target_teams_distribute_parallel_for: 2014 case OMPD_target_teams_distribute_parallel_for_simd: 2015 case OMPD_target_teams_distribute_simd: 2016 Diag(Tok, diag::err_omp_unexpected_directive) 2017 << 1 << getOpenMPDirectiveName(DKind); 2018 break; 2019 } 2020 while (Tok.isNot(tok::annot_pragma_openmp_end)) 2021 ConsumeAnyToken(); 2022 ConsumeAnyToken(); 2023 return nullptr; 2024 } 2025 2026 /// Parsing of declarative or executable OpenMP directives. 2027 /// 2028 /// threadprivate-directive: 2029 /// annot_pragma_openmp 'threadprivate' simple-variable-list 2030 /// annot_pragma_openmp_end 2031 /// 2032 /// allocate-directive: 2033 /// annot_pragma_openmp 'allocate' simple-variable-list 2034 /// annot_pragma_openmp_end 2035 /// 2036 /// declare-reduction-directive: 2037 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 2038 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 2039 /// ('omp_priv' '=' <expression>|<function_call>) ')'] 2040 /// annot_pragma_openmp_end 2041 /// 2042 /// declare-mapper-directive: 2043 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 2044 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 2045 /// annot_pragma_openmp_end 2046 /// 2047 /// executable-directive: 2048 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 2049 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 2050 /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' | 2051 /// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 2052 /// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target 2053 /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 2054 /// 'master taskloop' | 'master taskloop simd' | 'parallel master 2055 /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target 2056 /// enter data' | 'target exit data' | 'target parallel' | 'target 2057 /// parallel for' | 'target update' | 'distribute parallel for' | 2058 /// 'distribute paralle for simd' | 'distribute simd' | 'target parallel 2059 /// for simd' | 'target simd' | 'teams distribute' | 'teams distribute 2060 /// simd' | 'teams distribute parallel for simd' | 'teams distribute 2061 /// parallel for' | 'target teams' | 'target teams distribute' | 'target 2062 /// teams distribute parallel for' | 'target teams distribute parallel 2063 /// for simd' | 'target teams distribute simd' {clause} 2064 /// annot_pragma_openmp_end 2065 /// 2066 StmtResult 2067 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { 2068 assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); 2069 ParsingOpenMPDirectiveRAII DirScope(*this); 2070 ParenBraceBracketBalancer BalancerRAIIObj(*this); 2071 SmallVector<OMPClause *, 5> Clauses; 2072 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2073 unsigned(OMPC_unknown) + 1> 2074 FirstClauses(unsigned(OMPC_unknown) + 1); 2075 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 2076 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 2077 SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; 2078 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 2079 OpenMPDirectiveKind CancelRegion = OMPD_unknown; 2080 // Name of critical directive. 2081 DeclarationNameInfo DirName; 2082 StmtResult Directive = StmtError(); 2083 bool HasAssociatedStatement = true; 2084 2085 switch (DKind) { 2086 case OMPD_threadprivate: { 2087 // FIXME: Should this be permitted in C++? 2088 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2089 ParsedStmtContext()) { 2090 Diag(Tok, diag::err_omp_immediate_directive) 2091 << getOpenMPDirectiveName(DKind) << 0; 2092 } 2093 ConsumeToken(); 2094 DeclDirectiveListParserHelper Helper(this, DKind); 2095 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2096 /*AllowScopeSpecifier=*/false)) { 2097 skipUntilPragmaOpenMPEnd(DKind); 2098 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 2099 Loc, Helper.getIdentifiers()); 2100 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2101 } 2102 SkipUntil(tok::annot_pragma_openmp_end); 2103 break; 2104 } 2105 case OMPD_allocate: { 2106 // FIXME: Should this be permitted in C++? 2107 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2108 ParsedStmtContext()) { 2109 Diag(Tok, diag::err_omp_immediate_directive) 2110 << getOpenMPDirectiveName(DKind) << 0; 2111 } 2112 ConsumeToken(); 2113 DeclDirectiveListParserHelper Helper(this, DKind); 2114 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2115 /*AllowScopeSpecifier=*/false)) { 2116 SmallVector<OMPClause *, 1> Clauses; 2117 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 2118 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2119 unsigned(OMPC_unknown) + 1> 2120 FirstClauses(unsigned(OMPC_unknown) + 1); 2121 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2122 OpenMPClauseKind CKind = 2123 Tok.isAnnotation() ? OMPC_unknown 2124 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2125 Actions.StartOpenMPClause(CKind); 2126 OMPClause *Clause = ParseOpenMPClause( 2127 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2128 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2129 StopBeforeMatch); 2130 FirstClauses[unsigned(CKind)].setInt(true); 2131 if (Clause != nullptr) 2132 Clauses.push_back(Clause); 2133 if (Tok.is(tok::annot_pragma_openmp_end)) { 2134 Actions.EndOpenMPClause(); 2135 break; 2136 } 2137 // Skip ',' if any. 2138 if (Tok.is(tok::comma)) 2139 ConsumeToken(); 2140 Actions.EndOpenMPClause(); 2141 } 2142 skipUntilPragmaOpenMPEnd(DKind); 2143 } 2144 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective( 2145 Loc, Helper.getIdentifiers(), Clauses); 2146 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2147 } 2148 SkipUntil(tok::annot_pragma_openmp_end); 2149 break; 2150 } 2151 case OMPD_declare_reduction: 2152 ConsumeToken(); 2153 if (DeclGroupPtrTy Res = 2154 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 2155 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 2156 ConsumeAnyToken(); 2157 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2158 } else { 2159 SkipUntil(tok::annot_pragma_openmp_end); 2160 } 2161 break; 2162 case OMPD_declare_mapper: { 2163 ConsumeToken(); 2164 if (DeclGroupPtrTy Res = 2165 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) { 2166 // Skip the last annot_pragma_openmp_end. 2167 ConsumeAnnotationToken(); 2168 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2169 } else { 2170 SkipUntil(tok::annot_pragma_openmp_end); 2171 } 2172 break; 2173 } 2174 case OMPD_flush: 2175 case OMPD_depobj: 2176 case OMPD_scan: 2177 case OMPD_taskyield: 2178 case OMPD_barrier: 2179 case OMPD_taskwait: 2180 case OMPD_cancellation_point: 2181 case OMPD_cancel: 2182 case OMPD_target_enter_data: 2183 case OMPD_target_exit_data: 2184 case OMPD_target_update: 2185 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2186 ParsedStmtContext()) { 2187 Diag(Tok, diag::err_omp_immediate_directive) 2188 << getOpenMPDirectiveName(DKind) << 0; 2189 } 2190 HasAssociatedStatement = false; 2191 // Fall through for further analysis. 2192 LLVM_FALLTHROUGH; 2193 case OMPD_parallel: 2194 case OMPD_simd: 2195 case OMPD_for: 2196 case OMPD_for_simd: 2197 case OMPD_sections: 2198 case OMPD_single: 2199 case OMPD_section: 2200 case OMPD_master: 2201 case OMPD_critical: 2202 case OMPD_parallel_for: 2203 case OMPD_parallel_for_simd: 2204 case OMPD_parallel_sections: 2205 case OMPD_parallel_master: 2206 case OMPD_task: 2207 case OMPD_ordered: 2208 case OMPD_atomic: 2209 case OMPD_target: 2210 case OMPD_teams: 2211 case OMPD_taskgroup: 2212 case OMPD_target_data: 2213 case OMPD_target_parallel: 2214 case OMPD_target_parallel_for: 2215 case OMPD_taskloop: 2216 case OMPD_taskloop_simd: 2217 case OMPD_master_taskloop: 2218 case OMPD_master_taskloop_simd: 2219 case OMPD_parallel_master_taskloop: 2220 case OMPD_parallel_master_taskloop_simd: 2221 case OMPD_distribute: 2222 case OMPD_distribute_parallel_for: 2223 case OMPD_distribute_parallel_for_simd: 2224 case OMPD_distribute_simd: 2225 case OMPD_target_parallel_for_simd: 2226 case OMPD_target_simd: 2227 case OMPD_teams_distribute: 2228 case OMPD_teams_distribute_simd: 2229 case OMPD_teams_distribute_parallel_for_simd: 2230 case OMPD_teams_distribute_parallel_for: 2231 case OMPD_target_teams: 2232 case OMPD_target_teams_distribute: 2233 case OMPD_target_teams_distribute_parallel_for: 2234 case OMPD_target_teams_distribute_parallel_for_simd: 2235 case OMPD_target_teams_distribute_simd: { 2236 // Special processing for flush and depobj clauses. 2237 Token ImplicitTok; 2238 bool ImplicitClauseAllowed = false; 2239 if (DKind == OMPD_flush || DKind == OMPD_depobj) { 2240 ImplicitTok = Tok; 2241 ImplicitClauseAllowed = true; 2242 } 2243 ConsumeToken(); 2244 // Parse directive name of the 'critical' directive if any. 2245 if (DKind == OMPD_critical) { 2246 BalancedDelimiterTracker T(*this, tok::l_paren, 2247 tok::annot_pragma_openmp_end); 2248 if (!T.consumeOpen()) { 2249 if (Tok.isAnyIdentifier()) { 2250 DirName = 2251 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 2252 ConsumeAnyToken(); 2253 } else { 2254 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 2255 } 2256 T.consumeClose(); 2257 } 2258 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 2259 CancelRegion = parseOpenMPDirectiveKind(*this); 2260 if (Tok.isNot(tok::annot_pragma_openmp_end)) 2261 ConsumeToken(); 2262 } 2263 2264 if (isOpenMPLoopDirective(DKind)) 2265 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 2266 if (isOpenMPSimdDirective(DKind)) 2267 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 2268 ParseScope OMPDirectiveScope(this, ScopeFlags); 2269 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 2270 2271 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2272 bool HasImplicitClause = false; 2273 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) { 2274 HasImplicitClause = true; 2275 // Push copy of the current token back to stream to properly parse 2276 // pseudo-clause OMPFlushClause or OMPDepobjClause. 2277 PP.EnterToken(Tok, /*IsReinject*/ true); 2278 PP.EnterToken(ImplicitTok, /*IsReinject*/ true); 2279 ConsumeAnyToken(); 2280 } 2281 OpenMPClauseKind CKind = Tok.isAnnotation() 2282 ? OMPC_unknown 2283 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2284 if (HasImplicitClause) { 2285 assert(CKind == OMPC_unknown && "Must be unknown implicit clause."); 2286 if (DKind == OMPD_flush) { 2287 CKind = OMPC_flush; 2288 } else { 2289 assert(DKind == OMPD_depobj && 2290 "Expected flush or depobj directives."); 2291 CKind = OMPC_depobj; 2292 } 2293 } 2294 // No more implicit clauses allowed. 2295 ImplicitClauseAllowed = false; 2296 Actions.StartOpenMPClause(CKind); 2297 HasImplicitClause = false; 2298 OMPClause *Clause = ParseOpenMPClause( 2299 DKind, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2300 FirstClauses[unsigned(CKind)].setInt(true); 2301 if (Clause) { 2302 FirstClauses[unsigned(CKind)].setPointer(Clause); 2303 Clauses.push_back(Clause); 2304 } 2305 2306 // Skip ',' if any. 2307 if (Tok.is(tok::comma)) 2308 ConsumeToken(); 2309 Actions.EndOpenMPClause(); 2310 } 2311 // End location of the directive. 2312 EndLoc = Tok.getLocation(); 2313 // Consume final annot_pragma_openmp_end. 2314 ConsumeAnnotationToken(); 2315 2316 // OpenMP [2.13.8, ordered Construct, Syntax] 2317 // If the depend clause is specified, the ordered construct is a stand-alone 2318 // directive. 2319 if (DKind == OMPD_ordered && FirstClauses[unsigned(OMPC_depend)].getInt()) { 2320 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2321 ParsedStmtContext()) { 2322 Diag(Loc, diag::err_omp_immediate_directive) 2323 << getOpenMPDirectiveName(DKind) << 1 2324 << getOpenMPClauseName(OMPC_depend); 2325 } 2326 HasAssociatedStatement = false; 2327 } 2328 2329 StmtResult AssociatedStmt; 2330 if (HasAssociatedStatement) { 2331 // The body is a block scope like in Lambdas and Blocks. 2332 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2333 // FIXME: We create a bogus CompoundStmt scope to hold the contents of 2334 // the captured region. Code elsewhere assumes that any FunctionScopeInfo 2335 // should have at least one compound statement scope within it. 2336 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement()); 2337 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2338 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 2339 DKind == OMPD_target_exit_data) { 2340 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2341 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 2342 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, 2343 /*isStmtExpr=*/false)); 2344 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2345 } 2346 Directive = Actions.ActOnOpenMPExecutableDirective( 2347 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 2348 EndLoc); 2349 2350 // Exit scope. 2351 Actions.EndOpenMPDSABlock(Directive.get()); 2352 OMPDirectiveScope.Exit(); 2353 break; 2354 } 2355 case OMPD_declare_simd: 2356 case OMPD_declare_target: 2357 case OMPD_end_declare_target: 2358 case OMPD_requires: 2359 case OMPD_begin_declare_variant: 2360 case OMPD_end_declare_variant: 2361 case OMPD_declare_variant: 2362 Diag(Tok, diag::err_omp_unexpected_directive) 2363 << 1 << getOpenMPDirectiveName(DKind); 2364 SkipUntil(tok::annot_pragma_openmp_end); 2365 break; 2366 case OMPD_unknown: 2367 Diag(Tok, diag::err_omp_unknown_directive); 2368 SkipUntil(tok::annot_pragma_openmp_end); 2369 break; 2370 } 2371 return Directive; 2372 } 2373 2374 // Parses simple list: 2375 // simple-variable-list: 2376 // '(' id-expression {, id-expression} ')' 2377 // 2378 bool Parser::ParseOpenMPSimpleVarList( 2379 OpenMPDirectiveKind Kind, 2380 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & 2381 Callback, 2382 bool AllowScopeSpecifier) { 2383 // Parse '('. 2384 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2385 if (T.expectAndConsume(diag::err_expected_lparen_after, 2386 getOpenMPDirectiveName(Kind).data())) 2387 return true; 2388 bool IsCorrect = true; 2389 bool NoIdentIsFound = true; 2390 2391 // Read tokens while ')' or annot_pragma_openmp_end is not found. 2392 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 2393 CXXScopeSpec SS; 2394 UnqualifiedId Name; 2395 // Read var name. 2396 Token PrevTok = Tok; 2397 NoIdentIsFound = false; 2398 2399 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 2400 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 2401 /*ObjectHadErrors=*/false, false)) { 2402 IsCorrect = false; 2403 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2404 StopBeforeMatch); 2405 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr, 2406 /*ObjectHadErrors=*/false, false, false, 2407 false, false, nullptr, Name)) { 2408 IsCorrect = false; 2409 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2410 StopBeforeMatch); 2411 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 2412 Tok.isNot(tok::annot_pragma_openmp_end)) { 2413 IsCorrect = false; 2414 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2415 StopBeforeMatch); 2416 Diag(PrevTok.getLocation(), diag::err_expected) 2417 << tok::identifier 2418 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 2419 } else { 2420 Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 2421 } 2422 // Consume ','. 2423 if (Tok.is(tok::comma)) { 2424 ConsumeToken(); 2425 } 2426 } 2427 2428 if (NoIdentIsFound) { 2429 Diag(Tok, diag::err_expected) << tok::identifier; 2430 IsCorrect = false; 2431 } 2432 2433 // Parse ')'. 2434 IsCorrect = !T.consumeClose() && IsCorrect; 2435 2436 return !IsCorrect; 2437 } 2438 2439 /// Parsing of OpenMP clauses. 2440 /// 2441 /// clause: 2442 /// if-clause | final-clause | num_threads-clause | safelen-clause | 2443 /// default-clause | private-clause | firstprivate-clause | shared-clause 2444 /// | linear-clause | aligned-clause | collapse-clause | 2445 /// lastprivate-clause | reduction-clause | proc_bind-clause | 2446 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 2447 /// mergeable-clause | flush-clause | read-clause | write-clause | 2448 /// update-clause | capture-clause | seq_cst-clause | device-clause | 2449 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 2450 /// thread_limit-clause | priority-clause | grainsize-clause | 2451 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 2452 /// from-clause | is_device_ptr-clause | task_reduction-clause | 2453 /// in_reduction-clause | allocator-clause | allocate-clause | 2454 /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause | 2455 /// depobj-clause | destroy-clause | detach-clause | inclusive-clause | 2456 /// exclusive-clause 2457 /// 2458 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 2459 OpenMPClauseKind CKind, bool FirstClause) { 2460 OMPClause *Clause = nullptr; 2461 bool ErrorFound = false; 2462 bool WrongDirective = false; 2463 // Check if clause is allowed for the given directive. 2464 if (CKind != OMPC_unknown && 2465 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) { 2466 Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) 2467 << getOpenMPDirectiveName(DKind); 2468 ErrorFound = true; 2469 WrongDirective = true; 2470 } 2471 2472 switch (CKind) { 2473 case OMPC_final: 2474 case OMPC_num_threads: 2475 case OMPC_safelen: 2476 case OMPC_simdlen: 2477 case OMPC_collapse: 2478 case OMPC_ordered: 2479 case OMPC_num_teams: 2480 case OMPC_thread_limit: 2481 case OMPC_priority: 2482 case OMPC_grainsize: 2483 case OMPC_num_tasks: 2484 case OMPC_hint: 2485 case OMPC_allocator: 2486 case OMPC_depobj: 2487 case OMPC_detach: 2488 // OpenMP [2.5, Restrictions] 2489 // At most one num_threads clause can appear on the directive. 2490 // OpenMP [2.8.1, simd construct, Restrictions] 2491 // Only one safelen clause can appear on a simd directive. 2492 // Only one simdlen clause can appear on a simd directive. 2493 // Only one collapse clause can appear on a simd directive. 2494 // OpenMP [2.11.1, task Construct, Restrictions] 2495 // At most one if clause can appear on the directive. 2496 // At most one final clause can appear on the directive. 2497 // OpenMP [teams Construct, Restrictions] 2498 // At most one num_teams clause can appear on the directive. 2499 // At most one thread_limit clause can appear on the directive. 2500 // OpenMP [2.9.1, task Construct, Restrictions] 2501 // At most one priority clause can appear on the directive. 2502 // OpenMP [2.9.2, taskloop Construct, Restrictions] 2503 // At most one grainsize clause can appear on the directive. 2504 // OpenMP [2.9.2, taskloop Construct, Restrictions] 2505 // At most one num_tasks clause can appear on the directive. 2506 // OpenMP [2.11.3, allocate Directive, Restrictions] 2507 // At most one allocator clause can appear on the directive. 2508 // OpenMP 5.0, 2.10.1 task Construct, Restrictions. 2509 // At most one detach clause can appear on the directive. 2510 if (!FirstClause) { 2511 Diag(Tok, diag::err_omp_more_one_clause) 2512 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2513 ErrorFound = true; 2514 } 2515 2516 if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 2517 Clause = ParseOpenMPClause(CKind, WrongDirective); 2518 else 2519 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 2520 break; 2521 case OMPC_default: 2522 case OMPC_proc_bind: 2523 case OMPC_atomic_default_mem_order: 2524 case OMPC_order: 2525 // OpenMP [2.14.3.1, Restrictions] 2526 // Only a single default clause may be specified on a parallel, task or 2527 // teams directive. 2528 // OpenMP [2.5, parallel Construct, Restrictions] 2529 // At most one proc_bind clause can appear on the directive. 2530 // OpenMP [5.0, Requires directive, Restrictions] 2531 // At most one atomic_default_mem_order clause can appear 2532 // on the directive 2533 if (!FirstClause && CKind != OMPC_order) { 2534 Diag(Tok, diag::err_omp_more_one_clause) 2535 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2536 ErrorFound = true; 2537 } 2538 2539 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 2540 break; 2541 case OMPC_device: 2542 case OMPC_schedule: 2543 case OMPC_dist_schedule: 2544 case OMPC_defaultmap: 2545 // OpenMP [2.7.1, Restrictions, p. 3] 2546 // Only one schedule clause can appear on a loop directive. 2547 // OpenMP 4.5 [2.10.4, Restrictions, p. 106] 2548 // At most one defaultmap clause can appear on the directive. 2549 // OpenMP 5.0 [2.12.5, target construct, Restrictions] 2550 // At most one device clause can appear on the directive. 2551 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && 2552 !FirstClause) { 2553 Diag(Tok, diag::err_omp_more_one_clause) 2554 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2555 ErrorFound = true; 2556 } 2557 LLVM_FALLTHROUGH; 2558 case OMPC_if: 2559 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective); 2560 break; 2561 case OMPC_nowait: 2562 case OMPC_untied: 2563 case OMPC_mergeable: 2564 case OMPC_read: 2565 case OMPC_write: 2566 case OMPC_capture: 2567 case OMPC_seq_cst: 2568 case OMPC_acq_rel: 2569 case OMPC_acquire: 2570 case OMPC_release: 2571 case OMPC_relaxed: 2572 case OMPC_threads: 2573 case OMPC_simd: 2574 case OMPC_nogroup: 2575 case OMPC_unified_address: 2576 case OMPC_unified_shared_memory: 2577 case OMPC_reverse_offload: 2578 case OMPC_dynamic_allocators: 2579 case OMPC_destroy: 2580 // OpenMP [2.7.1, Restrictions, p. 9] 2581 // Only one ordered clause can appear on a loop directive. 2582 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 2583 // Only one nowait clause can appear on a for directive. 2584 // OpenMP [5.0, Requires directive, Restrictions] 2585 // Each of the requires clauses can appear at most once on the directive. 2586 if (!FirstClause) { 2587 Diag(Tok, diag::err_omp_more_one_clause) 2588 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2589 ErrorFound = true; 2590 } 2591 2592 Clause = ParseOpenMPClause(CKind, WrongDirective); 2593 break; 2594 case OMPC_update: 2595 if (!FirstClause) { 2596 Diag(Tok, diag::err_omp_more_one_clause) 2597 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 2598 ErrorFound = true; 2599 } 2600 2601 Clause = (DKind == OMPD_depobj) 2602 ? ParseOpenMPSimpleClause(CKind, WrongDirective) 2603 : ParseOpenMPClause(CKind, WrongDirective); 2604 break; 2605 case OMPC_private: 2606 case OMPC_firstprivate: 2607 case OMPC_lastprivate: 2608 case OMPC_shared: 2609 case OMPC_reduction: 2610 case OMPC_task_reduction: 2611 case OMPC_in_reduction: 2612 case OMPC_linear: 2613 case OMPC_aligned: 2614 case OMPC_copyin: 2615 case OMPC_copyprivate: 2616 case OMPC_flush: 2617 case OMPC_depend: 2618 case OMPC_map: 2619 case OMPC_to: 2620 case OMPC_from: 2621 case OMPC_use_device_ptr: 2622 case OMPC_is_device_ptr: 2623 case OMPC_allocate: 2624 case OMPC_nontemporal: 2625 case OMPC_inclusive: 2626 case OMPC_exclusive: 2627 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 2628 break; 2629 case OMPC_device_type: 2630 case OMPC_unknown: 2631 skipUntilPragmaOpenMPEnd(DKind); 2632 break; 2633 case OMPC_threadprivate: 2634 case OMPC_uniform: 2635 case OMPC_match: 2636 if (!WrongDirective) 2637 Diag(Tok, diag::err_omp_unexpected_clause) 2638 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 2639 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 2640 break; 2641 } 2642 return ErrorFound ? nullptr : Clause; 2643 } 2644 2645 /// Parses simple expression in parens for single-expression clauses of OpenMP 2646 /// constructs. 2647 /// \param RLoc Returned location of right paren. 2648 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 2649 SourceLocation &RLoc, 2650 bool IsAddressOfOperand) { 2651 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2652 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 2653 return ExprError(); 2654 2655 SourceLocation ELoc = Tok.getLocation(); 2656 ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand, 2657 NotTypeCast)); 2658 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 2659 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 2660 2661 // Parse ')'. 2662 RLoc = Tok.getLocation(); 2663 if (!T.consumeClose()) 2664 RLoc = T.getCloseLocation(); 2665 2666 return Val; 2667 } 2668 2669 /// Parsing of OpenMP clauses with single expressions like 'final', 2670 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 2671 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or 2672 /// 'detach'. 2673 /// 2674 /// final-clause: 2675 /// 'final' '(' expression ')' 2676 /// 2677 /// num_threads-clause: 2678 /// 'num_threads' '(' expression ')' 2679 /// 2680 /// safelen-clause: 2681 /// 'safelen' '(' expression ')' 2682 /// 2683 /// simdlen-clause: 2684 /// 'simdlen' '(' expression ')' 2685 /// 2686 /// collapse-clause: 2687 /// 'collapse' '(' expression ')' 2688 /// 2689 /// priority-clause: 2690 /// 'priority' '(' expression ')' 2691 /// 2692 /// grainsize-clause: 2693 /// 'grainsize' '(' expression ')' 2694 /// 2695 /// num_tasks-clause: 2696 /// 'num_tasks' '(' expression ')' 2697 /// 2698 /// hint-clause: 2699 /// 'hint' '(' expression ')' 2700 /// 2701 /// allocator-clause: 2702 /// 'allocator' '(' expression ')' 2703 /// 2704 /// detach-clause: 2705 /// 'detach' '(' event-handler-expression ')' 2706 /// 2707 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 2708 bool ParseOnly) { 2709 SourceLocation Loc = ConsumeToken(); 2710 SourceLocation LLoc = Tok.getLocation(); 2711 SourceLocation RLoc; 2712 2713 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 2714 2715 if (Val.isInvalid()) 2716 return nullptr; 2717 2718 if (ParseOnly) 2719 return nullptr; 2720 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 2721 } 2722 2723 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 2724 /// 2725 /// default-clause: 2726 /// 'default' '(' 'none' | 'shared' ')' 2727 /// 2728 /// proc_bind-clause: 2729 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')' 2730 /// 2731 /// update-clause: 2732 /// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')' 2733 /// 2734 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 2735 bool ParseOnly) { 2736 llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind); 2737 if (!Val || ParseOnly) 2738 return nullptr; 2739 return Actions.ActOnOpenMPSimpleClause( 2740 Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen, 2741 Val.getValue().Loc, Val.getValue().RLoc); 2742 } 2743 2744 /// Parsing of OpenMP clauses like 'ordered'. 2745 /// 2746 /// ordered-clause: 2747 /// 'ordered' 2748 /// 2749 /// nowait-clause: 2750 /// 'nowait' 2751 /// 2752 /// untied-clause: 2753 /// 'untied' 2754 /// 2755 /// mergeable-clause: 2756 /// 'mergeable' 2757 /// 2758 /// read-clause: 2759 /// 'read' 2760 /// 2761 /// threads-clause: 2762 /// 'threads' 2763 /// 2764 /// simd-clause: 2765 /// 'simd' 2766 /// 2767 /// nogroup-clause: 2768 /// 'nogroup' 2769 /// 2770 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 2771 SourceLocation Loc = Tok.getLocation(); 2772 ConsumeAnyToken(); 2773 2774 if (ParseOnly) 2775 return nullptr; 2776 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 2777 } 2778 2779 /// Parsing of OpenMP clauses with single expressions and some additional 2780 /// argument like 'schedule' or 'dist_schedule'. 2781 /// 2782 /// schedule-clause: 2783 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 2784 /// ')' 2785 /// 2786 /// if-clause: 2787 /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 2788 /// 2789 /// defaultmap: 2790 /// 'defaultmap' '(' modifier [ ':' kind ] ')' 2791 /// 2792 /// device-clause: 2793 /// 'device' '(' [ device-modifier ':' ] expression ')' 2794 /// 2795 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, 2796 OpenMPClauseKind Kind, 2797 bool ParseOnly) { 2798 SourceLocation Loc = ConsumeToken(); 2799 SourceLocation DelimLoc; 2800 // Parse '('. 2801 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2802 if (T.expectAndConsume(diag::err_expected_lparen_after, 2803 getOpenMPClauseName(Kind).data())) 2804 return nullptr; 2805 2806 ExprResult Val; 2807 SmallVector<unsigned, 4> Arg; 2808 SmallVector<SourceLocation, 4> KLoc; 2809 if (Kind == OMPC_schedule) { 2810 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 2811 Arg.resize(NumberOfElements); 2812 KLoc.resize(NumberOfElements); 2813 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 2814 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 2815 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 2816 unsigned KindModifier = getOpenMPSimpleClauseType( 2817 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2818 if (KindModifier > OMPC_SCHEDULE_unknown) { 2819 // Parse 'modifier' 2820 Arg[Modifier1] = KindModifier; 2821 KLoc[Modifier1] = Tok.getLocation(); 2822 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2823 Tok.isNot(tok::annot_pragma_openmp_end)) 2824 ConsumeAnyToken(); 2825 if (Tok.is(tok::comma)) { 2826 // Parse ',' 'modifier' 2827 ConsumeAnyToken(); 2828 KindModifier = getOpenMPSimpleClauseType( 2829 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2830 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 2831 ? KindModifier 2832 : (unsigned)OMPC_SCHEDULE_unknown; 2833 KLoc[Modifier2] = Tok.getLocation(); 2834 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2835 Tok.isNot(tok::annot_pragma_openmp_end)) 2836 ConsumeAnyToken(); 2837 } 2838 // Parse ':' 2839 if (Tok.is(tok::colon)) 2840 ConsumeAnyToken(); 2841 else 2842 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 2843 KindModifier = getOpenMPSimpleClauseType( 2844 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2845 } 2846 Arg[ScheduleKind] = KindModifier; 2847 KLoc[ScheduleKind] = Tok.getLocation(); 2848 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2849 Tok.isNot(tok::annot_pragma_openmp_end)) 2850 ConsumeAnyToken(); 2851 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 2852 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 2853 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 2854 Tok.is(tok::comma)) 2855 DelimLoc = ConsumeAnyToken(); 2856 } else if (Kind == OMPC_dist_schedule) { 2857 Arg.push_back(getOpenMPSimpleClauseType( 2858 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 2859 KLoc.push_back(Tok.getLocation()); 2860 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2861 Tok.isNot(tok::annot_pragma_openmp_end)) 2862 ConsumeAnyToken(); 2863 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 2864 DelimLoc = ConsumeAnyToken(); 2865 } else if (Kind == OMPC_defaultmap) { 2866 // Get a defaultmap modifier 2867 unsigned Modifier = getOpenMPSimpleClauseType( 2868 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); 2869 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or 2870 // pointer 2871 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) 2872 Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; 2873 Arg.push_back(Modifier); 2874 KLoc.push_back(Tok.getLocation()); 2875 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2876 Tok.isNot(tok::annot_pragma_openmp_end)) 2877 ConsumeAnyToken(); 2878 // Parse ':' 2879 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) { 2880 if (Tok.is(tok::colon)) 2881 ConsumeAnyToken(); 2882 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 2883 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 2884 // Get a defaultmap kind 2885 Arg.push_back(getOpenMPSimpleClauseType( 2886 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 2887 KLoc.push_back(Tok.getLocation()); 2888 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 2889 Tok.isNot(tok::annot_pragma_openmp_end)) 2890 ConsumeAnyToken(); 2891 } else { 2892 Arg.push_back(OMPC_DEFAULTMAP_unknown); 2893 KLoc.push_back(SourceLocation()); 2894 } 2895 } else if (Kind == OMPC_device) { 2896 // Only target executable directives support extended device construct. 2897 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 && 2898 NextToken().is(tok::colon)) { 2899 // Parse optional <device modifier> ':' 2900 Arg.push_back(getOpenMPSimpleClauseType( 2901 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok))); 2902 KLoc.push_back(Tok.getLocation()); 2903 ConsumeAnyToken(); 2904 // Parse ':' 2905 ConsumeAnyToken(); 2906 } else { 2907 Arg.push_back(OMPC_DEVICE_unknown); 2908 KLoc.emplace_back(); 2909 } 2910 } else { 2911 assert(Kind == OMPC_if); 2912 KLoc.push_back(Tok.getLocation()); 2913 TentativeParsingAction TPA(*this); 2914 auto DK = parseOpenMPDirectiveKind(*this); 2915 Arg.push_back(DK); 2916 if (DK != OMPD_unknown) { 2917 ConsumeToken(); 2918 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 2919 TPA.Commit(); 2920 DelimLoc = ConsumeToken(); 2921 } else { 2922 TPA.Revert(); 2923 Arg.back() = unsigned(OMPD_unknown); 2924 } 2925 } else { 2926 TPA.Revert(); 2927 } 2928 } 2929 2930 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 2931 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 2932 Kind == OMPC_if || Kind == OMPC_device; 2933 if (NeedAnExpression) { 2934 SourceLocation ELoc = Tok.getLocation(); 2935 ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); 2936 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 2937 Val = 2938 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 2939 } 2940 2941 // Parse ')'. 2942 SourceLocation RLoc = Tok.getLocation(); 2943 if (!T.consumeClose()) 2944 RLoc = T.getCloseLocation(); 2945 2946 if (NeedAnExpression && Val.isInvalid()) 2947 return nullptr; 2948 2949 if (ParseOnly) 2950 return nullptr; 2951 return Actions.ActOnOpenMPSingleExprWithArgClause( 2952 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 2953 } 2954 2955 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 2956 UnqualifiedId &ReductionId) { 2957 if (ReductionIdScopeSpec.isEmpty()) { 2958 auto OOK = OO_None; 2959 switch (P.getCurToken().getKind()) { 2960 case tok::plus: 2961 OOK = OO_Plus; 2962 break; 2963 case tok::minus: 2964 OOK = OO_Minus; 2965 break; 2966 case tok::star: 2967 OOK = OO_Star; 2968 break; 2969 case tok::amp: 2970 OOK = OO_Amp; 2971 break; 2972 case tok::pipe: 2973 OOK = OO_Pipe; 2974 break; 2975 case tok::caret: 2976 OOK = OO_Caret; 2977 break; 2978 case tok::ampamp: 2979 OOK = OO_AmpAmp; 2980 break; 2981 case tok::pipepipe: 2982 OOK = OO_PipePipe; 2983 break; 2984 default: 2985 break; 2986 } 2987 if (OOK != OO_None) { 2988 SourceLocation OpLoc = P.ConsumeToken(); 2989 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 2990 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 2991 return false; 2992 } 2993 } 2994 return P.ParseUnqualifiedId( 2995 ReductionIdScopeSpec, /*ObjectType=*/nullptr, 2996 /*ObjectHadErrors=*/false, /*EnteringContext*/ false, 2997 /*AllowDestructorName*/ false, 2998 /*AllowConstructorName*/ false, 2999 /*AllowDeductionGuide*/ false, nullptr, ReductionId); 3000 } 3001 3002 /// Checks if the token is a valid map-type-modifier. 3003 static OpenMPMapModifierKind isMapModifier(Parser &P) { 3004 Token Tok = P.getCurToken(); 3005 if (!Tok.is(tok::identifier)) 3006 return OMPC_MAP_MODIFIER_unknown; 3007 3008 Preprocessor &PP = P.getPreprocessor(); 3009 OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>( 3010 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); 3011 return TypeModifier; 3012 } 3013 3014 /// Parse the mapper modifier in map, to, and from clauses. 3015 bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { 3016 // Parse '('. 3017 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); 3018 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { 3019 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3020 StopBeforeMatch); 3021 return true; 3022 } 3023 // Parse mapper-identifier 3024 if (getLangOpts().CPlusPlus) 3025 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 3026 /*ObjectType=*/nullptr, 3027 /*ObjectHadErrors=*/false, 3028 /*EnteringContext=*/false); 3029 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 3030 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 3031 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3032 StopBeforeMatch); 3033 return true; 3034 } 3035 auto &DeclNames = Actions.getASTContext().DeclarationNames; 3036 Data.ReductionOrMapperId = DeclarationNameInfo( 3037 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation()); 3038 ConsumeToken(); 3039 // Parse ')'. 3040 return T.consumeClose(); 3041 } 3042 3043 /// Parse map-type-modifiers in map clause. 3044 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 3045 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) 3046 bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) { 3047 while (getCurToken().isNot(tok::colon)) { 3048 OpenMPMapModifierKind TypeModifier = isMapModifier(*this); 3049 if (TypeModifier == OMPC_MAP_MODIFIER_always || 3050 TypeModifier == OMPC_MAP_MODIFIER_close) { 3051 Data.MapTypeModifiers.push_back(TypeModifier); 3052 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 3053 ConsumeToken(); 3054 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { 3055 Data.MapTypeModifiers.push_back(TypeModifier); 3056 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 3057 ConsumeToken(); 3058 if (parseMapperModifier(Data)) 3059 return true; 3060 } else { 3061 // For the case of unknown map-type-modifier or a map-type. 3062 // Map-type is followed by a colon; the function returns when it 3063 // encounters a token followed by a colon. 3064 if (Tok.is(tok::comma)) { 3065 Diag(Tok, diag::err_omp_map_type_modifier_missing); 3066 ConsumeToken(); 3067 continue; 3068 } 3069 // Potential map-type token as it is followed by a colon. 3070 if (PP.LookAhead(0).is(tok::colon)) 3071 return false; 3072 Diag(Tok, diag::err_omp_unknown_map_type_modifier); 3073 ConsumeToken(); 3074 } 3075 if (getCurToken().is(tok::comma)) 3076 ConsumeToken(); 3077 } 3078 return false; 3079 } 3080 3081 /// Checks if the token is a valid map-type. 3082 static OpenMPMapClauseKind isMapType(Parser &P) { 3083 Token Tok = P.getCurToken(); 3084 // The map-type token can be either an identifier or the C++ delete keyword. 3085 if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) 3086 return OMPC_MAP_unknown; 3087 Preprocessor &PP = P.getPreprocessor(); 3088 OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>( 3089 getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok))); 3090 return MapType; 3091 } 3092 3093 /// Parse map-type in map clause. 3094 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 3095 /// where, map-type ::= to | from | tofrom | alloc | release | delete 3096 static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { 3097 Token Tok = P.getCurToken(); 3098 if (Tok.is(tok::colon)) { 3099 P.Diag(Tok, diag::err_omp_map_type_missing); 3100 return; 3101 } 3102 Data.ExtraModifier = isMapType(P); 3103 if (Data.ExtraModifier == OMPC_MAP_unknown) 3104 P.Diag(Tok, diag::err_omp_unknown_map_type); 3105 P.ConsumeToken(); 3106 } 3107 3108 /// Parses simple expression in parens for single-expression clauses of OpenMP 3109 /// constructs. 3110 /// \param RLoc Returned location of right paren. 3111 ExprResult Parser::ParseOpenMPIteratorsExpr() { 3112 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" && 3113 "Expected 'iterator' token."); 3114 SourceLocation IteratorKwLoc = ConsumeToken(); 3115 3116 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3117 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator")) 3118 return ExprError(); 3119 3120 SourceLocation LLoc = T.getOpenLocation(); 3121 SmallVector<Sema::OMPIteratorData, 4> Data; 3122 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 3123 // Check if the type parsing is required. 3124 ParsedType IteratorType; 3125 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) { 3126 // identifier '=' is not found - parse type. 3127 TypeResult TR = ParseTypeName(); 3128 if (TR.isInvalid()) { 3129 T.skipToEnd(); 3130 return ExprError(); 3131 } 3132 IteratorType = TR.get(); 3133 } 3134 3135 // Parse identifier. 3136 IdentifierInfo *II = nullptr; 3137 SourceLocation IdLoc; 3138 if (Tok.is(tok::identifier)) { 3139 II = Tok.getIdentifierInfo(); 3140 IdLoc = ConsumeToken(); 3141 } else { 3142 Diag(Tok, diag::err_expected_unqualified_id) << 0; 3143 } 3144 3145 // Parse '='. 3146 SourceLocation AssignLoc; 3147 if (Tok.is(tok::equal)) 3148 AssignLoc = ConsumeToken(); 3149 else 3150 Diag(Tok, diag::err_omp_expected_equal_in_iterator); 3151 3152 // Parse range-specification - <begin> ':' <end> [ ':' <step> ] 3153 ColonProtectionRAIIObject ColonRAII(*this); 3154 // Parse <begin> 3155 SourceLocation Loc = Tok.getLocation(); 3156 ExprResult LHS = ParseCastExpression(AnyCastExpr); 3157 ExprResult Begin = Actions.CorrectDelayedTyposInExpr( 3158 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3159 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc, 3160 /*DiscardedValue=*/false); 3161 // Parse ':'. 3162 SourceLocation ColonLoc; 3163 if (Tok.is(tok::colon)) 3164 ColonLoc = ConsumeToken(); 3165 3166 // Parse <end> 3167 Loc = Tok.getLocation(); 3168 LHS = ParseCastExpression(AnyCastExpr); 3169 ExprResult End = Actions.CorrectDelayedTyposInExpr( 3170 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3171 End = Actions.ActOnFinishFullExpr(End.get(), Loc, 3172 /*DiscardedValue=*/false); 3173 3174 SourceLocation SecColonLoc; 3175 ExprResult Step; 3176 // Parse optional step. 3177 if (Tok.is(tok::colon)) { 3178 // Parse ':' 3179 SecColonLoc = ConsumeToken(); 3180 // Parse <step> 3181 Loc = Tok.getLocation(); 3182 LHS = ParseCastExpression(AnyCastExpr); 3183 Step = Actions.CorrectDelayedTyposInExpr( 3184 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3185 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc, 3186 /*DiscardedValue=*/false); 3187 } 3188 3189 // Parse ',' or ')' 3190 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 3191 Diag(Tok, diag::err_omp_expected_punc_after_iterator); 3192 if (Tok.is(tok::comma)) 3193 ConsumeToken(); 3194 3195 Sema::OMPIteratorData &D = Data.emplace_back(); 3196 D.DeclIdent = II; 3197 D.DeclIdentLoc = IdLoc; 3198 D.Type = IteratorType; 3199 D.AssignLoc = AssignLoc; 3200 D.ColonLoc = ColonLoc; 3201 D.SecColonLoc = SecColonLoc; 3202 D.Range.Begin = Begin.get(); 3203 D.Range.End = End.get(); 3204 D.Range.Step = Step.get(); 3205 } 3206 3207 // Parse ')'. 3208 SourceLocation RLoc = Tok.getLocation(); 3209 if (!T.consumeClose()) 3210 RLoc = T.getCloseLocation(); 3211 3212 return Actions.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc, LLoc, RLoc, 3213 Data); 3214 } 3215 3216 /// Parses clauses with list. 3217 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 3218 OpenMPClauseKind Kind, 3219 SmallVectorImpl<Expr *> &Vars, 3220 OpenMPVarListDataTy &Data) { 3221 UnqualifiedId UnqualifiedReductionId; 3222 bool InvalidReductionId = false; 3223 bool IsInvalidMapperModifier = false; 3224 3225 // Parse '('. 3226 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3227 if (T.expectAndConsume(diag::err_expected_lparen_after, 3228 getOpenMPClauseName(Kind).data())) 3229 return true; 3230 3231 bool DependWithIterator = false; 3232 bool NeedRParenForLinear = false; 3233 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 3234 tok::annot_pragma_openmp_end); 3235 // Handle reduction-identifier for reduction clause. 3236 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 3237 Kind == OMPC_in_reduction) { 3238 Data.ExtraModifier = OMPC_REDUCTION_unknown; 3239 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 && 3240 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) && 3241 NextToken().is(tok::comma)) { 3242 // Parse optional reduction modifier. 3243 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); 3244 Data.ExtraModifierLoc = Tok.getLocation(); 3245 ConsumeToken(); 3246 assert(Tok.is(tok::comma) && "Expected comma."); 3247 (void)ConsumeToken(); 3248 } 3249 ColonProtectionRAIIObject ColonRAII(*this); 3250 if (getLangOpts().CPlusPlus) 3251 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 3252 /*ObjectType=*/nullptr, 3253 /*ObjectHadErrors=*/false, 3254 /*EnteringContext=*/false); 3255 InvalidReductionId = ParseReductionId( 3256 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); 3257 if (InvalidReductionId) { 3258 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3259 StopBeforeMatch); 3260 } 3261 if (Tok.is(tok::colon)) 3262 Data.ColonLoc = ConsumeToken(); 3263 else 3264 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 3265 if (!InvalidReductionId) 3266 Data.ReductionOrMapperId = 3267 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 3268 } else if (Kind == OMPC_depend) { 3269 if (getLangOpts().OpenMP >= 50) { 3270 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") { 3271 // Handle optional dependence modifier. 3272 // iterator(iterators-definition) 3273 // where iterators-definition is iterator-specifier [, 3274 // iterators-definition ] 3275 // where iterator-specifier is [ iterator-type ] identifier = 3276 // range-specification 3277 DependWithIterator = true; 3278 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 3279 ExprResult IteratorRes = ParseOpenMPIteratorsExpr(); 3280 Data.DepModOrTailExpr = IteratorRes.get(); 3281 // Parse ',' 3282 ExpectAndConsume(tok::comma); 3283 } 3284 } 3285 // Handle dependency type for depend clause. 3286 ColonProtectionRAIIObject ColonRAII(*this); 3287 Data.ExtraModifier = getOpenMPSimpleClauseType( 3288 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""); 3289 Data.ExtraModifierLoc = Tok.getLocation(); 3290 if (Data.ExtraModifier == OMPC_DEPEND_unknown) { 3291 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3292 StopBeforeMatch); 3293 } else { 3294 ConsumeToken(); 3295 // Special processing for depend(source) clause. 3296 if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) { 3297 // Parse ')'. 3298 T.consumeClose(); 3299 return false; 3300 } 3301 } 3302 if (Tok.is(tok::colon)) { 3303 Data.ColonLoc = ConsumeToken(); 3304 } else { 3305 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 3306 : diag::warn_pragma_expected_colon) 3307 << "dependency type"; 3308 } 3309 } else if (Kind == OMPC_linear) { 3310 // Try to parse modifier if any. 3311 Data.ExtraModifier = OMPC_LINEAR_val; 3312 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 3313 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); 3314 Data.ExtraModifierLoc = ConsumeToken(); 3315 LinearT.consumeOpen(); 3316 NeedRParenForLinear = true; 3317 } 3318 } else if (Kind == OMPC_lastprivate) { 3319 // Try to parse modifier if any. 3320 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown; 3321 // Conditional modifier allowed only in OpenMP 5.0 and not supported in 3322 // distribute and taskloop based directives. 3323 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) && 3324 !isOpenMPTaskLoopDirective(DKind)) && 3325 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) { 3326 Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)); 3327 Data.ExtraModifierLoc = Tok.getLocation(); 3328 ConsumeToken(); 3329 assert(Tok.is(tok::colon) && "Expected colon."); 3330 Data.ColonLoc = ConsumeToken(); 3331 } 3332 } else if (Kind == OMPC_map) { 3333 // Handle map type for map clause. 3334 ColonProtectionRAIIObject ColonRAII(*this); 3335 3336 // The first identifier may be a list item, a map-type or a 3337 // map-type-modifier. The map-type can also be delete which has the same 3338 // spelling of the C++ delete keyword. 3339 Data.ExtraModifier = OMPC_MAP_unknown; 3340 Data.ExtraModifierLoc = Tok.getLocation(); 3341 3342 // Check for presence of a colon in the map clause. 3343 TentativeParsingAction TPA(*this); 3344 bool ColonPresent = false; 3345 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3346 StopBeforeMatch)) { 3347 if (Tok.is(tok::colon)) 3348 ColonPresent = true; 3349 } 3350 TPA.Revert(); 3351 // Only parse map-type-modifier[s] and map-type if a colon is present in 3352 // the map clause. 3353 if (ColonPresent) { 3354 IsInvalidMapperModifier = parseMapTypeModifiers(Data); 3355 if (!IsInvalidMapperModifier) 3356 parseMapType(*this, Data); 3357 else 3358 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); 3359 } 3360 if (Data.ExtraModifier == OMPC_MAP_unknown) { 3361 Data.ExtraModifier = OMPC_MAP_tofrom; 3362 Data.IsMapTypeImplicit = true; 3363 } 3364 3365 if (Tok.is(tok::colon)) 3366 Data.ColonLoc = ConsumeToken(); 3367 } else if (Kind == OMPC_to || Kind == OMPC_from) { 3368 if (Tok.is(tok::identifier)) { 3369 bool IsMapperModifier = false; 3370 if (Kind == OMPC_to) { 3371 auto Modifier = static_cast<OpenMPToModifierKind>( 3372 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 3373 if (Modifier == OMPC_TO_MODIFIER_mapper) 3374 IsMapperModifier = true; 3375 } else { 3376 auto Modifier = static_cast<OpenMPFromModifierKind>( 3377 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); 3378 if (Modifier == OMPC_FROM_MODIFIER_mapper) 3379 IsMapperModifier = true; 3380 } 3381 if (IsMapperModifier) { 3382 // Parse the mapper modifier. 3383 ConsumeToken(); 3384 IsInvalidMapperModifier = parseMapperModifier(Data); 3385 if (Tok.isNot(tok::colon)) { 3386 if (!IsInvalidMapperModifier) 3387 Diag(Tok, diag::warn_pragma_expected_colon) << ")"; 3388 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3389 StopBeforeMatch); 3390 } 3391 // Consume ':'. 3392 if (Tok.is(tok::colon)) 3393 ConsumeToken(); 3394 } 3395 } 3396 } else if (Kind == OMPC_allocate) { 3397 // Handle optional allocator expression followed by colon delimiter. 3398 ColonProtectionRAIIObject ColonRAII(*this); 3399 TentativeParsingAction TPA(*this); 3400 ExprResult Tail = 3401 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 3402 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), 3403 /*DiscardedValue=*/false); 3404 if (Tail.isUsable()) { 3405 if (Tok.is(tok::colon)) { 3406 Data.DepModOrTailExpr = Tail.get(); 3407 Data.ColonLoc = ConsumeToken(); 3408 TPA.Commit(); 3409 } else { 3410 // colon not found, no allocator specified, parse only list of 3411 // variables. 3412 TPA.Revert(); 3413 } 3414 } else { 3415 // Parsing was unsuccessfull, revert and skip to the end of clause or 3416 // directive. 3417 TPA.Revert(); 3418 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3419 StopBeforeMatch); 3420 } 3421 } 3422 3423 bool IsComma = 3424 (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 3425 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 3426 (Kind == OMPC_reduction && !InvalidReductionId) || 3427 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) || 3428 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown); 3429 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 3430 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 3431 Tok.isNot(tok::annot_pragma_openmp_end))) { 3432 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope); 3433 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 3434 // Parse variable 3435 ExprResult VarExpr = 3436 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 3437 if (VarExpr.isUsable()) { 3438 Vars.push_back(VarExpr.get()); 3439 } else { 3440 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3441 StopBeforeMatch); 3442 } 3443 // Skip ',' if any 3444 IsComma = Tok.is(tok::comma); 3445 if (IsComma) 3446 ConsumeToken(); 3447 else if (Tok.isNot(tok::r_paren) && 3448 Tok.isNot(tok::annot_pragma_openmp_end) && 3449 (!MayHaveTail || Tok.isNot(tok::colon))) 3450 Diag(Tok, diag::err_omp_expected_punc) 3451 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 3452 : getOpenMPClauseName(Kind)) 3453 << (Kind == OMPC_flush); 3454 } 3455 3456 // Parse ')' for linear clause with modifier. 3457 if (NeedRParenForLinear) 3458 LinearT.consumeClose(); 3459 3460 // Parse ':' linear-step (or ':' alignment). 3461 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 3462 if (MustHaveTail) { 3463 Data.ColonLoc = Tok.getLocation(); 3464 SourceLocation ELoc = ConsumeToken(); 3465 ExprResult Tail = ParseAssignmentExpression(); 3466 Tail = 3467 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); 3468 if (Tail.isUsable()) 3469 Data.DepModOrTailExpr = Tail.get(); 3470 else 3471 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3472 StopBeforeMatch); 3473 } 3474 3475 // Parse ')'. 3476 Data.RLoc = Tok.getLocation(); 3477 if (!T.consumeClose()) 3478 Data.RLoc = T.getCloseLocation(); 3479 // Exit from scope when the iterator is used in depend clause. 3480 if (DependWithIterator) 3481 ExitScope(); 3482 return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 3483 (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId || 3484 IsInvalidMapperModifier; 3485 } 3486 3487 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 3488 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction', 3489 /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'. 3490 /// 3491 /// private-clause: 3492 /// 'private' '(' list ')' 3493 /// firstprivate-clause: 3494 /// 'firstprivate' '(' list ')' 3495 /// lastprivate-clause: 3496 /// 'lastprivate' '(' list ')' 3497 /// shared-clause: 3498 /// 'shared' '(' list ')' 3499 /// linear-clause: 3500 /// 'linear' '(' linear-list [ ':' linear-step ] ')' 3501 /// aligned-clause: 3502 /// 'aligned' '(' list [ ':' alignment ] ')' 3503 /// reduction-clause: 3504 /// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')' 3505 /// task_reduction-clause: 3506 /// 'task_reduction' '(' reduction-identifier ':' list ')' 3507 /// in_reduction-clause: 3508 /// 'in_reduction' '(' reduction-identifier ':' list ')' 3509 /// copyprivate-clause: 3510 /// 'copyprivate' '(' list ')' 3511 /// flush-clause: 3512 /// 'flush' '(' list ')' 3513 /// depend-clause: 3514 /// 'depend' '(' in | out | inout : list | source ')' 3515 /// map-clause: 3516 /// 'map' '(' [ [ always [,] ] [ close [,] ] 3517 /// [ mapper '(' mapper-identifier ')' [,] ] 3518 /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 3519 /// to-clause: 3520 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 3521 /// from-clause: 3522 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 3523 /// use_device_ptr-clause: 3524 /// 'use_device_ptr' '(' list ')' 3525 /// is_device_ptr-clause: 3526 /// 'is_device_ptr' '(' list ')' 3527 /// allocate-clause: 3528 /// 'allocate' '(' [ allocator ':' ] list ')' 3529 /// nontemporal-clause: 3530 /// 'nontemporal' '(' list ')' 3531 /// inclusive-clause: 3532 /// 'inclusive' '(' list ')' 3533 /// exclusive-clause: 3534 /// 'exclusive' '(' list ')' 3535 /// 3536 /// For 'linear' clause linear-list may have the following forms: 3537 /// list 3538 /// modifier(list) 3539 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 3540 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 3541 OpenMPClauseKind Kind, 3542 bool ParseOnly) { 3543 SourceLocation Loc = Tok.getLocation(); 3544 SourceLocation LOpen = ConsumeToken(); 3545 SmallVector<Expr *, 4> Vars; 3546 OpenMPVarListDataTy Data; 3547 3548 if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 3549 return nullptr; 3550 3551 if (ParseOnly) 3552 return nullptr; 3553 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); 3554 return Actions.ActOnOpenMPVarListClause( 3555 Kind, Vars, Data.DepModOrTailExpr, Locs, Data.ColonLoc, 3556 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, 3557 Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, 3558 Data.IsMapTypeImplicit, Data.ExtraModifierLoc); 3559 } 3560 3561