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