clang: lib/Parse/ParseOpenMP.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

26#include "llvm/ADT/SmallBitVector.h"

27#include "llvm/ADT/StringSwitch.h"

28#include "llvm/Frontend/OpenMP/DirectiveNameParser.h"

29#include "llvm/Frontend/OpenMP/OMPAssume.h"

30#include "llvm/Frontend/OpenMP/OMPContext.h"

31#include

32

33using namespace clang;

34using namespace llvm::omp;

35

36

37

38

39

40namespace {

41class DeclDirectiveListParserHelper final {

42 SmallVector<Expr *, 4> Identifiers;

43 Parser *P;

45

46public:

48 : P(P), Kind(Kind) {}

49 void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {

50 ExprResult Res = P->getActions().OpenMP().ActOnOpenMPIdExpression(

51 P->getCurScope(), SS, NameInfo, Kind);

53 Identifiers.push_back(Res.get());

54 }

55 llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }

56};

57}

58

62 StringRef Name) {

63 unsigned Version = P.getLangOpts().OpenMP;

64 auto [D, VR] = getOpenMPDirectiveKindAndVersions(Name);

65 assert(D == Kind && "Directive kind mismatch");

66

67

68 if (static_cast<int>(Version) < VR.Min)

69 P.Diag(Loc, diag::warn_omp_future_directive_spelling) << Name;

70

71 return Kind;

72}

73

75 static const DirectiveNameParser DirParser;

76

77 const DirectiveNameParser::State *S = DirParser.initial();

78

80 if (Tok.isAnnotation())

81 return OMPD_unknown;

82

85

86 S = DirParser.consume(S, Concat);

87 if (S == nullptr)

88 return OMPD_unknown;

89

90 while (Tok.isAnnotation()) {

93 if (Tok.isAnnotation()) {

95 S = DirParser.consume(S, TS);

96 if (S == nullptr)

98 Concat += ' ' + TS;

100 }

101 }

102

103 assert(S && "Should have exited early");

105}

106

111

112 bool WithOperator = false;

113 if (Tok.is(tok::kw_operator)) {

116 WithOperator = true;

117 }

118 switch (Tok.getKind()) {

119 case tok:➕

120 OOK = OO_Plus;

121 break;

122 case tok:➖

123 OOK = OO_Minus;

124 break;

125 case tok:⭐

126 OOK = OO_Star;

127 break;

128 case tok::amp:

129 OOK = OO_Amp;

130 break;

131 case tok::pipe:

132 OOK = OO_Pipe;

133 break;

134 case tok::caret:

135 OOK = OO_Caret;

136 break;

137 case tok::ampamp:

138 OOK = OO_AmpAmp;

139 break;

140 case tok::pipepipe:

141 OOK = OO_PipePipe;

142 break;

143 case tok::identifier:

144 if (!WithOperator)

145 break;

146 [[fallthrough]];

147 default:

148 P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);

149 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,

152 }

155 return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())

156 : DeclNames.getCXXOperatorName(OOK);

157}

158

160Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {

161 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

162

164 if (T.expectAndConsume(

165 diag::err_expected_lparen_after,

166 getOpenMPDirectiveName(OMPD_declare_reduction, OMPVersion).data())) {

169 }

170

172 if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))

174

175

176 bool IsCorrect = !ExpectAndConsume(tok::colon);

177

178 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))

180

181 IsCorrect = IsCorrect && !Name.isEmpty();

182

183 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {

184 Diag(Tok.getLocation(), diag::err_expected_type);

185 IsCorrect = false;

186 }

187

188 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))

190

191 SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;

192

193 do {

195 SourceRange Range;

198 QualType ReductionType = Actions.OpenMP().ActOnOpenMPDeclareReductionType(

199 Range.getBegin(), TR);

200 if (!ReductionType.isNull()) {

201 ReductionTypes.push_back(

202 std::make_pair(ReductionType, Range.getBegin()));

203 }

204 } else {

205 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,

207 }

208

209 if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))

210 break;

211

212

213 if (ExpectAndConsume(tok::comma)) {

214 IsCorrect = false;

215 if (Tok.is(tok::annot_pragma_openmp_end)) {

216 Diag(Tok.getLocation(), diag::err_expected_type);

218 }

219 }

220 } while (Tok.isNot(tok::annot_pragma_openmp_end));

221

222 if (ReductionTypes.empty()) {

225 }

226

227 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))

229

230

231 if (ExpectAndConsume(tok::colon))

232 IsCorrect = false;

233

234 if (Tok.is(tok::annot_pragma_openmp_end)) {

235 Diag(Tok.getLocation(), diag::err_expected_expression);

237 }

238

240 Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveStart(

241 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes,

242 AS);

243

244

245

246 unsigned I = 0, E = ReductionTypes.size();

247 for (Decl *D : DRD.get()) {

248 TentativeParsingAction TPA(*this);

252

253 Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);

254 ExprResult CombinerResult = Actions.ActOnFinishFullExpr(

255 ParseExpression().get(), D->getLocation(), false);

256 Actions.OpenMP().ActOnOpenMPDeclareReductionCombinerEnd(

257 D, CombinerResult.get());

258

259 if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&

260 Tok.isNot(tok::annot_pragma_openmp_end)) {

261 TPA.Commit();

262 IsCorrect = false;

263 break;

264 }

265 IsCorrect = T.consumeClose() && IsCorrect && CombinerResult.isUsable();

267 if (Tok.isNot(tok::annot_pragma_openmp_end)) {

268

269 if (Tok.is(tok::identifier) &&

270 Tok.getIdentifierInfo()->isStr("initializer")) {

272 } else {

273 Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";

274 TPA.Commit();

275 IsCorrect = false;

276 break;

277 }

278

280 tok::annot_pragma_openmp_end);

281 IsCorrect =

282 T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&

283 IsCorrect;

284 if (Tok.isNot(tok::annot_pragma_openmp_end)) {

288

289 VarDecl *OmpPrivParm =

290 Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerStart(

292

293 if (Tok.is(tok::identifier) &&

294 Tok.getIdentifierInfo()->isStr("omp_priv")) {

296 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);

297 } else {

298 InitializerResult = Actions.ActOnFinishFullExpr(

300 false);

301 }

302 Actions.OpenMP().ActOnOpenMPDeclareReductionInitializerEnd(

303 D, InitializerResult.get(), OmpPrivParm);

304 if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&

305 Tok.isNot(tok::annot_pragma_openmp_end)) {

306 TPA.Commit();

307 IsCorrect = false;

308 break;

309 }

310 IsCorrect =

311 T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();

312 }

313 }

314

315 ++I;

316

317

318 if (I != E)

319 TPA.Revert();

320 else

321 TPA.Commit();

322 }

323 return Actions.OpenMP().ActOnOpenMPDeclareReductionDirectiveEnd(

325}

326

327void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {

328

329

330 if (isTokenEqualOrEqualTypo()) {

332

333 if (Tok.is(tok::code_completion)) {

334 cutOffParsing();

335 Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(),

336 OmpPrivParm);

337 Actions.FinalizeDeclaration(OmpPrivParm);

338 return;

339 }

340

341 PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);

343

344 if (Init.isInvalid()) {

346 Actions.ActOnInitializerError(OmpPrivParm);

347 } else {

348 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),

349 false);

350 }

351 } else if (Tok.is(tok::l_paren)) {

352

354 T.consumeOpen();

355

356 ExprVector Exprs;

357

358 SourceLocation LParLoc = T.getOpenLocation();

359 auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {

360 QualType PreferredType =

361 Actions.CodeCompletion().ProduceConstructorSignatureHelp(

363 OmpPrivParm->getLocation(), Exprs, LParLoc, false);

364 CalledSignatureHelp = true;

365 return PreferredType;

366 };

367 if (ParseExpressionList(Exprs, [&] {

368 PreferredType.enterFunctionArgument(Tok.getLocation(),

369 RunSignatureHelp);

370 })) {

371 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)

372 RunSignatureHelp();

373 Actions.ActOnInitializerError(OmpPrivParm);

375 } else {

376

377 SourceLocation RLoc = Tok.getLocation();

378 if (T.consumeClose())

379 RLoc = T.getCloseLocation();

380

382 Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);

383 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),

384 true);

385 }

387

388 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);

389

391

392 if (Init.isInvalid()) {

393 Actions.ActOnInitializerError(OmpPrivParm);

394 } else {

395 Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),

396 true);

397 }

398 } else {

399 Actions.ActOnUninitializedDecl(OmpPrivParm);

400 }

401}

402

404Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {

405 bool IsCorrect = true;

406 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

407

409 if (T.expectAndConsume(

410 diag::err_expected_lparen_after,

411 getOpenMPDirectiveName(OMPD_declare_mapper, OMPVersion).data())) {

414 }

415

416

417 auto &DeclNames = Actions.getASTContext().DeclarationNames;

418 DeclarationName MapperId;

419 if (PP.LookAhead(0).is(tok::colon)) {

420 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {

421 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);

422 IsCorrect = false;

423 } else {

424 MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());

425 }

427

428 ExpectAndConsume(tok::colon);

429 } else {

430

431 MapperId =

432 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));

433 }

434

435 if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))

437

438

439 DeclarationName VName;

440 QualType MapperType;

441 SourceRange Range;

444 MapperType = Actions.OpenMP().ActOnOpenMPDeclareMapperType(Range.getBegin(),

446 if (MapperType.isNull())

447 IsCorrect = false;

448 if (!IsCorrect) {

451 }

452

453

454 IsCorrect &= T.consumeClose();

455 if (!IsCorrect) {

458 }

459

461

462 DeclarationNameInfo DirName;

463 SourceLocation Loc = Tok.getLocation();

466 ParseScope OMPDirectiveScope(this, ScopeFlags);

467 Actions.OpenMP().StartOpenMPDSABlock(OMPD_declare_mapper, DirName,

469

470

472 Actions.OpenMP().ActOnOpenMPDeclareMapperDirectiveVarDecl(

474

475

476 SmallVector<OMPClause *, 6> Clauses;

477 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

479 ? OMPC_unknown

480 : getOpenMPClauseKind(PP.getSpelling(Tok));

481 Actions.OpenMP().StartOpenMPClause(CKind);

482 OMPClause *Clause =

483 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());

484 if (Clause)

485 Clauses.push_back(Clause);

486 else

487 IsCorrect = false;

488

489 if (Tok.is(tok::comma))

491 Actions.OpenMP().EndOpenMPClause();

492 }

493 if (Clauses.empty()) {

494 Diag(Tok, diag::err_omp_expected_clause)

495 << getOpenMPDirectiveName(OMPD_declare_mapper, OMPVersion);

496 IsCorrect = false;

497 }

498

499

500

501

502

503

504 DeclGroupPtrTy DG = Actions.OpenMP().ActOnOpenMPDeclareMapperDirective(

505 OuterScope, Actions.getCurLexicalContext(), MapperId, MapperType,

506 Range.getBegin(), VName, AS, MapperVarRef.get(), Clauses);

507

508 Actions.OpenMP().EndOpenMPDSABlock(nullptr);

509 OMPDirectiveScope.Exit();

510 if (!IsCorrect)

512

513 return DG;

514}

515

519

520 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;

521 DeclSpec DS(AttrFactory);

522 ParseSpecifierQualifierList(DS, AS, DSC);

523

524

527 ParseDeclarator(DeclaratorInfo);

528 Range = DeclaratorInfo.getSourceRange();

529 if (DeclaratorInfo.getIdentifier() == nullptr) {

530 Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);

531 return true;

532 }

533 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();

534

535 return Actions.OpenMP().ActOnOpenMPDeclareMapperVarDecl(getCurScope(),

536 DeclaratorInfo);

537}

538

539

540

541

542

543

544

547 Actions.OpenMP().getOMPTraitInfoForSurroundingScope();

548 ASTContext &ASTCtx = Actions.getASTContext();

550 if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {

552 ;

553

554 (void)ConsumeAnnotationToken();

555 return true;

556 }

557

558

559 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);

560

562

563 VariantMatchInfo VMI;

565

566 std::function<void(StringRef)> DiagUnknownTrait = [this,

567 Loc](StringRef ISATrait) {

568

569

570 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;

571 };

573 ASTCtx, std::move(DiagUnknownTrait),

574 nullptr,

576 Actions.OpenMP().getOpenMPDeviceNum());

577

578 if (isVariantApplicableInContext(VMI, OMPCtx,

579 true)) {

580 Actions.OpenMP().ActOnOpenMPBeginDeclareVariant(Loc, TI);

581 return false;

582 }

583

584

585 unsigned Nesting = 1;

588 do {

589 DKLoc = Tok.getLocation();

591 if (DK == OMPD_end_declare_variant)

592 --Nesting;

593 else if (DK == OMPD_begin_declare_variant)

594 ++Nesting;

595 if (!Nesting || isEofOrEom())

596 break;

598 } while (true);

599

600 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant, DK,

601 Loc, DKLoc, true);

602 return false;

603}

604

605namespace {

606

607

608

609

610

611class FNContextRAII final {

615 bool HasFunScope = false;

616 FNContextRAII() = delete;

617 FNContextRAII(const FNContextRAII &) = delete;

618 FNContextRAII &operator=(const FNContextRAII &) = delete;

619

620public:

622 Decl *D = *Ptr.get().begin();

623 NamedDecl *ND = dyn_cast(D);

626

627

630

631

632

634

635

637 HasFunScope = true;

641 }

642 }

643 ~FNContextRAII() {

644 if (HasFunScope)

646 delete ThisScope;

647 }

648};

649}

650

651

652

653

654

655

656

657

659 Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,

665 bool IsError = false;

666 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

667 if (Tok.isNot(tok::identifier))

668 break;

669 OMPDeclareSimdDeclAttr::BranchStateTy Out;

671 StringRef ClauseName = II->getName();

672

673 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {

674 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {

675 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)

676 << ClauseName

677 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;

678 IsError = true;

679 }

680 BS = Out;

683 } else if (ClauseName == "simdlen") {

686 P.Diag(Tok, diag::err_omp_more_one_clause)

687 << getOpenMPDirectiveName(OMPD_declare_simd, OMPVersion)

688 << ClauseName << 0;

689 IsError = true;

690 }

695 IsError = true;

696 } else {

698 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||

699 CKind == OMPC_linear) {

702 if (CKind == OMPC_aligned) {

703 Vars = &Aligneds;

704 } else if (CKind == OMPC_linear) {

705 Data.ExtraModifier = OMPC_LINEAR_val;

706 Vars = &Linears;

707 }

708

711 getOpenMPClauseKind(ClauseName), *Vars, Data))

712 IsError = true;

713 if (CKind == OMPC_aligned) {

714 Alignments.append(Aligneds.size() - Alignments.size(),

715 Data.DepModOrTailExpr);

716 } else if (CKind == OMPC_linear) {

717 assert(0 <= Data.ExtraModifier &&

719 "Unexpected linear modifier.");

722 Data.ExtraModifierLoc))

723 Data.ExtraModifier = OMPC_LINEAR_val;

724 LinModifiers.append(Linears.size() - LinModifiers.size(),

725 Data.ExtraModifier);

726 Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);

727 }

728 } else

729

730 break;

731 }

732

733 if (Tok.is(tok::comma))

735 }

736 return IsError;

737}

738

742 PP.EnterToken(Tok, true);

743 PP.EnterTokenStream(Toks, true,

744 true);

745

748

749 FNContextRAII FnContext(*this, Ptr);

750 OMPDeclareSimdDeclAttr::BranchStateTy BS =

751 OMPDeclareSimdDeclAttr::BS_Undefined;

753 SmallVector<Expr *, 4> Uniforms;

754 SmallVector<Expr *, 4> Aligneds;

755 SmallVector<Expr *, 4> Alignments;

756 SmallVector<Expr *, 4> Linears;

757 SmallVector<unsigned, 4> LinModifiers;

758 SmallVector<Expr *, 4> Steps;

759 bool IsError =

761 Alignments, Linears, LinModifiers, Steps);

762 skipUntilPragmaOpenMPEnd(OMPD_declare_simd);

763

764 SourceLocation EndLoc = ConsumeAnnotationToken();

765 if (IsError)

766 return Ptr;

767 return Actions.OpenMP().ActOnOpenMPDeclareSimdDirective(

768 Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,

769 LinModifiers, Steps, SourceRange(Loc, EndLoc));

770}

771

772namespace {

773

774

775enum OMPContextLvl {

776 CONTEXT_SELECTOR_SET_LVL = 0,

777 CONTEXT_SELECTOR_LVL = 1,

778 CONTEXT_TRAIT_LVL = 2,

779};

780

781static StringRef stringLiteralParser(Parser &P) {

784}

785

786static StringRef getNameFromIdOrString(Parser &P, Token &Tok,

787 OMPContextLvl Lvl) {

788 if (Tok.is(tok::identifier) || Tok.is(tok::kw_for)) {

792 return Name;

793 }

794

796 return stringLiteralParser(P);

797

799 diag::warn_omp_declare_variant_string_literal_or_identifier)

800 << Lvl;

801 return "";

802}

803

804static bool checkForDuplicates(Parser &P, StringRef Name,

806 llvm::StringMap &Seen,

807 OMPContextLvl Lvl) {

808 auto Res = Seen.try_emplace(Name, NameLoc);

809 if (Res.second)

810 return false;

811

812

813

814 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)

815 << Lvl << Name;

816 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)

817 << Lvl << Name;

818 return true;

819}

820}

821

822void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,

823 llvm::omp::TraitSet Set,

824 llvm::omp::TraitSelector Selector,

825 llvm::StringMap &Seen) {

826 TIProperty.Kind = TraitProperty::invalid;

827

828 SourceLocation NameLoc = Tok.getLocation();

829 StringRef Name;

830 if (Selector == llvm::omp::TraitSelector::target_device_device_num) {

831 Name = "number";

832 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);

834 if (DeviceNumExprResult.isUsable()) {

835 Expr *DeviceNumExpr = DeviceNumExprResult.get();

836 Actions.OpenMP().ActOnOpenMPDeviceNum(DeviceNumExpr);

837 }

838 return;

839 }

840 Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);

841 if (Name.empty()) {

842 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)

843 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);

844 return;

845 }

846

848 TIProperty.Kind = getOpenMPContextTraitPropertyKind(Set, Selector, Name);

849 if (TIProperty.Kind != TraitProperty::invalid) {

850 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))

851 TIProperty.Kind = TraitProperty::invalid;

852 return;

853 }

854

855

856

857 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)

858 << Name << getOpenMPContextTraitSelectorName(Selector)

859 << getOpenMPContextTraitSetName(Set);

860

861 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);

862 if (SetForName != TraitSet::invalid) {

863 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

864 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;

865 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

866 << Name << ""

867 << "()";

868 return;

869 }

870 TraitSelector SelectorForName =

871 getOpenMPContextTraitSelectorKind(Name, SetForName);

872 if (SelectorForName != TraitSelector::invalid) {

873 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

874 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;

875 bool AllowsTraitScore = false;

876 bool RequiresProperty = false;

877 isValidTraitSelectorForTraitSet(

878 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),

879 AllowsTraitScore, RequiresProperty);

880 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

881 << getOpenMPContextTraitSetName(

882 getOpenMPContextTraitSetForSelector(SelectorForName))

883 << Name << (RequiresProperty ? "()" : "");

884 return;

885 }

886 for (const auto &PotentialSet :

887 {TraitSet::construct, TraitSet::user, TraitSet::implementation,

888 TraitSet::device, TraitSet::target_device}) {

889 TraitProperty PropertyForName =

890 getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);

891 if (PropertyForName == TraitProperty::invalid)

892 continue;

893 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

894 << getOpenMPContextTraitSetName(

895 getOpenMPContextTraitSetForProperty(PropertyForName))

896 << getOpenMPContextTraitSelectorName(

897 getOpenMPContextTraitSelectorForProperty(PropertyForName))

898 << ("(" + Name + ")").str();

899 return;

900 }

901 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)

902 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set, Selector);

903}

904

908 llvm::StringMap &Seen) {

909 assert(TISelector.Kind ==

910 llvm::omp::TraitSelector::implementation_extension &&

911 "Only for extension properties, e.g., "

912 "`implementation={extension(PROPERTY)}`");

913 if (TIProperty.Kind == TraitProperty::invalid)

914 return false;

915

916 if (TIProperty.Kind ==

917 TraitProperty::implementation_extension_disable_implicit_base)

918 return true;

919

920 if (TIProperty.Kind ==

921 TraitProperty::implementation_extension_allow_templates)

922 return true;

923

924 if (TIProperty.Kind ==

925 TraitProperty::implementation_extension_bind_to_declaration)

926 return true;

927

929 return (TP.Kind ==

930 llvm::omp::TraitProperty::implementation_extension_match_all ||

931 TP.Kind ==

932 llvm::omp::TraitProperty::implementation_extension_match_any ||

933 TP.Kind ==

934 llvm::omp::TraitProperty::implementation_extension_match_none);

935 };

936

937 if (IsMatchExtension(TIProperty)) {

939 if (IsMatchExtension(SeenProp)) {

940 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);

941 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(

944 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)

945 << CONTEXT_TRAIT_LVL << SeenName;

946 return false;

947 }

948 return true;

949 }

950

951 llvm_unreachable("Unknown extension property!");

952}

953

954void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,

955 llvm::omp::TraitSet Set,

956 llvm::StringMap &Seen) {

957 assert(TISelector.Kind != TraitSelector::user_condition &&

958 "User conditions are special properties not handled here!");

959

960 SourceLocation PropertyLoc = Tok.getLocation();

961 OMPTraitProperty TIProperty;

962 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.Kind, Seen);

963

964 if (TISelector.Kind == llvm::omp::TraitSelector::implementation_extension)

966 TISelector, Seen))

967 TIProperty.Kind = TraitProperty::invalid;

968

969

970 if (TIProperty.Kind == TraitProperty::invalid) {

971 if (PropertyLoc != Tok.getLocation())

972 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)

973 << CONTEXT_TRAIT_LVL;

974 return;

975 }

976

977 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,

979

980

981

982 TISelector.Properties.push_back(TIProperty);

983 return;

984 }

985

986 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)

987 << getOpenMPContextTraitPropertyName(TIProperty.Kind,

989 << getOpenMPContextTraitSelectorName(TISelector.Kind)

990 << getOpenMPContextTraitSetName(Set);

991 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)

992 << getOpenMPContextTraitPropertyName(TIProperty.Kind,

994 << getOpenMPContextTraitSelectorName(

995 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))

996 << getOpenMPContextTraitSetName(

997 getOpenMPContextTraitSetForProperty(TIProperty.Kind));

998 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)

999 << CONTEXT_TRAIT_LVL;

1000}

1001

1002void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,

1003 llvm::omp::TraitSet Set,

1004 llvm::StringMap &Seen) {

1005 TISelector.Kind = TraitSelector::invalid;

1006

1007 SourceLocation NameLoc = Tok.getLocation();

1008 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_LVL);

1009 if (Name.empty()) {

1010 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)

1011 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);

1012 return;

1013 }

1014

1015 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name, Set);

1016 if (TISelector.Kind != TraitSelector::invalid) {

1017 if (checkForDuplicates(*this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))

1018 TISelector.Kind = TraitSelector::invalid;

1019 return;

1020 }

1021

1022

1023 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)

1024 << Name << getOpenMPContextTraitSetName(Set);

1025

1026 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);

1027 if (SetForName != TraitSet::invalid) {

1028 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

1029 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;

1030 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

1031 << Name << ""

1032 << "";

1033 return;

1034 }

1035 for (const auto &PotentialSet :

1036 {TraitSet::construct, TraitSet::user, TraitSet::implementation,

1037 TraitSet::device, TraitSet::target_device}) {

1038 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(

1039 PotentialSet, TraitSelector::invalid, Name);

1040 if (PropertyForName == TraitProperty::invalid)

1041 continue;

1042 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

1043 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;

1044 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

1045 << getOpenMPContextTraitSetName(

1046 getOpenMPContextTraitSetForProperty(PropertyForName))

1047 << getOpenMPContextTraitSelectorName(

1048 getOpenMPContextTraitSelectorForProperty(PropertyForName))

1049 << ("(" + Name + ")").str();

1050 return;

1051 }

1052 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)

1053 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);

1054}

1055

1056

1060 StringRef SelectorName =

1062 if (SelectorName != "score")

1063 return ScoreExpr;

1067

1070 else

1071 P.Diag(P.getCurToken(), diag::warn_omp_declare_variant_expected)

1072 << "':'"

1073 << "score expression";

1074 return ScoreExpr;

1075}

1076

1077void Parser::parseOMPContextSelector(

1079 llvm::StringMap &SeenSelectors) {

1080 unsigned short OuterPC = ParenCount;

1081

1082

1083

1084

1085 auto FinishSelector = [OuterPC, this]() -> void {

1086 bool Done = false;

1087 while (!Done) {

1088 while (SkipUntil({tok::r_brace, tok::r_paren, tok::comma,

1089 tok::annot_pragma_openmp_end},

1091 ;

1092 if (Tok.is(tok::r_paren) && OuterPC > ParenCount)

1093 (void)ConsumeParen();

1094 if (OuterPC <= ParenCount) {

1095 Done = true;

1096 break;

1097 }

1098 if (!Tok.is(tok::comma) && !Tok.is(tok::r_paren)) {

1099 Done = true;

1100 break;

1101 }

1103 }

1104 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)

1105 << CONTEXT_SELECTOR_LVL;

1106 };

1107

1108 SourceLocation SelectorLoc = Tok.getLocation();

1109 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);

1110 if (TISelector.Kind == TraitSelector::invalid)

1111 return FinishSelector();

1112

1113 bool AllowsTraitScore = false;

1114 bool RequiresProperty = false;

1115 if (!isValidTraitSelectorForTraitSet(TISelector.Kind, Set, AllowsTraitScore,

1116 RequiresProperty)) {

1117 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)

1118 << getOpenMPContextTraitSelectorName(TISelector.Kind)

1119 << getOpenMPContextTraitSetName(Set);

1120 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)

1121 << getOpenMPContextTraitSelectorName(TISelector.Kind)

1122 << getOpenMPContextTraitSetName(

1123 getOpenMPContextTraitSetForSelector(TISelector.Kind))

1124 << RequiresProperty;

1125 return FinishSelector();

1126 }

1127

1128 if (!RequiresProperty) {

1130 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),

1131 getOpenMPContextTraitSelectorName(TISelector.Kind)});

1132 return;

1133 }

1134

1135 if (!Tok.is(tok::l_paren)) {

1136 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)

1137 << getOpenMPContextTraitSelectorName(TISelector.Kind)

1138 << getOpenMPContextTraitSetName(Set);

1139 return FinishSelector();

1140 }

1141

1142 if (TISelector.Kind == TraitSelector::user_condition) {

1143 SourceLocation RLoc;

1146 return FinishSelector();

1149 {TraitProperty::user_condition_unknown, ""});

1150 return;

1151 }

1152

1154 tok::annot_pragma_openmp_end);

1155

1156 (void)BDT.consumeOpen();

1157

1158 SourceLocation ScoreLoc = Tok.getLocation();

1160

1161 if (!AllowsTraitScore && !Score.isUnset()) {

1163 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)

1164 << getOpenMPContextTraitSelectorName(TISelector.Kind)

1165 << getOpenMPContextTraitSetName(Set) << Score.get();

1166 } else {

1167 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)

1168 << getOpenMPContextTraitSelectorName(TISelector.Kind)

1169 << getOpenMPContextTraitSetName(Set) << "";

1170 }

1172 }

1173

1176

1177 llvm::StringMap SeenProperties;

1178 do {

1179 parseOMPContextProperty(TISelector, Set, SeenProperties);

1181

1182

1183 BDT.consumeClose();

1184}

1185

1186void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,

1187 llvm::StringMap &Seen) {

1188 TISet.Kind = TraitSet::invalid;

1189

1190 SourceLocation NameLoc = Tok.getLocation();

1191 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_SELECTOR_SET_LVL);

1192 if (Name.empty()) {

1193 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_options)

1194 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();

1195 return;

1196 }

1197

1198 TISet.Kind = getOpenMPContextTraitSetKind(Name);

1199 if (TISet.Kind != TraitSet::invalid) {

1200 if (checkForDuplicates(*this, Name, NameLoc, Seen,

1201 CONTEXT_SELECTOR_SET_LVL))

1202 TISet.Kind = TraitSet::invalid;

1203 return;

1204 }

1205

1206

1207 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;

1208

1209 TraitSelector SelectorForName =

1210 getOpenMPContextTraitSelectorKind(Name, TISet.Kind);

1211 if (SelectorForName != TraitSelector::invalid) {

1212 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

1213 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;

1214 bool AllowsTraitScore = false;

1215 bool RequiresProperty = false;

1216 isValidTraitSelectorForTraitSet(

1217 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),

1218 AllowsTraitScore, RequiresProperty);

1219 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

1220 << getOpenMPContextTraitSetName(

1221 getOpenMPContextTraitSetForSelector(SelectorForName))

1222 << Name << (RequiresProperty ? "()" : "");

1223 return;

1224 }

1225 for (const auto &PotentialSet :

1226 {TraitSet::construct, TraitSet::user, TraitSet::implementation,

1227 TraitSet::device, TraitSet::target_device}) {

1228 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(

1229 PotentialSet, TraitSelector::invalid, Name);

1230 if (PropertyForName == TraitProperty::invalid)

1231 continue;

1232 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

1233 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;

1234 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

1235 << getOpenMPContextTraitSetName(

1236 getOpenMPContextTraitSetForProperty(PropertyForName))

1237 << getOpenMPContextTraitSelectorName(

1238 getOpenMPContextTraitSelectorForProperty(PropertyForName))

1239 << ("(" + Name + ")").str();

1240 return;

1241 }

1242 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)

1243 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();

1244}

1245

1246void Parser::parseOMPContextSelectorSet(

1247 OMPTraitSet &TISet, llvm::StringMap &SeenSets) {

1248 auto OuterBC = BraceCount;

1249

1250

1251

1252

1253 auto FinishSelectorSet = [this, OuterBC]() -> void {

1254 bool Done = false;

1255 while (!Done) {

1256 while (SkipUntil({tok::comma, tok::r_brace, tok::r_paren,

1257 tok::annot_pragma_openmp_end},

1259 ;

1260 if (Tok.is(tok::r_brace) && OuterBC > BraceCount)

1261 (void)ConsumeBrace();

1262 if (OuterBC <= BraceCount) {

1263 Done = true;

1264 break;

1265 }

1266 if (!Tok.is(tok::comma) && !Tok.is(tok::r_brace)) {

1267 Done = true;

1268 break;

1269 }

1271 }

1272 Diag(Tok.getLocation(), diag::note_omp_declare_variant_ctx_continue_here)

1273 << CONTEXT_SELECTOR_SET_LVL;

1274 };

1275

1276 parseOMPTraitSetKind(TISet, SeenSets);

1277 if (TISet.Kind == TraitSet::invalid)

1278 return FinishSelectorSet();

1279

1280

1282 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)

1283 << "="

1284 << ("context set name \"" + getOpenMPContextTraitSetName(TISet.Kind) +

1285 "\"")

1286 .str();

1287

1288

1289 if (Tok.is(tok::l_brace)) {

1290 (void)ConsumeBrace();

1291 } else {

1292 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)

1293 << "{"

1294 << ("'=' that follows the context set name \"" +

1295 getOpenMPContextTraitSetName(TISet.Kind) + "\"")

1296 .str();

1297 }

1298

1299 llvm::StringMap SeenSelectors;

1300 do {

1301 OMPTraitSelector TISelector;

1302 parseOMPContextSelector(TISelector, TISet.Kind, SeenSelectors);

1303 if (TISelector.Kind != TraitSelector::invalid &&

1305 TISet.Selectors.push_back(TISelector);

1307

1308

1309 if (Tok.is(tok::r_brace)) {

1310 (void)ConsumeBrace();

1311 } else {

1312 Diag(Tok.getLocation(), diag::warn_omp_declare_variant_expected)

1313 << "}"

1314 << ("context selectors for the context set \"" +

1315 getOpenMPContextTraitSetName(TISet.Kind) + "\"")

1316 .str();

1317 }

1318}

1319

1321 llvm::StringMap SeenSets;

1322 do {

1323 OMPTraitSet TISet;

1324 parseOMPContextSelectorSet(TISet, SeenSets);

1325 if (TISet.Kind != TraitSet::invalid && !TISet.Selectors.empty())

1326 TI.Sets.push_back(TISet);

1328

1329 return false;

1330}

1331

1335 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

1336 PP.EnterToken(Tok, true);

1337 PP.EnterTokenStream(Toks, true,

1338 true);

1339

1342

1343 FNContextRAII FnContext(*this, Ptr);

1344

1345 SourceLocation RLoc;

1346

1347

1349 {

1350

1351

1352 EnterExpressionEvaluationContext Unevaluated(

1355 getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion), RLoc,

1356 true);

1357 }

1358 if (!AssociatedFunction.isUsable()) {

1359 if (!Tok.is(tok::annot_pragma_openmp_end))

1361 ;

1362

1363 (void)ConsumeAnnotationToken();

1364 return;

1365 }

1366

1367 OMPTraitInfo *ParentTI =

1368 Actions.OpenMP().getOMPTraitInfoForSurroundingScope();

1369 ASTContext &ASTCtx = Actions.getASTContext();

1371 SmallVector<Expr *, 6> AdjustNothing;

1372 SmallVector<Expr *, 6> AdjustNeedDevicePtr;

1373 SmallVector<Expr *, 6> AdjustNeedDeviceAddr;

1374 SmallVector<OMPInteropInfo, 3> AppendArgs;

1375 SourceLocation AdjustArgsLoc, AppendArgsLoc;

1376

1377

1378 if (Tok.is(tok::annot_pragma_openmp_end)) {

1379 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)

1381 }

1382

1383 bool IsError = false;

1384 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

1386 ? OMPC_unknown

1387 : getOpenMPClauseKind(PP.getSpelling(Tok));

1388 if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,

1390 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)

1392 IsError = true;

1393 }

1394 if (!IsError) {

1395 switch (CKind) {

1396 case OMPC_match:

1397 IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);

1398 break;

1399 case OMPC_adjust_args: {

1400 AdjustArgsLoc = Tok.getLocation();

1402 SemaOpenMP::OpenMPVarListDataTy Data;

1403 SmallVector<Expr *> Vars;

1404 IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,

1405 Vars, Data);

1406 if (!IsError) {

1407 switch (Data.ExtraModifier) {

1408 case OMPC_ADJUST_ARGS_nothing:

1409 llvm::append_range(AdjustNothing, Vars);

1410 break;

1411 case OMPC_ADJUST_ARGS_need_device_ptr:

1412 llvm::append_range(AdjustNeedDevicePtr, Vars);

1413 break;

1414 case OMPC_ADJUST_ARGS_need_device_addr:

1415 llvm::append_range(AdjustNeedDeviceAddr, Vars);

1416 break;

1417 default:

1418 llvm_unreachable("Unexpected 'adjust_args' clause modifier.");

1419 }

1420 }

1421 break;

1422 }

1423 case OMPC_append_args:

1424 if (!AppendArgs.empty()) {

1425 Diag(AppendArgsLoc, diag::err_omp_more_one_clause)

1426 << getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion)

1427 << getOpenMPClauseName(CKind) << 0;

1428 IsError = true;

1429 }

1430 if (!IsError) {

1431 AppendArgsLoc = Tok.getLocation();

1433 IsError = parseOpenMPAppendArgs(AppendArgs);

1434 }

1435 break;

1436 default:

1437 llvm_unreachable("Unexpected clause for declare variant.");

1438 }

1439 }

1440 if (IsError) {

1442 ;

1443

1444 (void)ConsumeAnnotationToken();

1445 return;

1446 }

1447

1448 if (Tok.is(tok::comma))

1450 }

1451

1452 std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =

1453 Actions.OpenMP().checkOpenMPDeclareVariantFunction(

1454 Ptr, AssociatedFunction.get(), TI, AppendArgs.size(),

1455 SourceRange(Loc, Tok.getLocation()));

1456

1457 if (DeclVarData && !TI.Sets.empty())

1458 Actions.OpenMP().ActOnOpenMPDeclareVariantDirective(

1459 DeclVarData->first, DeclVarData->second, TI, AdjustNothing,

1460 AdjustNeedDevicePtr, AdjustNeedDeviceAddr, AppendArgs, AdjustArgsLoc,

1461 AppendArgsLoc, SourceRange(Loc, Tok.getLocation()));

1462

1463

1464 (void)ConsumeAnnotationToken();

1465}

1466

1467bool Parser::parseOpenMPAppendArgs(

1469 bool HasError = false;

1470

1472 if (T.expectAndConsume(diag::err_expected_lparen_after,

1473 getOpenMPClauseName(OMPC_append_args).data()))

1474 return true;

1475

1476

1477

1478 while (Tok.is(tok::identifier) && Tok.getIdentifierInfo()->isStr("interop")) {

1481 tok::annot_pragma_openmp_end);

1482 if (IT.expectAndConsume(diag::err_expected_lparen_after, "interop"))

1483 return true;

1484

1485 OMPInteropInfo InteropInfo;

1486 if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))

1487 HasError = true;

1488 else

1489 InteropInfos.push_back(InteropInfo);

1490

1491 IT.consumeClose();

1492 if (Tok.is(tok::comma))

1494 }

1495 if (!HasError && InteropInfos.empty()) {

1496 HasError = true;

1497 Diag(Tok.getLocation(), diag::err_omp_unexpected_append_op);

1498 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

1500 }

1501 HasError = T.consumeClose() || HasError;

1502 return HasError;

1503}

1504

1505bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,

1508

1510 ? OMPC_unknown

1511 : getOpenMPClauseKind(PP.getSpelling(Tok));

1512 if (CKind != OMPC_match) {

1513 Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)

1515 return true;

1516 }

1518

1520 if (T.expectAndConsume(diag::err_expected_lparen_after,

1521 getOpenMPClauseName(OMPC_match).data()))

1522 return true;

1523

1524

1525 parseOMPContextSelectors(Loc, TI);

1526

1527

1528 (void)T.consumeClose();

1529

1530 if (!ParentTI)

1531 return false;

1532

1533

1534

1535

1536

1537

1538 for (const OMPTraitSet &ParentSet : ParentTI->Sets) {

1539 bool MergedSet = false;

1540 for (OMPTraitSet &Set : TI.Sets) {

1541 if (Set.Kind != ParentSet.Kind)

1542 continue;

1543 MergedSet = true;

1544 for (const OMPTraitSelector &ParentSelector : ParentSet.Selectors) {

1545 bool MergedSelector = false;

1546 for (OMPTraitSelector &Selector : Set.Selectors) {

1547 if (Selector.Kind != ParentSelector.Kind)

1548 continue;

1549 MergedSelector = true;

1550 for (const OMPTraitProperty &ParentProperty :

1552 bool MergedProperty = false;

1554

1556 continue;

1557

1558

1559

1560 MergedProperty |= Property.RawString == ParentProperty.RawString;

1561

1564 continue;

1565

1566 if (Selector.Kind == llvm::omp::TraitSelector::user_condition) {

1567 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);

1570 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)

1571 << getOpenMPContextTraitPropertyName(

1573 << getOpenMPContextTraitSelectorName(ParentSelector.Kind)

1574 << getOpenMPContextTraitSetName(ParentSet.Kind);

1575 }

1576 }

1577 if (!MergedProperty)

1578 Selector.Properties.push_back(ParentProperty);

1579 }

1580 }

1581 if (!MergedSelector)

1582 Set.Selectors.push_back(ParentSelector);

1583 }

1584 }

1585 if (!MergedSet)

1586 TI.Sets.push_back(ParentSet);

1587 }

1588

1589 return false;

1590}

1591

1595 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;

1596 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

1598 ? OMPC_unknown

1599 : getOpenMPClauseKind(PP.getSpelling(Tok));

1600 Actions.OpenMP().StartOpenMPClause(CKind);

1601 OMPClause *Clause =

1602 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);

1603 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,

1605 SeenClauses[unsigned(CKind)] = true;

1606 if (Clause != nullptr)

1607 Clauses.push_back(Clause);

1608 if (Tok.is(tok::annot_pragma_openmp_end)) {

1609 Actions.OpenMP().EndOpenMPClause();

1610 break;

1611 }

1612

1613 if (Tok.is(tok::comma))

1615 Actions.OpenMP().EndOpenMPClause();

1616 }

1617}

1618

1621 SmallVector<std::string, 4> Assumptions;

1622 bool SkippedClauses = false;

1623

1624 auto SkipBraces = [&](llvm::StringRef Spelling, bool IssueNote) {

1626 tok::annot_pragma_openmp_end);

1627 if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))

1628 return;

1629 T.skipToEnd();

1630 if (IssueNote && T.getCloseLocation().isValid())

1631 Diag(T.getCloseLocation(),

1632 diag::note_omp_assumption_clause_continue_here);

1633 };

1634

1635

1636

1637

1638 auto MatchACMClause = [&](StringRef RawString) {

1639 llvm::StringSwitch SS(RawString);

1640 unsigned ACMIdx = 0;

1641 for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {

1642 if (ACMI.StartsWith)

1643 SS.StartsWith(ACMI.Identifier, ACMIdx++);

1644 else

1645 SS.Case(ACMI.Identifier, ACMIdx++);

1646 }

1647 return SS.Default(-1);

1648 };

1649

1650 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

1651 IdentifierInfo *II = nullptr;

1652 SourceLocation StartLoc = Tok.getLocation();

1653 int Idx = -1;

1654 if (Tok.isAnyIdentifier()) {

1655 II = Tok.getIdentifierInfo();

1656 Idx = MatchACMClause(II->getName());

1657 }

1659

1660 bool NextIsLPar = Tok.is(tok::l_paren);

1661

1662 if (Idx == -1) {

1663 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

1664 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)

1665 << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion)

1666 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;

1667 if (NextIsLPar)

1668 SkipBraces(II ? II->getName() : "", true);

1669 SkippedClauses = true;

1670 continue;

1671 }

1672 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];

1673 if (ACMI.HasDirectiveList || ACMI.HasExpression) {

1674

1675

1676 SkippedClauses = true;

1677 SkipBraces(II->getName(), false);

1678 continue;

1679 }

1680

1681 if (NextIsLPar) {

1682 Diag(Tok.getLocation(),

1683 diag::warn_omp_unknown_assumption_clause_without_args)

1684 << II;

1685 SkipBraces(II->getName(), true);

1686 }

1687

1688 assert(II && "Expected an identifier clause!");

1689 std::string Assumption = II->getName().str();

1690 if (ACMI.StartsWith)

1691 Assumption = "ompx_" + Assumption.substr(ACMI.Identifier.size());

1692 else

1693 Assumption = "omp_" + Assumption;

1694 Assumptions.push_back(Assumption);

1695 }

1696

1697 Actions.OpenMP().ActOnOpenMPAssumesDirective(Loc, DKind, Assumptions,

1698 SkippedClauses);

1699}

1700

1701void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {

1702 if (Actions.OpenMP().isInOpenMPAssumeScope())

1703 Actions.OpenMP().ActOnOpenMPEndAssumesDirective();

1704 else

1705 Diag(Loc, diag::err_expected_begin_assumes);

1706}

1707

1708

1709

1710

1711

1712

1713

1714

1715

1716

1717

1718namespace {

1719struct SimpleClauseData {

1720 unsigned Type;

1721 SourceLocation Loc;

1722 SourceLocation LOpen;

1723 SourceLocation TypeLoc;

1724 SourceLocation RLoc;

1725 SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,

1726 SourceLocation TypeLoc, SourceLocation RLoc)

1727 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}

1728};

1729}

1730

1731static std::optional

1736

1738 if (T.expectAndConsume(diag::err_expected_lparen_after,

1739 getOpenMPClauseName(Kind).data()))

1740 return std::nullopt;

1741

1746 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

1747 Tok.isNot(tok::annot_pragma_openmp_end))

1749

1750

1752 if (T.consumeClose())

1753 RLoc = T.getCloseLocation();

1754

1755 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);

1756}

1757

1758void Parser::ParseOMPDeclareTargetClauses(

1760 SourceLocation DeviceTypeLoc;

1761 bool RequiresToOrLinkOrIndirectClause = false;

1762 bool HasToOrLinkOrIndirectClause = false;

1763 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

1764 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;

1765 bool HasIdentifier = Tok.is(tok::identifier);

1766 if (HasIdentifier) {

1767

1768 RequiresToOrLinkOrIndirectClause = true;

1769 IdentifierInfo *II = Tok.getIdentifierInfo();

1770 StringRef ClauseName = II->getName();

1771 bool IsDeviceTypeClause =

1773 getOpenMPClauseKind(ClauseName) == OMPC_device_type;

1774

1775 bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&

1776 getOpenMPClauseKind(ClauseName) == OMPC_indirect;

1777 if (DTCI.Indirect && IsIndirectClause) {

1778 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

1779 Diag(Tok, diag::err_omp_more_one_clause)

1780 << getOpenMPDirectiveName(OMPD_declare_target, OMPVersion)

1781 << getOpenMPClauseName(OMPC_indirect) << 0;

1782 break;

1783 }

1784 bool IsToEnterOrLinkClause =

1785 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);

1786 assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&

1787 "Cannot be both!");

1788

1789

1790

1791 if (getLangOpts().OpenMP >= 52 && ClauseName == "to") {

1792 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);

1793 break;

1794 }

1795 if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") {

1796 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);

1797 break;

1798 }

1799

1800 if (!IsDeviceTypeClause && !IsIndirectClause &&

1801 DTCI.Kind == OMPD_begin_declare_target) {

1802 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)

1803 << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);

1804 break;

1805 }

1806 if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {

1808 ? diag::err_omp_declare_target_unexpected_clause_52

1809 : diag::err_omp_declare_target_unexpected_clause)

1810 << ClauseName

1812 ? 4

1814 break;

1815 }

1816

1817 if (IsToEnterOrLinkClause || IsIndirectClause)

1818 HasToOrLinkOrIndirectClause = true;

1819

1820 if (IsIndirectClause) {

1821 if (!ParseOpenMPIndirectClause(DTCI, false))

1822 break;

1823 continue;

1824 }

1825

1826 if (IsDeviceTypeClause) {

1827 std::optional DevTypeData =

1829 if (DevTypeData) {

1830 if (DeviceTypeLoc.isValid()) {

1831

1832 Diag(DevTypeData->Loc,

1833 diag::warn_omp_more_one_device_type_clause);

1834 break;

1835 }

1837 case OMPC_DEVICE_TYPE_any:

1838 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;

1839 break;

1840 case OMPC_DEVICE_TYPE_host:

1841 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;

1842 break;

1843 case OMPC_DEVICE_TYPE_nohost:

1844 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;

1845 break;

1847 llvm_unreachable("Unexpected device_type");

1848 }

1849 DeviceTypeLoc = DevTypeData->Loc;

1850 }

1851 continue;

1852 }

1854 }

1855

1856 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {

1857 auto &&Callback = [this, MT, &DTCI](CXXScopeSpec &SS,

1858 DeclarationNameInfo NameInfo) {

1859 NamedDecl *ND = Actions.OpenMP().lookupOpenMPDeclareTargetName(

1861 if (!ND)

1862 return;

1863 SemaOpenMP::DeclareTargetContextInfo::MapInfo MI{MT, NameInfo.getLoc()};

1864 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;

1865 if (!FirstMapping)

1866 Diag(NameInfo.getLoc(), diag::err_omp_declare_target_multiple)

1868 };

1869 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,

1870 true))

1871 break;

1872 }

1873

1874 if (Tok.is(tok::l_paren)) {

1876 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);

1877 break;

1878 }

1879 if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) {

1882 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter

1883 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);

1884 break;

1885 }

1886

1887

1888 if (Tok.is(tok::comma))

1890 }

1891

1892 if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)

1893 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);

1894

1895

1896 if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&

1897 !HasToOrLinkOrIndirectClause)

1900 ? diag::err_omp_declare_target_missing_enter_or_link_clause

1901 : diag::err_omp_declare_target_missing_to_or_link_clause)

1902 << (getLangOpts().OpenMP >= 51 ? 1 : 0);

1903

1905}

1906

1908

1909

1910 if (Tok.is(tok::annot_pragma_openmp_end))

1911 return;

1912

1913 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

1914 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)

1915 << getOpenMPDirectiveName(DKind, OMPVersion);

1916 while (Tok.isNot(tok::annot_pragma_openmp_end))

1918}

1919

1925 bool SkipUntilOpenMPEnd) {

1926 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;

1927

1928 if (FoundKind == ExpectedKind) {

1930 skipUntilPragmaOpenMPEnd(ExpectedKind);

1931 return;

1932 }

1933

1934 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

1935 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)

1936 << DiagSelection;

1937 Diag(BeginLoc, diag::note_matching)

1938 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind, OMPVersion) + "'")

1939 .str();

1940 if (SkipUntilOpenMPEnd)

1942}

1943

1944void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,

1947 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,

1948 Tok.getLocation(),

1949 false);

1950

1951 if (Tok.is(tok::annot_pragma_openmp_end))

1952 ConsumeAnnotationToken();

1953}

1954

1958 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&

1959 "Not an OpenMP directive!");

1962 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

1963

1964 SourceLocation Loc;

1966 if (Delayed) {

1967 TentativeParsingAction TPA(*this);

1968 Loc = ConsumeAnnotationToken();

1970 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {

1971

1972 TPA.Revert();

1974 unsigned Cnt = 1;

1975 Toks.push_back(Tok);

1976 while (Cnt && Tok.isNot(tok::eof)) {

1978 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))

1979 ++Cnt;

1980 else if (Tok.is(tok::annot_pragma_openmp_end))

1981 --Cnt;

1982 Toks.push_back(Tok);

1983 }

1984

1985 if (Cnt == 0)

1987 auto *LP = new LateParsedPragma(this, AS);

1988 LP->takeToks(Toks);

1989 getCurrentClass().LateParsedDeclarations.push_back(LP);

1990 return nullptr;

1991 }

1992 TPA.Commit();

1993 } else {

1994 Loc = ConsumeAnnotationToken();

1996 }

1997

1998 switch (DKind) {

1999 case OMPD_threadprivate: {

2001 DeclDirectiveListParserHelper Helper(this, DKind);

2002 if (!ParseOpenMPSimpleVarList(DKind, Helper,

2003 true)) {

2004 skipUntilPragmaOpenMPEnd(DKind);

2005

2006 ConsumeAnnotationToken();

2007 return Actions.OpenMP().ActOnOpenMPThreadprivateDirective(

2008 Loc, Helper.getIdentifiers());

2009 }

2010 break;

2011 }

2012 case OMPD_groupprivate: {

2014 DeclDirectiveListParserHelper Helper(this, DKind);

2015 if (!ParseOpenMPSimpleVarList(DKind, Helper,

2016 true)) {

2017 skipUntilPragmaOpenMPEnd(DKind);

2018

2019 ConsumeAnnotationToken();

2020 return Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(

2021 Loc, Helper.getIdentifiers());

2022 }

2023 break;

2024 }

2025 case OMPD_allocate: {

2027 DeclDirectiveListParserHelper Helper(this, DKind);

2028 if (!ParseOpenMPSimpleVarList(DKind, Helper,

2029 true)) {

2030 SmallVector<OMPClause *, 1> Clauses;

2031 if (Tok.isNot(tok::annot_pragma_openmp_end)) {

2032 std::bitset<llvm::omp::Clause_enumSize + 1> SeenClauses;

2033 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

2035 Tok.isAnnotation() ? OMPC_unknown

2036 : getOpenMPClauseKind(PP.getSpelling(Tok));

2037 Actions.OpenMP().StartOpenMPClause(CKind);

2038 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,

2039 !SeenClauses[unsigned(CKind)]);

2040 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,

2042 SeenClauses[unsigned(CKind)] = true;

2043 if (Clause != nullptr)

2044 Clauses.push_back(Clause);

2045 if (Tok.is(tok::annot_pragma_openmp_end)) {

2046 Actions.OpenMP().EndOpenMPClause();

2047 break;

2048 }

2049

2050 if (Tok.is(tok::comma))

2052 Actions.OpenMP().EndOpenMPClause();

2053 }

2054 skipUntilPragmaOpenMPEnd(DKind);

2055 }

2056

2057 ConsumeAnnotationToken();

2058 return Actions.OpenMP().ActOnOpenMPAllocateDirective(

2059 Loc, Helper.getIdentifiers(), Clauses);

2060 }

2061 break;

2062 }

2063 case OMPD_requires: {

2065 SmallVector<OMPClause *, 5> Clauses;

2066 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);

2067 if (Tok.is(tok::annot_pragma_openmp_end)) {

2068 Diag(Tok, diag::err_omp_expected_clause)

2069 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);

2070 break;

2071 }

2072 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

2074 ? OMPC_unknown

2075 : getOpenMPClauseKind(PP.getSpelling(Tok));

2076 Actions.OpenMP().StartOpenMPClause(CKind);

2077 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,

2078 !SeenClauses[unsigned(CKind)]);

2079 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,

2081 SeenClauses[unsigned(CKind)] = true;

2082 if (Clause != nullptr)

2083 Clauses.push_back(Clause);

2084 if (Tok.is(tok::annot_pragma_openmp_end)) {

2085 Actions.OpenMP().EndOpenMPClause();

2086 break;

2087 }

2088

2089 if (Tok.is(tok::comma))

2091 Actions.OpenMP().EndOpenMPClause();

2092 }

2093

2094 if (Clauses.empty()) {

2095 Diag(Tok, diag::err_omp_expected_clause)

2096 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);

2097 ConsumeAnnotationToken();

2098 return nullptr;

2099 }

2100 ConsumeAnnotationToken();

2101 return Actions.OpenMP().ActOnOpenMPRequiresDirective(StartLoc, Clauses);

2102 }

2103 case OMPD_error: {

2104 SmallVector<OMPClause *, 1> Clauses;

2106 ParseOpenMPClauses(DKind, Clauses, StartLoc);

2107 Actions.OpenMP().ActOnOpenMPErrorDirective(Clauses, StartLoc,

2108 SourceLocation(),

2109 false);

2110 break;

2111 }

2112 case OMPD_assumes:

2113 case OMPD_begin_assumes:

2114 ParseOpenMPAssumesDirective(DKind, ConsumeToken());

2115 break;

2116 case OMPD_end_assumes:

2117 ParseOpenMPEndAssumesDirective(ConsumeToken());

2118 break;

2119 case OMPD_declare_reduction:

2121 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {

2122 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);

2123

2124 ConsumeAnnotationToken();

2125 return Res;

2126 }

2127 break;

2128 case OMPD_declare_mapper: {

2130 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {

2131

2132 ConsumeAnnotationToken();

2133 return Res;

2134 }

2135 break;

2136 }

2137 case OMPD_begin_declare_variant: {

2140

2141 if (!isEofOrEom())

2142 ConsumeAnnotationToken();

2143 }

2144 return nullptr;

2145 }

2146 case OMPD_end_declare_variant: {

2148 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())

2149 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();

2150 else

2151 Diag(Loc, diag::err_expected_begin_declare_variant);

2152

2153 ConsumeAnnotationToken();

2154 return nullptr;

2155 }

2156 case OMPD_declare_variant:

2157 case OMPD_declare_simd: {

2158

2159

2160

2161

2163 Toks.push_back(Tok);

2165 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

2166 Toks.push_back(Tok);

2168 }

2169 Toks.push_back(Tok);

2171

2173 if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {

2174 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,

2175 TagType, Tag);

2176 } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {

2177

2180 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);

2181 MaybeParseCXX11Attributes(Attrs);

2182 ParsingDeclSpec PDS(*this);

2183 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);

2184 } else {

2185 Ptr =

2186 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);

2187 }

2188 }

2189 if (!Ptr) {

2190 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)

2191 << (DKind == OMPD_declare_simd ? 0 : 1);

2193 }

2194 if (DKind == OMPD_declare_simd)

2195 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);

2196 assert(DKind == OMPD_declare_variant &&

2197 "Expected declare variant directive only");

2198 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);

2199 return Ptr;

2200 }

2201 case OMPD_begin_declare_target:

2202 case OMPD_declare_target: {

2204 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);

2205 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);

2206 if (DKind == OMPD_declare_target && !HasClauses &&

2208 Diag(DTLoc, diag::warn_omp_deprecated_declare_target_delimited_form);

2209 if (HasClauses)

2210 ParseOMPDeclareTargetClauses(DTCI);

2211 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||

2212 !HasClauses ||

2214

2215

2217

2218 if (HasImplicitMappings) {

2219 Actions.OpenMP().ActOnStartOpenMPDeclareTargetContext(DTCI);

2220 return nullptr;

2221 }

2222

2223 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);

2224 llvm::SmallVector<Decl *, 4> Decls;

2226 Decls.push_back(It.first);

2227 return Actions.BuildDeclaratorGroup(Decls);

2228 }

2229 case OMPD_end_declare_target: {

2230 if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {

2231 Diag(Tok, diag::err_omp_unexpected_directive)

2232 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);

2233 break;

2234 }

2235 const SemaOpenMP::DeclareTargetContextInfo &DTCI =

2236 Actions.OpenMP().ActOnOpenMPEndDeclareTargetDirective();

2237 ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);

2238 return nullptr;

2239 }

2240 case OMPD_assume: {

2241 Diag(Tok, diag::err_omp_unexpected_directive)

2242 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);

2243 break;

2244 }

2245 case OMPD_unknown:

2246 Diag(Tok, diag::err_omp_unknown_directive);

2247 break;

2248 default:

2249 switch (getDirectiveCategory(DKind)) {

2250 case Category::Executable:

2251 case Category::Meta:

2252 case Category::Subsidiary:

2253 case Category::Utility:

2254 Diag(Tok, diag::err_omp_unexpected_directive)

2255 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);

2256 break;

2257 case Category::Declarative:

2258 case Category::Informational:

2259 break;

2260 }

2261 }

2262 while (Tok.isNot(tok::annot_pragma_openmp_end))

2265 return nullptr;

2266}

2267

2268StmtResult Parser::ParseOpenMPExecutableDirective(

2270 bool ReadDirectiveWithinMetadirective) {

2272 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

2273

2274 bool HasAssociatedStatement = true;

2275 Association Assoc = getDirectiveAssociation(DKind);

2276

2277

2278

2279

2280

2281 if (DKind != OMPD_ordered && DKind != OMPD_section &&

2282 (Assoc == Association::None || Assoc == Association::Separating)) {

2283 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==

2284 ParsedStmtContext()) {

2285 Diag(Tok, diag::err_omp_immediate_directive)

2286 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;

2287 if (DKind == OMPD_error) {

2288 SkipUntil(tok::annot_pragma_openmp_end);

2290 }

2291 }

2292 HasAssociatedStatement = false;

2293 }

2294

2295 SourceLocation EndLoc;

2296 SmallVector<OMPClause *, 5> Clauses;

2297 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);

2298 DeclarationNameInfo DirName;

2302

2303

2304 Token ImplicitTok;

2305 bool ImplicitClauseAllowed = false;

2306 if (DKind == OMPD_flush || DKind == OMPD_depobj) {

2307 ImplicitTok = Tok;

2308 ImplicitClauseAllowed = true;

2309 }

2311

2312 if (DKind == OMPD_critical) {

2314 tok::annot_pragma_openmp_end);

2315 if (T.consumeOpen()) {

2316 if (Tok.isAnyIdentifier()) {

2317 DirName =

2318 DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());

2320 } else {

2321 Diag(Tok, diag::err_omp_expected_identifier_for_critical);

2322 }

2323 T.consumeClose();

2324 }

2325 } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {

2327 if (Tok.isNot(tok::annot_pragma_openmp_end))

2329 }

2330

2335 ParseScope OMPDirectiveScope(this, ScopeFlags);

2336 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),

2337 Loc);

2338

2339 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

2340

2341

2342 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {

2343 while (Tok.isNot(tok::annot_pragma_openmp_end))

2345 break;

2346 }

2347 bool HasImplicitClause = false;

2348 if (ImplicitClauseAllowed && Tok.is(tok::l_paren)) {

2349 HasImplicitClause = true;

2350

2351

2352 PP.EnterToken(Tok, true);

2353 PP.EnterToken(ImplicitTok, true);

2355 }

2357 ? OMPC_unknown

2358 : getOpenMPClauseKind(PP.getSpelling(Tok));

2359 if (HasImplicitClause) {

2360 assert(CKind == OMPC_unknown && "Must be unknown implicit clause.");

2361 if (DKind == OMPD_flush) {

2362 CKind = OMPC_flush;

2363 } else {

2364 assert(DKind == OMPD_depobj && "Expected flush or depobj directives.");

2365 CKind = OMPC_depobj;

2366 }

2367 }

2368

2369 ImplicitClauseAllowed = false;

2370 Actions.OpenMP().StartOpenMPClause(CKind);

2371 HasImplicitClause = false;

2372 OMPClause *Clause =

2373 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);

2374 SeenClauses[unsigned(CKind)] = true;

2375 if (Clause)

2376 Clauses.push_back(Clause);

2377

2378

2379 if (Tok.is(tok::comma))

2381 Actions.OpenMP().EndOpenMPClause();

2382 }

2383

2384 EndLoc = Tok.getLocation();

2385

2386 ConsumeAnnotationToken();

2387

2388 if (DKind == OMPD_ordered) {

2389

2390

2391 for (auto CK : {OMPC_depend, OMPC_doacross}) {

2392 if (SeenClauses[unsigned(CK)]) {

2393 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==

2394 ParsedStmtContext()) {

2395 Diag(Loc, diag::err_omp_immediate_directive)

2396 << getOpenMPDirectiveName(DKind, OMPVersion) << 1

2397 << getOpenMPClauseName(CK);

2398 }

2399 HasAssociatedStatement = false;

2400 }

2401 }

2402 }

2403

2404 if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&

2405 !SeenClauses[unsigned(OMPC_sizes)]) {

2406 Diag(Loc, diag::err_omp_required_clause)

2407 << getOpenMPDirectiveName(DKind, OMPVersion) << "sizes";

2408 }

2409

2411 if (HasAssociatedStatement) {

2412

2413 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());

2414

2415

2416

2418 {

2419 Sema::CompoundScopeRAII Scope(Actions);

2420 AssociatedStmt = ParseStatement();

2421

2424 AssociatedStmt =

2425 Actions.OpenMP().ActOnOpenMPLoopnest(AssociatedStmt.get());

2426 }

2427 AssociatedStmt =

2428 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);

2429 } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||

2430 DKind == OMPD_target_exit_data) {

2431 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());

2432 AssociatedStmt = (Sema::CompoundScopeRAII(Actions),

2433 Actions.ActOnCompoundStmt(Loc, Loc, {},

2434 false));

2435 AssociatedStmt =

2436 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);

2437 }

2438

2440 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, EndLoc);

2441

2442

2443 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());

2444 OMPDirectiveScope.Exit();

2445

2447}

2448

2449StmtResult Parser::ParseOpenMPInformationalDirective(

2451 bool ReadDirectiveWithinMetadirective) {

2453 "Unexpected directive category");

2454

2455 bool HasAssociatedStatement = true;

2456

2457 SmallVector<OMPClause *, 5> Clauses;

2458 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);

2459 DeclarationNameInfo DirName;

2462 ParseScope OMPDirectiveScope(this, ScopeFlags);

2463

2464 Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),

2465 Loc);

2466

2467 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

2468 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {

2469 while (Tok.isNot(tok::annot_pragma_openmp_end))

2471 break;

2472 }

2473

2475 ? OMPC_unknown

2476 : getOpenMPClauseKind(PP.getSpelling(Tok));

2477 Actions.OpenMP().StartOpenMPClause(CKind);

2478 OMPClause *Clause =

2479 ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);

2480 SeenClauses[unsigned(CKind)] = true;

2481 if (Clause)

2482 Clauses.push_back(Clause);

2483

2484 if (Tok.is(tok::comma))

2486 Actions.OpenMP().EndOpenMPClause();

2487 }

2488

2489 SourceLocation EndLoc = Tok.getLocation();

2490 ConsumeAnnotationToken();

2491

2493 if (HasAssociatedStatement) {

2494 Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());

2496 {

2497 Sema::CompoundScopeRAII Scope(Actions);

2498 AssociatedStmt = ParseStatement();

2499 }

2500 AssociatedStmt =

2501 Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);

2502 }

2503

2504 StmtResult Directive = Actions.OpenMP().ActOnOpenMPInformationalDirective(

2505 DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);

2506

2507 Actions.OpenMP().EndOpenMPDSABlock(Directive.get());

2508 OMPDirectiveScope.Exit();

2509

2511}

2512

2513StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(

2514 ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {

2515 if (!ReadDirectiveWithinMetadirective)

2516 assert(Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&

2517 "Not an OpenMP directive!");

2520 SourceLocation Loc = ReadDirectiveWithinMetadirective

2521 ? Tok.getLocation()

2522 : ConsumeAnnotationToken();

2523 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

2525 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {

2526 Diag(Tok, diag::err_omp_unknown_directive);

2528 }

2529

2531

2532 bool IsExecutable = [&]() {

2533 if (DKind == OMPD_error)

2534 return true;

2535 auto Res = getDirectiveCategory(DKind);

2536 return Res == Category::Executable || Res == Category::Subsidiary;

2537 }();

2538

2539 if (IsExecutable) {

2540 Directive = ParseOpenMPExecutableDirective(

2541 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);

2542 assert(Directive.isUnset() && "Executable directive remained unprocessed");

2544 }

2545

2546 switch (DKind) {

2547 case OMPD_nothing:

2549

2550

2551 if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren))

2552 while (Tok.isNot(tok::annot_pragma_openmp_end))

2554 else

2555 skipUntilPragmaOpenMPEnd(DKind);

2556 if (Tok.is(tok::annot_pragma_openmp_end))

2557 ConsumeAnnotationToken();

2558

2560 case OMPD_metadirective: {

2562 SmallVector<VariantMatchInfo, 4> VMIs;

2563

2564

2565

2566

2567 TentativeParsingAction TPA(*this);

2568 ASTContext &ASTContext = Actions.getASTContext();

2569

2571 tok::annot_pragma_openmp_end);

2572 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

2574 ? OMPC_unknown

2575 : getOpenMPClauseKind(PP.getSpelling(Tok));

2576

2577 if (CKind == OMPC_unknown) {

2578 Diag(Tok, diag::err_omp_expected_clause) << "metadirective";

2579 TPA.Revert();

2580 SkipUntil(tok::annot_pragma_openmp_end);

2582 }

2583 if (getLangOpts().OpenMP < 52 && CKind == OMPC_otherwise)

2584 Diag(Tok, diag::err_omp_unexpected_clause)

2585 << getOpenMPClauseName(CKind) << "metadirective";

2586 if (CKind == OMPC_default && getLangOpts().OpenMP >= 52)

2587 Diag(Tok, diag::warn_omp_default_deprecated);

2588

2590

2591

2592 if (T.expectAndConsume(diag::err_expected_lparen_after,

2593 getOpenMPClauseName(CKind).data())) {

2594 TPA.Revert();

2595 SkipUntil(tok::annot_pragma_openmp_end);

2597 }

2598

2599 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();

2600 if (CKind == OMPC_when) {

2601

2602 parseOMPContextSelectors(Loc, TI);

2603 if (TI.Sets.size() == 0) {

2604 Diag(Tok, diag::err_omp_expected_context_selector) << "when clause";

2605 TPA.Commit();

2607 }

2608

2609

2610 if (Tok.is(tok::colon))

2612 else {

2613 Diag(Tok, diag::err_omp_expected_colon) << "when clause";

2614 TPA.Commit();

2616 }

2617 }

2618

2619

2620 int paren = 0;

2621 while (Tok.isNot(tok::r_paren) || paren != 0) {

2622 if (Tok.is(tok::l_paren))

2623 paren++;

2624 if (Tok.is(tok::r_paren))

2625 paren--;

2626 if (Tok.is(tok::annot_pragma_openmp_end)) {

2627 Diag(Tok, diag::err_omp_expected_punc)

2628 << getOpenMPClauseName(CKind) << 0;

2629 TPA.Commit();

2631 }

2633 }

2634

2635 if (Tok.is(tok::r_paren))

2636 T.consumeClose();

2637

2638 VariantMatchInfo VMI;

2640

2641 VMIs.push_back(VMI);

2642 }

2643

2644 TPA.Revert();

2645

2646

2647 std::function<void(StringRef)> DiagUnknownTrait =

2648 [this, Loc](StringRef ISATrait) {

2649

2650

2651 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;

2652 };

2653 TargetOMPContext OMPCtx(ASTContext, std::move(DiagUnknownTrait),

2654 nullptr,

2655 ArrayRefllvm::omp::TraitProperty(),

2656 Actions.OpenMP().getOpenMPDeviceNum());

2657

2658

2659 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);

2660

2661 int Idx = 0;

2662

2663

2664

2665

2666 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

2667

2668 if (Idx++ != BestIdx) {

2670 T.consumeOpen();

2671 int paren = 0;

2672

2673 while (Tok.isNot(tok::r_paren) || paren != 0) {

2674 if (Tok.is(tok::l_paren))

2675 paren++;

2676 if (Tok.is(tok::r_paren))

2677 paren--;

2679 }

2680

2681 if (Tok.is(tok::r_paren))

2682 T.consumeClose();

2683 continue;

2684 }

2685

2687 ? OMPC_unknown

2688 : getOpenMPClauseKind(PP.getSpelling(Tok));

2690

2691

2692 T.consumeOpen();

2693

2694

2695 if (CKind == OMPC_when) {

2696 OMPTraitInfo &TI = Actions.getASTContext().getNewOMPTraitInfo();

2697

2698 parseOMPContextSelectors(Loc, TI);

2699

2700

2702 }

2703

2704

2705

2706 if (Tok.is(tok::r_paren)) {

2707 SkipUntil(tok::annot_pragma_openmp_end);

2708 break;

2709 }

2710

2711

2712 Directive = ParseOpenMPDeclarativeOrExecutableDirective(

2713 StmtCtx,

2714 true);

2715 break;

2716 }

2717

2718

2719

2720 if (BestIdx == -1 && Idx > 0) {

2721 assert(Tok.is(tok::annot_pragma_openmp_end) &&

2722 "Expecting the end of the pragma here");

2723 ConsumeAnnotationToken();

2725 }

2726 break;

2727 }

2728 case OMPD_threadprivate: {

2729

2730 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==

2731 ParsedStmtContext()) {

2732 Diag(Tok, diag::err_omp_immediate_directive)

2733 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;

2734 }

2736 DeclDirectiveListParserHelper Helper(this, DKind);

2737 if (!ParseOpenMPSimpleVarList(DKind, Helper,

2738 false)) {

2739 skipUntilPragmaOpenMPEnd(DKind);

2740 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPThreadprivateDirective(

2741 Loc, Helper.getIdentifiers());

2742 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());

2743 }

2744 SkipUntil(tok::annot_pragma_openmp_end);

2745 break;

2746 }

2747 case OMPD_groupprivate: {

2748 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==

2749 ParsedStmtContext()) {

2750 Diag(Tok, diag::err_omp_immediate_directive)

2751 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;

2752 }

2754 DeclDirectiveListParserHelper Helper(this, DKind);

2755 if (!ParseOpenMPSimpleVarList(DKind, Helper,

2756 false)) {

2757 skipUntilPragmaOpenMPEnd(DKind);

2758 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPGroupPrivateDirective(

2759 Loc, Helper.getIdentifiers());

2760 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());

2761 }

2762 SkipUntil(tok::annot_pragma_openmp_end);

2763 break;

2764 }

2765 case OMPD_allocate: {

2766

2767 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==

2768 ParsedStmtContext()) {

2769 Diag(Tok, diag::err_omp_immediate_directive)

2770 << getOpenMPDirectiveName(DKind, OMPVersion) << 0;

2771 }

2773 DeclDirectiveListParserHelper Helper(this, DKind);

2774 if (!ParseOpenMPSimpleVarList(DKind, Helper,

2775 false)) {

2776 SmallVector<OMPClause *, 1> Clauses;

2777 if (Tok.isNot(tok::annot_pragma_openmp_end)) {

2778 llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);

2779 while (Tok.isNot(tok::annot_pragma_openmp_end)) {

2781 Tok.isAnnotation() ? OMPC_unknown

2782 : getOpenMPClauseKind(PP.getSpelling(Tok));

2783 Actions.OpenMP().StartOpenMPClause(CKind);

2784 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,

2785 !SeenClauses[unsigned(CKind)]);

2786 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,

2788 SeenClauses[unsigned(CKind)] = true;

2789 if (Clause != nullptr)

2790 Clauses.push_back(Clause);

2791 if (Tok.is(tok::annot_pragma_openmp_end)) {

2792 Actions.OpenMP().EndOpenMPClause();

2793 break;

2794 }

2795

2796 if (Tok.is(tok::comma))

2798 Actions.OpenMP().EndOpenMPClause();

2799 }

2800 skipUntilPragmaOpenMPEnd(DKind);

2801 }

2802 DeclGroupPtrTy Res = Actions.OpenMP().ActOnOpenMPAllocateDirective(

2803 Loc, Helper.getIdentifiers(), Clauses);

2804 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());

2805 }

2806 SkipUntil(tok::annot_pragma_openmp_end);

2807 break;

2808 }

2809 case OMPD_declare_reduction:

2812 ParseOpenMPDeclareReductionDirective(AS_none)) {

2813 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);

2815 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());

2816 } else {

2817 SkipUntil(tok::annot_pragma_openmp_end);

2818 }

2819 break;

2820 case OMPD_declare_mapper: {

2823 ParseOpenMPDeclareMapperDirective(AS_none)) {

2824

2825 ConsumeAnnotationToken();

2826 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());

2827 } else {

2828 SkipUntil(tok::annot_pragma_openmp_end);

2829 }

2830 break;

2831 }

2832 case OMPD_declare_target: {

2834 bool HasClauses = Tok.isNot(tok::annot_pragma_openmp_end);

2835 SemaOpenMP::DeclareTargetContextInfo DTCI(DKind, DTLoc);

2836 if (HasClauses)

2837 ParseOMPDeclareTargetClauses(DTCI);

2838 bool HasImplicitMappings =

2840

2841 if (HasImplicitMappings) {

2842 Diag(Tok, diag::err_omp_unexpected_directive)

2843 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);

2844 SkipUntil(tok::annot_pragma_openmp_end);

2845 break;

2846 }

2847

2848

2850

2851 Actions.OpenMP().ActOnFinishedOpenMPDeclareTargetContext(DTCI);

2852 break;

2853 }

2854 case OMPD_begin_declare_variant: {

2857

2858 if (!isEofOrEom())

2859 ConsumeAnnotationToken();

2860 }

2862 }

2863 case OMPD_end_declare_variant: {

2865 if (Actions.OpenMP().isInOpenMPDeclareVariantScope())

2866 Actions.OpenMP().ActOnOpenMPEndDeclareVariant();

2867 else

2868 Diag(Loc, diag::err_expected_begin_declare_variant);

2869 ConsumeAnnotationToken();

2870 break;

2871 }

2872 case OMPD_declare_simd:

2873 case OMPD_begin_declare_target:

2874 case OMPD_end_declare_target:

2875 case OMPD_requires:

2876 case OMPD_declare_variant:

2877 Diag(Tok, diag::err_omp_unexpected_directive)

2878 << 1 << getOpenMPDirectiveName(DKind, OMPVersion);

2879 SkipUntil(tok::annot_pragma_openmp_end);

2880 break;

2881 case OMPD_assume: {

2883 Directive = ParseOpenMPInformationalDirective(

2884 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);

2886 "Informational directive remains unprocessed");

2888 }

2889 case OMPD_unknown:

2890 default:

2891 Diag(Tok, diag::err_omp_unknown_directive);

2892 SkipUntil(tok::annot_pragma_openmp_end);

2893 break;

2894 }

2896}

2897

2898bool Parser::ParseOpenMPSimpleVarList(

2901 &Callback,

2902 bool AllowScopeSpecifier) {

2903 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

2904

2906 if (T.expectAndConsume(diag::err_expected_lparen_after,

2907 getOpenMPDirectiveName(Kind, OMPVersion).data()))

2908 return true;

2909 bool IsCorrect = true;

2910 bool NoIdentIsFound = true;

2911

2912

2913 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {

2914 CXXScopeSpec SS;

2916

2917 Token PrevTok = Tok;

2918 NoIdentIsFound = false;

2919

2921 ParseOptionalCXXScopeSpecifier(SS, nullptr,

2922 false, false)) {

2923 IsCorrect = false;

2924 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

2927 false, false, false,

2928 false, false, nullptr, Name)) {

2929 IsCorrect = false;

2930 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

2932 } else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&

2933 Tok.isNot(tok::annot_pragma_openmp_end)) {

2934 IsCorrect = false;

2935 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

2938 << tok::identifier

2939 << SourceRange(PrevTok.getLocation(), PrevTokLocation);

2940 } else {

2941 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));

2942 }

2943

2944 if (Tok.is(tok::comma)) {

2946 }

2947 }

2948

2949 if (NoIdentIsFound) {

2950 Diag(Tok, diag::err_expected) << tok::identifier;

2951 IsCorrect = false;

2952 }

2953

2954

2955 IsCorrect = T.consumeClose() && IsCorrect;

2956

2957 return !IsCorrect;

2958}

2959

2960OMPClause *Parser::ParseOpenMPSizesClause() {

2961 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;

2962 SmallVector<Expr *, 4> ValExprs;

2963 if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,

2964 ValExprs))

2965 return nullptr;

2966

2967 return Actions.OpenMP().ActOnOpenMPSizesClause(ValExprs, ClauseNameLoc,

2968 OpenLoc, CloseLoc);

2969}

2970

2971OMPClause *Parser::ParseOpenMPLoopRangeClause() {

2972 SourceLocation ClauseNameLoc = ConsumeToken();

2973 SourceLocation FirstLoc, CountLoc;

2974

2976 if (T.consumeOpen()) {

2977 Diag(Tok, diag::err_expected) << tok::l_paren;

2978 return nullptr;

2979 }

2980

2981 FirstLoc = Tok.getLocation();

2984 T.skipToEnd();

2985 return nullptr;

2986 }

2987

2988 ExpectAndConsume(tok::comma);

2989

2990 CountLoc = Tok.getLocation();

2993 T.skipToEnd();

2994 return nullptr;

2995 }

2996

2997 T.consumeClose();

2998

2999 return Actions.OpenMP().ActOnOpenMPLoopRangeClause(

3000 FirstVal.get(), CountVal.get(), ClauseNameLoc, T.getOpenLocation(),

3001 FirstLoc, CountLoc, T.getCloseLocation());

3002}

3003

3004OMPClause *Parser::ParseOpenMPPermutationClause() {

3005 SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;

3006 SmallVector<Expr *> ArgExprs;

3007 if (ParseOpenMPExprListClause(OMPC_permutation, ClauseNameLoc, OpenLoc,

3008 CloseLoc, ArgExprs,

3009 true))

3010 return nullptr;

3011

3012 return Actions.OpenMP().ActOnOpenMPPermutationClause(ArgExprs, ClauseNameLoc,

3013 OpenLoc, CloseLoc);

3014}

3015

3017 SourceLocation Loc = Tok.getLocation();

3019

3020

3022 if (T.expectAndConsume(diag::err_expected_lparen_after, "uses_allocator"))

3023 return nullptr;

3024 SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;

3025 do {

3026

3027 if (getLangOpts().OpenMP >= 52 && Tok.is(tok::identifier) &&

3028 Tok.getIdentifierInfo()->getName() == "traits") {

3029

3030 SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();

3031

3033

3034

3036 tok::annot_pragma_openmp_end);

3037 TraitParens.consumeOpen();

3040 TraitParens.consumeClose();

3041

3042 if (AllocatorTraits.isInvalid()) {

3043 SkipUntil(

3044 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},

3046 break;

3047 }

3048

3049

3050 if (Tok.isNot(tok::colon)) {

3051 Diag(Tok, diag::err_expected) << tok::colon;

3053 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},

3055 continue;

3056 }

3058

3059 CXXScopeSpec SS;

3060 Token Replacement;

3063 ? ParseCXXIdExpression()

3064 : tryParseCXXIdExpression(SS, false,

3065 Replacement);

3066

3067 if (AllocatorExpr.isInvalid()) {

3068 SkipUntil(

3069 {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},

3071 break;

3072 }

3073

3076 D.LParenLoc = TraitParens.getOpenLocation();

3077 D.RParenLoc = TraitParens.getCloseLocation();

3078

3079

3080 if (Tok.is(tok::comma)) {

3081

3082 Diag(Tok.getLocation(), diag::err_omp_allocator_comma_separator)

3085 } else if (Tok.is(tok::semi)) {

3087 }

3088

3089 continue;

3090 }

3091

3092

3094 Token Replacement;

3096 getLangOpts().CPlusPlus

3097 ? ParseCXXIdExpression()

3098 : tryParseCXXIdExpression(SS, false,

3099 Replacement);

3101 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

3102 StopBeforeMatch);

3103 break;

3104 }

3107 if (Tok.is(tok::l_paren)) {

3108 BalancedDelimiterTracker T(*this, tok::l_paren,

3109 tok::annot_pragma_openmp_end);

3110 T.consumeOpen();

3111 ExprResult AllocatorTraits =

3112 getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();

3113 T.consumeClose();

3114 if (AllocatorTraits.isInvalid()) {

3115 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

3116 StopBeforeMatch);

3117 break;

3118 }

3122

3123

3124 if (getLangOpts().OpenMP >= 52) {

3125 Diag(Loc, diag::err_omp_deprecate_old_syntax)

3126 << "allocator(expr)"

3127 << "uses_allocators"

3128 << "traits(expr): alloc";

3129 }

3130 }

3132 Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;

3133

3134 if (Tok.is(tok::comma))

3135 ConsumeAnyToken();

3136 } while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end));

3137 T.consumeClose();

3139 Loc, T.getOpenLocation(), T.getCloseLocation(), Data);

3140}

3141

3144 OMPClauseKind = CKind;

3145 OMPClause *Clause = nullptr;

3146 bool ErrorFound = false;

3147 bool WrongDirective = false;

3148 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

3149

3150

3151 if (CKind != OMPC_unknown &&

3152 !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {

3153 Diag(Tok, diag::err_omp_unexpected_clause)

3154 << getOpenMPClauseName(CKind)

3155 << getOpenMPDirectiveName(DKind, OMPVersion);

3156 ErrorFound = true;

3157 WrongDirective = true;

3158 }

3159

3160 switch (CKind) {

3161 case OMPC_final:

3162 case OMPC_num_threads:

3163 case OMPC_safelen:

3164 case OMPC_simdlen:

3165 case OMPC_collapse:

3166 case OMPC_ordered:

3167 case OMPC_priority:

3168 case OMPC_grainsize:

3169 case OMPC_num_tasks:

3170 case OMPC_hint:

3171 case OMPC_allocator:

3172 case OMPC_depobj:

3173 case OMPC_detach:

3174 case OMPC_novariants:

3175 case OMPC_nocontext:

3176 case OMPC_filter:

3177 case OMPC_partial:

3178 case OMPC_align:

3179 case OMPC_message:

3180 case OMPC_ompx_dyn_cgroup_mem:

3181 case OMPC_dyn_groupprivate:

3182

3183

3184

3185

3186

3187

3188

3189

3190

3191

3192

3193

3194

3195

3196

3197

3198

3199

3200

3201

3202

3203

3204

3205

3206

3207

3208

3209 if (!FirstClause) {

3210 Diag(Tok, diag::err_omp_more_one_clause)

3211 << getOpenMPDirectiveName(DKind, OMPVersion)

3212 << getOpenMPClauseName(CKind) << 0;

3213 ErrorFound = true;

3214 }

3215

3216 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&

3217 PP.LookAhead(0).isNot(tok::l_paren))

3218 Clause = ParseOpenMPClause(CKind, WrongDirective);

3219 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks ||

3220 CKind == OMPC_num_threads || CKind == OMPC_dyn_groupprivate)

3221 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);

3222 else

3223 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);

3224 break;

3225 case OMPC_threadset:

3226 case OMPC_fail:

3227 case OMPC_proc_bind:

3228 case OMPC_atomic_default_mem_order:

3229 case OMPC_at:

3230 case OMPC_severity:

3231 case OMPC_bind:

3232

3233

3234

3235

3236

3237

3238

3239

3240

3241

3242

3243

3244

3245 if (!FirstClause) {

3246 Diag(Tok, diag::err_omp_more_one_clause)

3247 << getOpenMPDirectiveName(DKind, OMPVersion)

3248 << getOpenMPClauseName(CKind) << 0;

3249 ErrorFound = true;

3250 }

3251

3252 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);

3253 break;

3254 case OMPC_device:

3255 case OMPC_schedule:

3256 case OMPC_dist_schedule:

3257 case OMPC_defaultmap:

3258 case OMPC_default:

3259 case OMPC_order:

3260

3261

3262

3263

3264

3265

3266

3267

3268 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&

3269 (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {

3270 Diag(Tok, diag::err_omp_more_one_clause)

3271 << getOpenMPDirectiveName(DKind, OMPVersion)

3272 << getOpenMPClauseName(CKind) << 0;

3273 ErrorFound = true;

3274 }

3275 [[fallthrough]];

3276 case OMPC_if:

3277 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);

3278 break;

3279 case OMPC_holds:

3280 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);

3281 break;

3282 case OMPC_nowait:

3283 case OMPC_untied:

3284 case OMPC_mergeable:

3285 case OMPC_read:

3286 case OMPC_write:

3287 case OMPC_capture:

3288 case OMPC_compare:

3289 case OMPC_seq_cst:

3290 case OMPC_acq_rel:

3291 case OMPC_acquire:

3292 case OMPC_release:

3293 case OMPC_relaxed:

3294 case OMPC_weak:

3295 case OMPC_threads:

3296 case OMPC_simd:

3297 case OMPC_nogroup:

3298 case OMPC_unified_address:

3299 case OMPC_unified_shared_memory:

3300 case OMPC_reverse_offload:

3301 case OMPC_dynamic_allocators:

3302 case OMPC_full:

3303

3304

3305

3306

3307

3308

3309 if (!FirstClause) {

3310 Diag(Tok, diag::err_omp_more_one_clause)

3311 << getOpenMPDirectiveName(DKind, OMPVersion)

3312 << getOpenMPClauseName(CKind) << 0;

3313 ErrorFound = true;

3314 }

3315

3316 if (CKind == OMPC_nowait && PP.LookAhead(0).is(tok::l_paren) &&

3318 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);

3319 else

3320 Clause = ParseOpenMPClause(CKind, WrongDirective);

3321 break;

3322 case OMPC_self_maps:

3323

3325 Diag(Tok, diag::err_omp_expected_clause)

3326 << getOpenMPDirectiveName(OMPD_requires, OMPVersion);

3327 ErrorFound = true;

3328 }

3329 if (!FirstClause) {

3330 Diag(Tok, diag::err_omp_more_one_clause)

3331 << getOpenMPDirectiveName(DKind, OMPVersion)

3332 << getOpenMPClauseName(CKind) << 0;

3333 ErrorFound = true;

3334 }

3335 Clause = ParseOpenMPClause(CKind, WrongDirective);

3336 break;

3337 case OMPC_update:

3338 if (!FirstClause) {

3339 Diag(Tok, diag::err_omp_more_one_clause)

3340 << getOpenMPDirectiveName(DKind, OMPVersion)

3341 << getOpenMPClauseName(CKind) << 0;

3342 ErrorFound = true;

3343 }

3344

3345 Clause = (DKind == OMPD_depobj)

3346 ? ParseOpenMPSimpleClause(CKind, WrongDirective)

3347 : ParseOpenMPClause(CKind, WrongDirective);

3348 break;

3349 case OMPC_num_teams:

3350 case OMPC_thread_limit:

3351 if (!FirstClause) {

3352 Diag(Tok, diag::err_omp_more_one_clause)

3353 << getOpenMPDirectiveName(DKind, OMPVersion)

3354 << getOpenMPClauseName(CKind) << 0;

3355 ErrorFound = true;

3356 }

3357 [[fallthrough]];

3358 case OMPC_private:

3359 case OMPC_firstprivate:

3360 case OMPC_lastprivate:

3361 case OMPC_shared:

3362 case OMPC_reduction:

3363 case OMPC_task_reduction:

3364 case OMPC_in_reduction:

3365 case OMPC_linear:

3366 case OMPC_aligned:

3367 case OMPC_copyin:

3368 case OMPC_copyprivate:

3369 case OMPC_flush:

3370 case OMPC_depend:

3371 case OMPC_map:

3372 case OMPC_to:

3373 case OMPC_from:

3374 case OMPC_use_device_ptr:

3375 case OMPC_use_device_addr:

3376 case OMPC_is_device_ptr:

3377 case OMPC_has_device_addr:

3378 case OMPC_allocate:

3379 case OMPC_nontemporal:

3380 case OMPC_inclusive:

3381 case OMPC_exclusive:

3382 case OMPC_affinity:

3383 case OMPC_doacross:

3384 case OMPC_enter:

3385 if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&

3386 CKind == OMPC_depend)

3387 Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);

3388 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);

3389 break;

3390 case OMPC_sizes:

3391 if (!FirstClause) {

3392 Diag(Tok, diag::err_omp_more_one_clause)

3393 << getOpenMPDirectiveName(DKind, OMPVersion)

3394 << getOpenMPClauseName(CKind) << 0;

3395 ErrorFound = true;

3396 }

3397

3398 Clause = ParseOpenMPSizesClause();

3399 break;

3400 case OMPC_permutation:

3401 if (!FirstClause) {

3402 Diag(Tok, diag::err_omp_more_one_clause)

3403 << getOpenMPDirectiveName(DKind, OMPVersion)

3404 << getOpenMPClauseName(CKind) << 0;

3405 ErrorFound = true;

3406 }

3407 Clause = ParseOpenMPPermutationClause();

3408 break;

3409 case OMPC_uses_allocators:

3410 Clause = ParseOpenMPUsesAllocatorClause(DKind);

3411 break;

3412 case OMPC_destroy:

3413 if (DKind != OMPD_interop) {

3414 if (!FirstClause) {

3415 Diag(Tok, diag::err_omp_more_one_clause)

3416 << getOpenMPDirectiveName(DKind, OMPVersion)

3417 << getOpenMPClauseName(CKind) << 0;

3418 ErrorFound = true;

3419 }

3420 Clause = ParseOpenMPClause(CKind, WrongDirective);

3421 break;

3422 }

3423 [[fallthrough]];

3424 case OMPC_init:

3425 case OMPC_use:

3426 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);

3427 break;

3428 case OMPC_device_type:

3429 case OMPC_unknown:

3430 skipUntilPragmaOpenMPEnd(DKind);

3431 break;

3432 case OMPC_threadprivate:

3433 case OMPC_groupprivate:

3434 case OMPC_uniform:

3435 case OMPC_match:

3436 if (!WrongDirective)

3437 Diag(Tok, diag::err_omp_unexpected_clause)

3438 << getOpenMPClauseName(CKind)

3439 << getOpenMPDirectiveName(DKind, OMPVersion);

3441 break;

3442 case OMPC_absent:

3443 case OMPC_contains: {

3445 SourceLocation LLoc = Tok.getLocation();

3446 SourceLocation RLoc;

3447 llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;

3449 T.consumeOpen();

3450 do {

3452 if (DK == OMPD_unknown) {

3453 skipUntilPragmaOpenMPEnd(OMPD_assume);

3454 Diag(Tok, diag::err_omp_unexpected_clause)

3455 << getOpenMPClauseName(CKind)

3456 << getOpenMPDirectiveName(DKind, OMPVersion);

3457 break;

3458 }

3460 DKVec.push_back(DK);

3462 } else {

3463 Diag(Tok, diag::err_omp_unexpected_clause)

3464 << getOpenMPClauseName(CKind)

3465 << getOpenMPDirectiveName(DKind, OMPVersion);

3466 }

3468 RLoc = Tok.getLocation();

3469 T.consumeClose();

3470 Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(

3471 CKind, DKVec, Loc, LLoc, RLoc);

3472 break;

3473 }

3474 case OMPC_no_openmp:

3475 case OMPC_no_openmp_routines:

3476 case OMPC_no_openmp_constructs:

3477 case OMPC_no_parallelism: {

3478 if (!FirstClause) {

3479 Diag(Tok, diag::err_omp_more_one_clause)

3480 << getOpenMPDirectiveName(DKind, OMPVersion)

3481 << getOpenMPClauseName(CKind) << 0;

3482 ErrorFound = true;

3483 }

3485 Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(

3486 CKind, Loc, Tok.getLocation());

3487 break;

3488 }

3489 case OMPC_ompx_attribute:

3490 Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);

3491 break;

3492 case OMPC_ompx_bare:

3493 if (DKind == llvm::omp::Directive::OMPD_target) {

3494

3495

3496

3497

3498 Diag(Tok, diag::err_omp_unexpected_clause)

3499 << getOpenMPClauseName(CKind)

3500 << getOpenMPDirectiveName(DKind, OMPVersion);

3501 ErrorFound = true;

3502 WrongDirective = true;

3503 }

3504 if (WrongDirective)

3505 Diag(Tok, diag::note_ompx_bare_clause)

3506 << getOpenMPClauseName(CKind) << "target teams";

3507 if (!ErrorFound && getLangOpts().OpenMPExtensions) {

3508 Diag(Tok, diag::err_omp_unexpected_clause_extension_only)

3509 << getOpenMPClauseName(CKind)

3510 << getOpenMPDirectiveName(DKind, OMPVersion);

3511 ErrorFound = true;

3512 }

3513 Clause = ParseOpenMPClause(CKind, WrongDirective);

3514 break;

3515 case OMPC_looprange:

3516 Clause = ParseOpenMPLoopRangeClause();

3517 break;

3518 default:

3519 break;

3520 }

3521 return ErrorFound ? nullptr : Clause;

3522}

3523

3524

3525

3526

3529 bool IsAddressOfOperand) {

3531 if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))

3533

3539 Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, false);

3540

3541

3542 RLoc = Tok.getLocation();

3543 if (T.consumeClose())

3544 RLoc = T.getCloseLocation();

3545

3546 return Val;

3547}

3548

3550 bool ParseOnly) {

3554

3556

3558 return nullptr;

3559

3560 if (ParseOnly)

3561 return nullptr;

3563 LLoc, RLoc);

3564}

3565

3566bool Parser::ParseOpenMPIndirectClause(

3570

3571 if (Tok.isNot(tok::l_paren)) {

3572 if (ParseOnly)

3573 return false;

3575 return true;

3576 }

3577

3581 return false;

3582

3583 if (ParseOnly)

3584 return false;

3585

3589 ExprResult Ret = Actions.CheckBooleanCondition(Loc, Val.get());

3590 if (Ret.isInvalid())

3591 return false;

3592 llvm::APSInt Result;

3593 Ret = Actions.VerifyIntegerConstantExpression(Val.get(), &Result,

3595 if (Ret.isInvalid())

3596 return false;

3598 return true;

3599 }

3600 return false;

3601}

3602

3603bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,

3606 bool HasError = false;

3607 bool IsTarget = false;

3608 bool IsTargetSync = false;

3609

3610 while (Tok.is(tok::identifier)) {

3611

3612 bool PreferTypeAllowed = Kind == OMPC_init &&

3613 InteropInfo.PreferTypes.empty() && !IsTarget &&

3614 !IsTargetSync;

3615 if (Tok.getIdentifierInfo()->isStr("target")) {

3616

3617

3618

3619 if (IsTarget)

3620 Diag(Tok, diag::warn_omp_more_one_interop_type) << "target";

3621 IsTarget = true;

3623 } else if (Tok.getIdentifierInfo()->isStr("targetsync")) {

3624 if (IsTargetSync)

3625 Diag(Tok, diag::warn_omp_more_one_interop_type) << "targetsync";

3626 IsTargetSync = true;

3628 } else if (Tok.getIdentifierInfo()->isStr("prefer_type") &&

3629 PreferTypeAllowed) {

3632 tok::annot_pragma_openmp_end);

3633 if (PT.expectAndConsume(diag::err_expected_lparen_after, "prefer_type"))

3634 HasError = true;

3635

3636 while (Tok.isNot(tok::r_paren)) {

3637 SourceLocation Loc = Tok.getLocation();

3640 PTExpr = Actions.ActOnFinishFullExpr(PTExpr.get(), Loc,

3641 false);

3644 } else {

3645 HasError = true;

3646 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

3648 }

3649

3650 if (Tok.is(tok::comma))

3652 }

3653 PT.consumeClose();

3654 } else {

3655 HasError = true;

3656 Diag(Tok, diag::err_omp_expected_interop_type);

3658 }

3659 if (!Tok.is(tok::comma))

3660 break;

3662 }

3663

3664 if (!HasError && !IsTarget && !IsTargetSync) {

3665 Diag(Tok, diag::err_omp_expected_interop_type);

3666 HasError = true;

3667 }

3668

3669 if (Kind == OMPC_init) {

3670 if (Tok.isNot(tok::colon) && (IsTarget || IsTargetSync))

3671 Diag(Tok, diag::warn_pragma_expected_colon) << "interop types";

3672 if (Tok.is(tok::colon))

3674 }

3675

3676

3677

3678 InteropInfo.IsTarget = IsTarget;

3680

3681 return HasError;

3682}

3683

3685 bool ParseOnly) {

3687

3689 if (T.expectAndConsume(diag::err_expected_lparen_after,

3690 getOpenMPClauseName(Kind).data()))

3691 return nullptr;

3692

3693 bool InteropError = false;

3694 OMPInteropInfo InteropInfo;

3695 if (Kind == OMPC_init)

3696 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);

3697

3698

3699 SourceLocation VarLoc = Tok.getLocation();

3701 if (!InteropVarExpr.isUsable()) {

3702 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

3704 }

3705

3706

3707 SourceLocation RLoc = Tok.getLocation();

3708 if (T.consumeClose())

3709 RLoc = T.getCloseLocation();

3710

3711 if (ParseOnly || !InteropVarExpr.isUsable() || InteropError)

3712 return nullptr;

3713

3714 if (Kind == OMPC_init)

3715 return Actions.OpenMP().ActOnOpenMPInitClause(

3716 InteropVarExpr.get(), InteropInfo, Loc, T.getOpenLocation(), VarLoc,

3717 RLoc);

3718 if (Kind == OMPC_use)

3719 return Actions.OpenMP().ActOnOpenMPUseClause(

3720 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);

3721

3722 if (Kind == OMPC_destroy)

3723 return Actions.OpenMP().ActOnOpenMPDestroyClause(

3724 InteropVarExpr.get(), Loc, T.getOpenLocation(), VarLoc, RLoc);

3725

3726 llvm_unreachable("Unexpected interop variable clause.");

3727}

3728

3729OMPClause *Parser::ParseOpenMPOMPXAttributesClause(bool ParseOnly) {

3731

3733 if (T.expectAndConsume(diag::err_expected_lparen_after,

3734 getOpenMPClauseName(OMPC_ompx_attribute).data()))

3735 return nullptr;

3736

3737 ParsedAttributes ParsedAttrs(AttrFactory);

3738 ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);

3739

3740

3741 if (T.consumeClose())

3742 return nullptr;

3743

3744 if (ParseOnly)

3745 return nullptr;

3746

3747 SmallVector<Attr *> Attrs;

3748 for (const ParsedAttr &PA : ParsedAttrs) {

3749 switch (PA.getKind()) {

3750 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:

3751 if (!PA.checkExactlyNumArgs(Actions, 2))

3752 continue;

3753 if (auto *A = Actions.AMDGPU().CreateAMDGPUFlatWorkGroupSizeAttr(

3754 PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))

3755 Attrs.push_back(A);

3756 continue;

3757 case ParsedAttr::AT_AMDGPUWavesPerEU:

3758 if (!PA.checkAtLeastNumArgs(Actions, 1) ||

3759 !PA.checkAtMostNumArgs(Actions, 2))

3760 continue;

3761 if (auto *A = Actions.AMDGPU().CreateAMDGPUWavesPerEUAttr(

3762 PA, PA.getArgAsExpr(0),

3763 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr))

3764 Attrs.push_back(A);

3765 continue;

3766 case ParsedAttr::AT_CUDALaunchBounds:

3767 if (!PA.checkAtLeastNumArgs(Actions, 1) ||

3768 !PA.checkAtMostNumArgs(Actions, 2))

3769 continue;

3770 if (auto *A = Actions.CreateLaunchBoundsAttr(

3771 PA, PA.getArgAsExpr(0),

3772 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) : nullptr,

3773 PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) : nullptr))

3774 Attrs.push_back(A);

3775 continue;

3776 default:

3777 Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;

3778 continue;

3779 };

3780 }

3781

3782 return Actions.OpenMP().ActOnOpenMPXAttributeClause(

3783 Attrs, Loc, T.getOpenLocation(), T.getCloseLocation());

3784}

3785

3787 bool ParseOnly) {

3789 if (!Val || ParseOnly)

3790 return nullptr;

3791 if (getLangOpts().OpenMP < 51 && Kind == OMPC_default &&

3792 (static_cast<DefaultKind>(Val->Type) == OMP_DEFAULT_private ||

3793 static_cast<DefaultKind>(Val->Type) ==

3794 OMP_DEFAULT_firstprivate)) {

3795 Diag(Val->LOpen, diag::err_omp_invalid_dsa)

3796 << getOpenMPClauseName(static_cast<DefaultKind>(Val->Type) ==

3797 OMP_DEFAULT_private

3798 ? OMPC_private

3799 : OMPC_firstprivate)

3800 << getOpenMPClauseName(OMPC_default) << "5.1";

3801 return nullptr;

3802 }

3803 return Actions.OpenMP().ActOnOpenMPSimpleClause(

3804 Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);

3805}

3806

3808 SourceLocation Loc = Tok.getLocation();

3810

3811 if (ParseOnly)

3812 return nullptr;

3813 return Actions.OpenMP().ActOnOpenMPClause(Kind, Loc, Tok.getLocation());

3814}

3815

3818 bool ParseOnly) {

3820 SourceLocation DelimLoc;

3821

3823 if (T.expectAndConsume(diag::err_expected_lparen_after,

3824 getOpenMPClauseName(Kind).data()))

3825 return nullptr;

3826

3828 SmallVector<unsigned, 4> Arg;

3829 SmallVector<SourceLocation, 4> KLoc;

3830 if (Kind == OMPC_schedule) {

3831 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };

3832 Arg.resize(NumberOfElements);

3833 KLoc.resize(NumberOfElements);

3838 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

3840

3841 Arg[Modifier1] = KindModifier;

3842 KLoc[Modifier1] = Tok.getLocation();

3843 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

3844 Tok.isNot(tok::annot_pragma_openmp_end))

3846 if (Tok.is(tok::comma)) {

3847

3850 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

3852 ? KindModifier

3854 KLoc[Modifier2] = Tok.getLocation();

3855 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

3856 Tok.isNot(tok::annot_pragma_openmp_end))

3858 }

3859

3860 if (Tok.is(tok::colon))

3862 else

3863 Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";

3865 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

3866 }

3867 Arg[ScheduleKind] = KindModifier;

3868 KLoc[ScheduleKind] = Tok.getLocation();

3869 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

3870 Tok.isNot(tok::annot_pragma_openmp_end))

3872 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||

3873 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||

3874 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&

3875 Tok.is(tok::comma))

3877 } else if (Kind == OMPC_dist_schedule) {

3879 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));

3880 KLoc.push_back(Tok.getLocation());

3881 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

3882 Tok.isNot(tok::annot_pragma_openmp_end))

3884 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))

3886 } else if (Kind == OMPC_default) {

3887

3889 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

3890

3891 Arg.push_back(Modifier);

3892 KLoc.push_back(Tok.getLocation());

3893 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

3894 Tok.isNot(tok::annot_pragma_openmp_end))

3896

3897 if (Tok.is(tok::colon) && getLangOpts().OpenMP >= 60) {

3899

3902 Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

3903 Arg.push_back(VariableCategory);

3904 KLoc.push_back(Tok.getLocation());

3905 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

3906 Tok.isNot(tok::annot_pragma_openmp_end))

3908 } else {

3909 Arg.push_back(OMPC_DEFAULT_VC_all);

3910 KLoc.push_back(SourceLocation());

3911 }

3912 } else if (Kind == OMPC_defaultmap) {

3913

3915 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

3916

3917

3918

3921 Arg.push_back(Modifier);

3922 KLoc.push_back(Tok.getLocation());

3923 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

3924 Tok.isNot(tok::annot_pragma_openmp_end))

3926

3927 if (Tok.is(tok::colon) || getLangOpts().OpenMP < 50) {

3928 if (Tok.is(tok::colon))

3931 Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";

3932

3934 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));

3935 KLoc.push_back(Tok.getLocation());

3936 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

3937 Tok.isNot(tok::annot_pragma_openmp_end))

3939 } else {

3941 KLoc.push_back(SourceLocation());

3942 }

3943 } else if (Kind == OMPC_order) {

3944 enum { Modifier, OrderKind, NumberOfElements };

3945 Arg.resize(NumberOfElements);

3946 KLoc.resize(NumberOfElements);

3950 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

3952

3953 Arg[Modifier] = KindModifier;

3954 KLoc[Modifier] = Tok.getLocation();

3955 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

3956 Tok.isNot(tok::annot_pragma_openmp_end))

3958

3959 if (Tok.is(tok::colon))

3961 else

3962 Diag(Tok, diag::warn_pragma_expected_colon) << "order modifier";

3964 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

3965 }

3966 Arg[OrderKind] = KindModifier;

3967 KLoc[OrderKind] = Tok.getLocation();

3968 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

3969 Tok.isNot(tok::annot_pragma_openmp_end))

3971 } else if (Kind == OMPC_device) {

3972

3975

3977 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts()));

3978 KLoc.push_back(Tok.getLocation());

3980

3982 } else {

3984 KLoc.emplace_back();

3985 }

3986 } else if (Kind == OMPC_grainsize) {

3987

3990 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),

3994 Arg.push_back(Modifier);

3995 KLoc.push_back(Tok.getLocation());

3996

3998

4000 } else {

4001 if (Modifier == OMPC_GRAINSIZE_strict) {

4002 Diag(Tok, diag::err_modifier_expected_colon) << "strict";

4003

4005 }

4007 KLoc.emplace_back();

4008 }

4009 } else {

4011 KLoc.emplace_back();

4012 }

4013 } else if (Kind == OMPC_dyn_groupprivate) {

4014 enum { SimpleModifier, ComplexModifier, NumberOfModifiers };

4015 Arg.resize(NumberOfModifiers);

4016 KLoc.resize(NumberOfModifiers);

4019

4020 auto ConsumeModifier = [&]() {

4021 unsigned Type = NumberOfModifiers;

4022 unsigned Modifier;

4023 SourceLocation Loc;

4024 if (!Tok.isAnnotation() && PP.getSpelling(Tok) == "fallback" &&

4028 ParenT.consumeOpen();

4029

4031 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

4034 Diag(Tok.getLocation(), diag::err_expected)

4035 << "'abort', 'null' or 'default_mem' in fallback modifier";

4037 return std::make_tuple(Type, Modifier, Loc);

4038 }

4039 Type = ComplexModifier;

4040 Loc = Tok.getLocation();

4041 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

4042 Tok.isNot(tok::annot_pragma_openmp_end))

4044 ParenT.consumeClose();

4045 } else {

4047 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok), getLangOpts());

4049 Type = SimpleModifier;

4050 Loc = Tok.getLocation();

4051 if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&

4052 Tok.isNot(tok::annot_pragma_openmp_end))

4054 }

4055 }

4056 return std::make_tuple(Type, Modifier, Loc);

4057 };

4058

4059 auto SaveModifier = [&](unsigned Type, unsigned Modifier,

4060 SourceLocation Loc) {

4061 assert(Type < NumberOfModifiers && "Unexpected modifier type");

4062 if (!KLoc[Type].isValid()) {

4063 Arg[Type] = Modifier;

4064 KLoc[Type] = Loc;

4065 } else {

4066 Diag(Loc, diag::err_omp_incompatible_dyn_groupprivate_modifier)

4069 }

4070 };

4071

4072

4073 auto [Type1, Mod1, Loc1] = ConsumeModifier();

4074 if (Type1 < NumberOfModifiers) {

4075 SaveModifier(Type1, Mod1, Loc1);

4076 if (Tok.is(tok::comma)) {

4077

4079 auto [Type2, Mod2, Loc2] = ConsumeModifier();

4080 if (Type2 < NumberOfModifiers)

4081 SaveModifier(Type2, Mod2, Loc2);

4082 }

4083

4084 if (Tok.is(tok::colon))

4086 else

4087 Diag(Tok, diag::warn_pragma_expected_colon)

4088 << "dyn_groupprivate modifier";

4089 }

4090 } else if (Kind == OMPC_num_tasks) {

4091

4094 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),

4098 Arg.push_back(Modifier);

4099 KLoc.push_back(Tok.getLocation());

4100

4102

4104 } else {

4105 if (Modifier == OMPC_NUMTASKS_strict) {

4106 Diag(Tok, diag::err_modifier_expected_colon) << "strict";

4107

4109 }

4111 KLoc.emplace_back();

4112 }

4113 } else {

4115 KLoc.emplace_back();

4116 }

4117 } else if (Kind == OMPC_num_threads) {

4118

4121 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),

4125 Arg.push_back(Modifier);

4126 KLoc.push_back(Tok.getLocation());

4127

4129

4131 } else {

4132 if (Modifier == OMPC_NUMTHREADS_strict) {

4133 Diag(Tok, diag::err_modifier_expected_colon) << "strict";

4134

4136 }

4138 KLoc.emplace_back();

4139 }

4140 } else {

4142 KLoc.emplace_back();

4143 }

4144 } else {

4145 assert(Kind == OMPC_if);

4146 KLoc.push_back(Tok.getLocation());

4147 TentativeParsingAction TPA(*this);

4149 Arg.push_back(static_cast<unsigned>(DK));

4150 if (DK != OMPD_unknown) {

4152 if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {

4153 TPA.Commit();

4155 } else {

4156 TPA.Revert();

4157 Arg.back() = unsigned(OMPD_unknown);

4158 }

4159 } else {

4160 TPA.Revert();

4161 }

4162 }

4163

4164 bool NeedAnExpression =

4165 (Kind == OMPC_schedule && DelimLoc.isValid()) ||

4166 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) || Kind == OMPC_if ||

4167 Kind == OMPC_device || Kind == OMPC_grainsize || Kind == OMPC_num_tasks ||

4168 Kind == OMPC_num_threads || Kind == OMPC_dyn_groupprivate;

4169 if (NeedAnExpression) {

4170 SourceLocation ELoc = Tok.getLocation();

4175 Val =

4176 Actions.ActOnFinishFullExpr(Val.get(), ELoc, false);

4177 }

4178

4179

4180 SourceLocation RLoc = Tok.getLocation();

4181 if (T.consumeClose())

4182 RLoc = T.getCloseLocation();

4183

4184 if (NeedAnExpression && Val.isInvalid())

4185 return nullptr;

4186

4187 if (Kind == OMPC_default && getLangOpts().OpenMP < 51 && Arg[0] &&

4188 (static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_private ||

4189 static_cast<DefaultKind>(Arg[0]) == OMP_DEFAULT_firstprivate)) {

4190 Diag(KLoc[0], diag::err_omp_invalid_dsa)

4191 << getOpenMPClauseName(static_cast<DefaultKind>(Arg[0]) ==

4192 OMP_DEFAULT_private

4193 ? OMPC_private

4194 : OMPC_firstprivate)

4195 << getOpenMPClauseName(OMPC_default) << "5.1";

4196 return nullptr;

4197 }

4198

4199 if (ParseOnly)

4200 return nullptr;

4201 return Actions.OpenMP().ActOnOpenMPSingleExprWithArgClause(

4202 Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);

4203}

4204

4207 if (ReductionIdScopeSpec.isEmpty()) {

4210 case tok:➕

4211 OOK = OO_Plus;

4212 break;

4213 case tok:➖

4214 OOK = OO_Minus;

4215 break;

4216 case tok:⭐

4217 OOK = OO_Star;

4218 break;

4219 case tok::amp:

4220 OOK = OO_Amp;

4221 break;

4222 case tok::pipe:

4223 OOK = OO_Pipe;

4224 break;

4225 case tok::caret:

4226 OOK = OO_Caret;

4227 break;

4228 case tok::ampamp:

4229 OOK = OO_AmpAmp;

4230 break;

4231 case tok::pipepipe:

4232 OOK = OO_PipePipe;

4233 break;

4234 default:

4235 break;

4236 }

4241 return false;

4242 }

4243 }

4245 ReductionIdScopeSpec, nullptr,

4246 false, false,

4247 false,

4248 false,

4249 false, nullptr, ReductionId);

4250}

4251

4252

4253

4256 if (Tok.is(tok::identifier))

4258

4263 return TypeModifier;

4264}

4265

4267

4269 if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {

4270 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,

4272 return true;

4273 }

4274

4276 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,

4277 nullptr,

4278 false,

4279 false);

4280 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {

4281 Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);

4282 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,

4284 return true;

4285 }

4286 auto &DeclNames = Actions.getASTContext().DeclarationNames;

4288 DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());

4290

4291 return T.consumeClose();

4292}

4293

4295

4297 bool HasMapType = false;

4299 StringRef PreMapName = "";

4303 if (TypeModifier == OMPC_MAP_MODIFIER_always ||

4304 TypeModifier == OMPC_MAP_MODIFIER_close ||

4305 TypeModifier == OMPC_MAP_MODIFIER_present ||

4306 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {

4307 Data.MapTypeModifiers.push_back(TypeModifier);

4308 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());

4309 if (PP.LookAhead(0).isNot(tok::comma) &&

4310 PP.LookAhead(0).isNot(tok::colon) && getLangOpts().OpenMP >= 52)

4311 Diag(Tok.getLocation(), diag::err_omp_missing_comma)

4312 << "map type modifier";

4314 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {

4315 Data.MapTypeModifiers.push_back(TypeModifier);

4316 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());

4319 return true;

4320 if (Tok.isNot(tok::comma) && Tok.isNot(tok::colon) &&

4322 Diag(Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)

4323 << "map type modifier";

4324

4326 if (!HasMapType) {

4327 HasMapType = true;

4328 Data.ExtraModifier = MapKind;

4330 PreMapLoc = Tok.getLocation();

4331 PreMapName = Tok.getIdentifierInfo()->getName();

4332 } else {

4333 Diag(Tok, diag::err_omp_more_one_map_type);

4334 Diag(PreMapLoc, diag::note_previous_map_type_specified_here)

4335 << PreMapName;

4336 }

4338 } else if (TypeModifier == OMPC_MAP_MODIFIER_self) {

4339 Data.MapTypeModifiers.push_back(TypeModifier);

4340 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());

4341 if (PP.LookAhead(0).isNot(tok::comma) &&

4342 PP.LookAhead(0).isNot(tok::colon))

4343 Diag(Tok.getLocation(), diag::err_omp_missing_comma)

4344 << "map type modifier";

4346 Diag(Tok, diag::err_omp_unknown_map_type_modifier)

4349 : 0)

4352 } else {

4353

4354

4355

4356 if (Tok.is(tok::comma)) {

4357 Diag(Tok, diag::err_omp_map_type_modifier_missing);

4359 continue;

4360 }

4361

4362 if (PP.LookAhead(0).is(tok::colon)) {

4364 break;

4365 } else {

4366 return false;

4367 }

4368 }

4369

4370 Diag(Tok, diag::err_omp_unknown_map_type_modifier)

4372 : 0)

4374 << (getLangOpts().OpenMP >= 60 ? 1 : 0);

4376 }

4379 }

4380 if (getLangOpts().OpenMP >= 60 && !HasMapType) {

4381 if (!Tok.is(tok::colon)) {

4382 Diag(Tok, diag::err_omp_unknown_map_type);

4384 } else {

4386 }

4387 }

4388 return false;

4389}

4390

4391

4392

4395

4396 if (Tok.isOneOf(tok::identifier, tok::kw_delete))

4399 unsigned MapType =

4401 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||

4402 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||

4403 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)

4406}

4407

4408

4409

4410

4413 if (Tok.is(tok::colon)) {

4414 P.Diag(Tok, diag::err_omp_map_type_missing);

4415 return;

4416 }

4419 P.Diag(Tok, diag::err_omp_unknown_map_type);

4421}

4422

4423ExprResult Parser::ParseOpenMPIteratorsExpr() {

4424 assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&

4425 "Expected 'iterator' token.");

4426 SourceLocation IteratorKwLoc = ConsumeToken();

4427

4429 if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))

4431

4432 SourceLocation LLoc = T.getOpenLocation();

4433 SmallVector<SemaOpenMP::OMPIteratorData, 4> Data;

4434 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {

4435

4437 if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {

4438

4441 T.skipToEnd();

4443 }

4444 IteratorType = TR.get();

4445 }

4446

4447

4448 IdentifierInfo *II = nullptr;

4449 SourceLocation IdLoc;

4450 if (Tok.is(tok::identifier)) {

4451 II = Tok.getIdentifierInfo();

4453 } else {

4454 Diag(Tok, diag::err_expected_unqualified_id) << 0;

4455 }

4456

4457

4458 SourceLocation AssignLoc;

4459 if (Tok.is(tok::equal))

4461 else

4462 Diag(Tok, diag::err_omp_expected_equal_in_iterator);

4463

4464

4466

4467 SourceLocation Loc = Tok.getLocation();

4470 Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,

4471 false);

4472

4473 SourceLocation ColonLoc;

4474 if (Tok.is(tok::colon))

4476

4477

4478 Loc = Tok.getLocation();

4481 End = Actions.ActOnFinishFullExpr(End.get(), Loc,

4482 false);

4483

4484 SourceLocation SecColonLoc;

4486

4487 if (Tok.is(tok::colon)) {

4488

4490

4491 Loc = Tok.getLocation();

4494 Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,

4495 false);

4496 }

4497

4498

4499 if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))

4500 Diag(Tok, diag::err_omp_expected_punc_after_iterator);

4501 if (Tok.is(tok::comma))

4503

4504 SemaOpenMP::OMPIteratorData &D = Data.emplace_back();

4507 D.Type = IteratorType;

4514 }

4515

4516

4517 SourceLocation RLoc = Tok.getLocation();

4518 if (T.consumeClose())

4519 RLoc = T.getCloseLocation();

4520

4521 return Actions.OpenMP().ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc,

4522 LLoc, RLoc, Data);

4523}

4524

4528

4529

4530 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)

4531 return false;

4532

4533 if (Tok.is(tok::identifier) &&

4534 Tok.getIdentifierInfo()->isStr("omp_all_memory")) {

4535

4536 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||

4537 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)

4538 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);

4539 else if (Data.ExtraModifier != OMPC_DEPEND_out &&

4540 Data.ExtraModifier != OMPC_DEPEND_inout)

4541 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);

4542 else

4543 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out

4544 ? OMPC_DEPEND_outallmemory

4545 : OMPC_DEPEND_inoutallmemory;

4547 return true;

4548 }

4549 return false;

4550}

4551

4552

4553

4559 false);

4561 Data.DepModOrTailExpr = Tail.get();

4563 if (CurTok.isNot(tok::r_paren) && CurTok.isNot(tok::comma)) {

4564 P.Diag(CurTok, diag::err_expected_punc) << "step expression";

4565 }

4566 return true;

4567 }

4568 return false;

4569}

4570

4571

4572

4573

4582 bool AllocatorSeen = false;

4583 bool AlignSeen = false;

4587

4588

4591

4592

4593

4594

4595

4596

4599

4600 do {

4602 if (Tok.is(tok::l_paren)) {

4603 switch (CurrentModifier) {

4604 case OMPC_ALLOCATE_allocator: {

4605 if (AllocatorSeen) {

4606 P.Diag(Tok, diag::err_omp_duplicate_modifier)

4608 << getOpenMPClauseName(Kind);

4609 } else {

4610 Data.AllocClauseModifiers.push_back(CurrentModifier);

4611 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);

4612 }

4614 tok::annot_pragma_openmp_end);

4618 AllocatorSeen = true;

4619 break;

4620 }

4621 case OMPC_ALLOCATE_align: {

4622 if (AlignSeen) {

4623 P.Diag(Tok, diag::err_omp_duplicate_modifier)

4625 << getOpenMPClauseName(Kind);

4626 } else {

4627 Data.AllocClauseModifiers.push_back(CurrentModifier);

4628 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);

4629 }

4632 Data.AllocateAlignment = Val.get();

4633 AlignSeen = true;

4634 break;

4635 }

4636 default:

4637 llvm_unreachable("Unexpected allocate modifier");

4638 }

4639 } else {

4640 P.Diag(Tok, diag::err_expected) << tok::l_paren;

4641 }

4642 if (Tok.isNot(tok::comma))

4643 break;

4645 CurrentModifierLoc = Tok.getLocation();

4648

4650 P.Diag(Tok, diag::err_omp_expected_modifier) << getOpenMPClauseName(Kind);

4651 break;

4652 }

4653 } while (!AllocatorSeen || !AlignSeen);

4654 return Tail;

4655}

4656

4662 bool InvalidReductionId = false;

4663 bool IsInvalidMapperModifier = false;

4664

4665

4667 if (T.expectAndConsume(diag::err_expected_lparen_after,

4668 getOpenMPClauseName(Kind).data()))

4669 return true;

4670

4671 bool HasIterator = false;

4672 bool InvalidIterator = false;

4673 bool NeedRParenForLinear = false;

4675 tok::annot_pragma_openmp_end);

4676

4677 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||

4678 Kind == OMPC_in_reduction) {

4680 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 50 &&

4681 (Tok.is(tok::identifier) || Tok.is(tok::kw_default)) &&

4683

4684 Data.ExtraModifier =

4686 Data.ExtraModifierLoc = Tok.getLocation();

4688 assert(Tok.is(tok::comma) && "Expected comma.");

4690 }

4691

4692 if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&

4693 Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&

4695

4699 if (Tok.is(tok::kw_private)) {

4700 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;

4701 Data.OriginalSharingModifierLoc = Tok.getLocation();

4703 } else if (Tok.is(tok::identifier) &&

4704 (PP.getSpelling(Tok) == "shared" ||

4705 PP.getSpelling(Tok) == "default")) {

4706 Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;

4707 Data.OriginalSharingModifierLoc = Tok.getLocation();

4709 } else {

4710 Diag(Tok.getLocation(), diag::err_expected)

4711 << "'private or shared or default'";

4713 return false;

4714 }

4716 if (!Tok.is(tok::comma)) {

4717 Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";

4718 return false;

4719 }

4721 }

4724 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,

4725 nullptr,

4726 false,

4727 false);

4729 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);

4730 if (InvalidReductionId) {

4731 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,

4733 }

4734 if (Tok.is(tok::colon))

4736 else

4737 Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";

4738 if (!InvalidReductionId)

4739 Data.ReductionOrMapperId =

4740 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);

4741 } else if (Kind == OMPC_depend || Kind == OMPC_doacross) {

4743 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {

4744

4745

4746

4747

4748

4749

4750 HasIterator = true;

4752 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();

4753 Data.DepModOrTailExpr = IteratorRes.get();

4754

4755 ExpectAndConsume(tok::comma);

4756 }

4757 }

4758

4761 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",

4763 Data.ExtraModifierLoc = Tok.getLocation();

4765 (Kind == OMPC_doacross &&

4767 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,

4769 } else {

4771

4772 if (DKind == OMPD_ordered && Kind == OMPC_depend &&

4773 Data.ExtraModifier == OMPC_DEPEND_source) {

4774

4775 T.consumeClose();

4776 return false;

4777 }

4778 }

4779 if (Tok.is(tok::colon)) {

4781 } else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {

4782 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren

4783 : diag::warn_pragma_expected_colon)

4784 << (Kind == OMPC_depend ? "dependency type" : "dependence-type");

4785 }

4786 if (Kind == OMPC_doacross) {

4787 if (Tok.is(tok::identifier) &&

4788 Tok.getIdentifierInfo()->isStr("omp_cur_iteration")) {

4789 Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source

4790 ? OMPC_DOACROSS_source_omp_cur_iteration

4791 : OMPC_DOACROSS_sink_omp_cur_iteration;

4793 }

4794 if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {

4795 if (Tok.isNot(tok::minus)) {

4796 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)

4797 << getOpenMPClauseName(Kind) << 0 << 0;

4799 return false;

4800 } else {

4803 uint64_t Value = 0;

4804 if (Tok.isNot(tok::numeric_constant) ||

4805 (PP.parseSimpleIntegerLiteral(Tok, Value) && Value != 1)) {

4806 Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)

4807 << getOpenMPClauseName(Kind) << 0 << 0;

4809 return false;

4810 }

4811 }

4812 }

4813 if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {

4814 if (Tok.isNot(tok::r_paren)) {

4815 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)

4816 << getOpenMPClauseName(Kind) << 1 << 1;

4818 return false;

4819 }

4820 }

4821

4822 if (Kind == OMPC_doacross &&

4823 (Data.ExtraModifier == OMPC_DOACROSS_source ||

4824 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||

4825 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {

4826

4827 T.consumeClose();

4828 return false;

4829 }

4830 }

4831 } else if (Kind == OMPC_linear) {

4832

4833 Data.ExtraModifier = OMPC_LINEAR_val;

4834 if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {

4835 Data.ExtraModifier =

4839 NeedRParenForLinear = true;

4841 Diag(Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)

4842 << "linear-modifier(list)" << getOpenMPClauseName(Kind)

4843 << "linear(list: [linear-modifier,] step(step-size))";

4844 }

4845 } else if (Kind == OMPC_lastprivate) {

4846

4848

4849

4852 Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {

4853 Data.ExtraModifier =

4855 Data.ExtraModifierLoc = Tok.getLocation();

4857 assert(Tok.is(tok::colon) && "Expected colon.");

4859 }

4860 } else if (Kind == OMPC_map) {

4861

4862 if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {

4863 HasIterator = true;

4865 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);

4866 Data.MapTypeModifiersLoc.push_back(Tok.getLocation());

4867 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();

4868 Data.IteratorExpr = IteratorRes.get();

4869

4870 ExpectAndConsume(tok::comma);

4872 Diag(Tok, diag::err_omp_unknown_map_type_modifier)

4875 InvalidIterator = true;

4876 }

4877 }

4878

4880

4881

4882

4883

4885 Data.ExtraModifierLoc = Tok.getLocation();

4886

4887

4888 TentativeParsingAction TPA(*this);

4889 bool ColonPresent = false;

4890 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,

4892 if (Tok.is(tok::colon))

4893 ColonPresent = true;

4894 }

4895 TPA.Revert();

4896

4897

4898 if (ColonPresent) {

4900 Diag(Tok, diag::err_omp_map_modifier_specification_list);

4902 if (getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)

4904 else

4906 }

4908 Data.ExtraModifier = OMPC_MAP_tofrom;

4910 if (DKind == OMPD_target_enter_data)

4911 Data.ExtraModifier = OMPC_MAP_to;

4912 else if (DKind == OMPD_target_exit_data)

4913 Data.ExtraModifier = OMPC_MAP_from;

4914 }

4915 Data.IsMapTypeImplicit = true;

4916 }

4917

4918 if (Tok.is(tok::colon))

4920 } else if (Kind == OMPC_to || Kind == OMPC_from) {

4921 while (Tok.is(tok::identifier)) {

4925 break;

4926 Data.MotionModifiers.push_back(Modifier);

4927 Data.MotionModifiersLoc.push_back(Tok.getLocation());

4928 if (PP.getSpelling(Tok) == "iterator" && getLangOpts().OpenMP >= 51) {

4930 Tail = ParseOpenMPIteratorsExpr();

4931 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),

4932 false);

4934 Data.IteratorExpr = Tail.get();

4935 } else {

4937 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {

4939 if (IsInvalidMapperModifier)

4940 break;

4941 }

4942

4944 break;

4945

4946

4947 if (Tok.is(tok::comma))

4949 }

4950 }

4951 if (Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {

4952 if (!IsInvalidMapperModifier) {

4954 Diag(Tok, diag::warn_pragma_expected_colon) << ")";

4955 else

4956 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";

4957 }

4958 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,

4960 }

4961

4962

4963 if ((Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&

4964 Tok.is(tok::colon))

4966 } else if (Kind == OMPC_allocate ||

4967 (Kind == OMPC_affinity && Tok.is(tok::identifier) &&

4968 PP.getSpelling(Tok) == "iterator")) {

4969

4970

4972 TentativeParsingAction TPA(*this);

4973

4974

4975

4977 if (Kind == OMPC_allocate) {

4979 } else {

4980 HasIterator = true;

4982 Tail = ParseOpenMPIteratorsExpr();

4983 }

4984 Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),

4985 false);

4986 if (Tail.isUsable() || Data.AllocateAlignment) {

4987 if (Tok.is(tok::colon)) {

4988 Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;

4990 TPA.Commit();

4991 } else {

4992

4993 TPA.Revert();

4994 if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {

4995 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,

4997 Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";

4998 }

4999 }

5000 } else {

5001

5002

5003 TPA.Revert();

5004 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

5006 }

5007 } else if (Kind == OMPC_adjust_args) {

5008

5011 Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "",

5013 Data.ExtraModifierLoc = Tok.getLocation();

5015 Diag(Tok, diag::err_omp_unknown_adjust_args_op)

5016 << (getLangOpts().OpenMP >= 60 ? 1 : 0);

5018 } else {

5020 if (Tok.is(tok::colon))

5021 Data.ColonLoc = Tok.getLocation();

5023

5024

5025 if (Tok.is(tok::l_paren)) {

5027 T.consumeOpen();

5028 if (Tok.is(tok::identifier)) {

5029 std::string Modifier = PP.getSpelling(Tok);

5030 if (Modifier == "fb_nullify" || Modifier == "fb_preserve") {

5031 Data.NeedDevicePtrModifier =

5032 Modifier == "fb_nullify" ? OMPC_NEED_DEVICE_PTR_fb_nullify

5033 : OMPC_NEED_DEVICE_PTR_fb_preserve;

5034 } else {

5035 Diag(Tok, diag::err_omp_unknown_need_device_ptr_kind);

5036 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,

5038 return false;

5039 }

5041 if (Tok.is(tok::r_paren)) {

5042 Data.NeedDevicePtrModifierLoc = Tok.getLocation();

5044 } else {

5045 Diag(Tok, diag::err_expected) << tok::r_paren;

5046 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,

5048 return false;

5049 }

5050 }

5051 }

5052 }

5053 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,

5054 "adjust-op");

5055 }

5056 }

5057

5058 bool IsComma =

5059 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&

5060 Kind != OMPC_in_reduction && Kind != OMPC_depend &&

5061 Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||

5062 (Kind == OMPC_reduction && !InvalidReductionId) ||

5066 (Kind == OMPC_adjust_args &&

5068 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);

5069 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&

5070 Tok.isNot(tok::annot_pragma_openmp_end))) {

5074

5077 Vars.push_back(VarExpr.get());

5078 } else {

5079 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

5081 }

5082 }

5083

5084 IsComma = Tok.is(tok::comma);

5085 if (IsComma)

5087 else if (Tok.isNot(tok::r_paren) &&

5088 Tok.isNot(tok::annot_pragma_openmp_end) &&

5089 (!MayHaveTail || Tok.isNot(tok::colon))) {

5090 unsigned OMPVersion = Actions.getLangOpts().OpenMP;

5091 Diag(Tok, diag::err_omp_expected_punc)

5092 << ((Kind == OMPC_flush)

5093 ? getOpenMPDirectiveName(OMPD_flush, OMPVersion)

5094 : getOpenMPClauseName(Kind))

5095 << (Kind == OMPC_flush);

5096 }

5097 }

5098

5099

5100 if (NeedRParenForLinear)

5102

5103

5104 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);

5105 bool StepFound = false;

5106 bool ModifierFound = false;

5107 if (MustHaveTail) {

5108 Data.ColonLoc = Tok.getLocation();

5110

5111 if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {

5112 bool Malformed = false;

5113 while (Tok.isNot(tok::r_paren)) {

5114 if (Tok.is(tok::identifier)) {

5115

5116

5119 Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok),

5121

5122 if (LinKind == OMPC_LINEAR_step) {

5123 if (StepFound)

5124 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;

5125

5127 tok::annot_pragma_openmp_end);

5129

5131 Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";

5132

5133

5134 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());

5135 if (StepFound)

5136 Data.StepModifierLoc = StepModifierLoc;

5137

5138

5140 } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {

5141 if (ModifierFound)

5142 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;

5143

5144 Data.ExtraModifier = LinKind;

5146 ModifierFound = true;

5147 } else {

5148 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());

5149 if (!StepFound) {

5150 Malformed = true;

5151 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

5153 }

5154 }

5155 } else {

5156

5157 StepFound = parseStepSize(*this, Data, Kind, Tok.getLocation());

5158 }

5159

5160 if (Tok.is(tok::comma))

5162 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))

5163 break;

5164 }

5165 if (!Malformed && !StepFound && !ModifierFound)

5166 Diag(ELoc, diag::err_expected_expression);

5167 } else {

5168

5170 Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc,

5171 false);

5173 Data.DepModOrTailExpr = Tail.get();

5174 else

5175 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,

5177 }

5178 }

5179

5180

5181 Data.RLoc = Tok.getLocation();

5182 if (T.consumeClose())

5183 Data.RLoc = T.getCloseLocation();

5184

5185 if (HasIterator)

5187 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&

5188 Vars.empty()) ||

5189 (MustHaveTail && Data.DepModOrTailExpr && StepFound) ||

5190 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;

5191}

5192

5195 bool ParseOnly) {

5200

5202 return nullptr;

5203

5204 if (ParseOnly)

5205 return nullptr;

5208}

5209

5210bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,

5215 bool ReqIntConst) {

5216 assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&

5217 "Expected parsing to start at clause name");

5219

5220

5222 if (T.consumeOpen()) {

5223 Diag(Tok, diag::err_expected) << tok::l_paren;

5224 return true;

5225 }

5226

5227

5228 do {

5232

5233 T.skipToEnd();

5234 return true;

5235 }

5236 Exprs.push_back(Val.get());

5238

5239 bool Result = T.consumeClose();

5240 OpenLoc = T.getOpenLocation();

5241 CloseLoc = T.getCloseLocation();

5243}

Defines the clang::ASTContext interface.

bool is(tok::TokenKind Kind) const

static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)

Produce a diagnostic highlighting some portion of a literal.

This file defines OpenMP AST classes for clauses.

Defines some OpenMP-specific enums and functions.

static OpenMPDirectiveKind checkOpenMPDirectiveName(Parser &P, SourceLocation Loc, OpenMPDirectiveKind Kind, StringRef Name)

Definition ParseOpenMP.cpp:59

static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P)

Definition ParseOpenMP.cpp:74

static OpenMPMapModifierKind isMapModifier(Parser &P)

Checks if the token is a valid map-type-modifier.

Definition ParseOpenMP.cpp:4254

static std::optional< SimpleClauseData > parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind)

Definition ParseOpenMP.cpp:1732

static bool checkExtensionProperty(Parser &P, SourceLocation Loc, OMPTraitProperty &TIProperty, OMPTraitSelector &TISelector, llvm::StringMap< SourceLocation > &Seen)

Definition ParseOpenMP.cpp:905

static ExprResult parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data)

Parse 'allocate' clause modifiers.

Definition ParseOpenMP.cpp:4575

static DeclarationName parseOpenMPReductionId(Parser &P)

Definition ParseOpenMP.cpp:107

static ExprResult parseContextScore(Parser &P)

Parse optional 'score' '(' ')' ':'.

Definition ParseOpenMP.cpp:1057

static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)

Definition ParseOpenMP.cpp:4205

static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data, OpenMPClauseKind CKind, SourceLocation ELoc)

Parse step size expression.

Definition ParseOpenMP.cpp:4554

static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data)

Parse map-type in map clause.

Definition ParseOpenMP.cpp:4411

static bool parseDeclareSimdClauses(Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, SmallVectorImpl< Expr * > &Uniforms, SmallVectorImpl< Expr * > &Aligneds, SmallVectorImpl< Expr * > &Alignments, SmallVectorImpl< Expr * > &Linears, SmallVectorImpl< unsigned > &LinModifiers, SmallVectorImpl< Expr * > &Steps)

Parses clauses for 'declare simd' directive.

Definition ParseOpenMP.cpp:658

static OpenMPMapClauseKind isMapType(Parser &P)

Checks if the token is a valid map-type.

Definition ParseOpenMP.cpp:4393

This file declares semantic analysis functions specific to AMDGPU.

This file declares facilities that support code completion.

This file declares semantic analysis for OpenMP constructs and clauses.

Defines the clang::TokenKind enum and support functions.

VerifyDiagnosticConsumer::Directive Directive

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

DeclarationNameTable DeclarationNames

OMPTraitInfo & getNewOMPTraitInfo()

Return a new OMPTraitInfo object owned by this context.

RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....

Represents a C++ nested-name-specifier or a global scope specifier.

bool isEmpty() const

No scope specifier.

static const TST TST_unspecified

Decl - This represents one declaration (or definition), e.g.

bool isFunctionOrFunctionTemplate() const

Whether this declaration is a function or function template.

SourceLocation getLocation() const

DeclContext * getDeclContext()

The name of a declaration.

bool isEmpty() const

Evaluates true when this declaration name is empty.

bool isValueDependent() const

Determines whether the value of this expression depends on.

bool isTypeDependent() const

Determines whether the type of this expression depends on.

bool containsUnexpandedParameterPack() const

Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).

bool isInstantiationDependent() const

Whether this expression is instantiation-dependent, meaning that it depends in some way on.

static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)

Create a code modification hint that replaces the given source range with the given code string.

One of these records is kept for each identifier that is lexed.

StringRef getName() const

Return the actual identifier string.

Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...

This represents a decl that may have a name.

bool isCXXInstanceMember() const

Determine whether the given declaration is an instance member of a C++ class.

This is a basic class for representing single OpenMP clause.

Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...

void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const

Create a variant match info object from this trait info object.

llvm::SmallVector< OMPTraitSet, 2 > Sets

The outermost level of selector sets.

static const ParsedAttributesView & none()

ParsedAttributes - A collection of parsed attributes.

Introduces zero or more scopes for parsing.

void Enter(unsigned ScopeFlags)

ParseScope - Introduces a new scope for parsing.

Parser - This implements a parser for the C family of languages.

bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, SemaOpenMP::OpenMPVarListDataTy &Data)

Parses clauses with list.

Definition ParseOpenMP.cpp:4657

TypeResult ParseTypeName(SourceRange *Range=nullptr, DeclaratorContext Context=DeclaratorContext::TypeName, AccessSpecifier AS=AS_none, Decl **OwnedType=nullptr, ParsedAttributes *Attrs=nullptr)

ParseTypeName.

DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

Preprocessor & getPreprocessor() const

bool parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data)

Parse map-type-modifiers in map clause.

Definition ParseOpenMP.cpp:4296

ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral=false)

ParseStringLiteralExpression - This handles the various token types that form string literals,...

SourceLocation ConsumeToken()

ConsumeToken - Consume the current 'peek token' and lex the next one.

Sema & getActions() const

void EnterScope(unsigned ScopeFlags)

EnterScope - Start a new scope.

bool parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data)

Parses the mapper modifier in map, to, and from clauses.

Definition ParseOpenMP.cpp:4266

friend class ParsingOpenMPDirectiveRAII

bool ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, SourceLocation *TemplateKWLoc, UnqualifiedId &Result)

Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.

friend class ColonProtectionRAIIObject

SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)

ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.

ExprResult ParseConstantExpression()

bool TryConsumeToken(tok::TokenKind Expected)

OpaquePtr< DeclGroupRef > DeclGroupPtrTy

Scope * getCurScope() const

bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))

SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...

const Token & getCurToken() const

void ExitScope()

ExitScope - Pop a scope off the scope stack.

ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc, bool IsAddressOfOperand=false)

Parses simple expression in parens for single-expression clauses of OpenMP constructs.

Definition ParseOpenMP.cpp:3527

const LangOptions & getLangOpts() const

friend class ParenBraceBracketBalancer

ExprResult ParseExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)

Simple precedence-based parser for binary/ternary operators.

@ StopBeforeMatch

Stop skipping at specified token, but don't skip the token itself.

bool ParseOpenMPReservedLocator(OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data, const LangOptions &LangOpts)

Parses a reserved locator like 'omp_all_memory'.

Definition ParseOpenMP.cpp:4525

const Token & NextToken()

NextToken - This peeks ahead one token and returns it without consuming it.

ExprResult ParseAssignmentExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)

Parse an expr that doesn't include (top-level) commas.

friend class BalancedDelimiterTracker

unsigned ReenterTemplateScopes(MultiParseScope &S, Decl *D)

Re-enter a possible template scope, creating as many template parameter scopes as necessary.

bool ParseOpenMPDeclareBeginVariantDirective(SourceLocation Loc)

Parses 'omp begin declare variant' directive.

Definition ParseOpenMP.cpp:545

Engages in a tight little dance with the lexer to efficiently preprocess tokens.

const Token & LookAhead(unsigned N)

Peeks ahead N tokens and returns that token without consuming any tokens.

StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const

Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...

bool isNull() const

Return true if this QualType doesn't point to a type yet.

The collection of all-type qualifiers we support.

Represents a struct/union/class.

@ OpenMPDirectiveScope

This is the scope of OpenMP executable directive.

@ CompoundStmtScope

This is a compound statement scope.

@ OpenMPSimdDirectiveScope

This is the scope of some OpenMP simd directive.

@ FnScope

This indicates that the scope corresponds to a function, which means that labels are set here.

@ OpenMPLoopDirectiveScope

This is the scope of some OpenMP loop directive.

@ DeclScope

This is a scope that can contain a declaration.

Smart pointer class that efficiently represents Objective-C method names.

bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)

Checks correctness of linear modifiers.

OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)

Called on well-formed 'uses_allocators' clause.

OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)

OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)

RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...

Sema - This implements semantic analysis and AST building for C.

Scope * getCurScope() const

Retrieve the parser's current scope.

void ActOnExitFunctionContext()

void ActOnReenterFunctionContext(Scope *S, Decl *D)

Push the parameters of D, which must be a function, into scope.

ASTContext & getASTContext() const

const LangOptions & getLangOpts() const

@ Unevaluated

The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...

ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)

Encodes a location in the source.

bool isValid() const

Return true if this is a valid SourceLocation object.

A trivial tuple used to represent a source range.

StringLiteral - This represents a string literal expression, e.g.

Token - This structure provides full information about a lexed token.

SourceLocation getLocation() const

Return a source location identifier for the specified offset in the current file.

bool is(tok::TokenKind K) const

is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....

tok::TokenKind getKind() const

bool isNot(tok::TokenKind K) const

Base wrapper for a particular "section" of type source info.

The base class of the type hierarchy.

QualType getCanonicalTypeInternal() const

Represents a C++ unqualified-id that has been parsed.

void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])

Specify that this unqualified-id was parsed as an operator-function-id.

Represents a variable declaration or definition.

Defines the clang::TargetInfo interface.

bool Ret(InterpState &S, CodePtr &PC)

bool isStringLiteral(TokenKind K)

Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.

The JSON file list parser is used to communicate input to InstallAPI.

OverloadedOperatorKind

Enumeration specifying the different kinds of C++ overloaded operators.

@ OO_None

Not an overloaded operator.

if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))

OpenMPDefaultClauseVariableCategory

OpenMP variable-category for 'default' clause.

@ OMPC_DEFAULTMAP_MODIFIER_unknown

@ OMPC_ORDER_MODIFIER_unknown

@ OMPC_ADJUST_ARGS_unknown

bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)

Checks if the specified directive is a distribute directive.

OpenMPDeviceType

OpenMP device type for 'device_type' clause.

@ OMPC_DEVICE_TYPE_unknown

@ OMPC_SCHEDULE_MODIFIER_unknown

AccessSpecifier

A C++ access specifier (public, private, protected), plus the special value "none" which means differ...

const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)

Checks if the specified directive is a target code offload directive.

@ OMPC_DYN_GROUPPRIVATE_FALLBACK_unknown

@ OMPC_DYN_GROUPPRIVATE_FALLBACK_last

@ Property

The type of a property.

@ Result

The result type of a method or function.

ActionResult< ParsedType > TypeResult

const FunctionProtoType * T

@ OMPC_LASTPRIVATE_unknown

OpenMPGrainsizeClauseModifier

unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str, const LangOptions &LangOpts)

OpenMPNumTasksClauseModifier

@ Type

The name was classified as a type.

bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)

Checks if the specified directive is a directive with an associated loop construct.

OpenMPMotionModifierKind

OpenMP modifier kind for 'to' or 'from' clause.

@ OMPC_MOTION_MODIFIER_unknown

@ OMPC_DEFAULTMAP_unknown

OpenMPAllocateClauseModifier

OpenMP modifiers for 'allocate' clause.

OpenMPLinearClauseKind

OpenMP attributes for 'linear' clause.

bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind)

Checks if the specified directive is considered as "executable".

llvm::omp::Directive OpenMPDirectiveKind

OpenMP directives.

@ OMPC_DYN_GROUPPRIVATE_unknown

bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind)

Checks if the specified directive is considered as "informational".

bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)

Checks if the specified directive is a simd directive.

OpenMPNumThreadsClauseModifier

@ OMPC_NUMTHREADS_unknown

SmallVector< Token, 4 > CachedTokens

A set of tokens that has been cached for later parsing.

OpaquePtr< QualType > ParsedType

An opaque type for threading parsed type information through the parser.

OpenMPMapModifierKind

OpenMP modifier kind for 'map' clause.

@ OMPC_MAP_MODIFIER_unknown

llvm::omp::Clause OpenMPClauseKind

OpenMP clauses.

ActionResult< Expr * > ExprResult

bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)

Checks if the specified directive is a taskloop directive.

ActionResult< Stmt * > StmtResult

OpenMPDefaultClauseVariableCategory getOpenMPDefaultVariableCategory(StringRef Str, const LangOptions &LangOpts)

OpenMPMapClauseKind

OpenMP mapping kind for 'map' clause.

int const char * function

DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...

SourceLocation getLoc() const

getLoc - Returns the main location of the declaration name.

DeclarationName getName() const

getName - Returns the embedded declaration name.

llvm::SmallVector< Expr *, 4 > PreferTypes

llvm::omp::TraitProperty Kind

StringRef RawString

The raw string as we parsed it.

llvm::omp::TraitSelector Kind

SmallVector< OMPTraitProperty, 1 > Properties

SmallVector< OMPTraitSelector, 2 > Selectors

This structure contains most locations needed for by an OMPVarListClause.

std::optional< Expr * > Indirect

The directive with indirect clause.

OpenMPDirectiveKind Kind

The directive kind, begin declare target or declare target.

OMPDeclareTargetDeclAttr::DevTypeTy DT

The 'device_type' as parsed from the clause.

SourceLocation Loc

The directive location.

llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped

Explicitly listed variables and functions in a 'to' or 'link' clause.

SourceLocation DeclIdentLoc

SourceLocation SecColonLoc

IdentifierInfo * DeclIdent

OMPIteratorExpr::IteratorRange Range

Data used for processing a list of variables in OpenMP clauses.

Data for list of allocators.

Expr * AllocatorTraits

Allocator traits.

SourceLocation LParenLoc

Locations of '(' and ')' symbols.

Expr * Allocator

Allocator.

Clang specific specialization of the OMPContext to lookup target features.