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/StringSwitch.h" 25 #include "llvm/ADT/UniqueVector.h" 26 #include "llvm/Frontend/OpenMP/OMPAssume.h" 27 #include "llvm/Frontend/OpenMP/OMPContext.h" 28 29 using namespace clang; 30 using namespace llvm::omp; 31 32 //===----------------------------------------------------------------------===// 33 // OpenMP declarative directives. 34 //===----------------------------------------------------------------------===// 35 36 namespace { 37 enum OpenMPDirectiveKindEx { 38 OMPD_cancellation = llvm::omp::Directive_enumSize + 1, 39 OMPD_data, 40 OMPD_declare, 41 OMPD_end, 42 OMPD_end_declare, 43 OMPD_enter, 44 OMPD_exit, 45 OMPD_point, 46 OMPD_reduction, 47 OMPD_target_enter, 48 OMPD_target_exit, 49 OMPD_update, 50 OMPD_distribute_parallel, 51 OMPD_teams_distribute_parallel, 52 OMPD_target_teams_distribute_parallel, 53 OMPD_mapper, 54 OMPD_variant, 55 OMPD_begin, 56 OMPD_begin_declare, 57 }; 58 59 // Helper to unify the enum class OpenMPDirectiveKind with its extension 60 // the OpenMPDirectiveKindEx enum which allows to use them together as if they 61 // are unsigned values. 62 struct OpenMPDirectiveKindExWrapper { 63 OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {} 64 OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {} 65 bool operator==(OpenMPDirectiveKindExWrapper V) const { 66 return Value == V.Value; 67 } 68 bool operator!=(OpenMPDirectiveKindExWrapper V) const { 69 return Value != V.Value; 70 } 71 bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); } 72 bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); } 73 bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); } 74 operator unsigned() const { return Value; } 75 operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); } 76 unsigned Value; 77 }; 78 79 class DeclDirectiveListParserHelper final { 80 SmallVector<Expr *, 4> Identifiers; 81 Parser *P; 82 OpenMPDirectiveKind Kind; 83 84 public: 85 DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind) 86 : P(P), Kind(Kind) {} 87 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { 88 ExprResult Res = P->getActions().ActOnOpenMPIdExpression( 89 P->getCurScope(), SS, NameInfo, Kind); 90 if (Res.isUsable()) 91 Identifiers.push_back(Res.get()); 92 } 93 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; } 94 }; 95 } // namespace 96 97 // Map token string to extended OMP token kind that are 98 // OpenMPDirectiveKind + OpenMPDirectiveKindEx. 99 static unsigned getOpenMPDirectiveKindEx(StringRef S) { 100 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S); 101 if (DKind != OMPD_unknown) 102 return DKind; 103 104 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S) 105 .Case("cancellation", OMPD_cancellation) 106 .Case("data", OMPD_data) 107 .Case("declare", OMPD_declare) 108 .Case("end", OMPD_end) 109 .Case("enter", OMPD_enter) 110 .Case("exit", OMPD_exit) 111 .Case("point", OMPD_point) 112 .Case("reduction", OMPD_reduction) 113 .Case("update", OMPD_update) 114 .Case("mapper", OMPD_mapper) 115 .Case("variant", OMPD_variant) 116 .Case("begin", OMPD_begin) 117 .Default(OMPD_unknown); 118 } 119 120 static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) { 121 // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. 122 // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd 123 // TODO: add other combined directives in topological order. 124 static const OpenMPDirectiveKindExWrapper F[][3] = { 125 {OMPD_begin, OMPD_declare, OMPD_begin_declare}, 126 {OMPD_begin, OMPD_assumes, OMPD_begin_assumes}, 127 {OMPD_end, OMPD_declare, OMPD_end_declare}, 128 {OMPD_end, OMPD_assumes, OMPD_end_assumes}, 129 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point}, 130 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction}, 131 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper}, 132 {OMPD_declare, OMPD_simd, OMPD_declare_simd}, 133 {OMPD_declare, OMPD_target, OMPD_declare_target}, 134 {OMPD_declare, OMPD_variant, OMPD_declare_variant}, 135 {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target}, 136 {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant}, 137 {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant}, 138 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel}, 139 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for}, 140 {OMPD_distribute_parallel_for, OMPD_simd, 141 OMPD_distribute_parallel_for_simd}, 142 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd}, 143 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target}, 144 {OMPD_target, OMPD_data, OMPD_target_data}, 145 {OMPD_target, OMPD_enter, OMPD_target_enter}, 146 {OMPD_target, OMPD_exit, OMPD_target_exit}, 147 {OMPD_target, OMPD_update, OMPD_target_update}, 148 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data}, 149 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data}, 150 {OMPD_for, OMPD_simd, OMPD_for_simd}, 151 {OMPD_parallel, OMPD_for, OMPD_parallel_for}, 152 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, 153 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, 154 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}, 155 {OMPD_target, OMPD_parallel, OMPD_target_parallel}, 156 {OMPD_target, OMPD_simd, OMPD_target_simd}, 157 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for}, 158 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd}, 159 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute}, 160 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd}, 161 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel}, 162 {OMPD_teams_distribute_parallel, OMPD_for, 163 OMPD_teams_distribute_parallel_for}, 164 {OMPD_teams_distribute_parallel_for, OMPD_simd, 165 OMPD_teams_distribute_parallel_for_simd}, 166 {OMPD_target, OMPD_teams, OMPD_target_teams}, 167 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute}, 168 {OMPD_target_teams_distribute, OMPD_parallel, 169 OMPD_target_teams_distribute_parallel}, 170 {OMPD_target_teams_distribute, OMPD_simd, 171 OMPD_target_teams_distribute_simd}, 172 {OMPD_target_teams_distribute_parallel, OMPD_for, 173 OMPD_target_teams_distribute_parallel_for}, 174 {OMPD_target_teams_distribute_parallel_for, OMPD_simd, 175 OMPD_target_teams_distribute_parallel_for_simd}, 176 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop}, 177 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd}, 178 {OMPD_parallel, OMPD_master, OMPD_parallel_master}, 179 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}, 180 {OMPD_parallel_master_taskloop, OMPD_simd, 181 OMPD_parallel_master_taskloop_simd}}; 182 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; 183 Token Tok = P.getCurToken(); 184 OpenMPDirectiveKindExWrapper DKind = 185 Tok.isAnnotation() 186 ? static_cast<unsigned>(OMPD_unknown) 187 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 188 if (DKind == OMPD_unknown) 189 return OMPD_unknown; 190 191 for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) { 192 if (DKind != F[I][0]) 193 continue; 194 195 Tok = P.getPreprocessor().LookAhead(0); 196 OpenMPDirectiveKindExWrapper SDKind = 197 Tok.isAnnotation() 198 ? static_cast<unsigned>(OMPD_unknown) 199 : getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok)); 200 if (SDKind == OMPD_unknown) 201 continue; 202 203 if (SDKind == F[I][1]) { 204 P.ConsumeToken(); 205 DKind = F[I][2]; 206 } 207 } 208 return unsigned(DKind) < llvm::omp::Directive_enumSize 209 ? static_cast<OpenMPDirectiveKind>(DKind) 210 : OMPD_unknown; 211 } 212 213 static DeclarationName parseOpenMPReductionId(Parser &P) { 214 Token Tok = P.getCurToken(); 215 Sema &Actions = P.getActions(); 216 OverloadedOperatorKind OOK = OO_None; 217 // Allow to use 'operator' keyword for C++ operators 218 bool WithOperator = false; 219 if (Tok.is(tok::kw_operator)) { 220 P.ConsumeToken(); 221 Tok = P.getCurToken(); 222 WithOperator = true; 223 } 224 switch (Tok.getKind()) { 225 case tok::plus: // '+' 226 OOK = OO_Plus; 227 break; 228 case tok::minus: // '-' 229 OOK = OO_Minus; 230 break; 231 case tok::star: // '*' 232 OOK = OO_Star; 233 break; 234 case tok::amp: // '&' 235 OOK = OO_Amp; 236 break; 237 case tok::pipe: // '|' 238 OOK = OO_Pipe; 239 break; 240 case tok::caret: // '^' 241 OOK = OO_Caret; 242 break; 243 case tok::ampamp: // '&&' 244 OOK = OO_AmpAmp; 245 break; 246 case tok::pipepipe: // '||' 247 OOK = OO_PipePipe; 248 break; 249 case tok::identifier: // identifier 250 if (!WithOperator) 251 break; 252 LLVM_FALLTHROUGH; 253 default: 254 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier); 255 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 256 Parser::StopBeforeMatch); 257 return DeclarationName(); 258 } 259 P.ConsumeToken(); 260 auto &DeclNames = Actions.getASTContext().DeclarationNames; 261 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo()) 262 : DeclNames.getCXXOperatorName(OOK); 263 } 264 265 /// Parse 'omp declare reduction' construct. 266 /// 267 /// declare-reduction-directive: 268 /// annot_pragma_openmp 'declare' 'reduction' 269 /// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')' 270 /// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')'] 271 /// annot_pragma_openmp_end 272 /// <reduction_id> is either a base language identifier or one of the following 273 /// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'. 274 /// 275 Parser::DeclGroupPtrTy 276 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { 277 // Parse '('. 278 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 279 if (T.expectAndConsume( 280 diag::err_expected_lparen_after, 281 getOpenMPDirectiveName(OMPD_declare_reduction).data())) { 282 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 283 return DeclGroupPtrTy(); 284 } 285 286 DeclarationName Name = parseOpenMPReductionId(*this); 287 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end)) 288 return DeclGroupPtrTy(); 289 290 // Consume ':'. 291 bool IsCorrect = !ExpectAndConsume(tok::colon); 292 293 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 294 return DeclGroupPtrTy(); 295 296 IsCorrect = IsCorrect && !Name.isEmpty(); 297 298 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) { 299 Diag(Tok.getLocation(), diag::err_expected_type); 300 IsCorrect = false; 301 } 302 303 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 304 return DeclGroupPtrTy(); 305 306 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes; 307 // Parse list of types until ':' token. 308 do { 309 ColonProtectionRAIIObject ColonRAII(*this); 310 SourceRange Range; 311 TypeResult TR = ParseTypeName(&Range, DeclaratorContext::Prototype, AS); 312 if (TR.isUsable()) { 313 QualType ReductionType = 314 Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR); 315 if (!ReductionType.isNull()) { 316 ReductionTypes.push_back( 317 std::make_pair(ReductionType, Range.getBegin())); 318 } 319 } else { 320 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end, 321 StopBeforeMatch); 322 } 323 324 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) 325 break; 326 327 // Consume ','. 328 if (ExpectAndConsume(tok::comma)) { 329 IsCorrect = false; 330 if (Tok.is(tok::annot_pragma_openmp_end)) { 331 Diag(Tok.getLocation(), diag::err_expected_type); 332 return DeclGroupPtrTy(); 333 } 334 } 335 } while (Tok.isNot(tok::annot_pragma_openmp_end)); 336 337 if (ReductionTypes.empty()) { 338 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 339 return DeclGroupPtrTy(); 340 } 341 342 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 343 return DeclGroupPtrTy(); 344 345 // Consume ':'. 346 if (ExpectAndConsume(tok::colon)) 347 IsCorrect = false; 348 349 if (Tok.is(tok::annot_pragma_openmp_end)) { 350 Diag(Tok.getLocation(), diag::err_expected_expression); 351 return DeclGroupPtrTy(); 352 } 353 354 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart( 355 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS); 356 357 // Parse <combiner> expression and then parse initializer if any for each 358 // correct type. 359 unsigned I = 0, E = ReductionTypes.size(); 360 for (Decl *D : DRD.get()) { 361 TentativeParsingAction TPA(*this); 362 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 363 Scope::CompoundStmtScope | 364 Scope::OpenMPDirectiveScope); 365 // Parse <combiner> expression. 366 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D); 367 ExprResult CombinerResult = Actions.ActOnFinishFullExpr( 368 ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false); 369 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get()); 370 371 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) && 372 Tok.isNot(tok::annot_pragma_openmp_end)) { 373 TPA.Commit(); 374 IsCorrect = false; 375 break; 376 } 377 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable(); 378 ExprResult InitializerResult; 379 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 380 // Parse <initializer> expression. 381 if (Tok.is(tok::identifier) && 382 Tok.getIdentifierInfo()->isStr("initializer")) { 383 ConsumeToken(); 384 } else { 385 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'"; 386 TPA.Commit(); 387 IsCorrect = false; 388 break; 389 } 390 // Parse '('. 391 BalancedDelimiterTracker T(*this, tok::l_paren, 392 tok::annot_pragma_openmp_end); 393 IsCorrect = 394 !T.expectAndConsume(diag::err_expected_lparen_after, "initializer") && 395 IsCorrect; 396 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 397 ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | 398 Scope::CompoundStmtScope | 399 Scope::OpenMPDirectiveScope); 400 // Parse expression. 401 VarDecl *OmpPrivParm = 402 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(), 403 D); 404 // Check if initializer is omp_priv <init_expr> or something else. 405 if (Tok.is(tok::identifier) && 406 Tok.getIdentifierInfo()->isStr("omp_priv")) { 407 ConsumeToken(); 408 ParseOpenMPReductionInitializerForDecl(OmpPrivParm); 409 } else { 410 InitializerResult = Actions.ActOnFinishFullExpr( 411 ParseAssignmentExpression().get(), D->getLocation(), 412 /*DiscardedValue*/ false); 413 } 414 Actions.ActOnOpenMPDeclareReductionInitializerEnd( 415 D, InitializerResult.get(), OmpPrivParm); 416 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) && 417 Tok.isNot(tok::annot_pragma_openmp_end)) { 418 TPA.Commit(); 419 IsCorrect = false; 420 break; 421 } 422 IsCorrect = 423 !T.consumeClose() && IsCorrect && !InitializerResult.isInvalid(); 424 } 425 } 426 427 ++I; 428 // Revert parsing if not the last type, otherwise accept it, we're done with 429 // parsing. 430 if (I != E) 431 TPA.Revert(); 432 else 433 TPA.Commit(); 434 } 435 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD, 436 IsCorrect); 437 } 438 439 void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { 440 // Parse declarator '=' initializer. 441 // If a '==' or '+=' is found, suggest a fixit to '='. 442 if (isTokenEqualOrEqualTypo()) { 443 ConsumeToken(); 444 445 if (Tok.is(tok::code_completion)) { 446 cutOffParsing(); 447 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm); 448 Actions.FinalizeDeclaration(OmpPrivParm); 449 return; 450 } 451 452 PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm); 453 ExprResult Init = ParseInitializer(); 454 455 if (Init.isInvalid()) { 456 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 457 Actions.ActOnInitializerError(OmpPrivParm); 458 } else { 459 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 460 /*DirectInit=*/false); 461 } 462 } else if (Tok.is(tok::l_paren)) { 463 // Parse C++ direct initializer: '(' expression-list ')' 464 BalancedDelimiterTracker T(*this, tok::l_paren); 465 T.consumeOpen(); 466 467 ExprVector Exprs; 468 CommaLocsTy CommaLocs; 469 470 SourceLocation LParLoc = T.getOpenLocation(); 471 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() { 472 QualType PreferredType = Actions.ProduceConstructorSignatureHelp( 473 OmpPrivParm->getType()->getCanonicalTypeInternal(), 474 OmpPrivParm->getLocation(), Exprs, LParLoc, /*Braced=*/false); 475 CalledSignatureHelp = true; 476 return PreferredType; 477 }; 478 if (ParseExpressionList(Exprs, CommaLocs, [&] { 479 PreferredType.enterFunctionArgument(Tok.getLocation(), 480 RunSignatureHelp); 481 })) { 482 if (PP.isCodeCompletionReached() && !CalledSignatureHelp) 483 RunSignatureHelp(); 484 Actions.ActOnInitializerError(OmpPrivParm); 485 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); 486 } else { 487 // Match the ')'. 488 SourceLocation RLoc = Tok.getLocation(); 489 if (!T.consumeClose()) 490 RLoc = T.getCloseLocation(); 491 492 assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() && 493 "Unexpected number of commas!"); 494 495 ExprResult Initializer = 496 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs); 497 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(), 498 /*DirectInit=*/true); 499 } 500 } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { 501 // Parse C++0x braced-init-list. 502 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); 503 504 ExprResult Init(ParseBraceInitializer()); 505 506 if (Init.isInvalid()) { 507 Actions.ActOnInitializerError(OmpPrivParm); 508 } else { 509 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(), 510 /*DirectInit=*/true); 511 } 512 } else { 513 Actions.ActOnUninitializedDecl(OmpPrivParm); 514 } 515 } 516 517 /// Parses 'omp declare mapper' directive. 518 /// 519 /// declare-mapper-directive: 520 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':'] 521 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 522 /// annot_pragma_openmp_end 523 /// <mapper-identifier> and <var> are base language identifiers. 524 /// 525 Parser::DeclGroupPtrTy 526 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) { 527 bool IsCorrect = true; 528 // Parse '(' 529 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 530 if (T.expectAndConsume(diag::err_expected_lparen_after, 531 getOpenMPDirectiveName(OMPD_declare_mapper).data())) { 532 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 533 return DeclGroupPtrTy(); 534 } 535 536 // Parse <mapper-identifier> 537 auto &DeclNames = Actions.getASTContext().DeclarationNames; 538 DeclarationName MapperId; 539 if (PP.LookAhead(0).is(tok::colon)) { 540 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 541 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 542 IsCorrect = false; 543 } else { 544 MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo()); 545 } 546 ConsumeToken(); 547 // Consume ':'. 548 ExpectAndConsume(tok::colon); 549 } else { 550 // If no mapper identifier is provided, its name is "default" by default 551 MapperId = 552 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default")); 553 } 554 555 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end)) 556 return DeclGroupPtrTy(); 557 558 // Parse <type> <var> 559 DeclarationName VName; 560 QualType MapperType; 561 SourceRange Range; 562 TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS); 563 if (ParsedType.isUsable()) 564 MapperType = 565 Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType); 566 if (MapperType.isNull()) 567 IsCorrect = false; 568 if (!IsCorrect) { 569 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 570 return DeclGroupPtrTy(); 571 } 572 573 // Consume ')'. 574 IsCorrect &= !T.consumeClose(); 575 if (!IsCorrect) { 576 SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch); 577 return DeclGroupPtrTy(); 578 } 579 580 // Enter scope. 581 DeclarationNameInfo DirName; 582 SourceLocation Loc = Tok.getLocation(); 583 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 584 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 585 ParseScope OMPDirectiveScope(this, ScopeFlags); 586 Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc); 587 588 // Add the mapper variable declaration. 589 ExprResult MapperVarRef = Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl( 590 getCurScope(), MapperType, Range.getBegin(), VName); 591 592 // Parse map clauses. 593 SmallVector<OMPClause *, 6> Clauses; 594 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 595 OpenMPClauseKind CKind = Tok.isAnnotation() 596 ? OMPC_unknown 597 : getOpenMPClauseKind(PP.getSpelling(Tok)); 598 Actions.StartOpenMPClause(CKind); 599 OMPClause *Clause = 600 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty()); 601 if (Clause) 602 Clauses.push_back(Clause); 603 else 604 IsCorrect = false; 605 // Skip ',' if any. 606 if (Tok.is(tok::comma)) 607 ConsumeToken(); 608 Actions.EndOpenMPClause(); 609 } 610 if (Clauses.empty()) { 611 Diag(Tok, diag::err_omp_expected_clause) 612 << getOpenMPDirectiveName(OMPD_declare_mapper); 613 IsCorrect = false; 614 } 615 616 // Exit scope. 617 Actions.EndOpenMPDSABlock(nullptr); 618 OMPDirectiveScope.Exit(); 619 DeclGroupPtrTy DG = Actions.ActOnOpenMPDeclareMapperDirective( 620 getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType, 621 Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses); 622 if (!IsCorrect) 623 return DeclGroupPtrTy(); 624 625 return DG; 626 } 627 628 TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range, 629 DeclarationName &Name, 630 AccessSpecifier AS) { 631 // Parse the common declaration-specifiers piece. 632 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier; 633 DeclSpec DS(AttrFactory); 634 ParseSpecifierQualifierList(DS, AS, DSC); 635 636 // Parse the declarator. 637 DeclaratorContext Context = DeclaratorContext::Prototype; 638 Declarator DeclaratorInfo(DS, Context); 639 ParseDeclarator(DeclaratorInfo); 640 Range = DeclaratorInfo.getSourceRange(); 641 if (DeclaratorInfo.getIdentifier() == nullptr) { 642 Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator); 643 return true; 644 } 645 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName(); 646 647 return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo); 648 } 649 650 namespace { 651 /// RAII that recreates function context for correct parsing of clauses of 652 /// 'declare simd' construct. 653 /// OpenMP, 2.8.2 declare simd Construct 654 /// The expressions appearing in the clauses of this directive are evaluated in 655 /// the scope of the arguments of the function declaration or definition. 656 class FNContextRAII final { 657 Parser &P; 658 Sema::CXXThisScopeRAII *ThisScope; 659 Parser::MultiParseScope Scopes; 660 bool HasFunScope = false; 661 FNContextRAII() = delete; 662 FNContextRAII(const FNContextRAII &) = delete; 663 FNContextRAII &operator=(const FNContextRAII &) = delete; 664 665 public: 666 FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P), Scopes(P) { 667 Decl *D = *Ptr.get().begin(); 668 NamedDecl *ND = dyn_cast<NamedDecl>(D); 669 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext()); 670 Sema &Actions = P.getActions(); 671 672 // Allow 'this' within late-parsed attributes. 673 ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(), 674 ND && ND->isCXXInstanceMember()); 675 676 // If the Decl is templatized, add template parameters to scope. 677 // FIXME: Track CurTemplateDepth? 678 P.ReenterTemplateScopes(Scopes, D); 679 680 // If the Decl is on a function, add function parameters to the scope. 681 if (D->isFunctionOrFunctionTemplate()) { 682 HasFunScope = true; 683 Scopes.Enter(Scope::FnScope | Scope::DeclScope | 684 Scope::CompoundStmtScope); 685 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D); 686 } 687 } 688 ~FNContextRAII() { 689 if (HasFunScope) 690 P.getActions().ActOnExitFunctionContext(); 691 delete ThisScope; 692 } 693 }; 694 } // namespace 695 696 /// Parses clauses for 'declare simd' directive. 697 /// clause: 698 /// 'inbranch' | 'notinbranch' 699 /// 'simdlen' '(' <expr> ')' 700 /// { 'uniform' '(' <argument_list> ')' } 701 /// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' } 702 /// { 'linear '(' <argument_list> [ ':' <step> ] ')' } 703 static bool parseDeclareSimdClauses( 704 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, 705 SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds, 706 SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears, 707 SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) { 708 SourceRange BSRange; 709 const Token &Tok = P.getCurToken(); 710 bool IsError = false; 711 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 712 if (Tok.isNot(tok::identifier)) 713 break; 714 OMPDeclareSimdDeclAttr::BranchStateTy Out; 715 IdentifierInfo *II = Tok.getIdentifierInfo(); 716 StringRef ClauseName = II->getName(); 717 // Parse 'inranch|notinbranch' clauses. 718 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) { 719 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) { 720 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch) 721 << ClauseName 722 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange; 723 IsError = true; 724 } 725 BS = Out; 726 BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc()); 727 P.ConsumeToken(); 728 } else if (ClauseName.equals("simdlen")) { 729 if (SimdLen.isUsable()) { 730 P.Diag(Tok, diag::err_omp_more_one_clause) 731 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0; 732 IsError = true; 733 } 734 P.ConsumeToken(); 735 SourceLocation RLoc; 736 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc); 737 if (SimdLen.isInvalid()) 738 IsError = true; 739 } else { 740 OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName); 741 if (CKind == OMPC_uniform || CKind == OMPC_aligned || 742 CKind == OMPC_linear) { 743 Parser::OpenMPVarListDataTy Data; 744 SmallVectorImpl<Expr *> *Vars = &Uniforms; 745 if (CKind == OMPC_aligned) { 746 Vars = &Aligneds; 747 } else if (CKind == OMPC_linear) { 748 Data.ExtraModifier = OMPC_LINEAR_val; 749 Vars = &Linears; 750 } 751 752 P.ConsumeToken(); 753 if (P.ParseOpenMPVarList(OMPD_declare_simd, 754 getOpenMPClauseKind(ClauseName), *Vars, Data)) 755 IsError = true; 756 if (CKind == OMPC_aligned) { 757 Alignments.append(Aligneds.size() - Alignments.size(), 758 Data.DepModOrTailExpr); 759 } else if (CKind == OMPC_linear) { 760 assert(0 <= Data.ExtraModifier && 761 Data.ExtraModifier <= OMPC_LINEAR_unknown && 762 "Unexpected linear modifier."); 763 if (P.getActions().CheckOpenMPLinearModifier( 764 static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier), 765 Data.ExtraModifierLoc)) 766 Data.ExtraModifier = OMPC_LINEAR_val; 767 LinModifiers.append(Linears.size() - LinModifiers.size(), 768 Data.ExtraModifier); 769 Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr); 770 } 771 } else 772 // TODO: add parsing of other clauses. 773 break; 774 } 775 // Skip ',' if any. 776 if (Tok.is(tok::comma)) 777 P.ConsumeToken(); 778 } 779 return IsError; 780 } 781 782 /// Parse clauses for '#pragma omp declare simd'. 783 Parser::DeclGroupPtrTy 784 Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, 785 CachedTokens &Toks, SourceLocation Loc) { 786 PP.EnterToken(Tok, /*IsReinject*/ true); 787 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 788 /*IsReinject*/ true); 789 // Consume the previously pushed token. 790 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 791 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 792 793 FNContextRAII FnContext(*this, Ptr); 794 OMPDeclareSimdDeclAttr::BranchStateTy BS = 795 OMPDeclareSimdDeclAttr::BS_Undefined; 796 ExprResult Simdlen; 797 SmallVector<Expr *, 4> Uniforms; 798 SmallVector<Expr *, 4> Aligneds; 799 SmallVector<Expr *, 4> Alignments; 800 SmallVector<Expr *, 4> Linears; 801 SmallVector<unsigned, 4> LinModifiers; 802 SmallVector<Expr *, 4> Steps; 803 bool IsError = 804 parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds, 805 Alignments, Linears, LinModifiers, Steps); 806 skipUntilPragmaOpenMPEnd(OMPD_declare_simd); 807 // Skip the last annot_pragma_openmp_end. 808 SourceLocation EndLoc = ConsumeAnnotationToken(); 809 if (IsError) 810 return Ptr; 811 return Actions.ActOnOpenMPDeclareSimdDirective( 812 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, 813 LinModifiers, Steps, SourceRange(Loc, EndLoc)); 814 } 815 816 namespace { 817 /// Constant used in the diagnostics to distinguish the levels in an OpenMP 818 /// contexts: selector-set={selector(trait, ...), ...}, .... 819 enum OMPContextLvl { 820 CONTEXT_SELECTOR_SET_LVL = 0, 821 CONTEXT_SELECTOR_LVL = 1, 822 CONTEXT_TRAIT_LVL = 2, 823 }; 824 825 static StringRef stringLiteralParser(Parser &P) { 826 ExprResult Res = P.ParseStringLiteralExpression(true); 827 return Res.isUsable() ? Res.getAs<StringLiteral>()->getString() : ""; 828 } 829 830 static StringRef getNameFromIdOrString(Parser &P, Token &Tok, 831 OMPContextLvl Lvl) { 832 if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) { 833 llvm::SmallString<16> Buffer; 834 StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer); 835 (void)P.ConsumeToken(); 836 return Name; 837 } 838 839 if (tok::isStringLiteral(Tok.getKind())) 840 return stringLiteralParser(P); 841 842 P.Diag(Tok.getLocation(), 843 diag::warn_omp_declare_variant_string_literal_or_identifier) 844 << Lvl; 845 return ""; 846 } 847 848 static bool checkForDuplicates(Parser &P, StringRef Name, 849 SourceLocation NameLoc, 850 llvm::StringMap<SourceLocation> &Seen, 851 OMPContextLvl Lvl) { 852 auto Res = Seen.try_emplace(Name, NameLoc); 853 if (Res.second) 854 return false; 855 856 // Each trait-set-selector-name, trait-selector-name and trait-name can 857 // only be specified once. 858 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use) 859 << Lvl << Name; 860 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here) 861 << Lvl << Name; 862 return true; 863 } 864 } // namespace 865 866 void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty, 867 llvm::omp::TraitSet Set, 868 llvm::omp::TraitSelector Selector, 869 llvm::StringMap<SourceLocation> &Seen) { 870 TIProperty.Kind = TraitProperty::invalid; 871 872 SourceLocation NameLoc = Tok.getLocation(); 873 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL); 874 if (Name.empty()) { 875 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 876 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector); 877 return; 878 } 879 880 TIProperty.RawString = Name; 881 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name); 882 if (TIProperty.Kind != TraitProperty::invalid) { 883 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL)) 884 TIProperty.Kind = TraitProperty::invalid; 885 return; 886 } 887 888 // It follows diagnosis and helping notes. 889 // FIXME: We should move the diagnosis string generation into libFrontend. 890 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property) 891 << Name << getOpenMPContextTraitSelectorName(Selector) 892 << getOpenMPContextTraitSetName(Set); 893 894 TraitSet SetForName = getOpenMPContextTraitSetKind(Name); 895 if (SetForName != TraitSet::invalid) { 896 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 897 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL; 898 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 899 << Name << "<selector-name>" 900 << "(<property-name>)"; 901 return; 902 } 903 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name); 904 if (SelectorForName != TraitSelector::invalid) { 905 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 906 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL; 907 bool AllowsTraitScore = false; 908 bool RequiresProperty = false; 909 isValidTraitSelectorForTraitSet( 910 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName), 911 AllowsTraitScore, RequiresProperty); 912 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 913 << getOpenMPContextTraitSetName( 914 getOpenMPContextTraitSetForSelector(SelectorForName)) 915 << Name << (RequiresProperty ? "(<property-name>)" : ""); 916 return; 917 } 918 for (const auto &PotentialSet : 919 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 920 TraitSet::device}) { 921 TraitProperty PropertyForName = 922 getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name); 923 if (PropertyForName == TraitProperty::invalid) 924 continue; 925 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 926 << getOpenMPContextTraitSetName( 927 getOpenMPContextTraitSetForProperty(PropertyForName)) 928 << getOpenMPContextTraitSelectorName( 929 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 930 << ("(" + Name + ")").str(); 931 return; 932 } 933 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 934 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector); 935 } 936 937 static bool checkExtensionProperty(Parser &P, SourceLocation Loc, 938 OMPTraitProperty &TIProperty, 939 OMPTraitSelector &TISelector, 940 llvm::StringMap<SourceLocation> &Seen) { 941 assert(TISelector.Kind == 942 llvm::omp::TraitSelector::implementation_extension && 943 "Only for extension properties, e.g., " 944 "`implementation={extension(PROPERTY)}`"); 945 if (TIProperty.Kind == TraitProperty::invalid) 946 return false; 947 948 if (TIProperty.Kind == 949 TraitProperty::implementation_extension_disable_implicit_base) 950 return true; 951 952 if (TIProperty.Kind == 953 TraitProperty::implementation_extension_allow_templates) 954 return true; 955 956 auto IsMatchExtension = [](OMPTraitProperty &TP) { 957 return (TP.Kind == 958 llvm::omp::TraitProperty::implementation_extension_match_all || 959 TP.Kind == 960 llvm::omp::TraitProperty::implementation_extension_match_any || 961 TP.Kind == 962 llvm::omp::TraitProperty::implementation_extension_match_none); 963 }; 964 965 if (IsMatchExtension(TIProperty)) { 966 for (OMPTraitProperty &SeenProp : TISelector.Properties) 967 if (IsMatchExtension(SeenProp)) { 968 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension); 969 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName( 970 SeenProp.Kind, SeenProp.RawString); 971 SourceLocation SeenLoc = Seen[SeenName]; 972 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here) 973 << CONTEXT_TRAIT_LVL << SeenName; 974 return false; 975 } 976 return true; 977 } 978 979 llvm_unreachable("Unknown extension property!"); 980 } 981 982 void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector, 983 llvm::omp::TraitSet Set, 984 llvm::StringMap<SourceLocation> &Seen) { 985 assert(TISelector.Kind != TraitSelector::user_condition && 986 "User conditions are special properties not handled here!"); 987 988 SourceLocation PropertyLoc = Tok.getLocation(); 989 OMPTraitProperty TIProperty; 990 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen); 991 992 if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension) 993 if (!checkExtensionProperty(*this, Tok.getLocation(), TIProperty, 994 TISelector, Seen)) 995 TIProperty.Kind = TraitProperty::invalid; 996 997 // If we have an invalid property here we already issued a warning. 998 if (TIProperty.Kind == TraitProperty::invalid) { 999 if (PropertyLoc != Tok.getLocation()) 1000 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1001 << CONTEXT_TRAIT_LVL; 1002 return; 1003 } 1004 1005 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind, 1006 TISelector.Kind, Set)) { 1007 1008 // If we make it here the property, selector, set, score, condition, ... are 1009 // all valid (or have been corrected). Thus we can record the property. 1010 TISelector.Properties.push_back(TIProperty); 1011 return; 1012 } 1013 1014 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector) 1015 << getOpenMPContextTraitPropertyName(TIProperty.Kind, 1016 TIProperty.RawString) 1017 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1018 << getOpenMPContextTraitSetName(Set); 1019 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property) 1020 << getOpenMPContextTraitPropertyName(TIProperty.Kind, 1021 TIProperty.RawString) 1022 << getOpenMPContextTraitSelectorName( 1023 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind)) 1024 << getOpenMPContextTraitSetName( 1025 getOpenMPContextTraitSetForProperty(TIProperty.Kind)); 1026 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1027 << CONTEXT_TRAIT_LVL; 1028 } 1029 1030 void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector, 1031 llvm::omp::TraitSet Set, 1032 llvm::StringMap<SourceLocation> &Seen) { 1033 TISelector.Kind = TraitSelector::invalid; 1034 1035 SourceLocation NameLoc = Tok.getLocation(); 1036 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL); 1037 if (Name.empty()) { 1038 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 1039 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set); 1040 return; 1041 } 1042 1043 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name); 1044 if (TISelector.Kind != TraitSelector::invalid) { 1045 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL)) 1046 TISelector.Kind = TraitSelector::invalid; 1047 return; 1048 } 1049 1050 // It follows diagnosis and helping notes. 1051 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector) 1052 << Name << getOpenMPContextTraitSetName(Set); 1053 1054 TraitSet SetForName = getOpenMPContextTraitSetKind(Name); 1055 if (SetForName != TraitSet::invalid) { 1056 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1057 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL; 1058 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1059 << Name << "<selector-name>" 1060 << "<property-name>"; 1061 return; 1062 } 1063 for (const auto &PotentialSet : 1064 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 1065 TraitSet::device}) { 1066 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind( 1067 PotentialSet, TraitSelector::invalid, Name); 1068 if (PropertyForName == TraitProperty::invalid) 1069 continue; 1070 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1071 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL; 1072 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1073 << getOpenMPContextTraitSetName( 1074 getOpenMPContextTraitSetForProperty(PropertyForName)) 1075 << getOpenMPContextTraitSelectorName( 1076 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 1077 << ("(" + Name + ")").str(); 1078 return; 1079 } 1080 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 1081 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set); 1082 } 1083 1084 /// Parse optional 'score' '(' <expr> ')' ':'. 1085 static ExprResult parseContextScore(Parser &P) { 1086 ExprResult ScoreExpr; 1087 llvm::SmallString<16> Buffer; 1088 StringRef SelectorName = 1089 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer); 1090 if (!SelectorName.equals("score")) 1091 return ScoreExpr; 1092 (void)P.ConsumeToken(); 1093 SourceLocation RLoc; 1094 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc); 1095 // Parse ':' 1096 if (P.getCurToken().is(tok::colon)) 1097 (void)P.ConsumeAnyToken(); 1098 else 1099 P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected) 1100 << "':'" 1101 << "score expression"; 1102 return ScoreExpr; 1103 } 1104 1105 /// Parses an OpenMP context selector. 1106 /// 1107 /// <trait-selector-name> ['('[<trait-score>] <trait-property> [, <t-p>]* ')'] 1108 void Parser::parseOMPContextSelector( 1109 OMPTraitSelector &TISelector, llvm::omp::TraitSet Set, 1110 llvm::StringMap<SourceLocation> &SeenSelectors) { 1111 unsigned short OuterPC = ParenCount; 1112 1113 // If anything went wrong we issue an error or warning and then skip the rest 1114 // of the selector. However, commas are ambiguous so we look for the nesting 1115 // of parentheses here as well. 1116 auto FinishSelector = [OuterPC, this]() -> void { 1117 bool Done = false; 1118 while (!Done) { 1119 while (!SkipUntil({tok::r_brace, tok::r_paren, tok::comma, 1120 tok::annot_pragma_openmp_end}, 1121 StopBeforeMatch)) 1122 ; 1123 if (Tok.is(tok::r_paren) && OuterPC > ParenCount) 1124 (void)ConsumeParen(); 1125 if (OuterPC <= ParenCount) { 1126 Done = true; 1127 break; 1128 } 1129 if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) { 1130 Done = true; 1131 break; 1132 } 1133 (void)ConsumeAnyToken(); 1134 } 1135 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1136 << CONTEXT_SELECTOR_LVL; 1137 }; 1138 1139 SourceLocation SelectorLoc = Tok.getLocation(); 1140 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors); 1141 if (TISelector.Kind == TraitSelector::invalid) 1142 return FinishSelector(); 1143 1144 bool AllowsTraitScore = false; 1145 bool RequiresProperty = false; 1146 if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore, 1147 RequiresProperty)) { 1148 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set) 1149 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1150 << getOpenMPContextTraitSetName(Set); 1151 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector) 1152 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1153 << getOpenMPContextTraitSetName( 1154 getOpenMPContextTraitSetForSelector(TISelector.Kind)) 1155 << RequiresProperty; 1156 return FinishSelector(); 1157 } 1158 1159 if (!RequiresProperty) { 1160 TISelector.Properties.push_back( 1161 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind), 1162 getOpenMPContextTraitSelectorName(TISelector.Kind)}); 1163 return; 1164 } 1165 1166 if (!Tok.is(tok::l_paren)) { 1167 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties) 1168 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1169 << getOpenMPContextTraitSetName(Set); 1170 return FinishSelector(); 1171 } 1172 1173 if (TISelector.Kind == TraitSelector::user_condition) { 1174 SourceLocation RLoc; 1175 ExprResult Condition = ParseOpenMPParensExpr("user condition", RLoc); 1176 if (!Condition.isUsable()) 1177 return FinishSelector(); 1178 TISelector.ScoreOrCondition = Condition.get(); 1179 TISelector.Properties.push_back( 1180 {TraitProperty::user_condition_unknown, "<condition>"}); 1181 return; 1182 } 1183 1184 BalancedDelimiterTracker BDT(*this, tok::l_paren, 1185 tok::annot_pragma_openmp_end); 1186 // Parse '('. 1187 (void)BDT.consumeOpen(); 1188 1189 SourceLocation ScoreLoc = Tok.getLocation(); 1190 ExprResult Score = parseContextScore(*this); 1191 1192 if (!AllowsTraitScore && !Score.isUnset()) { 1193 if (Score.isUsable()) { 1194 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property) 1195 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1196 << getOpenMPContextTraitSetName(Set) << Score.get(); 1197 } else { 1198 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property) 1199 << getOpenMPContextTraitSelectorName(TISelector.Kind) 1200 << getOpenMPContextTraitSetName(Set) << "<invalid>"; 1201 } 1202 Score = ExprResult(); 1203 } 1204 1205 if (Score.isUsable()) 1206 TISelector.ScoreOrCondition = Score.get(); 1207 1208 llvm::StringMap<SourceLocation> SeenProperties; 1209 do { 1210 parseOMPContextProperty(TISelector, Set, SeenProperties); 1211 } while (TryConsumeToken(tok::comma)); 1212 1213 // Parse ')'. 1214 BDT.consumeClose(); 1215 } 1216 1217 void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet, 1218 llvm::StringMap<SourceLocation> &Seen) { 1219 TISet.Kind = TraitSet::invalid; 1220 1221 SourceLocation NameLoc = Tok.getLocation(); 1222 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL); 1223 if (Name.empty()) { 1224 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options) 1225 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets(); 1226 return; 1227 } 1228 1229 TISet.Kind = getOpenMPContextTraitSetKind(Name); 1230 if (TISet.Kind != TraitSet::invalid) { 1231 if (checkForDuplicates(*this, Name, NameLoc, Seen, 1232 CONTEXT_SELECTOR_SET_LVL)) 1233 TISet.Kind = TraitSet::invalid; 1234 return; 1235 } 1236 1237 // It follows diagnosis and helping notes. 1238 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name; 1239 1240 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name); 1241 if (SelectorForName != TraitSelector::invalid) { 1242 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1243 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL; 1244 bool AllowsTraitScore = false; 1245 bool RequiresProperty = false; 1246 isValidTraitSelectorForTraitSet( 1247 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName), 1248 AllowsTraitScore, RequiresProperty); 1249 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1250 << getOpenMPContextTraitSetName( 1251 getOpenMPContextTraitSetForSelector(SelectorForName)) 1252 << Name << (RequiresProperty ? "(<property-name>)" : ""); 1253 return; 1254 } 1255 for (const auto &PotentialSet : 1256 {TraitSet::construct, TraitSet::user, TraitSet::implementation, 1257 TraitSet::device}) { 1258 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind( 1259 PotentialSet, TraitSelector::invalid, Name); 1260 if (PropertyForName == TraitProperty::invalid) 1261 continue; 1262 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a) 1263 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL; 1264 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try) 1265 << getOpenMPContextTraitSetName( 1266 getOpenMPContextTraitSetForProperty(PropertyForName)) 1267 << getOpenMPContextTraitSelectorName( 1268 getOpenMPContextTraitSelectorForProperty(PropertyForName)) 1269 << ("(" + Name + ")").str(); 1270 return; 1271 } 1272 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options) 1273 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets(); 1274 } 1275 1276 /// Parses an OpenMP context selector set. 1277 /// 1278 /// <trait-set-selector-name> '=' '{' <trait-selector> [, <trait-selector>]* '}' 1279 void Parser::parseOMPContextSelectorSet( 1280 OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) { 1281 auto OuterBC = BraceCount; 1282 1283 // If anything went wrong we issue an error or warning and then skip the rest 1284 // of the set. However, commas are ambiguous so we look for the nesting 1285 // of braces here as well. 1286 auto FinishSelectorSet = [this, OuterBC]() -> void { 1287 bool Done = false; 1288 while (!Done) { 1289 while (!SkipUntil({tok::comma, tok::r_brace, tok::r_paren, 1290 tok::annot_pragma_openmp_end}, 1291 StopBeforeMatch)) 1292 ; 1293 if (Tok.is(tok::r_brace) && OuterBC > BraceCount) 1294 (void)ConsumeBrace(); 1295 if (OuterBC <= BraceCount) { 1296 Done = true; 1297 break; 1298 } 1299 if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) { 1300 Done = true; 1301 break; 1302 } 1303 (void)ConsumeAnyToken(); 1304 } 1305 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here) 1306 << CONTEXT_SELECTOR_SET_LVL; 1307 }; 1308 1309 parseOMPTraitSetKind(TISet, SeenSets); 1310 if (TISet.Kind == TraitSet::invalid) 1311 return FinishSelectorSet(); 1312 1313 // Parse '='. 1314 if (!TryConsumeToken(tok::equal)) 1315 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1316 << "=" 1317 << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) + 1318 "\"") 1319 .str(); 1320 1321 // Parse '{'. 1322 if (Tok.is(tok::l_brace)) { 1323 (void)ConsumeBrace(); 1324 } else { 1325 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1326 << "{" 1327 << ("'=' that follows the context set name \"" + 1328 getOpenMPContextTraitSetName(TISet.Kind) + "\"") 1329 .str(); 1330 } 1331 1332 llvm::StringMap<SourceLocation> SeenSelectors; 1333 do { 1334 OMPTraitSelector TISelector; 1335 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors); 1336 if (TISelector.Kind != TraitSelector::invalid && 1337 !TISelector.Properties.empty()) 1338 TISet.Selectors.push_back(TISelector); 1339 } while (TryConsumeToken(tok::comma)); 1340 1341 // Parse '}'. 1342 if (Tok.is(tok::r_brace)) { 1343 (void)ConsumeBrace(); 1344 } else { 1345 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected) 1346 << "}" 1347 << ("context selectors for the context set \"" + 1348 getOpenMPContextTraitSetName(TISet.Kind) + "\"") 1349 .str(); 1350 } 1351 } 1352 1353 /// Parse OpenMP context selectors: 1354 /// 1355 /// <trait-set-selector> [, <trait-set-selector>]* 1356 bool Parser::parseOMPContextSelectors(SourceLocation Loc, OMPTraitInfo &TI) { 1357 llvm::StringMap<SourceLocation> SeenSets; 1358 do { 1359 OMPTraitSet TISet; 1360 parseOMPContextSelectorSet(TISet, SeenSets); 1361 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty()) 1362 TI.Sets.push_back(TISet); 1363 } while (TryConsumeToken(tok::comma)); 1364 1365 return false; 1366 } 1367 1368 /// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'. 1369 void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr, 1370 CachedTokens &Toks, 1371 SourceLocation Loc) { 1372 PP.EnterToken(Tok, /*IsReinject*/ true); 1373 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true, 1374 /*IsReinject*/ true); 1375 // Consume the previously pushed token. 1376 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1377 ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true); 1378 1379 FNContextRAII FnContext(*this, Ptr); 1380 // Parse function declaration id. 1381 SourceLocation RLoc; 1382 // Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs 1383 // instead of MemberExprs. 1384 ExprResult AssociatedFunction; 1385 { 1386 // Do not mark function as is used to prevent its emission if this is the 1387 // only place where it is used. 1388 EnterExpressionEvaluationContext Unevaluated( 1389 Actions, Sema::ExpressionEvaluationContext::Unevaluated); 1390 AssociatedFunction = ParseOpenMPParensExpr( 1391 getOpenMPDirectiveName(OMPD_declare_variant), RLoc, 1392 /*IsAddressOfOperand=*/true); 1393 } 1394 if (!AssociatedFunction.isUsable()) { 1395 if (!Tok.is(tok::annot_pragma_openmp_end)) 1396 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1397 ; 1398 // Skip the last annot_pragma_openmp_end. 1399 (void)ConsumeAnnotationToken(); 1400 return; 1401 } 1402 1403 OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope(); 1404 ASTContext &ASTCtx = Actions.getASTContext(); 1405 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo(); 1406 SmallVector<Expr *, 6> AdjustNothing; 1407 SmallVector<Expr *, 6> AdjustNeedDevicePtr; 1408 SmallVector<OMPDeclareVariantAttr::InteropType, 3> AppendArgs; 1409 SourceLocation AdjustArgsLoc, AppendArgsLoc; 1410 1411 // At least one clause is required. 1412 if (Tok.is(tok::annot_pragma_openmp_end)) { 1413 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1414 << (getLangOpts().OpenMP < 51 ? 0 : 1); 1415 } 1416 1417 bool IsError = false; 1418 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1419 OpenMPClauseKind CKind = Tok.isAnnotation() 1420 ? OMPC_unknown 1421 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1422 if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind, 1423 getLangOpts().OpenMP)) { 1424 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1425 << (getLangOpts().OpenMP < 51 ? 0 : 1); 1426 IsError = true; 1427 } 1428 if (!IsError) { 1429 switch (CKind) { 1430 case OMPC_match: 1431 IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI); 1432 break; 1433 case OMPC_adjust_args: { 1434 AdjustArgsLoc = Tok.getLocation(); 1435 ConsumeToken(); 1436 Parser::OpenMPVarListDataTy Data; 1437 SmallVector<Expr *> Vars; 1438 IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args, 1439 Vars, Data); 1440 if (!IsError) 1441 llvm::append_range(Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing 1442 ? AdjustNothing 1443 : AdjustNeedDevicePtr, 1444 Vars); 1445 break; 1446 } 1447 case OMPC_append_args: 1448 if (!AppendArgs.empty()) { 1449 Diag(AppendArgsLoc, diag::err_omp_more_one_clause) 1450 << getOpenMPDirectiveName(OMPD_declare_variant) 1451 << getOpenMPClauseName(CKind) << 0; 1452 IsError = true; 1453 } 1454 if (!IsError) { 1455 AppendArgsLoc = Tok.getLocation(); 1456 ConsumeToken(); 1457 IsError = parseOpenMPAppendArgs(AppendArgs); 1458 } 1459 break; 1460 default: 1461 llvm_unreachable("Unexpected clause for declare variant."); 1462 } 1463 } 1464 if (IsError) { 1465 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch)) 1466 ; 1467 // Skip the last annot_pragma_openmp_end. 1468 (void)ConsumeAnnotationToken(); 1469 return; 1470 } 1471 // Skip ',' if any. 1472 if (Tok.is(tok::comma)) 1473 ConsumeToken(); 1474 } 1475 1476 Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = 1477 Actions.checkOpenMPDeclareVariantFunction( 1478 Ptr, AssociatedFunction.get(), TI, AppendArgs.size(), 1479 SourceRange(Loc, Tok.getLocation())); 1480 1481 if (DeclVarData && !TI.Sets.empty()) 1482 Actions.ActOnOpenMPDeclareVariantDirective( 1483 DeclVarData->first, DeclVarData->second, TI, AdjustNothing, 1484 AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc, 1485 SourceRange(Loc, Tok.getLocation())); 1486 1487 // Skip the last annot_pragma_openmp_end. 1488 (void)ConsumeAnnotationToken(); 1489 } 1490 1491 /// Parse a list of interop-types. These are 'target' and 'targetsync'. Both 1492 /// are allowed but duplication of either is not meaningful. 1493 static Optional<OMPDeclareVariantAttr::InteropType> 1494 parseInteropTypeList(Parser &P) { 1495 const Token &Tok = P.getCurToken(); 1496 bool HasError = false; 1497 bool IsTarget = false; 1498 bool IsTargetSync = false; 1499 1500 while (Tok.is(tok::identifier)) { 1501 if (Tok.getIdentifierInfo()->isStr("target")) { 1502 // OpenMP 5.1 [2.15.1, interop Construct, Restrictions] 1503 // Each interop-type may be specified on an action-clause at most 1504 // once. 1505 if (IsTarget) 1506 P.Diag(Tok, diag::warn_omp_more_one_interop_type) << "target"; 1507 IsTarget = true; 1508 } else if (Tok.getIdentifierInfo()->isStr("targetsync")) { 1509 if (IsTargetSync) 1510 P.Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync"; 1511 IsTargetSync = true; 1512 } else { 1513 HasError = true; 1514 P.Diag(Tok, diag::err_omp_expected_interop_type); 1515 } 1516 P.ConsumeToken(); 1517 1518 if (!Tok.is(tok::comma)) 1519 break; 1520 P.ConsumeToken(); 1521 } 1522 if (HasError) 1523 return None; 1524 1525 if (!IsTarget && !IsTargetSync) { 1526 P.Diag(Tok, diag::err_omp_expected_interop_type); 1527 return None; 1528 } 1529 1530 // As of OpenMP 5.1,there are two interop-types, "target" and 1531 // "targetsync". Either or both are allowed for a single interop. 1532 if (IsTarget && IsTargetSync) 1533 return OMPDeclareVariantAttr::Target_TargetSync; 1534 if (IsTarget) 1535 return OMPDeclareVariantAttr::Target; 1536 return OMPDeclareVariantAttr::TargetSync; 1537 } 1538 1539 bool Parser::parseOpenMPAppendArgs( 1540 SmallVectorImpl<OMPDeclareVariantAttr::InteropType> &InterOpTypes) { 1541 bool HasError = false; 1542 // Parse '('. 1543 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1544 if (T.expectAndConsume(diag::err_expected_lparen_after, 1545 getOpenMPClauseName(OMPC_append_args).data())) 1546 return true; 1547 1548 // Parse the list of append-ops, each is; 1549 // interop(interop-type[,interop-type]...) 1550 while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) { 1551 ConsumeToken(); 1552 BalancedDelimiterTracker IT(*this, tok::l_paren, 1553 tok::annot_pragma_openmp_end); 1554 if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop")) 1555 return true; 1556 1557 // Parse the interop-types. 1558 if (Optional<OMPDeclareVariantAttr::InteropType> IType = 1559 parseInteropTypeList(*this)) 1560 InterOpTypes.push_back(IType.getValue()); 1561 else 1562 HasError = true; 1563 1564 IT.consumeClose(); 1565 if (Tok.is(tok::comma)) 1566 ConsumeToken(); 1567 } 1568 if (!HasError && InterOpTypes.empty()) { 1569 HasError = true; 1570 Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op); 1571 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 1572 StopBeforeMatch); 1573 } 1574 HasError = T.consumeClose() || HasError; 1575 return HasError; 1576 } 1577 1578 bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc, 1579 OMPTraitInfo &TI, 1580 OMPTraitInfo *ParentTI) { 1581 // Parse 'match'. 1582 OpenMPClauseKind CKind = Tok.isAnnotation() 1583 ? OMPC_unknown 1584 : getOpenMPClauseKind(PP.getSpelling(Tok)); 1585 if (CKind != OMPC_match) { 1586 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause) 1587 << (getLangOpts().OpenMP < 51 ? 0 : 1); 1588 return true; 1589 } 1590 (void)ConsumeToken(); 1591 // Parse '('. 1592 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 1593 if (T.expectAndConsume(diag::err_expected_lparen_after, 1594 getOpenMPClauseName(OMPC_match).data())) 1595 return true; 1596 1597 // Parse inner context selectors. 1598 parseOMPContextSelectors(Loc, TI); 1599 1600 // Parse ')' 1601 (void)T.consumeClose(); 1602 1603 if (!ParentTI) 1604 return false; 1605 1606 // Merge the parent/outer trait info into the one we just parsed and diagnose 1607 // problems. 1608 // TODO: Keep some source location in the TI to provide better diagnostics. 1609 // TODO: Perform some kind of equivalence check on the condition and score 1610 // expressions. 1611 for (const OMPTraitSet &ParentSet : ParentTI->Sets) { 1612 bool MergedSet = false; 1613 for (OMPTraitSet &Set : TI.Sets) { 1614 if (Set.Kind != ParentSet.Kind) 1615 continue; 1616 MergedSet = true; 1617 for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) { 1618 bool MergedSelector = false; 1619 for (OMPTraitSelector &Selector : Set.Selectors) { 1620 if (Selector.Kind != ParentSelector.Kind) 1621 continue; 1622 MergedSelector = true; 1623 for (const OMPTraitProperty &ParentProperty : 1624 ParentSelector.Properties) { 1625 bool MergedProperty = false; 1626 for (OMPTraitProperty &Property : Selector.Properties) { 1627 // Ignore "equivalent" properties. 1628 if (Property.Kind != ParentProperty.Kind) 1629 continue; 1630 1631 // If the kind is the same but the raw string not, we don't want 1632 // to skip out on the property. 1633 MergedProperty |= Property.RawString == ParentProperty.RawString; 1634 1635 if (Property.RawString == ParentProperty.RawString && 1636 Selector.ScoreOrCondition == ParentSelector.ScoreOrCondition) 1637 continue; 1638 1639 if (Selector.Kind == llvm::omp::TraitSelector::user_condition) { 1640 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition); 1641 } else if (Selector.ScoreOrCondition != 1642 ParentSelector.ScoreOrCondition) { 1643 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait) 1644 << getOpenMPContextTraitPropertyName( 1645 ParentProperty.Kind, ParentProperty.RawString) 1646 << getOpenMPContextTraitSelectorName(ParentSelector.Kind) 1647 << getOpenMPContextTraitSetName(ParentSet.Kind); 1648 } 1649 } 1650 if (!MergedProperty) 1651 Selector.Properties.push_back(ParentProperty); 1652 } 1653 } 1654 if (!MergedSelector) 1655 Set.Selectors.push_back(ParentSelector); 1656 } 1657 } 1658 if (!MergedSet) 1659 TI.Sets.push_back(ParentSet); 1660 } 1661 1662 return false; 1663 } 1664 1665 /// `omp assumes` or `omp begin/end assumes` <clause> [[,]<clause>]... 1666 /// where 1667 /// 1668 /// clause: 1669 /// 'ext_IMPL_DEFINED' 1670 /// 'absent' '(' directive-name [, directive-name]* ')' 1671 /// 'contains' '(' directive-name [, directive-name]* ')' 1672 /// 'holds' '(' scalar-expression ')' 1673 /// 'no_openmp' 1674 /// 'no_openmp_routines' 1675 /// 'no_parallelism' 1676 /// 1677 void Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind, 1678 SourceLocation Loc) { 1679 SmallVector<std::string, 4> Assumptions; 1680 bool SkippedClauses = false; 1681 1682 auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) { 1683 BalancedDelimiterTracker T(*this, tok::l_paren, 1684 tok::annot_pragma_openmp_end); 1685 if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data())) 1686 return; 1687 T.skipToEnd(); 1688 if (IssueNote && T.getCloseLocation().isValid()) 1689 Diag(T.getCloseLocation(), 1690 diag::note_omp_assumption_clause_continue_here); 1691 }; 1692 1693 /// Helper to determine which AssumptionClauseMapping (ACM) in the 1694 /// AssumptionClauseMappings table matches \p RawString. The return value is 1695 /// the index of the matching ACM into the table or -1 if there was no match. 1696 auto MatchACMClause = [&](StringRef RawString) { 1697 llvm::StringSwitch<int> SS(RawString); 1698 unsigned ACMIdx = 0; 1699 for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) { 1700 if (ACMI.StartsWith) 1701 SS.StartsWith(ACMI.Identifier, ACMIdx++); 1702 else 1703 SS.Case(ACMI.Identifier, ACMIdx++); 1704 } 1705 return SS.Default(-1); 1706 }; 1707 1708 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1709 IdentifierInfo *II = nullptr; 1710 SourceLocation StartLoc = Tok.getLocation(); 1711 int Idx = -1; 1712 if (Tok.isAnyIdentifier()) { 1713 II = Tok.getIdentifierInfo(); 1714 Idx = MatchACMClause(II->getName()); 1715 } 1716 ConsumeAnyToken(); 1717 1718 bool NextIsLPar = Tok.is(tok::l_paren); 1719 // Handle unknown clauses by skipping them. 1720 if (Idx == -1) { 1721 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id) 1722 << llvm::omp::getOpenMPDirectiveName(DKind) 1723 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar; 1724 if (NextIsLPar) 1725 SkipBraces(II ? II->getName() : "", /* IssueNote */ true); 1726 SkippedClauses = true; 1727 continue; 1728 } 1729 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx]; 1730 if (ACMI.HasDirectiveList || ACMI.HasExpression) { 1731 // TODO: We ignore absent, contains, and holds assumptions for now. We 1732 // also do not verify the content in the parenthesis at all. 1733 SkippedClauses = true; 1734 SkipBraces(II->getName(), /* IssueNote */ false); 1735 continue; 1736 } 1737 1738 if (NextIsLPar) { 1739 Diag(Tok.getLocation(), 1740 diag::warn_omp_unknown_assumption_clause_without_args) 1741 << II; 1742 SkipBraces(II->getName(), /* IssueNote */ true); 1743 } 1744 1745 assert(II && "Expected an identifier clause!"); 1746 std::string Assumption = II->getName().str(); 1747 if (ACMI.StartsWith) 1748 Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size()); 1749 else 1750 Assumption = "omp_" + Assumption; 1751 Assumptions.push_back(Assumption); 1752 } 1753 1754 Actions.ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions, SkippedClauses); 1755 } 1756 1757 void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) { 1758 if (Actions.isInOpenMPAssumeScope()) 1759 Actions.ActOnOpenMPEndAssumesDirective(); 1760 else 1761 Diag(Loc, diag::err_expected_begin_assumes); 1762 } 1763 1764 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 1765 /// 1766 /// default-clause: 1767 /// 'default' '(' 'none' | 'shared' | 'firstprivate' ') 1768 /// 1769 /// proc_bind-clause: 1770 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') 1771 /// 1772 /// device_type-clause: 1773 /// 'device_type' '(' 'host' | 'nohost' | 'any' )' 1774 namespace { 1775 struct SimpleClauseData { 1776 unsigned Type; 1777 SourceLocation Loc; 1778 SourceLocation LOpen; 1779 SourceLocation TypeLoc; 1780 SourceLocation RLoc; 1781 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen, 1782 SourceLocation TypeLoc, SourceLocation RLoc) 1783 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {} 1784 }; 1785 } // anonymous namespace 1786 1787 static Optional<SimpleClauseData> 1788 parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) { 1789 const Token &Tok = P.getCurToken(); 1790 SourceLocation Loc = Tok.getLocation(); 1791 SourceLocation LOpen = P.ConsumeToken(); 1792 // Parse '('. 1793 BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end); 1794 if (T.expectAndConsume(diag::err_expected_lparen_after, 1795 getOpenMPClauseName(Kind).data())) 1796 return llvm::None; 1797 1798 unsigned Type = getOpenMPSimpleClauseType( 1799 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok), 1800 P.getLangOpts()); 1801 SourceLocation TypeLoc = Tok.getLocation(); 1802 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 1803 Tok.isNot(tok::annot_pragma_openmp_end)) 1804 P.ConsumeAnyToken(); 1805 1806 // Parse ')'. 1807 SourceLocation RLoc = Tok.getLocation(); 1808 if (!T.consumeClose()) 1809 RLoc = T.getCloseLocation(); 1810 1811 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc); 1812 } 1813 1814 void Parser::ParseOMPDeclareTargetClauses( 1815 Sema::DeclareTargetContextInfo &DTCI) { 1816 SourceLocation DeviceTypeLoc; 1817 bool RequiresToOrLinkOrIndirectClause = false; 1818 bool HasToOrLinkOrIndirectClause = false; 1819 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 1820 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; 1821 bool HasIdentifier = Tok.is(tok::identifier); 1822 if (HasIdentifier) { 1823 // If we see any clause we need a to or link clause. 1824 RequiresToOrLinkOrIndirectClause = true; 1825 IdentifierInfo *II = Tok.getIdentifierInfo(); 1826 StringRef ClauseName = II->getName(); 1827 bool IsDeviceTypeClause = 1828 getLangOpts().OpenMP >= 50 && 1829 getOpenMPClauseKind(ClauseName) == OMPC_device_type; 1830 1831 bool IsIndirectClause = getLangOpts().OpenMP >= 51 && 1832 getOpenMPClauseKind(ClauseName) == OMPC_indirect; 1833 if (DTCI.Indirect.hasValue() && IsIndirectClause) { 1834 Diag(Tok, diag::err_omp_more_one_clause) 1835 << getOpenMPDirectiveName(OMPD_declare_target) 1836 << getOpenMPClauseName(OMPC_indirect) << 0; 1837 break; 1838 } 1839 bool IsToOrLinkClause = 1840 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT); 1841 assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!"); 1842 1843 if (!IsDeviceTypeClause && !IsIndirectClause && 1844 DTCI.Kind == OMPD_begin_declare_target) { 1845 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 1846 << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0); 1847 break; 1848 } 1849 if (!IsDeviceTypeClause && !IsToOrLinkClause && !IsIndirectClause) { 1850 Diag(Tok, diag::err_omp_declare_target_unexpected_clause) 1851 << ClauseName 1852 << (getLangOpts().OpenMP >= 51 ? 4 1853 : getLangOpts().OpenMP >= 50 ? 2 1854 : 1); 1855 break; 1856 } 1857 1858 if (IsToOrLinkClause || IsIndirectClause) 1859 HasToOrLinkOrIndirectClause = true; 1860 1861 if (IsIndirectClause) { 1862 if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false)) 1863 break; 1864 continue; 1865 } 1866 // Parse 'device_type' clause and go to next clause if any. 1867 if (IsDeviceTypeClause) { 1868 Optional<SimpleClauseData> DevTypeData = 1869 parseOpenMPSimpleClause(*this, OMPC_device_type); 1870 if (DevTypeData.hasValue()) { 1871 if (DeviceTypeLoc.isValid()) { 1872 // We already saw another device_type clause, diagnose it. 1873 Diag(DevTypeData.getValue().Loc, 1874 diag::warn_omp_more_one_device_type_clause); 1875 break; 1876 } 1877 switch (static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) { 1878 case OMPC_DEVICE_TYPE_any: 1879 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any; 1880 break; 1881 case OMPC_DEVICE_TYPE_host: 1882 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host; 1883 break; 1884 case OMPC_DEVICE_TYPE_nohost: 1885 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost; 1886 break; 1887 case OMPC_DEVICE_TYPE_unknown: 1888 llvm_unreachable("Unexpected device_type"); 1889 } 1890 DeviceTypeLoc = DevTypeData.getValue().Loc; 1891 } 1892 continue; 1893 } 1894 ConsumeToken(); 1895 } 1896 1897 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) { 1898 auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS, 1899 DeclarationNameInfo NameInfo) { 1900 NamedDecl *ND = 1901 Actions.lookupOpenMPDeclareTargetName(getCurScope(), SS, NameInfo); 1902 if (!ND) 1903 return; 1904 Sema::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()}; 1905 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second; 1906 if (!FirstMapping) 1907 Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple) 1908 << NameInfo.getName(); 1909 }; 1910 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, 1911 /*AllowScopeSpecifier=*/true)) 1912 break; 1913 } 1914 1915 if (Tok.is(tok::l_paren)) { 1916 Diag(Tok, 1917 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause); 1918 break; 1919 } 1920 if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) { 1921 Diag(Tok, 1922 diag::err_omp_declare_target_unexpected_clause_after_implicit_to); 1923 break; 1924 } 1925 1926 // Consume optional ','. 1927 if (Tok.is(tok::comma)) 1928 ConsumeToken(); 1929 } 1930 1931 if (DTCI.Indirect.hasValue() && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any) 1932 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type); 1933 1934 // For declare target require at least 'to' or 'link' to be present. 1935 if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause && 1936 !HasToOrLinkOrIndirectClause) 1937 Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause) 1938 << (getLangOpts().OpenMP >= 51 ? 1 : 0); 1939 1940 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1941 } 1942 1943 void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind DKind) { 1944 // The last seen token is annot_pragma_openmp_end - need to check for 1945 // extra tokens. 1946 if (Tok.is(tok::annot_pragma_openmp_end)) 1947 return; 1948 1949 Diag(Tok, diag::warn_omp_extra_tokens_at_eol) 1950 << getOpenMPDirectiveName(DKind); 1951 while (Tok.isNot(tok::annot_pragma_openmp_end)) 1952 ConsumeAnyToken(); 1953 } 1954 1955 void Parser::parseOMPEndDirective(OpenMPDirectiveKind BeginKind, 1956 OpenMPDirectiveKind ExpectedKind, 1957 OpenMPDirectiveKind FoundKind, 1958 SourceLocation BeginLoc, 1959 SourceLocation FoundLoc, 1960 bool SkipUntilOpenMPEnd) { 1961 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1; 1962 1963 if (FoundKind == ExpectedKind) { 1964 ConsumeAnyToken(); 1965 skipUntilPragmaOpenMPEnd(ExpectedKind); 1966 return; 1967 } 1968 1969 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant) 1970 << DiagSelection; 1971 Diag(BeginLoc, diag::note_matching) 1972 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str(); 1973 if (SkipUntilOpenMPEnd) 1974 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); 1975 } 1976 1977 void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind, 1978 OpenMPDirectiveKind EndDKind, 1979 SourceLocation DKLoc) { 1980 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc, 1981 Tok.getLocation(), 1982 /* SkipUntilOpenMPEnd */ false); 1983 // Skip the last annot_pragma_openmp_end. 1984 if (Tok.is(tok::annot_pragma_openmp_end)) 1985 ConsumeAnnotationToken(); 1986 } 1987 1988 /// Parsing of declarative OpenMP directives. 1989 /// 1990 /// threadprivate-directive: 1991 /// annot_pragma_openmp 'threadprivate' simple-variable-list 1992 /// annot_pragma_openmp_end 1993 /// 1994 /// allocate-directive: 1995 /// annot_pragma_openmp 'allocate' simple-variable-list [<clause>] 1996 /// annot_pragma_openmp_end 1997 /// 1998 /// declare-reduction-directive: 1999 /// annot_pragma_openmp 'declare' 'reduction' [...] 2000 /// annot_pragma_openmp_end 2001 /// 2002 /// declare-mapper-directive: 2003 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 2004 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 2005 /// annot_pragma_openmp_end 2006 /// 2007 /// declare-simd-directive: 2008 /// annot_pragma_openmp 'declare simd' {<clause> [,]} 2009 /// annot_pragma_openmp_end 2010 /// <function declaration/definition> 2011 /// 2012 /// requires directive: 2013 /// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ] 2014 /// annot_pragma_openmp_end 2015 /// 2016 /// assumes directive: 2017 /// annot_pragma_openmp 'assumes' <clause> [[[,] <clause>] ... ] 2018 /// annot_pragma_openmp_end 2019 /// or 2020 /// annot_pragma_openmp 'begin assumes' <clause> [[[,] <clause>] ... ] 2021 /// annot_pragma_openmp 'end assumes' 2022 /// annot_pragma_openmp_end 2023 /// 2024 Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( 2025 AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed, 2026 DeclSpec::TST TagType, Decl *Tag) { 2027 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && 2028 "Not an OpenMP directive!"); 2029 ParsingOpenMPDirectiveRAII DirScope(*this); 2030 ParenBraceBracketBalancer BalancerRAIIObj(*this); 2031 2032 SourceLocation Loc; 2033 OpenMPDirectiveKind DKind; 2034 if (Delayed) { 2035 TentativeParsingAction TPA(*this); 2036 Loc = ConsumeAnnotationToken(); 2037 DKind = parseOpenMPDirectiveKind(*this); 2038 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) { 2039 // Need to delay parsing until completion of the parent class. 2040 TPA.Revert(); 2041 CachedTokens Toks; 2042 unsigned Cnt = 1; 2043 Toks.push_back(Tok); 2044 while (Cnt && Tok.isNot(tok::eof)) { 2045 (void)ConsumeAnyToken(); 2046 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) 2047 ++Cnt; 2048 else if (Tok.is(tok::annot_pragma_openmp_end)) 2049 --Cnt; 2050 Toks.push_back(Tok); 2051 } 2052 // Skip last annot_pragma_openmp_end. 2053 if (Cnt == 0) 2054 (void)ConsumeAnyToken(); 2055 auto *LP = new LateParsedPragma(this, AS); 2056 LP->takeToks(Toks); 2057 getCurrentClass().LateParsedDeclarations.push_back(LP); 2058 return nullptr; 2059 } 2060 TPA.Commit(); 2061 } else { 2062 Loc = ConsumeAnnotationToken(); 2063 DKind = parseOpenMPDirectiveKind(*this); 2064 } 2065 2066 switch (DKind) { 2067 case OMPD_threadprivate: { 2068 ConsumeToken(); 2069 DeclDirectiveListParserHelper Helper(this, DKind); 2070 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2071 /*AllowScopeSpecifier=*/true)) { 2072 skipUntilPragmaOpenMPEnd(DKind); 2073 // Skip the last annot_pragma_openmp_end. 2074 ConsumeAnnotationToken(); 2075 return Actions.ActOnOpenMPThreadprivateDirective(Loc, 2076 Helper.getIdentifiers()); 2077 } 2078 break; 2079 } 2080 case OMPD_allocate: { 2081 ConsumeToken(); 2082 DeclDirectiveListParserHelper Helper(this, DKind); 2083 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2084 /*AllowScopeSpecifier=*/true)) { 2085 SmallVector<OMPClause *, 1> Clauses; 2086 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 2087 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2088 llvm::omp::Clause_enumSize + 1> 2089 FirstClauses(llvm::omp::Clause_enumSize + 1); 2090 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2091 OpenMPClauseKind CKind = 2092 Tok.isAnnotation() ? OMPC_unknown 2093 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2094 Actions.StartOpenMPClause(CKind); 2095 OMPClause *Clause = ParseOpenMPClause( 2096 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2097 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2098 StopBeforeMatch); 2099 FirstClauses[unsigned(CKind)].setInt(true); 2100 if (Clause != nullptr) 2101 Clauses.push_back(Clause); 2102 if (Tok.is(tok::annot_pragma_openmp_end)) { 2103 Actions.EndOpenMPClause(); 2104 break; 2105 } 2106 // Skip ',' if any. 2107 if (Tok.is(tok::comma)) 2108 ConsumeToken(); 2109 Actions.EndOpenMPClause(); 2110 } 2111 skipUntilPragmaOpenMPEnd(DKind); 2112 } 2113 // Skip the last annot_pragma_openmp_end. 2114 ConsumeAnnotationToken(); 2115 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(), 2116 Clauses); 2117 } 2118 break; 2119 } 2120 case OMPD_requires: { 2121 SourceLocation StartLoc = ConsumeToken(); 2122 SmallVector<OMPClause *, 5> Clauses; 2123 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2124 llvm::omp::Clause_enumSize + 1> 2125 FirstClauses(llvm::omp::Clause_enumSize + 1); 2126 if (Tok.is(tok::annot_pragma_openmp_end)) { 2127 Diag(Tok, diag::err_omp_expected_clause) 2128 << getOpenMPDirectiveName(OMPD_requires); 2129 break; 2130 } 2131 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2132 OpenMPClauseKind CKind = Tok.isAnnotation() 2133 ? OMPC_unknown 2134 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2135 Actions.StartOpenMPClause(CKind); 2136 OMPClause *Clause = ParseOpenMPClause( 2137 OMPD_requires, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2138 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2139 StopBeforeMatch); 2140 FirstClauses[unsigned(CKind)].setInt(true); 2141 if (Clause != nullptr) 2142 Clauses.push_back(Clause); 2143 if (Tok.is(tok::annot_pragma_openmp_end)) { 2144 Actions.EndOpenMPClause(); 2145 break; 2146 } 2147 // Skip ',' if any. 2148 if (Tok.is(tok::comma)) 2149 ConsumeToken(); 2150 Actions.EndOpenMPClause(); 2151 } 2152 // Consume final annot_pragma_openmp_end 2153 if (Clauses.empty()) { 2154 Diag(Tok, diag::err_omp_expected_clause) 2155 << getOpenMPDirectiveName(OMPD_requires); 2156 ConsumeAnnotationToken(); 2157 return nullptr; 2158 } 2159 ConsumeAnnotationToken(); 2160 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses); 2161 } 2162 case OMPD_assumes: 2163 case OMPD_begin_assumes: 2164 ParseOpenMPAssumesDirective(DKind, ConsumeToken()); 2165 break; 2166 case OMPD_end_assumes: 2167 ParseOpenMPEndAssumesDirective(ConsumeToken()); 2168 break; 2169 case OMPD_declare_reduction: 2170 ConsumeToken(); 2171 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { 2172 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 2173 // Skip the last annot_pragma_openmp_end. 2174 ConsumeAnnotationToken(); 2175 return Res; 2176 } 2177 break; 2178 case OMPD_declare_mapper: { 2179 ConsumeToken(); 2180 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) { 2181 // Skip the last annot_pragma_openmp_end. 2182 ConsumeAnnotationToken(); 2183 return Res; 2184 } 2185 break; 2186 } 2187 case OMPD_begin_declare_variant: { 2188 // The syntax is: 2189 // { #pragma omp begin declare variant clause } 2190 // <function-declaration-or-definition-sequence> 2191 // { #pragma omp end declare variant } 2192 // 2193 ConsumeToken(); 2194 OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope(); 2195 ASTContext &ASTCtx = Actions.getASTContext(); 2196 OMPTraitInfo &TI = ASTCtx.getNewOMPTraitInfo(); 2197 if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) { 2198 while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch)) 2199 ; 2200 // Skip the last annot_pragma_openmp_end. 2201 (void)ConsumeAnnotationToken(); 2202 break; 2203 } 2204 2205 // Skip last tokens. 2206 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant); 2207 2208 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 2209 2210 VariantMatchInfo VMI; 2211 TI.getAsVariantMatchInfo(ASTCtx, VMI); 2212 2213 std::function<void(StringRef)> DiagUnknownTrait = 2214 [this, Loc](StringRef ISATrait) { 2215 // TODO Track the selector locations in a way that is accessible here 2216 // to improve the diagnostic location. 2217 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait; 2218 }; 2219 TargetOMPContext OMPCtx( 2220 ASTCtx, std::move(DiagUnknownTrait), 2221 /* CurrentFunctionDecl */ nullptr, 2222 /* ConstructTraits */ ArrayRef<llvm::omp::TraitProperty>()); 2223 2224 if (isVariantApplicableInContext(VMI, OMPCtx, /* DeviceSetOnly */ true)) { 2225 Actions.ActOnOpenMPBeginDeclareVariant(Loc, TI); 2226 break; 2227 } 2228 2229 // Elide all the code till the matching end declare variant was found. 2230 unsigned Nesting = 1; 2231 SourceLocation DKLoc; 2232 OpenMPDirectiveKind DK = OMPD_unknown; 2233 do { 2234 DKLoc = Tok.getLocation(); 2235 DK = parseOpenMPDirectiveKind(*this); 2236 if (DK == OMPD_end_declare_variant) 2237 --Nesting; 2238 else if (DK == OMPD_begin_declare_variant) 2239 ++Nesting; 2240 if (!Nesting || isEofOrEom()) 2241 break; 2242 ConsumeAnyToken(); 2243 } while (true); 2244 2245 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, 2246 DK, Loc, DKLoc, /* SkipUntilOpenMPEnd */ true); 2247 if (isEofOrEom()) 2248 return nullptr; 2249 break; 2250 } 2251 case OMPD_end_declare_variant: { 2252 if (Actions.isInOpenMPDeclareVariantScope()) 2253 Actions.ActOnOpenMPEndDeclareVariant(); 2254 else 2255 Diag(Loc, diag::err_expected_begin_declare_variant); 2256 ConsumeToken(); 2257 break; 2258 } 2259 case OMPD_declare_variant: 2260 case OMPD_declare_simd: { 2261 // The syntax is: 2262 // { #pragma omp declare {simd|variant} } 2263 // <function-declaration-or-definition> 2264 // 2265 CachedTokens Toks; 2266 Toks.push_back(Tok); 2267 ConsumeToken(); 2268 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2269 Toks.push_back(Tok); 2270 ConsumeAnyToken(); 2271 } 2272 Toks.push_back(Tok); 2273 ConsumeAnyToken(); 2274 2275 DeclGroupPtrTy Ptr; 2276 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) { 2277 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed, 2278 TagType, Tag); 2279 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { 2280 // Here we expect to see some function declaration. 2281 if (AS == AS_none) { 2282 assert(TagType == DeclSpec::TST_unspecified); 2283 MaybeParseCXX11Attributes(Attrs); 2284 ParsingDeclSpec PDS(*this); 2285 Ptr = ParseExternalDeclaration(Attrs, &PDS); 2286 } else { 2287 Ptr = 2288 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); 2289 } 2290 } 2291 if (!Ptr) { 2292 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant) 2293 << (DKind == OMPD_declare_simd ? 0 : 1); 2294 return DeclGroupPtrTy(); 2295 } 2296 if (DKind == OMPD_declare_simd) 2297 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc); 2298 assert(DKind == OMPD_declare_variant && 2299 "Expected declare variant directive only"); 2300 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc); 2301 return Ptr; 2302 } 2303 case OMPD_begin_declare_target: 2304 case OMPD_declare_target: { 2305 SourceLocation DTLoc = ConsumeAnyToken(); 2306 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end); 2307 Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc); 2308 if (HasClauses) 2309 ParseOMPDeclareTargetClauses(DTCI); 2310 bool HasImplicitMappings = 2311 DKind == OMPD_begin_declare_target || !HasClauses || 2312 (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect.hasValue()); 2313 2314 // Skip the last annot_pragma_openmp_end. 2315 ConsumeAnyToken(); 2316 2317 if (HasImplicitMappings) { 2318 Actions.ActOnStartOpenMPDeclareTargetContext(DTCI); 2319 return nullptr; 2320 } 2321 2322 Actions.ActOnFinishedOpenMPDeclareTargetContext(DTCI); 2323 llvm::SmallVector<Decl *, 4> Decls; 2324 for (auto &It : DTCI.ExplicitlyMapped) 2325 Decls.push_back(It.first); 2326 return Actions.BuildDeclaratorGroup(Decls); 2327 } 2328 case OMPD_end_declare_target: { 2329 if (!Actions.isInOpenMPDeclareTargetContext()) { 2330 Diag(Tok, diag::err_omp_unexpected_directive) 2331 << 1 << getOpenMPDirectiveName(DKind); 2332 break; 2333 } 2334 const Sema::DeclareTargetContextInfo &DTCI = 2335 Actions.ActOnOpenMPEndDeclareTargetDirective(); 2336 ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc); 2337 return nullptr; 2338 } 2339 case OMPD_unknown: 2340 Diag(Tok, diag::err_omp_unknown_directive); 2341 break; 2342 case OMPD_parallel: 2343 case OMPD_simd: 2344 case OMPD_tile: 2345 case OMPD_unroll: 2346 case OMPD_task: 2347 case OMPD_taskyield: 2348 case OMPD_barrier: 2349 case OMPD_taskwait: 2350 case OMPD_taskgroup: 2351 case OMPD_flush: 2352 case OMPD_depobj: 2353 case OMPD_scan: 2354 case OMPD_for: 2355 case OMPD_for_simd: 2356 case OMPD_sections: 2357 case OMPD_section: 2358 case OMPD_single: 2359 case OMPD_master: 2360 case OMPD_ordered: 2361 case OMPD_critical: 2362 case OMPD_parallel_for: 2363 case OMPD_parallel_for_simd: 2364 case OMPD_parallel_sections: 2365 case OMPD_parallel_master: 2366 case OMPD_atomic: 2367 case OMPD_target: 2368 case OMPD_teams: 2369 case OMPD_cancellation_point: 2370 case OMPD_cancel: 2371 case OMPD_target_data: 2372 case OMPD_target_enter_data: 2373 case OMPD_target_exit_data: 2374 case OMPD_target_parallel: 2375 case OMPD_target_parallel_for: 2376 case OMPD_taskloop: 2377 case OMPD_taskloop_simd: 2378 case OMPD_master_taskloop: 2379 case OMPD_master_taskloop_simd: 2380 case OMPD_parallel_master_taskloop: 2381 case OMPD_parallel_master_taskloop_simd: 2382 case OMPD_distribute: 2383 case OMPD_target_update: 2384 case OMPD_distribute_parallel_for: 2385 case OMPD_distribute_parallel_for_simd: 2386 case OMPD_distribute_simd: 2387 case OMPD_target_parallel_for_simd: 2388 case OMPD_target_simd: 2389 case OMPD_teams_distribute: 2390 case OMPD_teams_distribute_simd: 2391 case OMPD_teams_distribute_parallel_for_simd: 2392 case OMPD_teams_distribute_parallel_for: 2393 case OMPD_target_teams: 2394 case OMPD_target_teams_distribute: 2395 case OMPD_target_teams_distribute_parallel_for: 2396 case OMPD_target_teams_distribute_parallel_for_simd: 2397 case OMPD_target_teams_distribute_simd: 2398 case OMPD_dispatch: 2399 case OMPD_masked: 2400 case OMPD_metadirective: 2401 case OMPD_loop: 2402 Diag(Tok, diag::err_omp_unexpected_directive) 2403 << 1 << getOpenMPDirectiveName(DKind); 2404 break; 2405 default: 2406 break; 2407 } 2408 while (Tok.isNot(tok::annot_pragma_openmp_end)) 2409 ConsumeAnyToken(); 2410 ConsumeAnyToken(); 2411 return nullptr; 2412 } 2413 2414 /// Parsing of declarative or executable OpenMP directives. 2415 /// 2416 /// threadprivate-directive: 2417 /// annot_pragma_openmp 'threadprivate' simple-variable-list 2418 /// annot_pragma_openmp_end 2419 /// 2420 /// allocate-directive: 2421 /// annot_pragma_openmp 'allocate' simple-variable-list 2422 /// annot_pragma_openmp_end 2423 /// 2424 /// declare-reduction-directive: 2425 /// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':' 2426 /// <type> {',' <type>} ':' <expression> ')' ['initializer' '(' 2427 /// ('omp_priv' '=' <expression>|<function_call>) ')'] 2428 /// annot_pragma_openmp_end 2429 /// 2430 /// declare-mapper-directive: 2431 /// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':'] 2432 /// <type> <var> ')' [<clause>[[,] <clause>] ... ] 2433 /// annot_pragma_openmp_end 2434 /// 2435 /// executable-directive: 2436 /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | 2437 /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | 2438 /// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' | 2439 /// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' | 2440 /// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target 2441 /// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 2442 /// 'master taskloop' | 'master taskloop simd' | 'parallel master 2443 /// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target 2444 /// enter data' | 'target exit data' | 'target parallel' | 'target 2445 /// parallel for' | 'target update' | 'distribute parallel for' | 2446 /// 'distribute paralle for simd' | 'distribute simd' | 'target parallel 2447 /// for simd' | 'target simd' | 'teams distribute' | 'teams distribute 2448 /// simd' | 'teams distribute parallel for simd' | 'teams distribute 2449 /// parallel for' | 'target teams' | 'target teams distribute' | 'target 2450 /// teams distribute parallel for' | 'target teams distribute parallel 2451 /// for simd' | 'target teams distribute simd' | 'masked' {clause} 2452 /// annot_pragma_openmp_end 2453 /// 2454 StmtResult 2455 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) { 2456 static bool ReadDirectiveWithinMetadirective = false; 2457 if (!ReadDirectiveWithinMetadirective) 2458 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) && 2459 "Not an OpenMP directive!"); 2460 ParsingOpenMPDirectiveRAII DirScope(*this); 2461 ParenBraceBracketBalancer BalancerRAIIObj(*this); 2462 SmallVector<OMPClause *, 5> Clauses; 2463 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2464 llvm::omp::Clause_enumSize + 1> 2465 FirstClauses(llvm::omp::Clause_enumSize + 1); 2466 unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | 2467 Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; 2468 SourceLocation Loc = ReadDirectiveWithinMetadirective 2469 ? Tok.getLocation() 2470 : ConsumeAnnotationToken(), 2471 EndLoc; 2472 OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); 2473 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) { 2474 Diag(Tok, diag::err_omp_unknown_directive); 2475 return StmtError(); 2476 } 2477 OpenMPDirectiveKind CancelRegion = OMPD_unknown; 2478 // Name of critical directive. 2479 DeclarationNameInfo DirName; 2480 StmtResult Directive = StmtError(); 2481 bool HasAssociatedStatement = true; 2482 2483 switch (DKind) { 2484 case OMPD_metadirective: { 2485 ConsumeToken(); 2486 SmallVector<VariantMatchInfo, 4> VMIs; 2487 2488 // First iteration of parsing all clauses of metadirective. 2489 // This iteration only parses and collects all context selector ignoring the 2490 // associated directives. 2491 TentativeParsingAction TPA(*this); 2492 ASTContext &ASTContext = Actions.getASTContext(); 2493 2494 BalancedDelimiterTracker T(*this, tok::l_paren, 2495 tok::annot_pragma_openmp_end); 2496 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2497 OpenMPClauseKind CKind = Tok.isAnnotation() 2498 ? OMPC_unknown 2499 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2500 SourceLocation Loc = ConsumeToken(); 2501 2502 // Parse '('. 2503 if (T.expectAndConsume(diag::err_expected_lparen_after, 2504 getOpenMPClauseName(CKind).data())) 2505 return Directive; 2506 2507 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); 2508 if (CKind == OMPC_when) { 2509 // parse and get OMPTraitInfo to pass to the When clause 2510 parseOMPContextSelectors(Loc, TI); 2511 if (TI.Sets.size() == 0) { 2512 Diag(Tok, diag::err_omp_expected_context_selector) << "when clause"; 2513 TPA.Commit(); 2514 return Directive; 2515 } 2516 2517 // Parse ':' 2518 if (Tok.is(tok::colon)) 2519 ConsumeAnyToken(); 2520 else { 2521 Diag(Tok, diag::err_omp_expected_colon) << "when clause"; 2522 TPA.Commit(); 2523 return Directive; 2524 } 2525 } 2526 // Skip Directive for now. We will parse directive in the second iteration 2527 int paren = 0; 2528 while (Tok.isNot(tok::r_paren) || paren != 0) { 2529 if (Tok.is(tok::l_paren)) 2530 paren++; 2531 if (Tok.is(tok::r_paren)) 2532 paren--; 2533 if (Tok.is(tok::annot_pragma_openmp_end)) { 2534 Diag(Tok, diag::err_omp_expected_punc) 2535 << getOpenMPClauseName(CKind) << 0; 2536 TPA.Commit(); 2537 return Directive; 2538 } 2539 ConsumeAnyToken(); 2540 } 2541 // Parse ')' 2542 if (Tok.is(tok::r_paren)) 2543 T.consumeClose(); 2544 2545 VariantMatchInfo VMI; 2546 TI.getAsVariantMatchInfo(ASTContext, VMI); 2547 2548 VMIs.push_back(VMI); 2549 } 2550 2551 TPA.Revert(); 2552 // End of the first iteration. Parser is reset to the start of metadirective 2553 2554 std::function<void(StringRef)> DiagUnknownTrait = 2555 [this, Loc](StringRef ISATrait) { 2556 // TODO Track the selector locations in a way that is accessible here 2557 // to improve the diagnostic location. 2558 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait; 2559 }; 2560 TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait), 2561 /* CurrentFunctionDecl */ nullptr, 2562 ArrayRef<llvm::omp::TraitProperty>()); 2563 2564 // A single match is returned for OpenMP 5.0 2565 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx); 2566 2567 int Idx = 0; 2568 // In OpenMP 5.0 metadirective is either replaced by another directive or 2569 // ignored. 2570 // TODO: In OpenMP 5.1 generate multiple directives based upon the matches 2571 // found by getBestWhenMatchForContext. 2572 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2573 // OpenMP 5.0 implementation - Skip to the best index found. 2574 if (Idx++ != BestIdx) { 2575 ConsumeToken(); // Consume clause name 2576 T.consumeOpen(); // Consume '(' 2577 int paren = 0; 2578 // Skip everything inside the clause 2579 while (Tok.isNot(tok::r_paren) || paren != 0) { 2580 if (Tok.is(tok::l_paren)) 2581 paren++; 2582 if (Tok.is(tok::r_paren)) 2583 paren--; 2584 ConsumeAnyToken(); 2585 } 2586 // Parse ')' 2587 if (Tok.is(tok::r_paren)) 2588 T.consumeClose(); 2589 continue; 2590 } 2591 2592 OpenMPClauseKind CKind = Tok.isAnnotation() 2593 ? OMPC_unknown 2594 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2595 SourceLocation Loc = ConsumeToken(); 2596 2597 // Parse '('. 2598 T.consumeOpen(); 2599 2600 // Skip ContextSelectors for when clause 2601 if (CKind == OMPC_when) { 2602 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo(); 2603 // parse and skip the ContextSelectors 2604 parseOMPContextSelectors(Loc, TI); 2605 2606 // Parse ':' 2607 ConsumeAnyToken(); 2608 } 2609 2610 // If no directive is passed, skip in OpenMP 5.0. 2611 // TODO: Generate nothing directive from OpenMP 5.1. 2612 if (Tok.is(tok::r_paren)) { 2613 SkipUntil(tok::annot_pragma_openmp_end); 2614 break; 2615 } 2616 2617 // Parse Directive 2618 ReadDirectiveWithinMetadirective = true; 2619 Directive = ParseOpenMPDeclarativeOrExecutableDirective(StmtCtx); 2620 ReadDirectiveWithinMetadirective = false; 2621 break; 2622 } 2623 break; 2624 } 2625 case OMPD_threadprivate: { 2626 // FIXME: Should this be permitted in C++? 2627 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2628 ParsedStmtContext()) { 2629 Diag(Tok, diag::err_omp_immediate_directive) 2630 << getOpenMPDirectiveName(DKind) << 0; 2631 } 2632 ConsumeToken(); 2633 DeclDirectiveListParserHelper Helper(this, DKind); 2634 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2635 /*AllowScopeSpecifier=*/false)) { 2636 skipUntilPragmaOpenMPEnd(DKind); 2637 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective( 2638 Loc, Helper.getIdentifiers()); 2639 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2640 } 2641 SkipUntil(tok::annot_pragma_openmp_end); 2642 break; 2643 } 2644 case OMPD_allocate: { 2645 // FIXME: Should this be permitted in C++? 2646 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) == 2647 ParsedStmtContext()) { 2648 Diag(Tok, diag::err_omp_immediate_directive) 2649 << getOpenMPDirectiveName(DKind) << 0; 2650 } 2651 ConsumeToken(); 2652 DeclDirectiveListParserHelper Helper(this, DKind); 2653 if (!ParseOpenMPSimpleVarList(DKind, Helper, 2654 /*AllowScopeSpecifier=*/false)) { 2655 SmallVector<OMPClause *, 1> Clauses; 2656 if (Tok.isNot(tok::annot_pragma_openmp_end)) { 2657 SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, 2658 llvm::omp::Clause_enumSize + 1> 2659 FirstClauses(llvm::omp::Clause_enumSize + 1); 2660 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2661 OpenMPClauseKind CKind = 2662 Tok.isAnnotation() ? OMPC_unknown 2663 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2664 Actions.StartOpenMPClause(CKind); 2665 OMPClause *Clause = ParseOpenMPClause( 2666 OMPD_allocate, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2667 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end, 2668 StopBeforeMatch); 2669 FirstClauses[unsigned(CKind)].setInt(true); 2670 if (Clause != nullptr) 2671 Clauses.push_back(Clause); 2672 if (Tok.is(tok::annot_pragma_openmp_end)) { 2673 Actions.EndOpenMPClause(); 2674 break; 2675 } 2676 // Skip ',' if any. 2677 if (Tok.is(tok::comma)) 2678 ConsumeToken(); 2679 Actions.EndOpenMPClause(); 2680 } 2681 skipUntilPragmaOpenMPEnd(DKind); 2682 } 2683 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective( 2684 Loc, Helper.getIdentifiers(), Clauses); 2685 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2686 } 2687 SkipUntil(tok::annot_pragma_openmp_end); 2688 break; 2689 } 2690 case OMPD_declare_reduction: 2691 ConsumeToken(); 2692 if (DeclGroupPtrTy Res = 2693 ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { 2694 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction); 2695 ConsumeAnyToken(); 2696 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2697 } else { 2698 SkipUntil(tok::annot_pragma_openmp_end); 2699 } 2700 break; 2701 case OMPD_declare_mapper: { 2702 ConsumeToken(); 2703 if (DeclGroupPtrTy Res = 2704 ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) { 2705 // Skip the last annot_pragma_openmp_end. 2706 ConsumeAnnotationToken(); 2707 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); 2708 } else { 2709 SkipUntil(tok::annot_pragma_openmp_end); 2710 } 2711 break; 2712 } 2713 case OMPD_flush: 2714 case OMPD_depobj: 2715 case OMPD_scan: 2716 case OMPD_taskyield: 2717 case OMPD_barrier: 2718 case OMPD_taskwait: 2719 case OMPD_cancellation_point: 2720 case OMPD_cancel: 2721 case OMPD_target_enter_data: 2722 case OMPD_target_exit_data: 2723 case OMPD_target_update: 2724 case OMPD_interop: 2725 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2726 ParsedStmtContext()) { 2727 Diag(Tok, diag::err_omp_immediate_directive) 2728 << getOpenMPDirectiveName(DKind) << 0; 2729 } 2730 HasAssociatedStatement = false; 2731 // Fall through for further analysis. 2732 LLVM_FALLTHROUGH; 2733 case OMPD_parallel: 2734 case OMPD_simd: 2735 case OMPD_tile: 2736 case OMPD_unroll: 2737 case OMPD_for: 2738 case OMPD_for_simd: 2739 case OMPD_sections: 2740 case OMPD_single: 2741 case OMPD_section: 2742 case OMPD_master: 2743 case OMPD_critical: 2744 case OMPD_parallel_for: 2745 case OMPD_parallel_for_simd: 2746 case OMPD_parallel_sections: 2747 case OMPD_parallel_master: 2748 case OMPD_task: 2749 case OMPD_ordered: 2750 case OMPD_atomic: 2751 case OMPD_target: 2752 case OMPD_teams: 2753 case OMPD_taskgroup: 2754 case OMPD_target_data: 2755 case OMPD_target_parallel: 2756 case OMPD_target_parallel_for: 2757 case OMPD_loop: 2758 case OMPD_taskloop: 2759 case OMPD_taskloop_simd: 2760 case OMPD_master_taskloop: 2761 case OMPD_master_taskloop_simd: 2762 case OMPD_parallel_master_taskloop: 2763 case OMPD_parallel_master_taskloop_simd: 2764 case OMPD_distribute: 2765 case OMPD_distribute_parallel_for: 2766 case OMPD_distribute_parallel_for_simd: 2767 case OMPD_distribute_simd: 2768 case OMPD_target_parallel_for_simd: 2769 case OMPD_target_simd: 2770 case OMPD_teams_distribute: 2771 case OMPD_teams_distribute_simd: 2772 case OMPD_teams_distribute_parallel_for_simd: 2773 case OMPD_teams_distribute_parallel_for: 2774 case OMPD_target_teams: 2775 case OMPD_target_teams_distribute: 2776 case OMPD_target_teams_distribute_parallel_for: 2777 case OMPD_target_teams_distribute_parallel_for_simd: 2778 case OMPD_target_teams_distribute_simd: 2779 case OMPD_dispatch: 2780 case OMPD_masked: { 2781 // Special processing for flush and depobj clauses. 2782 Token ImplicitTok; 2783 bool ImplicitClauseAllowed = false; 2784 if (DKind == OMPD_flush || DKind == OMPD_depobj) { 2785 ImplicitTok = Tok; 2786 ImplicitClauseAllowed = true; 2787 } 2788 ConsumeToken(); 2789 // Parse directive name of the 'critical' directive if any. 2790 if (DKind == OMPD_critical) { 2791 BalancedDelimiterTracker T(*this, tok::l_paren, 2792 tok::annot_pragma_openmp_end); 2793 if (!T.consumeOpen()) { 2794 if (Tok.isAnyIdentifier()) { 2795 DirName = 2796 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation()); 2797 ConsumeAnyToken(); 2798 } else { 2799 Diag(Tok, diag::err_omp_expected_identifier_for_critical); 2800 } 2801 T.consumeClose(); 2802 } 2803 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { 2804 CancelRegion = parseOpenMPDirectiveKind(*this); 2805 if (Tok.isNot(tok::annot_pragma_openmp_end)) 2806 ConsumeToken(); 2807 } 2808 2809 if (isOpenMPLoopDirective(DKind)) 2810 ScopeFlags |= Scope::OpenMPLoopDirectiveScope; 2811 if (isOpenMPSimdDirective(DKind)) 2812 ScopeFlags |= Scope::OpenMPSimdDirectiveScope; 2813 ParseScope OMPDirectiveScope(this, ScopeFlags); 2814 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc); 2815 2816 while (Tok.isNot(tok::annot_pragma_openmp_end)) { 2817 // If we are parsing for a directive within a metadirective, the directive 2818 // ends with a ')'. 2819 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) { 2820 while (Tok.isNot(tok::annot_pragma_openmp_end)) 2821 ConsumeAnyToken(); 2822 break; 2823 } 2824 bool HasImplicitClause = false; 2825 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) { 2826 HasImplicitClause = true; 2827 // Push copy of the current token back to stream to properly parse 2828 // pseudo-clause OMPFlushClause or OMPDepobjClause. 2829 PP.EnterToken(Tok, /*IsReinject*/ true); 2830 PP.EnterToken(ImplicitTok, /*IsReinject*/ true); 2831 ConsumeAnyToken(); 2832 } 2833 OpenMPClauseKind CKind = Tok.isAnnotation() 2834 ? OMPC_unknown 2835 : getOpenMPClauseKind(PP.getSpelling(Tok)); 2836 if (HasImplicitClause) { 2837 assert(CKind == OMPC_unknown && "Must be unknown implicit clause."); 2838 if (DKind == OMPD_flush) { 2839 CKind = OMPC_flush; 2840 } else { 2841 assert(DKind == OMPD_depobj && 2842 "Expected flush or depobj directives."); 2843 CKind = OMPC_depobj; 2844 } 2845 } 2846 // No more implicit clauses allowed. 2847 ImplicitClauseAllowed = false; 2848 Actions.StartOpenMPClause(CKind); 2849 HasImplicitClause = false; 2850 OMPClause *Clause = ParseOpenMPClause( 2851 DKind, CKind, !FirstClauses[unsigned(CKind)].getInt()); 2852 FirstClauses[unsigned(CKind)].setInt(true); 2853 if (Clause) { 2854 FirstClauses[unsigned(CKind)].setPointer(Clause); 2855 Clauses.push_back(Clause); 2856 } 2857 2858 // Skip ',' if any. 2859 if (Tok.is(tok::comma)) 2860 ConsumeToken(); 2861 Actions.EndOpenMPClause(); 2862 } 2863 // End location of the directive. 2864 EndLoc = Tok.getLocation(); 2865 // Consume final annot_pragma_openmp_end. 2866 ConsumeAnnotationToken(); 2867 2868 // OpenMP [2.13.8, ordered Construct, Syntax] 2869 // If the depend clause is specified, the ordered construct is a stand-alone 2870 // directive. 2871 if (DKind == OMPD_ordered && FirstClauses[unsigned(OMPC_depend)].getInt()) { 2872 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) == 2873 ParsedStmtContext()) { 2874 Diag(Loc, diag::err_omp_immediate_directive) 2875 << getOpenMPDirectiveName(DKind) << 1 2876 << getOpenMPClauseName(OMPC_depend); 2877 } 2878 HasAssociatedStatement = false; 2879 } 2880 2881 if (DKind == OMPD_tile && !FirstClauses[unsigned(OMPC_sizes)].getInt()) { 2882 Diag(Loc, diag::err_omp_required_clause) 2883 << getOpenMPDirectiveName(OMPD_tile) << "sizes"; 2884 } 2885 2886 StmtResult AssociatedStmt; 2887 if (HasAssociatedStatement) { 2888 // The body is a block scope like in Lambdas and Blocks. 2889 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2890 // FIXME: We create a bogus CompoundStmt scope to hold the contents of 2891 // the captured region. Code elsewhere assumes that any FunctionScopeInfo 2892 // should have at least one compound statement scope within it. 2893 ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false); 2894 { 2895 Sema::CompoundScopeRAII Scope(Actions); 2896 AssociatedStmt = ParseStatement(); 2897 2898 if (AssociatedStmt.isUsable() && isOpenMPLoopDirective(DKind) && 2899 getLangOpts().OpenMPIRBuilder) 2900 AssociatedStmt = Actions.ActOnOpenMPLoopnest(AssociatedStmt.get()); 2901 } 2902 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2903 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || 2904 DKind == OMPD_target_exit_data) { 2905 Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); 2906 AssociatedStmt = (Sema::CompoundScopeRAII(Actions), 2907 Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, 2908 /*isStmtExpr=*/false)); 2909 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); 2910 } 2911 Directive = Actions.ActOnOpenMPExecutableDirective( 2912 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, 2913 EndLoc); 2914 2915 // Exit scope. 2916 Actions.EndOpenMPDSABlock(Directive.get()); 2917 OMPDirectiveScope.Exit(); 2918 break; 2919 } 2920 case OMPD_declare_simd: 2921 case OMPD_declare_target: 2922 case OMPD_begin_declare_target: 2923 case OMPD_end_declare_target: 2924 case OMPD_requires: 2925 case OMPD_begin_declare_variant: 2926 case OMPD_end_declare_variant: 2927 case OMPD_declare_variant: 2928 Diag(Tok, diag::err_omp_unexpected_directive) 2929 << 1 << getOpenMPDirectiveName(DKind); 2930 SkipUntil(tok::annot_pragma_openmp_end); 2931 break; 2932 case OMPD_unknown: 2933 default: 2934 Diag(Tok, diag::err_omp_unknown_directive); 2935 SkipUntil(tok::annot_pragma_openmp_end); 2936 break; 2937 } 2938 return Directive; 2939 } 2940 2941 // Parses simple list: 2942 // simple-variable-list: 2943 // '(' id-expression {, id-expression} ')' 2944 // 2945 bool Parser::ParseOpenMPSimpleVarList( 2946 OpenMPDirectiveKind Kind, 2947 const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> 2948 &Callback, 2949 bool AllowScopeSpecifier) { 2950 // Parse '('. 2951 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 2952 if (T.expectAndConsume(diag::err_expected_lparen_after, 2953 getOpenMPDirectiveName(Kind).data())) 2954 return true; 2955 bool IsCorrect = true; 2956 bool NoIdentIsFound = true; 2957 2958 // Read tokens while ')' or annot_pragma_openmp_end is not found. 2959 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 2960 CXXScopeSpec SS; 2961 UnqualifiedId Name; 2962 // Read var name. 2963 Token PrevTok = Tok; 2964 NoIdentIsFound = false; 2965 2966 if (AllowScopeSpecifier && getLangOpts().CPlusPlus && 2967 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, 2968 /*ObjectHasErrors=*/false, false)) { 2969 IsCorrect = false; 2970 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2971 StopBeforeMatch); 2972 } else if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr, 2973 /*ObjectHadErrors=*/false, false, false, 2974 false, false, nullptr, Name)) { 2975 IsCorrect = false; 2976 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2977 StopBeforeMatch); 2978 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) && 2979 Tok.isNot(tok::annot_pragma_openmp_end)) { 2980 IsCorrect = false; 2981 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 2982 StopBeforeMatch); 2983 Diag(PrevTok.getLocation(), diag::err_expected) 2984 << tok::identifier 2985 << SourceRange(PrevTok.getLocation(), PrevTokLocation); 2986 } else { 2987 Callback(SS, Actions.GetNameFromUnqualifiedId(Name)); 2988 } 2989 // Consume ','. 2990 if (Tok.is(tok::comma)) { 2991 ConsumeToken(); 2992 } 2993 } 2994 2995 if (NoIdentIsFound) { 2996 Diag(Tok, diag::err_expected) << tok::identifier; 2997 IsCorrect = false; 2998 } 2999 3000 // Parse ')'. 3001 IsCorrect = !T.consumeClose() && IsCorrect; 3002 3003 return !IsCorrect; 3004 } 3005 3006 OMPClause *Parser::ParseOpenMPSizesClause() { 3007 SourceLocation ClauseNameLoc = ConsumeToken(); 3008 SmallVector<Expr *, 4> ValExprs; 3009 3010 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3011 if (T.consumeOpen()) { 3012 Diag(Tok, diag::err_expected) << tok::l_paren; 3013 return nullptr; 3014 } 3015 3016 while (true) { 3017 ExprResult Val = ParseConstantExpression(); 3018 if (!Val.isUsable()) { 3019 T.skipToEnd(); 3020 return nullptr; 3021 } 3022 3023 ValExprs.push_back(Val.get()); 3024 3025 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end)) 3026 break; 3027 3028 ExpectAndConsume(tok::comma); 3029 } 3030 3031 T.consumeClose(); 3032 3033 return Actions.ActOnOpenMPSizesClause( 3034 ValExprs, ClauseNameLoc, T.getOpenLocation(), T.getCloseLocation()); 3035 } 3036 3037 OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) { 3038 SourceLocation Loc = Tok.getLocation(); 3039 ConsumeAnyToken(); 3040 3041 // Parse '('. 3042 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3043 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator")) 3044 return nullptr; 3045 SmallVector<Sema::UsesAllocatorsData, 4> Data; 3046 do { 3047 ExprResult Allocator = 3048 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression(); 3049 if (Allocator.isInvalid()) { 3050 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3051 StopBeforeMatch); 3052 break; 3053 } 3054 Sema::UsesAllocatorsData &D = Data.emplace_back(); 3055 D.Allocator = Allocator.get(); 3056 if (Tok.is(tok::l_paren)) { 3057 BalancedDelimiterTracker T(*this, tok::l_paren, 3058 tok::annot_pragma_openmp_end); 3059 T.consumeOpen(); 3060 ExprResult AllocatorTraits = 3061 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression(); 3062 T.consumeClose(); 3063 if (AllocatorTraits.isInvalid()) { 3064 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3065 StopBeforeMatch); 3066 break; 3067 } 3068 D.AllocatorTraits = AllocatorTraits.get(); 3069 D.LParenLoc = T.getOpenLocation(); 3070 D.RParenLoc = T.getCloseLocation(); 3071 } 3072 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 3073 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0; 3074 // Parse ',' 3075 if (Tok.is(tok::comma)) 3076 ConsumeAnyToken(); 3077 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)); 3078 T.consumeClose(); 3079 return Actions.ActOnOpenMPUsesAllocatorClause(Loc, T.getOpenLocation(), 3080 T.getCloseLocation(), Data); 3081 } 3082 3083 /// Parsing of OpenMP clauses. 3084 /// 3085 /// clause: 3086 /// if-clause | final-clause | num_threads-clause | safelen-clause | 3087 /// default-clause | private-clause | firstprivate-clause | shared-clause 3088 /// | linear-clause | aligned-clause | collapse-clause | bind-clause | 3089 /// lastprivate-clause | reduction-clause | proc_bind-clause | 3090 /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | 3091 /// mergeable-clause | flush-clause | read-clause | write-clause | 3092 /// update-clause | capture-clause | seq_cst-clause | device-clause | 3093 /// simdlen-clause | threads-clause | simd-clause | num_teams-clause | 3094 /// thread_limit-clause | priority-clause | grainsize-clause | 3095 /// nogroup-clause | num_tasks-clause | hint-clause | to-clause | 3096 /// from-clause | is_device_ptr-clause | task_reduction-clause | 3097 /// in_reduction-clause | allocator-clause | allocate-clause | 3098 /// acq_rel-clause | acquire-clause | release-clause | relaxed-clause | 3099 /// depobj-clause | destroy-clause | detach-clause | inclusive-clause | 3100 /// exclusive-clause | uses_allocators-clause | use_device_addr-clause 3101 /// 3102 OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, 3103 OpenMPClauseKind CKind, bool FirstClause) { 3104 OMPClauseKind = CKind; 3105 OMPClause *Clause = nullptr; 3106 bool ErrorFound = false; 3107 bool WrongDirective = false; 3108 // Check if clause is allowed for the given directive. 3109 if (CKind != OMPC_unknown && 3110 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) { 3111 Diag(Tok, diag::err_omp_unexpected_clause) 3112 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 3113 ErrorFound = true; 3114 WrongDirective = true; 3115 } 3116 3117 switch (CKind) { 3118 case OMPC_final: 3119 case OMPC_num_threads: 3120 case OMPC_safelen: 3121 case OMPC_simdlen: 3122 case OMPC_collapse: 3123 case OMPC_ordered: 3124 case OMPC_num_teams: 3125 case OMPC_thread_limit: 3126 case OMPC_priority: 3127 case OMPC_grainsize: 3128 case OMPC_num_tasks: 3129 case OMPC_hint: 3130 case OMPC_allocator: 3131 case OMPC_depobj: 3132 case OMPC_detach: 3133 case OMPC_novariants: 3134 case OMPC_nocontext: 3135 case OMPC_filter: 3136 case OMPC_partial: 3137 case OMPC_align: 3138 // OpenMP [2.5, Restrictions] 3139 // At most one num_threads clause can appear on the directive. 3140 // OpenMP [2.8.1, simd construct, Restrictions] 3141 // Only one safelen clause can appear on a simd directive. 3142 // Only one simdlen clause can appear on a simd directive. 3143 // Only one collapse clause can appear on a simd directive. 3144 // OpenMP [2.11.1, task Construct, Restrictions] 3145 // At most one if clause can appear on the directive. 3146 // At most one final clause can appear on the directive. 3147 // OpenMP [teams Construct, Restrictions] 3148 // At most one num_teams clause can appear on the directive. 3149 // At most one thread_limit clause can appear on the directive. 3150 // OpenMP [2.9.1, task Construct, Restrictions] 3151 // At most one priority clause can appear on the directive. 3152 // OpenMP [2.9.2, taskloop Construct, Restrictions] 3153 // At most one grainsize clause can appear on the directive. 3154 // OpenMP [2.9.2, taskloop Construct, Restrictions] 3155 // At most one num_tasks clause can appear on the directive. 3156 // OpenMP [2.11.3, allocate Directive, Restrictions] 3157 // At most one allocator clause can appear on the directive. 3158 // OpenMP 5.0, 2.10.1 task Construct, Restrictions. 3159 // At most one detach clause can appear on the directive. 3160 // OpenMP 5.1, 2.3.6 dispatch Construct, Restrictions. 3161 // At most one novariants clause can appear on a dispatch directive. 3162 // At most one nocontext clause can appear on a dispatch directive. 3163 if (!FirstClause) { 3164 Diag(Tok, diag::err_omp_more_one_clause) 3165 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3166 ErrorFound = true; 3167 } 3168 3169 if ((CKind == OMPC_ordered || CKind == OMPC_partial) && 3170 PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) 3171 Clause = ParseOpenMPClause(CKind, WrongDirective); 3172 else 3173 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); 3174 break; 3175 case OMPC_default: 3176 case OMPC_proc_bind: 3177 case OMPC_atomic_default_mem_order: 3178 case OMPC_order: 3179 case OMPC_bind: 3180 // OpenMP [2.14.3.1, Restrictions] 3181 // Only a single default clause may be specified on a parallel, task or 3182 // teams directive. 3183 // OpenMP [2.5, parallel Construct, Restrictions] 3184 // At most one proc_bind clause can appear on the directive. 3185 // OpenMP [5.0, Requires directive, Restrictions] 3186 // At most one atomic_default_mem_order clause can appear 3187 // on the directive 3188 // OpenMP 5.1, 2.11.7 loop Construct, Restrictions. 3189 // At most one bind clause can appear on a loop directive. 3190 if (!FirstClause && CKind != OMPC_order) { 3191 Diag(Tok, diag::err_omp_more_one_clause) 3192 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3193 ErrorFound = true; 3194 } 3195 3196 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); 3197 break; 3198 case OMPC_device: 3199 case OMPC_schedule: 3200 case OMPC_dist_schedule: 3201 case OMPC_defaultmap: 3202 // OpenMP [2.7.1, Restrictions, p. 3] 3203 // Only one schedule clause can appear on a loop directive. 3204 // OpenMP 4.5 [2.10.4, Restrictions, p. 106] 3205 // At most one defaultmap clause can appear on the directive. 3206 // OpenMP 5.0 [2.12.5, target construct, Restrictions] 3207 // At most one device clause can appear on the directive. 3208 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) && 3209 !FirstClause) { 3210 Diag(Tok, diag::err_omp_more_one_clause) 3211 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3212 ErrorFound = true; 3213 } 3214 LLVM_FALLTHROUGH; 3215 case OMPC_if: 3216 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective); 3217 break; 3218 case OMPC_nowait: 3219 case OMPC_untied: 3220 case OMPC_mergeable: 3221 case OMPC_read: 3222 case OMPC_write: 3223 case OMPC_capture: 3224 case OMPC_compare: 3225 case OMPC_seq_cst: 3226 case OMPC_acq_rel: 3227 case OMPC_acquire: 3228 case OMPC_release: 3229 case OMPC_relaxed: 3230 case OMPC_threads: 3231 case OMPC_simd: 3232 case OMPC_nogroup: 3233 case OMPC_unified_address: 3234 case OMPC_unified_shared_memory: 3235 case OMPC_reverse_offload: 3236 case OMPC_dynamic_allocators: 3237 case OMPC_full: 3238 // OpenMP [2.7.1, Restrictions, p. 9] 3239 // Only one ordered clause can appear on a loop directive. 3240 // OpenMP [2.7.1, Restrictions, C/C++, p. 4] 3241 // Only one nowait clause can appear on a for directive. 3242 // OpenMP [5.0, Requires directive, Restrictions] 3243 // Each of the requires clauses can appear at most once on the directive. 3244 if (!FirstClause) { 3245 Diag(Tok, diag::err_omp_more_one_clause) 3246 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3247 ErrorFound = true; 3248 } 3249 3250 Clause = ParseOpenMPClause(CKind, WrongDirective); 3251 break; 3252 case OMPC_update: 3253 if (!FirstClause) { 3254 Diag(Tok, diag::err_omp_more_one_clause) 3255 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3256 ErrorFound = true; 3257 } 3258 3259 Clause = (DKind == OMPD_depobj) 3260 ? ParseOpenMPSimpleClause(CKind, WrongDirective) 3261 : ParseOpenMPClause(CKind, WrongDirective); 3262 break; 3263 case OMPC_private: 3264 case OMPC_firstprivate: 3265 case OMPC_lastprivate: 3266 case OMPC_shared: 3267 case OMPC_reduction: 3268 case OMPC_task_reduction: 3269 case OMPC_in_reduction: 3270 case OMPC_linear: 3271 case OMPC_aligned: 3272 case OMPC_copyin: 3273 case OMPC_copyprivate: 3274 case OMPC_flush: 3275 case OMPC_depend: 3276 case OMPC_map: 3277 case OMPC_to: 3278 case OMPC_from: 3279 case OMPC_use_device_ptr: 3280 case OMPC_use_device_addr: 3281 case OMPC_is_device_ptr: 3282 case OMPC_allocate: 3283 case OMPC_nontemporal: 3284 case OMPC_inclusive: 3285 case OMPC_exclusive: 3286 case OMPC_affinity: 3287 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); 3288 break; 3289 case OMPC_sizes: 3290 if (!FirstClause) { 3291 Diag(Tok, diag::err_omp_more_one_clause) 3292 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3293 ErrorFound = true; 3294 } 3295 3296 Clause = ParseOpenMPSizesClause(); 3297 break; 3298 case OMPC_uses_allocators: 3299 Clause = ParseOpenMPUsesAllocatorClause(DKind); 3300 break; 3301 case OMPC_destroy: 3302 if (DKind != OMPD_interop) { 3303 if (!FirstClause) { 3304 Diag(Tok, diag::err_omp_more_one_clause) 3305 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; 3306 ErrorFound = true; 3307 } 3308 Clause = ParseOpenMPClause(CKind, WrongDirective); 3309 break; 3310 } 3311 LLVM_FALLTHROUGH; 3312 case OMPC_init: 3313 case OMPC_use: 3314 Clause = ParseOpenMPInteropClause(CKind, WrongDirective); 3315 break; 3316 case OMPC_device_type: 3317 case OMPC_unknown: 3318 skipUntilPragmaOpenMPEnd(DKind); 3319 break; 3320 case OMPC_threadprivate: 3321 case OMPC_uniform: 3322 case OMPC_match: 3323 if (!WrongDirective) 3324 Diag(Tok, diag::err_omp_unexpected_clause) 3325 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); 3326 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); 3327 break; 3328 default: 3329 break; 3330 } 3331 return ErrorFound ? nullptr : Clause; 3332 } 3333 3334 /// Parses simple expression in parens for single-expression clauses of OpenMP 3335 /// constructs. 3336 /// \param RLoc Returned location of right paren. 3337 ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, 3338 SourceLocation &RLoc, 3339 bool IsAddressOfOperand) { 3340 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3341 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data())) 3342 return ExprError(); 3343 3344 SourceLocation ELoc = Tok.getLocation(); 3345 ExprResult LHS( 3346 ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast)); 3347 ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3348 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 3349 3350 // Parse ')'. 3351 RLoc = Tok.getLocation(); 3352 if (!T.consumeClose()) 3353 RLoc = T.getCloseLocation(); 3354 3355 return Val; 3356 } 3357 3358 /// Parsing of OpenMP clauses with single expressions like 'final', 3359 /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', 3360 /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks', 'hint' or 3361 /// 'detach'. 3362 /// 3363 /// final-clause: 3364 /// 'final' '(' expression ')' 3365 /// 3366 /// num_threads-clause: 3367 /// 'num_threads' '(' expression ')' 3368 /// 3369 /// safelen-clause: 3370 /// 'safelen' '(' expression ')' 3371 /// 3372 /// simdlen-clause: 3373 /// 'simdlen' '(' expression ')' 3374 /// 3375 /// collapse-clause: 3376 /// 'collapse' '(' expression ')' 3377 /// 3378 /// priority-clause: 3379 /// 'priority' '(' expression ')' 3380 /// 3381 /// grainsize-clause: 3382 /// 'grainsize' '(' expression ')' 3383 /// 3384 /// num_tasks-clause: 3385 /// 'num_tasks' '(' expression ')' 3386 /// 3387 /// hint-clause: 3388 /// 'hint' '(' expression ')' 3389 /// 3390 /// allocator-clause: 3391 /// 'allocator' '(' expression ')' 3392 /// 3393 /// detach-clause: 3394 /// 'detach' '(' event-handler-expression ')' 3395 /// 3396 /// align-clause 3397 /// 'align' '(' positive-integer-constant ')' 3398 /// 3399 OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, 3400 bool ParseOnly) { 3401 SourceLocation Loc = ConsumeToken(); 3402 SourceLocation LLoc = Tok.getLocation(); 3403 SourceLocation RLoc; 3404 3405 ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc); 3406 3407 if (Val.isInvalid()) 3408 return nullptr; 3409 3410 if (ParseOnly) 3411 return nullptr; 3412 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); 3413 } 3414 3415 /// Parse indirect clause for '#pragma omp declare target' directive. 3416 /// 'indirect' '[' '(' invoked-by-fptr ')' ']' 3417 /// where invoked-by-fptr is a constant boolean expression that evaluates to 3418 /// true or false at compile time. 3419 bool Parser::ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI, 3420 bool ParseOnly) { 3421 SourceLocation Loc = ConsumeToken(); 3422 SourceLocation RLoc; 3423 3424 if (Tok.isNot(tok::l_paren)) { 3425 if (ParseOnly) 3426 return false; 3427 DTCI.Indirect = nullptr; 3428 return true; 3429 } 3430 3431 ExprResult Val = 3432 ParseOpenMPParensExpr(getOpenMPClauseName(OMPC_indirect), RLoc); 3433 if (Val.isInvalid()) 3434 return false; 3435 3436 if (ParseOnly) 3437 return false; 3438 3439 if (!Val.get()->isValueDependent() && !Val.get()->isTypeDependent() && 3440 !Val.get()->isInstantiationDependent() && 3441 !Val.get()->containsUnexpandedParameterPack()) { 3442 ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get()); 3443 if (Ret.isInvalid()) 3444 return false; 3445 llvm::APSInt Result; 3446 Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result, 3447 Sema::AllowFold); 3448 if (Ret.isInvalid()) 3449 return false; 3450 DTCI.Indirect = Val.get(); 3451 return true; 3452 } 3453 return false; 3454 } 3455 3456 /// Parsing of OpenMP clauses that use an interop-var. 3457 /// 3458 /// init-clause: 3459 /// init([interop-modifier, ]interop-type[[, interop-type] ... ]:interop-var) 3460 /// 3461 /// destroy-clause: 3462 /// destroy(interop-var) 3463 /// 3464 /// use-clause: 3465 /// use(interop-var) 3466 /// 3467 /// interop-modifier: 3468 /// prefer_type(preference-list) 3469 /// 3470 /// preference-list: 3471 /// foreign-runtime-id [, foreign-runtime-id]... 3472 /// 3473 /// foreign-runtime-id: 3474 /// <string-literal> | <constant-integral-expression> 3475 /// 3476 /// interop-type: 3477 /// target | targetsync 3478 /// 3479 OMPClause *Parser::ParseOpenMPInteropClause(OpenMPClauseKind Kind, 3480 bool ParseOnly) { 3481 SourceLocation Loc = ConsumeToken(); 3482 // Parse '('. 3483 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3484 if (T.expectAndConsume(diag::err_expected_lparen_after, 3485 getOpenMPClauseName(Kind).data())) 3486 return nullptr; 3487 3488 bool IsTarget = false; 3489 bool IsTargetSync = false; 3490 SmallVector<Expr *, 4> Prefs; 3491 3492 if (Kind == OMPC_init) { 3493 3494 // Parse optional interop-modifier. 3495 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "prefer_type") { 3496 ConsumeToken(); 3497 BalancedDelimiterTracker PT(*this, tok::l_paren, 3498 tok::annot_pragma_openmp_end); 3499 if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type")) 3500 return nullptr; 3501 3502 while (Tok.isNot(tok::r_paren)) { 3503 SourceLocation Loc = Tok.getLocation(); 3504 ExprResult LHS = ParseCastExpression(AnyCastExpr); 3505 ExprResult PTExpr = Actions.CorrectDelayedTyposInExpr( 3506 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 3507 PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc, 3508 /*DiscardedValue=*/false); 3509 if (PTExpr.isUsable()) 3510 Prefs.push_back(PTExpr.get()); 3511 else 3512 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3513 StopBeforeMatch); 3514 3515 if (Tok.is(tok::comma)) 3516 ConsumeToken(); 3517 } 3518 PT.consumeClose(); 3519 } 3520 3521 if (!Prefs.empty()) { 3522 if (Tok.is(tok::comma)) 3523 ConsumeToken(); 3524 else 3525 Diag(Tok, diag::err_omp_expected_punc_after_interop_mod); 3526 } 3527 3528 // Parse the interop-types. 3529 if (Optional<OMPDeclareVariantAttr::InteropType> IType = 3530 parseInteropTypeList(*this)) { 3531 IsTarget = IType != OMPDeclareVariantAttr::TargetSync; 3532 IsTargetSync = IType != OMPDeclareVariantAttr::Target; 3533 if (Tok.isNot(tok::colon)) 3534 Diag(Tok, diag::warn_pragma_expected_colon) << "interop types"; 3535 } 3536 if (Tok.is(tok::colon)) 3537 ConsumeToken(); 3538 } 3539 3540 // Parse the variable. 3541 SourceLocation VarLoc = Tok.getLocation(); 3542 ExprResult InteropVarExpr = 3543 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 3544 if (!InteropVarExpr.isUsable()) { 3545 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 3546 StopBeforeMatch); 3547 } 3548 3549 // Parse ')'. 3550 SourceLocation RLoc = Tok.getLocation(); 3551 if (!T.consumeClose()) 3552 RLoc = T.getCloseLocation(); 3553 3554 if (ParseOnly || !InteropVarExpr.isUsable() || 3555 (Kind == OMPC_init && !IsTarget && !IsTargetSync)) 3556 return nullptr; 3557 3558 if (Kind == OMPC_init) 3559 return Actions.ActOnOpenMPInitClause(InteropVarExpr.get(), Prefs, IsTarget, 3560 IsTargetSync, Loc, T.getOpenLocation(), 3561 VarLoc, RLoc); 3562 if (Kind == OMPC_use) 3563 return Actions.ActOnOpenMPUseClause(InteropVarExpr.get(), Loc, 3564 T.getOpenLocation(), VarLoc, RLoc); 3565 3566 if (Kind == OMPC_destroy) 3567 return Actions.ActOnOpenMPDestroyClause(InteropVarExpr.get(), Loc, 3568 T.getOpenLocation(), VarLoc, RLoc); 3569 3570 llvm_unreachable("Unexpected interop variable clause."); 3571 } 3572 3573 /// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. 3574 /// 3575 /// default-clause: 3576 /// 'default' '(' 'none' | 'shared' | 'firstprivate' ')' 3577 /// 3578 /// proc_bind-clause: 3579 /// 'proc_bind' '(' 'master' | 'close' | 'spread' ')' 3580 /// 3581 /// bind-clause: 3582 /// 'bind' '(' 'teams' | 'parallel' | 'thread' ')' 3583 /// 3584 /// update-clause: 3585 /// 'update' '(' 'in' | 'out' | 'inout' | 'mutexinoutset' ')' 3586 /// 3587 OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, 3588 bool ParseOnly) { 3589 llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind); 3590 if (!Val || ParseOnly) 3591 return nullptr; 3592 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default && 3593 static_cast<DefaultKind>(Val.getValue().Type) == 3594 OMP_DEFAULT_firstprivate) { 3595 Diag(Val.getValue().LOpen, diag::err_omp_invalid_dsa) 3596 << getOpenMPClauseName(OMPC_firstprivate) 3597 << getOpenMPClauseName(OMPC_default) << "5.1"; 3598 return nullptr; 3599 } 3600 return Actions.ActOnOpenMPSimpleClause( 3601 Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen, 3602 Val.getValue().Loc, Val.getValue().RLoc); 3603 } 3604 3605 /// Parsing of OpenMP clauses like 'ordered'. 3606 /// 3607 /// ordered-clause: 3608 /// 'ordered' 3609 /// 3610 /// nowait-clause: 3611 /// 'nowait' 3612 /// 3613 /// untied-clause: 3614 /// 'untied' 3615 /// 3616 /// mergeable-clause: 3617 /// 'mergeable' 3618 /// 3619 /// read-clause: 3620 /// 'read' 3621 /// 3622 /// threads-clause: 3623 /// 'threads' 3624 /// 3625 /// simd-clause: 3626 /// 'simd' 3627 /// 3628 /// nogroup-clause: 3629 /// 'nogroup' 3630 /// 3631 OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { 3632 SourceLocation Loc = Tok.getLocation(); 3633 ConsumeAnyToken(); 3634 3635 if (ParseOnly) 3636 return nullptr; 3637 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); 3638 } 3639 3640 /// Parsing of OpenMP clauses with single expressions and some additional 3641 /// argument like 'schedule' or 'dist_schedule'. 3642 /// 3643 /// schedule-clause: 3644 /// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] 3645 /// ')' 3646 /// 3647 /// if-clause: 3648 /// 'if' '(' [ directive-name-modifier ':' ] expression ')' 3649 /// 3650 /// defaultmap: 3651 /// 'defaultmap' '(' modifier [ ':' kind ] ')' 3652 /// 3653 /// device-clause: 3654 /// 'device' '(' [ device-modifier ':' ] expression ')' 3655 /// 3656 OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPDirectiveKind DKind, 3657 OpenMPClauseKind Kind, 3658 bool ParseOnly) { 3659 SourceLocation Loc = ConsumeToken(); 3660 SourceLocation DelimLoc; 3661 // Parse '('. 3662 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3663 if (T.expectAndConsume(diag::err_expected_lparen_after, 3664 getOpenMPClauseName(Kind).data())) 3665 return nullptr; 3666 3667 ExprResult Val; 3668 SmallVector<unsigned, 4> Arg; 3669 SmallVector<SourceLocation, 4> KLoc; 3670 if (Kind == OMPC_schedule) { 3671 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; 3672 Arg.resize(NumberOfElements); 3673 KLoc.resize(NumberOfElements); 3674 Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; 3675 Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; 3676 Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; 3677 unsigned KindModifier = getOpenMPSimpleClauseType( 3678 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3679 if (KindModifier > OMPC_SCHEDULE_unknown) { 3680 // Parse 'modifier' 3681 Arg[Modifier1] = KindModifier; 3682 KLoc[Modifier1] = Tok.getLocation(); 3683 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3684 Tok.isNot(tok::annot_pragma_openmp_end)) 3685 ConsumeAnyToken(); 3686 if (Tok.is(tok::comma)) { 3687 // Parse ',' 'modifier' 3688 ConsumeAnyToken(); 3689 KindModifier = getOpenMPSimpleClauseType( 3690 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3691 Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown 3692 ? KindModifier 3693 : (unsigned)OMPC_SCHEDULE_unknown; 3694 KLoc[Modifier2] = Tok.getLocation(); 3695 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3696 Tok.isNot(tok::annot_pragma_openmp_end)) 3697 ConsumeAnyToken(); 3698 } 3699 // Parse ':' 3700 if (Tok.is(tok::colon)) 3701 ConsumeAnyToken(); 3702 else 3703 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; 3704 KindModifier = getOpenMPSimpleClauseType( 3705 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3706 } 3707 Arg[ScheduleKind] = KindModifier; 3708 KLoc[ScheduleKind] = Tok.getLocation(); 3709 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3710 Tok.isNot(tok::annot_pragma_openmp_end)) 3711 ConsumeAnyToken(); 3712 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || 3713 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || 3714 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && 3715 Tok.is(tok::comma)) 3716 DelimLoc = ConsumeAnyToken(); 3717 } else if (Kind == OMPC_dist_schedule) { 3718 Arg.push_back(getOpenMPSimpleClauseType( 3719 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); 3720 KLoc.push_back(Tok.getLocation()); 3721 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3722 Tok.isNot(tok::annot_pragma_openmp_end)) 3723 ConsumeAnyToken(); 3724 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma)) 3725 DelimLoc = ConsumeAnyToken(); 3726 } else if (Kind == OMPC_defaultmap) { 3727 // Get a defaultmap modifier 3728 unsigned Modifier = getOpenMPSimpleClauseType( 3729 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()); 3730 // Set defaultmap modifier to unknown if it is either scalar, aggregate, or 3731 // pointer 3732 if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown) 3733 Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; 3734 Arg.push_back(Modifier); 3735 KLoc.push_back(Tok.getLocation()); 3736 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3737 Tok.isNot(tok::annot_pragma_openmp_end)) 3738 ConsumeAnyToken(); 3739 // Parse ':' 3740 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) { 3741 if (Tok.is(tok::colon)) 3742 ConsumeAnyToken(); 3743 else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown) 3744 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier"; 3745 // Get a defaultmap kind 3746 Arg.push_back(getOpenMPSimpleClauseType( 3747 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); 3748 KLoc.push_back(Tok.getLocation()); 3749 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && 3750 Tok.isNot(tok::annot_pragma_openmp_end)) 3751 ConsumeAnyToken(); 3752 } else { 3753 Arg.push_back(OMPC_DEFAULTMAP_unknown); 3754 KLoc.push_back(SourceLocation()); 3755 } 3756 } else if (Kind == OMPC_device) { 3757 // Only target executable directives support extended device construct. 3758 if (isOpenMPTargetExecutionDirective(DKind) && getLangOpts().OpenMP >= 50 && 3759 NextToken().is(tok::colon)) { 3760 // Parse optional <device modifier> ':' 3761 Arg.push_back(getOpenMPSimpleClauseType( 3762 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts())); 3763 KLoc.push_back(Tok.getLocation()); 3764 ConsumeAnyToken(); 3765 // Parse ':' 3766 ConsumeAnyToken(); 3767 } else { 3768 Arg.push_back(OMPC_DEVICE_unknown); 3769 KLoc.emplace_back(); 3770 } 3771 } else { 3772 assert(Kind == OMPC_if); 3773 KLoc.push_back(Tok.getLocation()); 3774 TentativeParsingAction TPA(*this); 3775 auto DK = parseOpenMPDirectiveKind(*this); 3776 Arg.push_back(DK); 3777 if (DK != OMPD_unknown) { 3778 ConsumeToken(); 3779 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { 3780 TPA.Commit(); 3781 DelimLoc = ConsumeToken(); 3782 } else { 3783 TPA.Revert(); 3784 Arg.back() = unsigned(OMPD_unknown); 3785 } 3786 } else { 3787 TPA.Revert(); 3788 } 3789 } 3790 3791 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || 3792 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || 3793 Kind == OMPC_if || Kind == OMPC_device; 3794 if (NeedAnExpression) { 3795 SourceLocation ELoc = Tok.getLocation(); 3796 ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast)); 3797 Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); 3798 Val = 3799 Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false); 3800 } 3801 3802 // Parse ')'. 3803 SourceLocation RLoc = Tok.getLocation(); 3804 if (!T.consumeClose()) 3805 RLoc = T.getCloseLocation(); 3806 3807 if (NeedAnExpression && Val.isInvalid()) 3808 return nullptr; 3809 3810 if (ParseOnly) 3811 return nullptr; 3812 return Actions.ActOnOpenMPSingleExprWithArgClause( 3813 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); 3814 } 3815 3816 static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, 3817 UnqualifiedId &ReductionId) { 3818 if (ReductionIdScopeSpec.isEmpty()) { 3819 auto OOK = OO_None; 3820 switch (P.getCurToken().getKind()) { 3821 case tok::plus: 3822 OOK = OO_Plus; 3823 break; 3824 case tok::minus: 3825 OOK = OO_Minus; 3826 break; 3827 case tok::star: 3828 OOK = OO_Star; 3829 break; 3830 case tok::amp: 3831 OOK = OO_Amp; 3832 break; 3833 case tok::pipe: 3834 OOK = OO_Pipe; 3835 break; 3836 case tok::caret: 3837 OOK = OO_Caret; 3838 break; 3839 case tok::ampamp: 3840 OOK = OO_AmpAmp; 3841 break; 3842 case tok::pipepipe: 3843 OOK = OO_PipePipe; 3844 break; 3845 default: 3846 break; 3847 } 3848 if (OOK != OO_None) { 3849 SourceLocation OpLoc = P.ConsumeToken(); 3850 SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()}; 3851 ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations); 3852 return false; 3853 } 3854 } 3855 return P.ParseUnqualifiedId( 3856 ReductionIdScopeSpec, /*ObjectType=*/nullptr, 3857 /*ObjectHadErrors=*/false, /*EnteringContext*/ false, 3858 /*AllowDestructorName*/ false, 3859 /*AllowConstructorName*/ false, 3860 /*AllowDeductionGuide*/ false, nullptr, ReductionId); 3861 } 3862 3863 /// Checks if the token is a valid map-type-modifier. 3864 /// FIXME: It will return an OpenMPMapClauseKind if that's what it parses. 3865 static OpenMPMapModifierKind isMapModifier(Parser &P) { 3866 Token Tok = P.getCurToken(); 3867 if (!Tok.is(tok::identifier)) 3868 return OMPC_MAP_MODIFIER_unknown; 3869 3870 Preprocessor &PP = P.getPreprocessor(); 3871 OpenMPMapModifierKind TypeModifier = 3872 static_cast<OpenMPMapModifierKind>(getOpenMPSimpleClauseType( 3873 OMPC_map, PP.getSpelling(Tok), P.getLangOpts())); 3874 return TypeModifier; 3875 } 3876 3877 /// Parse the mapper modifier in map, to, and from clauses. 3878 bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) { 3879 // Parse '('. 3880 BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon); 3881 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) { 3882 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3883 StopBeforeMatch); 3884 return true; 3885 } 3886 // Parse mapper-identifier 3887 if (getLangOpts().CPlusPlus) 3888 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 3889 /*ObjectType=*/nullptr, 3890 /*ObjectHasErrors=*/false, 3891 /*EnteringContext=*/false); 3892 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) { 3893 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier); 3894 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 3895 StopBeforeMatch); 3896 return true; 3897 } 3898 auto &DeclNames = Actions.getASTContext().DeclarationNames; 3899 Data.ReductionOrMapperId = DeclarationNameInfo( 3900 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation()); 3901 ConsumeToken(); 3902 // Parse ')'. 3903 return T.consumeClose(); 3904 } 3905 3906 /// Parse map-type-modifiers in map clause. 3907 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 3908 /// where, map-type-modifier ::= always | close | mapper(mapper-identifier) | 3909 /// present 3910 bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) { 3911 while (getCurToken().isNot(tok::colon)) { 3912 OpenMPMapModifierKind TypeModifier = isMapModifier(*this); 3913 if (TypeModifier == OMPC_MAP_MODIFIER_always || 3914 TypeModifier == OMPC_MAP_MODIFIER_close || 3915 TypeModifier == OMPC_MAP_MODIFIER_present || 3916 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) { 3917 Data.MapTypeModifiers.push_back(TypeModifier); 3918 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 3919 ConsumeToken(); 3920 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) { 3921 Data.MapTypeModifiers.push_back(TypeModifier); 3922 Data.MapTypeModifiersLoc.push_back(Tok.getLocation()); 3923 ConsumeToken(); 3924 if (parseMapperModifier(Data)) 3925 return true; 3926 } else { 3927 // For the case of unknown map-type-modifier or a map-type. 3928 // Map-type is followed by a colon; the function returns when it 3929 // encounters a token followed by a colon. 3930 if (Tok.is(tok::comma)) { 3931 Diag(Tok, diag::err_omp_map_type_modifier_missing); 3932 ConsumeToken(); 3933 continue; 3934 } 3935 // Potential map-type token as it is followed by a colon. 3936 if (PP.LookAhead(0).is(tok::colon)) 3937 return false; 3938 Diag(Tok, diag::err_omp_unknown_map_type_modifier) 3939 << (getLangOpts().OpenMP >= 51 ? 1 : 0) 3940 << getLangOpts().OpenMPExtensions; 3941 ConsumeToken(); 3942 } 3943 if (getCurToken().is(tok::comma)) 3944 ConsumeToken(); 3945 } 3946 return false; 3947 } 3948 3949 /// Checks if the token is a valid map-type. 3950 /// FIXME: It will return an OpenMPMapModifierKind if that's what it parses. 3951 static OpenMPMapClauseKind isMapType(Parser &P) { 3952 Token Tok = P.getCurToken(); 3953 // The map-type token can be either an identifier or the C++ delete keyword. 3954 if (!Tok.isOneOf(tok::identifier, tok::kw_delete)) 3955 return OMPC_MAP_unknown; 3956 Preprocessor &PP = P.getPreprocessor(); 3957 OpenMPMapClauseKind MapType = 3958 static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( 3959 OMPC_map, PP.getSpelling(Tok), P.getLangOpts())); 3960 return MapType; 3961 } 3962 3963 /// Parse map-type in map clause. 3964 /// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list) 3965 /// where, map-type ::= to | from | tofrom | alloc | release | delete 3966 static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) { 3967 Token Tok = P.getCurToken(); 3968 if (Tok.is(tok::colon)) { 3969 P.Diag(Tok, diag::err_omp_map_type_missing); 3970 return; 3971 } 3972 Data.ExtraModifier = isMapType(P); 3973 if (Data.ExtraModifier == OMPC_MAP_unknown) 3974 P.Diag(Tok, diag::err_omp_unknown_map_type); 3975 P.ConsumeToken(); 3976 } 3977 3978 /// Parses simple expression in parens for single-expression clauses of OpenMP 3979 /// constructs. 3980 ExprResult Parser::ParseOpenMPIteratorsExpr() { 3981 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" && 3982 "Expected 'iterator' token."); 3983 SourceLocation IteratorKwLoc = ConsumeToken(); 3984 3985 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 3986 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator")) 3987 return ExprError(); 3988 3989 SourceLocation LLoc = T.getOpenLocation(); 3990 SmallVector<Sema::OMPIteratorData, 4> Data; 3991 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { 3992 // Check if the type parsing is required. 3993 ParsedType IteratorType; 3994 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) { 3995 // identifier '=' is not found - parse type. 3996 TypeResult TR = ParseTypeName(); 3997 if (TR.isInvalid()) { 3998 T.skipToEnd(); 3999 return ExprError(); 4000 } 4001 IteratorType = TR.get(); 4002 } 4003 4004 // Parse identifier. 4005 IdentifierInfo *II = nullptr; 4006 SourceLocation IdLoc; 4007 if (Tok.is(tok::identifier)) { 4008 II = Tok.getIdentifierInfo(); 4009 IdLoc = ConsumeToken(); 4010 } else { 4011 Diag(Tok, diag::err_expected_unqualified_id) << 0; 4012 } 4013 4014 // Parse '='. 4015 SourceLocation AssignLoc; 4016 if (Tok.is(tok::equal)) 4017 AssignLoc = ConsumeToken(); 4018 else 4019 Diag(Tok, diag::err_omp_expected_equal_in_iterator); 4020 4021 // Parse range-specification - <begin> ':' <end> [ ':' <step> ] 4022 ColonProtectionRAIIObject ColonRAII(*this); 4023 // Parse <begin> 4024 SourceLocation Loc = Tok.getLocation(); 4025 ExprResult LHS = ParseCastExpression(AnyCastExpr); 4026 ExprResult Begin = Actions.CorrectDelayedTyposInExpr( 4027 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 4028 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc, 4029 /*DiscardedValue=*/false); 4030 // Parse ':'. 4031 SourceLocation ColonLoc; 4032 if (Tok.is(tok::colon)) 4033 ColonLoc = ConsumeToken(); 4034 4035 // Parse <end> 4036 Loc = Tok.getLocation(); 4037 LHS = ParseCastExpression(AnyCastExpr); 4038 ExprResult End = Actions.CorrectDelayedTyposInExpr( 4039 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 4040 End = Actions.ActOnFinishFullExpr(End.get(), Loc, 4041 /*DiscardedValue=*/false); 4042 4043 SourceLocation SecColonLoc; 4044 ExprResult Step; 4045 // Parse optional step. 4046 if (Tok.is(tok::colon)) { 4047 // Parse ':' 4048 SecColonLoc = ConsumeToken(); 4049 // Parse <step> 4050 Loc = Tok.getLocation(); 4051 LHS = ParseCastExpression(AnyCastExpr); 4052 Step = Actions.CorrectDelayedTyposInExpr( 4053 ParseRHSOfBinaryExpression(LHS, prec::Conditional)); 4054 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc, 4055 /*DiscardedValue=*/false); 4056 } 4057 4058 // Parse ',' or ')' 4059 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren)) 4060 Diag(Tok, diag::err_omp_expected_punc_after_iterator); 4061 if (Tok.is(tok::comma)) 4062 ConsumeToken(); 4063 4064 Sema::OMPIteratorData &D = Data.emplace_back(); 4065 D.DeclIdent = II; 4066 D.DeclIdentLoc = IdLoc; 4067 D.Type = IteratorType; 4068 D.AssignLoc = AssignLoc; 4069 D.ColonLoc = ColonLoc; 4070 D.SecColonLoc = SecColonLoc; 4071 D.Range.Begin = Begin.get(); 4072 D.Range.End = End.get(); 4073 D.Range.Step = Step.get(); 4074 } 4075 4076 // Parse ')'. 4077 SourceLocation RLoc = Tok.getLocation(); 4078 if (!T.consumeClose()) 4079 RLoc = T.getCloseLocation(); 4080 4081 return Actions.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc, LLoc, RLoc, 4082 Data); 4083 } 4084 4085 /// Parses clauses with list. 4086 bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, 4087 OpenMPClauseKind Kind, 4088 SmallVectorImpl<Expr *> &Vars, 4089 OpenMPVarListDataTy &Data) { 4090 UnqualifiedId UnqualifiedReductionId; 4091 bool InvalidReductionId = false; 4092 bool IsInvalidMapperModifier = false; 4093 4094 // Parse '('. 4095 BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); 4096 if (T.expectAndConsume(diag::err_expected_lparen_after, 4097 getOpenMPClauseName(Kind).data())) 4098 return true; 4099 4100 bool HasIterator = false; 4101 bool NeedRParenForLinear = false; 4102 BalancedDelimiterTracker LinearT(*this, tok::l_paren, 4103 tok::annot_pragma_openmp_end); 4104 // Handle reduction-identifier for reduction clause. 4105 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction || 4106 Kind == OMPC_in_reduction) { 4107 Data.ExtraModifier = OMPC_REDUCTION_unknown; 4108 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 && 4109 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) && 4110 NextToken().is(tok::comma)) { 4111 // Parse optional reduction modifier. 4112 Data.ExtraModifier = 4113 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); 4114 Data.ExtraModifierLoc = Tok.getLocation(); 4115 ConsumeToken(); 4116 assert(Tok.is(tok::comma) && "Expected comma."); 4117 (void)ConsumeToken(); 4118 } 4119 ColonProtectionRAIIObject ColonRAII(*this); 4120 if (getLangOpts().CPlusPlus) 4121 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec, 4122 /*ObjectType=*/nullptr, 4123 /*ObjectHasErrors=*/false, 4124 /*EnteringContext=*/false); 4125 InvalidReductionId = ParseReductionId( 4126 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId); 4127 if (InvalidReductionId) { 4128 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4129 StopBeforeMatch); 4130 } 4131 if (Tok.is(tok::colon)) 4132 Data.ColonLoc = ConsumeToken(); 4133 else 4134 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier"; 4135 if (!InvalidReductionId) 4136 Data.ReductionOrMapperId = 4137 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId); 4138 } else if (Kind == OMPC_depend) { 4139 if (getLangOpts().OpenMP >= 50) { 4140 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") { 4141 // Handle optional dependence modifier. 4142 // iterator(iterators-definition) 4143 // where iterators-definition is iterator-specifier [, 4144 // iterators-definition ] 4145 // where iterator-specifier is [ iterator-type ] identifier = 4146 // range-specification 4147 HasIterator = true; 4148 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 4149 ExprResult IteratorRes = ParseOpenMPIteratorsExpr(); 4150 Data.DepModOrTailExpr = IteratorRes.get(); 4151 // Parse ',' 4152 ExpectAndConsume(tok::comma); 4153 } 4154 } 4155 // Handle dependency type for depend clause. 4156 ColonProtectionRAIIObject ColonRAII(*this); 4157 Data.ExtraModifier = getOpenMPSimpleClauseType( 4158 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "", 4159 getLangOpts()); 4160 Data.ExtraModifierLoc = Tok.getLocation(); 4161 if (Data.ExtraModifier == OMPC_DEPEND_unknown) { 4162 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4163 StopBeforeMatch); 4164 } else { 4165 ConsumeToken(); 4166 // Special processing for depend(source) clause. 4167 if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) { 4168 // Parse ')'. 4169 T.consumeClose(); 4170 return false; 4171 } 4172 } 4173 if (Tok.is(tok::colon)) { 4174 Data.ColonLoc = ConsumeToken(); 4175 } else { 4176 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren 4177 : diag::warn_pragma_expected_colon) 4178 << "dependency type"; 4179 } 4180 } else if (Kind == OMPC_linear) { 4181 // Try to parse modifier if any. 4182 Data.ExtraModifier = OMPC_LINEAR_val; 4183 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { 4184 Data.ExtraModifier = 4185 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); 4186 Data.ExtraModifierLoc = ConsumeToken(); 4187 LinearT.consumeOpen(); 4188 NeedRParenForLinear = true; 4189 } 4190 } else if (Kind == OMPC_lastprivate) { 4191 // Try to parse modifier if any. 4192 Data.ExtraModifier = OMPC_LASTPRIVATE_unknown; 4193 // Conditional modifier allowed only in OpenMP 5.0 and not supported in 4194 // distribute and taskloop based directives. 4195 if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) && 4196 !isOpenMPTaskLoopDirective(DKind)) && 4197 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) { 4198 Data.ExtraModifier = 4199 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts()); 4200 Data.ExtraModifierLoc = Tok.getLocation(); 4201 ConsumeToken(); 4202 assert(Tok.is(tok::colon) && "Expected colon."); 4203 Data.ColonLoc = ConsumeToken(); 4204 } 4205 } else if (Kind == OMPC_map) { 4206 // Handle map type for map clause. 4207 ColonProtectionRAIIObject ColonRAII(*this); 4208 4209 // The first identifier may be a list item, a map-type or a 4210 // map-type-modifier. The map-type can also be delete which has the same 4211 // spelling of the C++ delete keyword. 4212 Data.ExtraModifier = OMPC_MAP_unknown; 4213 Data.ExtraModifierLoc = Tok.getLocation(); 4214 4215 // Check for presence of a colon in the map clause. 4216 TentativeParsingAction TPA(*this); 4217 bool ColonPresent = false; 4218 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4219 StopBeforeMatch)) { 4220 if (Tok.is(tok::colon)) 4221 ColonPresent = true; 4222 } 4223 TPA.Revert(); 4224 // Only parse map-type-modifier[s] and map-type if a colon is present in 4225 // the map clause. 4226 if (ColonPresent) { 4227 IsInvalidMapperModifier = parseMapTypeModifiers(Data); 4228 if (!IsInvalidMapperModifier) 4229 parseMapType(*this, Data); 4230 else 4231 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch); 4232 } 4233 if (Data.ExtraModifier == OMPC_MAP_unknown) { 4234 Data.ExtraModifier = OMPC_MAP_tofrom; 4235 Data.IsMapTypeImplicit = true; 4236 } 4237 4238 if (Tok.is(tok::colon)) 4239 Data.ColonLoc = ConsumeToken(); 4240 } else if (Kind == OMPC_to || Kind == OMPC_from) { 4241 while (Tok.is(tok::identifier)) { 4242 auto Modifier = static_cast<OpenMPMotionModifierKind>( 4243 getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok), getLangOpts())); 4244 if (Modifier == OMPC_MOTION_MODIFIER_unknown) 4245 break; 4246 Data.MotionModifiers.push_back(Modifier); 4247 Data.MotionModifiersLoc.push_back(Tok.getLocation()); 4248 ConsumeToken(); 4249 if (Modifier == OMPC_MOTION_MODIFIER_mapper) { 4250 IsInvalidMapperModifier = parseMapperModifier(Data); 4251 if (IsInvalidMapperModifier) 4252 break; 4253 } 4254 // OpenMP < 5.1 doesn't permit a ',' or additional modifiers. 4255 if (getLangOpts().OpenMP < 51) 4256 break; 4257 // OpenMP 5.1 accepts an optional ',' even if the next character is ':'. 4258 // TODO: Is that intentional? 4259 if (Tok.is(tok::comma)) 4260 ConsumeToken(); 4261 } 4262 if (!Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) { 4263 if (!IsInvalidMapperModifier) { 4264 if (getLangOpts().OpenMP < 51) 4265 Diag(Tok, diag::warn_pragma_expected_colon) << ")"; 4266 else 4267 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier"; 4268 } 4269 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4270 StopBeforeMatch); 4271 } 4272 // OpenMP 5.1 permits a ':' even without a preceding modifier. TODO: Is 4273 // that intentional? 4274 if ((!Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) && 4275 Tok.is(tok::colon)) 4276 Data.ColonLoc = ConsumeToken(); 4277 } else if (Kind == OMPC_allocate || 4278 (Kind == OMPC_affinity && Tok.is(tok::identifier) && 4279 PP.getSpelling(Tok) == "iterator")) { 4280 // Handle optional allocator expression followed by colon delimiter. 4281 ColonProtectionRAIIObject ColonRAII(*this); 4282 TentativeParsingAction TPA(*this); 4283 // OpenMP 5.0, 2.10.1, task Construct. 4284 // where aff-modifier is one of the following: 4285 // iterator(iterators-definition) 4286 ExprResult Tail; 4287 if (Kind == OMPC_allocate) { 4288 Tail = ParseAssignmentExpression(); 4289 } else { 4290 HasIterator = true; 4291 EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope); 4292 Tail = ParseOpenMPIteratorsExpr(); 4293 } 4294 Tail = Actions.CorrectDelayedTyposInExpr(Tail); 4295 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(), 4296 /*DiscardedValue=*/false); 4297 if (Tail.isUsable()) { 4298 if (Tok.is(tok::colon)) { 4299 Data.DepModOrTailExpr = Tail.get(); 4300 Data.ColonLoc = ConsumeToken(); 4301 TPA.Commit(); 4302 } else { 4303 // Colon not found, parse only list of variables. 4304 TPA.Revert(); 4305 } 4306 } else { 4307 // Parsing was unsuccessfull, revert and skip to the end of clause or 4308 // directive. 4309 TPA.Revert(); 4310 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 4311 StopBeforeMatch); 4312 } 4313 } else if (Kind == OMPC_adjust_args) { 4314 // Handle adjust-op for adjust_args clause. 4315 ColonProtectionRAIIObject ColonRAII(*this); 4316 Data.ExtraModifier = getOpenMPSimpleClauseType( 4317 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "", 4318 getLangOpts()); 4319 Data.ExtraModifierLoc = Tok.getLocation(); 4320 if (Data.ExtraModifier == OMPC_ADJUST_ARGS_unknown) { 4321 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, 4322 StopBeforeMatch); 4323 } else { 4324 ConsumeToken(); 4325 if (Tok.is(tok::colon)) 4326 Data.ColonLoc = Tok.getLocation(); 4327 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon, 4328 "adjust-op"); 4329 } 4330 } 4331 4332 bool IsComma = 4333 (Kind != OMPC_reduction && Kind != OMPC_task_reduction && 4334 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) || 4335 (Kind == OMPC_reduction && !InvalidReductionId) || 4336 (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) || 4337 (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown) || 4338 (Kind == OMPC_adjust_args && 4339 Data.ExtraModifier != OMPC_ADJUST_ARGS_unknown); 4340 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); 4341 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && 4342 Tok.isNot(tok::annot_pragma_openmp_end))) { 4343 ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope); 4344 ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail); 4345 // Parse variable 4346 ExprResult VarExpr = 4347 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); 4348 if (VarExpr.isUsable()) { 4349 Vars.push_back(VarExpr.get()); 4350 } else { 4351 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 4352 StopBeforeMatch); 4353 } 4354 // Skip ',' if any 4355 IsComma = Tok.is(tok::comma); 4356 if (IsComma) 4357 ConsumeToken(); 4358 else if (Tok.isNot(tok::r_paren) && 4359 Tok.isNot(tok::annot_pragma_openmp_end) && 4360 (!MayHaveTail || Tok.isNot(tok::colon))) 4361 Diag(Tok, diag::err_omp_expected_punc) 4362 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush) 4363 : getOpenMPClauseName(Kind)) 4364 << (Kind == OMPC_flush); 4365 } 4366 4367 // Parse ')' for linear clause with modifier. 4368 if (NeedRParenForLinear) 4369 LinearT.consumeClose(); 4370 4371 // Parse ':' linear-step (or ':' alignment). 4372 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); 4373 if (MustHaveTail) { 4374 Data.ColonLoc = Tok.getLocation(); 4375 SourceLocation ELoc = ConsumeToken(); 4376 ExprResult Tail = ParseAssignmentExpression(); 4377 Tail = 4378 Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false); 4379 if (Tail.isUsable()) 4380 Data.DepModOrTailExpr = Tail.get(); 4381 else 4382 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, 4383 StopBeforeMatch); 4384 } 4385 4386 // Parse ')'. 4387 Data.RLoc = Tok.getLocation(); 4388 if (!T.consumeClose()) 4389 Data.RLoc = T.getCloseLocation(); 4390 // Exit from scope when the iterator is used in depend clause. 4391 if (HasIterator) 4392 ExitScope(); 4393 return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || 4394 (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId || 4395 IsInvalidMapperModifier; 4396 } 4397 4398 /// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', 4399 /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction', 4400 /// 'in_reduction', 'nontemporal', 'exclusive' or 'inclusive'. 4401 /// 4402 /// private-clause: 4403 /// 'private' '(' list ')' 4404 /// firstprivate-clause: 4405 /// 'firstprivate' '(' list ')' 4406 /// lastprivate-clause: 4407 /// 'lastprivate' '(' list ')' 4408 /// shared-clause: 4409 /// 'shared' '(' list ')' 4410 /// linear-clause: 4411 /// 'linear' '(' linear-list [ ':' linear-step ] ')' 4412 /// aligned-clause: 4413 /// 'aligned' '(' list [ ':' alignment ] ')' 4414 /// reduction-clause: 4415 /// 'reduction' '(' [ modifier ',' ] reduction-identifier ':' list ')' 4416 /// task_reduction-clause: 4417 /// 'task_reduction' '(' reduction-identifier ':' list ')' 4418 /// in_reduction-clause: 4419 /// 'in_reduction' '(' reduction-identifier ':' list ')' 4420 /// copyprivate-clause: 4421 /// 'copyprivate' '(' list ')' 4422 /// flush-clause: 4423 /// 'flush' '(' list ')' 4424 /// depend-clause: 4425 /// 'depend' '(' in | out | inout : list | source ')' 4426 /// map-clause: 4427 /// 'map' '(' [ [ always [,] ] [ close [,] ] 4428 /// [ mapper '(' mapper-identifier ')' [,] ] 4429 /// to | from | tofrom | alloc | release | delete ':' ] list ')'; 4430 /// to-clause: 4431 /// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 4432 /// from-clause: 4433 /// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')' 4434 /// use_device_ptr-clause: 4435 /// 'use_device_ptr' '(' list ')' 4436 /// use_device_addr-clause: 4437 /// 'use_device_addr' '(' list ')' 4438 /// is_device_ptr-clause: 4439 /// 'is_device_ptr' '(' list ')' 4440 /// allocate-clause: 4441 /// 'allocate' '(' [ allocator ':' ] list ')' 4442 /// nontemporal-clause: 4443 /// 'nontemporal' '(' list ')' 4444 /// inclusive-clause: 4445 /// 'inclusive' '(' list ')' 4446 /// exclusive-clause: 4447 /// 'exclusive' '(' list ')' 4448 /// 4449 /// For 'linear' clause linear-list may have the following forms: 4450 /// list 4451 /// modifier(list) 4452 /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). 4453 OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, 4454 OpenMPClauseKind Kind, 4455 bool ParseOnly) { 4456 SourceLocation Loc = Tok.getLocation(); 4457 SourceLocation LOpen = ConsumeToken(); 4458 SmallVector<Expr *, 4> Vars; 4459 OpenMPVarListDataTy Data; 4460 4461 if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) 4462 return nullptr; 4463 4464 if (ParseOnly) 4465 return nullptr; 4466 OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc); 4467 return Actions.ActOnOpenMPVarListClause( 4468 Kind, Vars, Data.DepModOrTailExpr, Locs, Data.ColonLoc, 4469 Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, 4470 Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc, 4471 Data.IsMapTypeImplicit, Data.ExtraModifierLoc, Data.MotionModifiers, 4472 Data.MotionModifiersLoc); 4473 } 4474