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

1

2

3

4

5

6

7

8

9

10

11

12

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

28#include "llvm/ADT/StringSwitch.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 {

41enum OpenMPDirectiveKindEx {

42 OMPD_cancellation = llvm::omp::Directive_enumSize + 1,

43 OMPD_data,

44 OMPD_declare,

45 OMPD_end,

46 OMPD_end_declare,

47 OMPD_enter,

48 OMPD_exit,

49 OMPD_point,

50 OMPD_reduction,

51 OMPD_target_enter,

52 OMPD_target_exit,

53 OMPD_update,

54 OMPD_distribute_parallel,

55 OMPD_teams_distribute_parallel,

56 OMPD_target_teams_distribute_parallel,

57 OMPD_mapper,

58 OMPD_variant,

59 OMPD_begin,

60 OMPD_begin_declare,

61};

62

63

64

65

66struct OpenMPDirectiveKindExWrapper {

67 OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}

69 bool operator==(OpenMPDirectiveKindExWrapper V) const {

70 return Value == V.Value;

71 }

72 bool operator!=(OpenMPDirectiveKindExWrapper V) const {

73 return Value != V.Value;

74 }

81};

82

83class DeclDirectiveListParserHelper final {

87

88public:

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

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

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

96 }

98};

99}

100

101

102

104 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);

105 if (DKind != OMPD_unknown)

106 return DKind;

107

108 return llvm::StringSwitch(S)

109 .Case("cancellation", OMPD_cancellation)

110 .Case("data", OMPD_data)

111 .Case("declare", OMPD_declare)

112 .Case("end", OMPD_end)

113 .Case("enter", OMPD_enter)

114 .Case("exit", OMPD_exit)

115 .Case("point", OMPD_point)

116 .Case("reduction", OMPD_reduction)

117 .Case("update", OMPD_update)

118 .Case("mapper", OMPD_mapper)

119 .Case("variant", OMPD_variant)

120 .Case("begin", OMPD_begin)

121 .Default(OMPD_unknown);

122}

123

125

126

127

128 static const OpenMPDirectiveKindExWrapper F[][3] = {

129 {OMPD_begin, OMPD_declare, OMPD_begin_declare},

130 {OMPD_begin, OMPD_assumes, OMPD_begin_assumes},

131 {OMPD_end, OMPD_declare, OMPD_end_declare},

132 {OMPD_end, OMPD_assumes, OMPD_end_assumes},

133 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},

134 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},

135 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},

136 {OMPD_declare, OMPD_simd, OMPD_declare_simd},

137 {OMPD_declare, OMPD_target, OMPD_declare_target},

138 {OMPD_declare, OMPD_variant, OMPD_declare_variant},

139 {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},

140 {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},

141 {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},

142 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},

143 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},

144 {OMPD_distribute_parallel_for, OMPD_simd,

145 OMPD_distribute_parallel_for_simd},

146 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},

147 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},

148 {OMPD_target, OMPD_data, OMPD_target_data},

149 {OMPD_target, OMPD_enter, OMPD_target_enter},

150 {OMPD_target, OMPD_exit, OMPD_target_exit},

151 {OMPD_target, OMPD_update, OMPD_target_update},

152 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},

153 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},

154 {OMPD_for, OMPD_simd, OMPD_for_simd},

155 {OMPD_parallel, OMPD_for, OMPD_parallel_for},

156 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},

157 {OMPD_parallel, OMPD_loop, OMPD_parallel_loop},

158 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},

159 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},

160 {OMPD_target, OMPD_parallel, OMPD_target_parallel},

161 {OMPD_target, OMPD_simd, OMPD_target_simd},

162 {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop},

163 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},

164 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},

165 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},

166 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},

167 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},

168 {OMPD_teams_distribute_parallel, OMPD_for,

169 OMPD_teams_distribute_parallel_for},

170 {OMPD_teams_distribute_parallel_for, OMPD_simd,

171 OMPD_teams_distribute_parallel_for_simd},

172 {OMPD_teams, OMPD_loop, OMPD_teams_loop},

173 {OMPD_target, OMPD_teams, OMPD_target_teams},

174 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},

175 {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop},

176 {OMPD_target_teams_distribute, OMPD_parallel,

177 OMPD_target_teams_distribute_parallel},

178 {OMPD_target_teams_distribute, OMPD_simd,

179 OMPD_target_teams_distribute_simd},

180 {OMPD_target_teams_distribute_parallel, OMPD_for,

181 OMPD_target_teams_distribute_parallel_for},

182 {OMPD_target_teams_distribute_parallel_for, OMPD_simd,

183 OMPD_target_teams_distribute_parallel_for_simd},

184 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},

185 {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop},

186 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},

187 {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd},

188 {OMPD_parallel, OMPD_master, OMPD_parallel_master},

189 {OMPD_parallel, OMPD_masked, OMPD_parallel_masked},

190 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},

191 {OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop},

192 {OMPD_parallel_master_taskloop, OMPD_simd,

193 OMPD_parallel_master_taskloop_simd},

194 {OMPD_parallel_masked_taskloop, OMPD_simd,

195 OMPD_parallel_masked_taskloop_simd}};

196 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };

197 Token Tok = P.getCurToken();

198 OpenMPDirectiveKindExWrapper DKind =

200 ? static_cast<unsigned>(OMPD_unknown)

202 if (DKind == OMPD_unknown)

203 return OMPD_unknown;

204

205 for (const auto &I : F) {

206 if (DKind != I[0])

207 continue;

208

209 Tok = P.getPreprocessor().LookAhead(0);

210 OpenMPDirectiveKindExWrapper SDKind =

212 ? static_cast<unsigned>(OMPD_unknown)

214 if (SDKind == OMPD_unknown)

215 continue;

216

217 if (SDKind == I[1]) {

218 P.ConsumeToken();

219 DKind = I[2];

220 }

221 }

222 return unsigned(DKind) < llvm::omp::Directive_enumSize

224 : OMPD_unknown;

225}

226

228 Token Tok = P.getCurToken();

229 Sema &Actions = P.getActions();

231

232 bool WithOperator = false;

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

234 P.ConsumeToken();

235 Tok = P.getCurToken();

236 WithOperator = true;

237 }

239 case tok:➕

240 OOK = OO_Plus;

241 break;

242 case tok:➖

243 OOK = OO_Minus;

244 break;

245 case tok:⭐

246 OOK = OO_Star;

247 break;

248 case tok::amp:

249 OOK = OO_Amp;

250 break;

251 case tok::pipe:

252 OOK = OO_Pipe;

253 break;

254 case tok::caret:

255 OOK = OO_Caret;

256 break;

257 case tok::ampamp:

258 OOK = OO_AmpAmp;

259 break;

260 case tok::pipepipe:

261 OOK = OO_PipePipe;

262 break;

263 case tok::identifier:

264 if (!WithOperator)

265 break;

266 [[fallthrough]];

267 default:

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

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

272 }

273 P.ConsumeToken();

276 : DeclNames.getCXXOperatorName(OOK);

277}

278

279

280

281

282

283

284

285

286

287

288

290Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {

291

293 if (T.expectAndConsume(

294 diag::err_expected_lparen_after,

295 getOpenMPDirectiveName(OMPD_declare_reduction).data())) {

298 }

299

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

303

304

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

306

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

309

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

311

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

314 IsCorrect = false;

315 }

316

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

319

321

322 do {

329 if (!ReductionType.isNull()) {

330 ReductionTypes.push_back(

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

332 }

333 } else {

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

336 }

337

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

339 break;

340

341

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

343 IsCorrect = false;

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

347 }

348 }

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

350

351 if (ReductionTypes.empty()) {

354 }

355

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

358

359

360 if (ExpectAndConsume(tok::colon))

361 IsCorrect = false;

362

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

366 }

367

371 AS);

372

373

374

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

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

377 TentativeParsingAction TPA(*this);

381

386 D, CombinerResult.get());

387

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

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

390 TPA.Commit();

391 IsCorrect = false;

392 break;

393 }

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

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

397

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

401 } else {

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

403 TPA.Commit();

404 IsCorrect = false;

405 break;

406 }

407

409 tok::annot_pragma_openmp_end);

410 IsCorrect =

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

412 IsCorrect;

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

417

421

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

425 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);

426 } else {

429 false);

430 }

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

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

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

435 TPA.Commit();

436 IsCorrect = false;

437 break;

438 }

439 IsCorrect =

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

441 }

442 }

443

444 ++I;

445

446

447 if (I != E)

448 TPA.Revert();

449 else

450 TPA.Commit();

451 }

454}

455

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

457

458

459 if (isTokenEqualOrEqualTypo()) {

461

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

463 cutOffParsing();

465 OmpPrivParm);

467 return;

468 }

469

472

473 if (Init.isInvalid()) {

476 } else {

478 false);

479 }

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

481

483 T.consumeOpen();

484

485 ExprVector Exprs;

486

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

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

493 CalledSignatureHelp = true;

494 return PreferredType;

495 };

496 if (ParseExpressionList(Exprs, [&] {

497 PreferredType.enterFunctionArgument(Tok.getLocation(),

498 RunSignatureHelp);

499 })) {

501 RunSignatureHelp();

504 } else {

505

507 if (T.consumeClose())

508 RLoc = T.getCloseLocation();

509

513 true);

514 }

516

517 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);

518

520

521 if (Init.isInvalid()) {

523 } else {

525 true);

526 }

527 } else {

529 }

530}

531

532

533

534

535

536

537

538

539

541Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {

542 bool IsCorrect = true;

543

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

546 getOpenMPDirectiveName(OMPD_declare_mapper).data())) {

549 }

550

551

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

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

557 IsCorrect = false;

558 } else {

560 }

562

563 ExpectAndConsume(tok::colon);

564 } else {

565

566 MapperId =

568 }

569

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

572

573

581 if (MapperType.isNull())

582 IsCorrect = false;

583 if (!IsCorrect) {

586 }

587

588

589 IsCorrect &= T.consumeClose();

590 if (!IsCorrect) {

593 }

594

595

600 ParseScope OMPDirectiveScope(this, ScopeFlags);

603

604

608

609

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

613 ? OMPC_unknown

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

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

618 if (Clause)

619 Clauses.push_back(Clause);

620 else

621 IsCorrect = false;

622

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

626 }

627 if (Clauses.empty()) {

628 Diag(Tok, diag::err_omp_expected_clause)

629 << getOpenMPDirectiveName(OMPD_declare_mapper);

630 IsCorrect = false;

631 }

632

633

635 OMPDirectiveScope.Exit();

639 if (!IsCorrect)

641

642 return DG;

643}

644

648

649 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;

651 ParseSpecifierQualifierList(DS, AS, DSC);

652

653

656 ParseDeclarator(DeclaratorInfo);

657 Range = DeclaratorInfo.getSourceRange();

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

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

660 return true;

661 }

663

665 DeclaratorInfo);

666}

667

668namespace {

669

670

671

672

673

674class FNContextRAII final {

678 bool HasFunScope = false;

679 FNContextRAII() = delete;

680 FNContextRAII(const FNContextRAII &) = delete;

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

682

683public:

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

686 NamedDecl *ND = dyn_cast(D);

688 Sema &Actions = P.getActions();

689

690

693

694

695

696 P.ReenterTemplateScopes(Scopes, D);

697

698

700 HasFunScope = true;

704 }

705 }

706 ~FNContextRAII() {

707 if (HasFunScope)

708 P.getActions().ActOnExitFunctionContext();

709 delete ThisScope;

710 }

711};

712}

713

714

715

716

717

718

719

720

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

727 const Token &Tok = P.getCurToken();

728 bool IsError = false;

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

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

731 break;

732 OMPDeclareSimdDeclAttr::BranchStateTy Out;

734 StringRef ClauseName = II->getName();

735

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

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

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

739 << ClauseName

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

741 IsError = true;

742 }

743 BS = Out;

745 P.ConsumeToken();

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

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

749 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;

750 IsError = true;

751 }

752 P.ConsumeToken();

754 SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);

756 IsError = true;

757 } else {

759 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||

760 CKind == OMPC_linear) {

763 if (CKind == OMPC_aligned) {

764 Vars = &Aligneds;

765 } else if (CKind == OMPC_linear) {

766 Data.ExtraModifier = OMPC_LINEAR_val;

767 Vars = &Linears;

768 }

769

770 P.ConsumeToken();

771 if (P.ParseOpenMPVarList(OMPD_declare_simd,

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

773 IsError = true;

774 if (CKind == OMPC_aligned) {

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

776 Data.DepModOrTailExpr);

777 } else if (CKind == OMPC_linear) {

778 assert(0 <= Data.ExtraModifier &&

780 "Unexpected linear modifier.");

781 if (P.getActions().OpenMP().CheckOpenMPLinearModifier(

783 Data.ExtraModifierLoc))

784 Data.ExtraModifier = OMPC_LINEAR_val;

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

786 Data.ExtraModifier);

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

788 }

789 } else

790

791 break;

792 }

793

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

795 P.ConsumeToken();

796 }

797 return IsError;

798}

799

800

804 PP.EnterToken(Tok, true);

805 PP.EnterTokenStream(Toks, true,

806 true);

807

810

811 FNContextRAII FnContext(*this, Ptr);

812 OMPDeclareSimdDeclAttr::BranchStateTy BS =

813 OMPDeclareSimdDeclAttr::BS_Undefined;

821 bool IsError =

823 Alignments, Linears, LinModifiers, Steps);

824 skipUntilPragmaOpenMPEnd(OMPD_declare_simd);

825

827 if (IsError)

828 return Ptr;

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

832}

833

834namespace {

835

836

837enum OMPContextLvl {

838 CONTEXT_SELECTOR_SET_LVL = 0,

839 CONTEXT_SELECTOR_LVL = 1,

840 CONTEXT_TRAIT_LVL = 2,

841};

842

843static StringRef stringLiteralParser(Parser &P) {

844 ExprResult Res = P.ParseStringLiteralExpression(true);

846}

847

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

849 OMPContextLvl Lvl) {

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

852 StringRef Name = P.getPreprocessor().getSpelling(Tok, Buffer);

853 (void)P.ConsumeToken();

854 return Name;

855 }

856

858 return stringLiteralParser(P);

859

861 diag::warn_omp_declare_variant_string_literal_or_identifier)

862 << Lvl;

863 return "";

864}

865

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

868 llvm::StringMap &Seen,

869 OMPContextLvl Lvl) {

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

871 if (Res.second)

872 return false;

873

874

875

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

877 << Lvl << Name;

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

879 << Lvl << Name;

880 return true;

881}

882}

883

884void Parser::parseOMPTraitPropertyKind(OMPTraitProperty &TIProperty,

885 llvm::omp::TraitSet Set,

886 llvm::omp::TraitSelector Selector,

887 llvm::StringMap &Seen) {

888 TIProperty.Kind = TraitProperty::invalid;

889

891 StringRef Name = getNameFromIdOrString(*this, Tok, CONTEXT_TRAIT_LVL);

892 if (Name.empty()) {

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

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

895 return;

896 }

897

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

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

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

902 TIProperty.Kind = TraitProperty::invalid;

903 return;

904 }

905

906

907

908 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)

909 << Name << getOpenMPContextTraitSelectorName(Selector)

910 << getOpenMPContextTraitSetName(Set);

911

912 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);

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

914 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

915 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;

916 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

917 << Name << ""

918 << "()";

919 return;

920 }

921 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);

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

923 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

924 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;

925 bool AllowsTraitScore = false;

926 bool RequiresProperty = false;

927 isValidTraitSelectorForTraitSet(

928 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),

929 AllowsTraitScore, RequiresProperty);

930 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

931 << getOpenMPContextTraitSetName(

932 getOpenMPContextTraitSetForSelector(SelectorForName))

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

934 return;

935 }

936 for (const auto &PotentialSet :

937 {TraitSet::construct, TraitSet::user, TraitSet::implementation,

938 TraitSet::device}) {

939 TraitProperty PropertyForName =

940 getOpenMPContextTraitPropertyKind(PotentialSet, Selector, Name);

941 if (PropertyForName == TraitProperty::invalid)

942 continue;

943 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

944 << getOpenMPContextTraitSetName(

945 getOpenMPContextTraitSetForProperty(PropertyForName))

946 << getOpenMPContextTraitSelectorName(

947 getOpenMPContextTraitSelectorForProperty(PropertyForName))

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

949 return;

950 }

951 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)

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

953}

954

958 llvm::StringMap &Seen) {

959 assert(TISelector.Kind ==

960 llvm::omp::TraitSelector::implementation_extension &&

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

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

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

964 return false;

965

966 if (TIProperty.Kind ==

967 TraitProperty::implementation_extension_disable_implicit_base)

968 return true;

969

970 if (TIProperty.Kind ==

971 TraitProperty::implementation_extension_allow_templates)

972 return true;

973

974 if (TIProperty.Kind ==

975 TraitProperty::implementation_extension_bind_to_declaration)

976 return true;

977

979 return (TP.Kind ==

980 llvm::omp::TraitProperty::implementation_extension_match_all ||

981 TP.Kind ==

982 llvm::omp::TraitProperty::implementation_extension_match_any ||

983 TP.Kind ==

984 llvm::omp::TraitProperty::implementation_extension_match_none);

985 };

986

987 if (IsMatchExtension(TIProperty)) {

989 if (IsMatchExtension(SeenProp)) {

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

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

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

995 << CONTEXT_TRAIT_LVL << SeenName;

996 return false;

997 }

998 return true;

999 }

1000

1001 llvm_unreachable("Unknown extension property!");

1002}

1003

1004void Parser::parseOMPContextProperty(OMPTraitSelector &TISelector,

1005 llvm::omp::TraitSet Set,

1006 llvm::StringMap &Seen) {

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

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

1009

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

1013

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

1016 TISelector, Seen))

1017 TIProperty.Kind = TraitProperty::invalid;

1018

1019

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

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

1023 << CONTEXT_TRAIT_LVL;

1024 return;

1025 }

1026

1027 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.Kind,

1028 TISelector.Kind, Set)) {

1029

1030

1031

1032 TISelector.Properties.push_back(TIProperty);

1033 return;

1034 }

1035

1036 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)

1037 << getOpenMPContextTraitPropertyName(TIProperty.Kind,

1039 << getOpenMPContextTraitSelectorName(TISelector.Kind)

1040 << getOpenMPContextTraitSetName(Set);

1041 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)

1042 << getOpenMPContextTraitPropertyName(TIProperty.Kind,

1044 << getOpenMPContextTraitSelectorName(

1045 getOpenMPContextTraitSelectorForProperty(TIProperty.Kind))

1046 << getOpenMPContextTraitSetName(

1047 getOpenMPContextTraitSetForProperty(TIProperty.Kind));

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

1049 << CONTEXT_TRAIT_LVL;

1050}

1051

1052void Parser::parseOMPTraitSelectorKind(OMPTraitSelector &TISelector,

1053 llvm::omp::TraitSet Set,

1054 llvm::StringMap &Seen) {

1055 TISelector.Kind = TraitSelector::invalid;

1056

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

1059 if (Name.empty()) {

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

1061 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);

1062 return;

1063 }

1064

1065 TISelector.Kind = getOpenMPContextTraitSelectorKind(Name);

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

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

1068 TISelector.Kind = TraitSelector::invalid;

1069 return;

1070 }

1071

1072

1073 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)

1074 << Name << getOpenMPContextTraitSetName(Set);

1075

1076 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);

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

1078 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

1079 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;

1080 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

1081 << Name << ""

1082 << "";

1083 return;

1084 }

1085 for (const auto &PotentialSet :

1086 {TraitSet::construct, TraitSet::user, TraitSet::implementation,

1087 TraitSet::device}) {

1088 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(

1089 PotentialSet, TraitSelector::invalid, Name);

1090 if (PropertyForName == TraitProperty::invalid)

1091 continue;

1092 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

1093 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;

1094 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

1095 << getOpenMPContextTraitSetName(

1096 getOpenMPContextTraitSetForProperty(PropertyForName))

1097 << getOpenMPContextTraitSelectorName(

1098 getOpenMPContextTraitSelectorForProperty(PropertyForName))

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

1100 return;

1101 }

1102 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)

1103 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);

1104}

1105

1106

1110 StringRef SelectorName =

1111 P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);

1112 if (SelectorName != "score")

1113 return ScoreExpr;

1114 (void)P.ConsumeToken();

1116 ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);

1117

1118 if (P.getCurToken().is(tok::colon))

1119 (void)P.ConsumeAnyToken();

1120 else

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

1122 << "':'"

1123 << "score expression";

1124 return ScoreExpr;

1125}

1126

1127

1128

1129

1130void Parser::parseOMPContextSelector(

1132 llvm::StringMap &SeenSelectors) {

1133 unsigned short OuterPC = ParenCount;

1134

1135

1136

1137

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

1139 bool Done = false;

1140 while (!Done) {

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

1142 tok::annot_pragma_openmp_end},

1144 ;

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

1146 (void)ConsumeParen();

1147 if (OuterPC <= ParenCount) {

1148 Done = true;

1149 break;

1150 }

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

1152 Done = true;

1153 break;

1154 }

1156 }

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

1158 << CONTEXT_SELECTOR_LVL;

1159 };

1160

1162 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);

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

1164 return FinishSelector();

1165

1166 bool AllowsTraitScore = false;

1167 bool RequiresProperty = false;

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

1169 RequiresProperty)) {

1170 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)

1171 << getOpenMPContextTraitSelectorName(TISelector.Kind)

1172 << getOpenMPContextTraitSetName(Set);

1173 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)

1174 << getOpenMPContextTraitSelectorName(TISelector.Kind)

1175 << getOpenMPContextTraitSetName(

1176 getOpenMPContextTraitSetForSelector(TISelector.Kind))

1177 << RequiresProperty;

1178 return FinishSelector();

1179 }

1180

1181 if (!RequiresProperty) {

1183 {getOpenMPContextTraitPropertyForSelector(TISelector.Kind),

1184 getOpenMPContextTraitSelectorName(TISelector.Kind)});

1185 return;

1186 }

1187

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

1189 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)

1190 << getOpenMPContextTraitSelectorName(TISelector.Kind)

1191 << getOpenMPContextTraitSetName(Set);

1192 return FinishSelector();

1193 }

1194

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

1199 return FinishSelector();

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

1203 return;

1204 }

1205

1207 tok::annot_pragma_openmp_end);

1208

1209 (void)BDT.consumeOpen();

1210

1213

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

1216 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)

1217 << getOpenMPContextTraitSelectorName(TISelector.Kind)

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

1219 } else {

1220 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)

1221 << getOpenMPContextTraitSelectorName(TISelector.Kind)

1222 << getOpenMPContextTraitSetName(Set) << "";

1223 }

1225 }

1226

1229

1230 llvm::StringMap SeenProperties;

1231 do {

1232 parseOMPContextProperty(TISelector, Set, SeenProperties);

1234

1235

1236 BDT.consumeClose();

1237}

1238

1239void Parser::parseOMPTraitSetKind(OMPTraitSet &TISet,

1240 llvm::StringMap &Seen) {

1241 TISet.Kind = TraitSet::invalid;

1242

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

1245 if (Name.empty()) {

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

1247 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();

1248 return;

1249 }

1250

1251 TISet.Kind = getOpenMPContextTraitSetKind(Name);

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

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

1254 CONTEXT_SELECTOR_SET_LVL))

1255 TISet.Kind = TraitSet::invalid;

1256 return;

1257 }

1258

1259

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

1261

1262 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);

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

1264 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

1265 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;

1266 bool AllowsTraitScore = false;

1267 bool RequiresProperty = false;

1268 isValidTraitSelectorForTraitSet(

1269 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),

1270 AllowsTraitScore, RequiresProperty);

1271 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

1272 << getOpenMPContextTraitSetName(

1273 getOpenMPContextTraitSetForSelector(SelectorForName))

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

1275 return;

1276 }

1277 for (const auto &PotentialSet :

1278 {TraitSet::construct, TraitSet::user, TraitSet::implementation,

1279 TraitSet::device}) {

1280 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(

1281 PotentialSet, TraitSelector::invalid, Name);

1282 if (PropertyForName == TraitProperty::invalid)

1283 continue;

1284 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)

1285 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;

1286 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)

1287 << getOpenMPContextTraitSetName(

1288 getOpenMPContextTraitSetForProperty(PropertyForName))

1289 << getOpenMPContextTraitSelectorName(

1290 getOpenMPContextTraitSelectorForProperty(PropertyForName))

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

1292 return;

1293 }

1294 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)

1295 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();

1296}

1297

1298

1299

1300

1301void Parser::parseOMPContextSelectorSet(

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

1303 auto OuterBC = BraceCount;

1304

1305

1306

1307

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

1309 bool Done = false;

1310 while (!Done) {

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

1312 tok::annot_pragma_openmp_end},

1314 ;

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

1316 (void)ConsumeBrace();

1317 if (OuterBC <= BraceCount) {

1318 Done = true;

1319 break;

1320 }

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

1322 Done = true;

1323 break;

1324 }

1326 }

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

1328 << CONTEXT_SELECTOR_SET_LVL;

1329 };

1330

1331 parseOMPTraitSetKind(TISet, SeenSets);

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

1333 return FinishSelectorSet();

1334

1335

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

1338 << "="

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

1340 "\"")

1341 .str();

1342

1343

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

1345 (void)ConsumeBrace();

1346 } else {

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

1348 << "{"

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

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

1351 .str();

1352 }

1353

1354 llvm::StringMap SeenSelectors;

1355 do {

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

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

1360 TISet.Selectors.push_back(TISelector);

1362

1363

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

1365 (void)ConsumeBrace();

1366 } else {

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

1368 << "}"

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

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

1371 .str();

1372 }

1373}

1374

1375

1376

1377

1379 llvm::StringMap SeenSets;

1380 do {

1382 parseOMPContextSelectorSet(TISet, SeenSets);

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

1384 TI.Sets.push_back(TISet);

1386

1387 return false;

1388}

1389

1390

1394 PP.EnterToken(Tok, true);

1395 PP.EnterTokenStream(Toks, true,

1396 true);

1397

1400

1401 FNContextRAII FnContext(*this, Ptr);

1402

1404

1405

1407 {

1408

1409

1413 getOpenMPDirectiveName(OMPD_declare_variant), RLoc,

1414 true);

1415 }

1416 if (!AssociatedFunction.isUsable()) {

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

1419 ;

1420

1421 (void)ConsumeAnnotationToken();

1422 return;

1423 }

1424

1426 Actions.OpenMP().getOMPTraitInfoForSurroundingScope();

1433

1434

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

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

1438 }

1439

1440 bool IsError = false;

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

1443 ? OMPC_unknown

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

1445 if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,

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

1449 IsError = true;

1450 }

1451 if (!IsError) {

1452 switch (CKind) {

1453 case OMPC_match:

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

1455 break;

1456 case OMPC_adjust_args: {

1461 IsError = ParseOpenMPVarList(OMPD_declare_variant, OMPC_adjust_args,

1462 Vars, Data);

1463 if (!IsError)

1464 llvm::append_range(Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing

1465 ? AdjustNothing

1466 : AdjustNeedDevicePtr,

1467 Vars);

1468 break;

1469 }

1470 case OMPC_append_args:

1471 if (!AppendArgs.empty()) {

1472 Diag(AppendArgsLoc, diag::err_omp_more_one_clause)

1473 << getOpenMPDirectiveName(OMPD_declare_variant)

1474 << getOpenMPClauseName(CKind) << 0;

1475 IsError = true;

1476 }

1477 if (!IsError) {

1480 IsError = parseOpenMPAppendArgs(AppendArgs);

1481 }

1482 break;

1483 default:

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

1485 }

1486 }

1487 if (IsError) {

1489 ;

1490

1491 (void)ConsumeAnnotationToken();

1492 return;

1493 }

1494

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

1497 }

1498

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

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

1503

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

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

1507 AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc,

1509

1510

1511 (void)ConsumeAnnotationToken();

1512}

1513

1514bool Parser::parseOpenMPAppendArgs(

1516 bool HasError = false;

1517

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

1520 getOpenMPClauseName(OMPC_append_args).data()))

1521 return true;

1522

1523

1524

1528 tok::annot_pragma_openmp_end);

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

1530 return true;

1531

1533 if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))

1534 HasError = true;

1535 else

1536 InteropInfos.push_back(InteropInfo);

1537

1538 IT.consumeClose();

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

1541 }

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

1543 HasError = true;

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

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

1547 }

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

1549 return HasError;

1550}

1551

1552bool Parser::parseOMPDeclareVariantMatchClause(SourceLocation Loc,

1555

1557 ? OMPC_unknown

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

1559 if (CKind != OMPC_match) {

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

1562 return true;

1563 }

1565

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

1568 getOpenMPClauseName(OMPC_match).data()))

1569 return true;

1570

1571

1572 parseOMPContextSelectors(Loc, TI);

1573

1574

1575 (void)T.consumeClose();

1576

1577 if (!ParentTI)

1578 return false;

1579

1580

1581

1582

1583

1584

1586 bool MergedSet = false;

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

1589 continue;

1590 MergedSet = true;

1592 bool MergedSelector = false;

1595 continue;

1596 MergedSelector = true;

1599 bool MergedProperty = false;

1601

1603 continue;

1604

1605

1606

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

1608

1611 continue;

1612

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

1614 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);

1615 } else if (Selector.ScoreOrCondition !=

1617 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)

1618 << getOpenMPContextTraitPropertyName(

1620 << getOpenMPContextTraitSelectorName(ParentSelector.Kind)

1621 << getOpenMPContextTraitSetName(ParentSet.Kind);

1622 }

1623 }

1624 if (!MergedProperty)

1625 Selector.Properties.push_back(ParentProperty);

1626 }

1627 }

1628 if (!MergedSelector)

1629 Set.Selectors.push_back(ParentSelector);

1630 }

1631 }

1632 if (!MergedSet)

1633 TI.Sets.push_back(ParentSet);

1634 }

1635

1636 return false;

1637}

1638

1639

1640

1641

1642

1643

1644

1645

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

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

1652 ? OMPC_unknown

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

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

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

1659 SeenClauses[unsigned(CKind)] = true;

1660 if (Clause != nullptr)

1661 Clauses.push_back(Clause);

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

1664 break;

1665 }

1666

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

1670 }

1671}

1672

1673

1674

1675

1676

1677

1678

1679

1680

1681

1682

1683

1684

1688 bool SkippedClauses = false;

1689

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

1692 tok::annot_pragma_openmp_end);

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

1694 return;

1695 T.skipToEnd();

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

1697 Diag(T.getCloseLocation(),

1698 diag::note_omp_assumption_clause_continue_here);

1699 };

1700

1701

1702

1703

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

1705 llvm::StringSwitch SS(RawString);

1706 unsigned ACMIdx = 0;

1707 for (const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {

1708 if (ACMI.StartsWith)

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

1710 else

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

1712 }

1713 return SS.Default(-1);

1714 };

1715

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

1719 int Idx = -1;

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

1723 }

1725

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

1727

1728 if (Idx == -1) {

1729 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)

1730 << llvm::omp::getOpenMPDirectiveName(DKind)

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

1732 if (NextIsLPar)

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

1734 SkippedClauses = true;

1735 continue;

1736 }

1737 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];

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

1739

1740

1741 SkippedClauses = true;

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

1743 continue;

1744 }

1745

1746 if (NextIsLPar) {

1748 diag::warn_omp_unknown_assumption_clause_without_args)

1749 << II;

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

1751 }

1752

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

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

1755 if (ACMI.StartsWith)

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

1757 else

1758 Assumption = "omp_" + Assumption;

1759 Assumptions.push_back(Assumption);

1760 }

1761

1763 SkippedClauses);

1764}

1765

1766void Parser::ParseOpenMPEndAssumesDirective(SourceLocation Loc) {

1769 else

1770 Diag(Loc, diag::err_expected_begin_assumes);

1771}

1772

1773

1774

1775

1776

1777

1778

1779

1780

1781

1782

1783namespace {

1784struct SimpleClauseData {

1785 unsigned Type;

1793};

1794}

1795

1796static std::optional

1798 const Token &Tok = P.getCurToken();

1801

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

1804 getOpenMPClauseName(Kind).data()))

1805 return std::nullopt;

1806

1808 Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok),

1809 P.getLangOpts());

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

1812 Tok.isNot(tok::annot_pragma_openmp_end))

1813 P.ConsumeAnyToken();

1814

1815

1817 if (T.consumeClose())

1818 RLoc = T.getCloseLocation();

1819

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

1821}

1822

1823void Parser::ParseOMPDeclareTargetClauses(

1826 bool RequiresToOrLinkOrIndirectClause = false;

1827 bool HasToOrLinkOrIndirectClause = false;

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

1829 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;

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

1831 if (HasIdentifier) {

1832

1833 RequiresToOrLinkOrIndirectClause = true;

1835 StringRef ClauseName = II->getName();

1836 bool IsDeviceTypeClause =

1838 getOpenMPClauseKind(ClauseName) == OMPC_device_type;

1839

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

1841 getOpenMPClauseKind(ClauseName) == OMPC_indirect;

1842 if (DTCI.Indirect && IsIndirectClause) {

1843 Diag(Tok, diag::err_omp_more_one_clause)

1844 << getOpenMPDirectiveName(OMPD_declare_target)

1845 << getOpenMPClauseName(OMPC_indirect) << 0;

1846 break;

1847 }

1848 bool IsToEnterOrLinkClause =

1849 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);

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

1851 "Cannot be both!");

1852

1853

1854

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

1856 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);

1857 break;

1858 }

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

1860 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);

1861 break;

1862 }

1863

1864 if (!IsDeviceTypeClause && !IsIndirectClause &&

1865 DTCI.Kind == OMPD_begin_declare_target) {

1866 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)

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

1868 break;

1869 }

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

1872 ? diag::err_omp_declare_target_unexpected_clause_52

1873 : diag::err_omp_declare_target_unexpected_clause)

1874 << ClauseName

1876 ? 4

1878 break;

1879 }

1880

1881 if (IsToEnterOrLinkClause || IsIndirectClause)

1882 HasToOrLinkOrIndirectClause = true;

1883

1884 if (IsIndirectClause) {

1885 if (!ParseOpenMPIndirectClause(DTCI, false))

1886 break;

1887 continue;

1888 }

1889

1890 if (IsDeviceTypeClause) {

1891 std::optional DevTypeData =

1893 if (DevTypeData) {

1894 if (DeviceTypeLoc.isValid()) {

1895

1896 Diag(DevTypeData->Loc,

1897 diag::warn_omp_more_one_device_type_clause);

1898 break;

1899 }

1901 case OMPC_DEVICE_TYPE_any:

1902 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;

1903 break;

1904 case OMPC_DEVICE_TYPE_host:

1905 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;

1906 break;

1907 case OMPC_DEVICE_TYPE_nohost:

1908 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;

1909 break;

1911 llvm_unreachable("Unexpected device_type");

1912 }

1913 DeviceTypeLoc = DevTypeData->Loc;

1914 }

1915 continue;

1916 }

1918 }

1919

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

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

1925 if (!ND)

1926 return;

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

1929 if (!FirstMapping)

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

1932 };

1933 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,

1934 true))

1935 break;

1936 }

1937

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

1940 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);

1941 break;

1942 }

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

1946 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter

1947 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);

1948 break;

1949 }

1950

1951

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

1954 }

1955

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

1957 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);

1958

1959

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

1961 !HasToOrLinkOrIndirectClause)

1964 ? diag::err_omp_declare_target_missing_enter_or_link_clause

1965 : diag::err_omp_declare_target_missing_to_or_link_clause)

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

1967

1969}

1970

1972

1973

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

1975 return;

1976

1977 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)

1978 << getOpenMPDirectiveName(DKind);

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

1981}

1982

1988 bool SkipUntilOpenMPEnd) {

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

1990

1991 if (FoundKind == ExpectedKind) {

1993 skipUntilPragmaOpenMPEnd(ExpectedKind);

1994 return;

1995 }

1996

1997 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)

1998 << DiagSelection;

1999 Diag(BeginLoc, diag::note_matching)

2000 << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str();

2001 if (SkipUntilOpenMPEnd)

2003}

2004

2005void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind BeginDKind,

2008 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,

2010 false);

2011

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

2013 ConsumeAnnotationToken();

2014}

2015

2016

2017

2018

2019

2020

2021

2022

2023

2024

2025

2026

2027

2028

2029

2030

2031

2032

2033

2034

2035

2036

2037

2038

2039

2040

2041

2042

2043

2044

2045

2046

2047

2048

2049

2050

2051

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

2056 "Not an OpenMP directive!");

2059

2062 if (Delayed) {

2063 TentativeParsingAction TPA(*this);

2064 Loc = ConsumeAnnotationToken();

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

2067

2068 TPA.Revert();

2070 unsigned Cnt = 1;

2071 Toks.push_back(Tok);

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

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

2075 ++Cnt;

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

2077 --Cnt;

2078 Toks.push_back(Tok);

2079 }

2080

2081 if (Cnt == 0)

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

2084 LP->takeToks(Toks);

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

2086 return nullptr;

2087 }

2088 TPA.Commit();

2089 } else {

2090 Loc = ConsumeAnnotationToken();

2092 }

2093

2094 switch (DKind) {

2095 case OMPD_threadprivate: {

2097 DeclDirectiveListParserHelper Helper(this, DKind);

2098 if (!ParseOpenMPSimpleVarList(DKind, Helper,

2099 true)) {

2100 skipUntilPragmaOpenMPEnd(DKind);

2101

2102 ConsumeAnnotationToken();

2104 Loc, Helper.getIdentifiers());

2105 }

2106 break;

2107 }

2108 case OMPD_allocate: {

2110 DeclDirectiveListParserHelper Helper(this, DKind);

2111 if (!ParseOpenMPSimpleVarList(DKind, Helper,

2112 true)) {

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

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

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

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

2121 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,

2122 !SeenClauses[unsigned(CKind)]);

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

2125 SeenClauses[unsigned(CKind)] = true;

2126 if (Clause != nullptr)

2127 Clauses.push_back(Clause);

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

2130 break;

2131 }

2132

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

2136 }

2137 skipUntilPragmaOpenMPEnd(DKind);

2138 }

2139

2140 ConsumeAnnotationToken();

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

2143 }

2144 break;

2145 }

2146 case OMPD_requires: {

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

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

2151 Diag(Tok, diag::err_omp_expected_clause)

2152 << getOpenMPDirectiveName(OMPD_requires);

2153 break;

2154 }

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

2157 ? OMPC_unknown

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

2160 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,

2161 !SeenClauses[unsigned(CKind)]);

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

2164 SeenClauses[unsigned(CKind)] = true;

2165 if (Clause != nullptr)

2166 Clauses.push_back(Clause);

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

2169 break;

2170 }

2171

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

2175 }

2176

2177 if (Clauses.empty()) {

2178 Diag(Tok, diag::err_omp_expected_clause)

2179 << getOpenMPDirectiveName(OMPD_requires);

2180 ConsumeAnnotationToken();

2181 return nullptr;

2182 }

2183 ConsumeAnnotationToken();

2185 }

2186 case OMPD_error: {

2189 ParseOpenMPClauses(DKind, Clauses, StartLoc);

2192 false);

2193 break;

2194 }

2195 case OMPD_assumes:

2196 case OMPD_begin_assumes:

2197 ParseOpenMPAssumesDirective(DKind, ConsumeToken());

2198 break;

2199 case OMPD_end_assumes:

2200 ParseOpenMPEndAssumesDirective(ConsumeToken());

2201 break;

2202 case OMPD_declare_reduction:

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

2205 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);

2206

2207 ConsumeAnnotationToken();

2208 return Res;

2209 }

2210 break;

2211 case OMPD_declare_mapper: {

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

2214

2215 ConsumeAnnotationToken();

2216 return Res;

2217 }

2218 break;

2219 }

2220 case OMPD_begin_declare_variant: {

2221

2222

2223

2224

2225

2228 Actions.OpenMP().getOMPTraitInfoForSurroundingScope();

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

2233 ;

2234

2235 (void)ConsumeAnnotationToken();

2236 break;

2237 }

2238

2239

2240 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);

2241

2243

2244 VariantMatchInfo VMI;

2246

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

2248 [this, Loc](StringRef ISATrait) {

2249

2250

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

2252 };

2254 ASTCtx, std::move(DiagUnknownTrait),

2255 nullptr,

2257

2258 if (isVariantApplicableInContext(VMI, OMPCtx, true)) {

2260 break;

2261 }

2262

2263

2264 unsigned Nesting = 1;

2267 do {

2270 if (DK == OMPD_end_declare_variant)

2271 --Nesting;

2272 else if (DK == OMPD_begin_declare_variant)

2273 ++Nesting;

2274 if (!Nesting || isEofOrEom())

2275 break;

2277 } while (true);

2278

2279 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,

2280 DK, Loc, DKLoc, true);

2281 if (isEofOrEom())

2282 return nullptr;

2283 break;

2284 }

2285 case OMPD_end_declare_variant: {

2288 else

2289 Diag(Loc, diag::err_expected_begin_declare_variant);

2291 break;

2292 }

2293 case OMPD_declare_variant:

2294 case OMPD_declare_simd: {

2295

2296

2297

2298

2300 Toks.push_back(Tok);

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

2303 Toks.push_back(Tok);

2305 }

2306 Toks.push_back(Tok);

2308

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

2311 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,

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

2314

2318 MaybeParseCXX11Attributes(Attrs);

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

2321 } else {

2322 Ptr =

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

2324 }

2325 }

2326 if (!Ptr) {

2327 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)

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

2330 }

2331 if (DKind == OMPD_declare_simd)

2332 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);

2333 assert(DKind == OMPD_declare_variant &&

2334 "Expected declare variant directive only");

2335 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);

2336 return Ptr;

2337 }

2338 case OMPD_begin_declare_target:

2339 case OMPD_declare_target: {

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

2343 if (HasClauses)

2344 ParseOMPDeclareTargetClauses(DTCI);

2345 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||

2346 !HasClauses ||

2348

2349

2351

2352 if (HasImplicitMappings) {

2354 return nullptr;

2355 }

2356

2360 Decls.push_back(It.first);

2362 }

2363 case OMPD_end_declare_target: {

2365 Diag(Tok, diag::err_omp_unexpected_directive)

2366 << 1 << getOpenMPDirectiveName(DKind);

2367 break;

2368 }

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

2372 return nullptr;

2373 }

2374 case OMPD_assume: {

2375 Diag(Tok, diag::err_omp_unexpected_directive)

2376 << 1 << getOpenMPDirectiveName(DKind);

2377 break;

2378 }

2379 case OMPD_unknown:

2380 Diag(Tok, diag::err_omp_unknown_directive);

2381 break;

2382 default:

2383 switch (getDirectiveCategory(DKind)) {

2384 case Category::Executable:

2385 case Category::Meta:

2386 case Category::Subsidiary:

2387 case Category::Utility:

2388 Diag(Tok, diag::err_omp_unexpected_directive)

2389 << 1 << getOpenMPDirectiveName(DKind);

2390 break;

2391 case Category::Declarative:

2392 case Category::Informational:

2393 break;

2394 }

2395 }

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

2399 return nullptr;

2400}

2401

2402StmtResult Parser::ParseOpenMPExecutableDirective(

2404 bool ReadDirectiveWithinMetadirective) {

2406

2407 bool HasAssociatedStatement = true;

2408 Association Assoc = getDirectiveAssociation(DKind);

2409

2410

2411

2412

2413

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

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

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

2417 ParsedStmtContext()) {

2418 Diag(Tok, diag::err_omp_immediate_directive)

2419 << getOpenMPDirectiveName(DKind) << 0;

2420 if (DKind == OMPD_error) {

2421 SkipUntil(tok::annot_pragma_openmp_end);

2423 }

2424 }

2425 HasAssociatedStatement = false;

2426 }

2427

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

2435

2436

2437 Token ImplicitTok;

2438 bool ImplicitClauseAllowed = false;

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

2440 ImplicitTok = Tok;

2441 ImplicitClauseAllowed = true;

2442 }

2444

2445 if (DKind == OMPD_critical) {

2447 tok::annot_pragma_openmp_end);

2448 if (T.consumeOpen()) {

2450 DirName =

2453 } else {

2454 Diag(Tok, diag::err_omp_expected_identifier_for_critical);

2455 }

2456 T.consumeClose();

2457 }

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

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

2462 }

2463

2468 ParseScope OMPDirectiveScope(this, ScopeFlags);

2471

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

2473

2474

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

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

2478 break;

2479 }

2480 bool HasImplicitClause = false;

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

2482 HasImplicitClause = true;

2483

2484

2485 PP.EnterToken(Tok, true);

2486 PP.EnterToken(ImplicitTok, true);

2488 }

2490 ? OMPC_unknown

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

2492 if (HasImplicitClause) {

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

2494 if (DKind == OMPD_flush) {

2495 CKind = OMPC_flush;

2496 } else {

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

2498 CKind = OMPC_depobj;

2499 }

2500 }

2501

2502 ImplicitClauseAllowed = false;

2504 HasImplicitClause = false;

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

2507 SeenClauses[unsigned(CKind)] = true;

2508 if (Clause)

2509 Clauses.push_back(Clause);

2510

2511

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

2515 }

2516

2518

2519 ConsumeAnnotationToken();

2520

2521 if (DKind == OMPD_ordered) {

2522

2523

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

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

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

2527 ParsedStmtContext()) {

2528 Diag(Loc, diag::err_omp_immediate_directive)

2529 << getOpenMPDirectiveName(DKind) << 1 << getOpenMPClauseName(CK);

2530 }

2531 HasAssociatedStatement = false;

2532 }

2533 }

2534 }

2535

2536 if (DKind == OMPD_tile && !SeenClauses[unsigned(OMPC_sizes)]) {

2537 Diag(Loc, diag::err_omp_required_clause)

2538 << getOpenMPDirectiveName(OMPD_tile) << "sizes";

2539 }

2540

2542 if (HasAssociatedStatement) {

2543

2545

2546

2547

2549 {

2551 AssociatedStmt = ParseStatement();

2552

2555 AssociatedStmt =

2557 }

2558 AssociatedStmt =

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

2561 DKind == OMPD_target_exit_data) {

2565 false));

2566 AssociatedStmt =

2568 }

2569

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

2572

2573

2575 OMPDirectiveScope.Exit();

2576

2578}

2579

2580StmtResult Parser::ParseOpenMPInformationalDirective(

2582 bool ReadDirectiveWithinMetadirective) {

2584 "Unexpected directive category");

2585

2586 bool HasAssociatedStatement = true;

2587

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

2593 ParseScope OMPDirectiveScope(this, ScopeFlags);

2594

2597

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

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

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

2602 break;

2603 }

2604

2606 ? OMPC_unknown

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

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

2611 SeenClauses[unsigned(CKind)] = true;

2612 if (Clause)

2613 Clauses.push_back(Clause);

2614

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

2618 }

2619

2621 ConsumeAnnotationToken();

2622

2624 if (HasAssociatedStatement) {

2627 {

2629 AssociatedStmt = ParseStatement();

2630 }

2631 AssociatedStmt =

2633 }

2634

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

2637

2639 OMPDirectiveScope.Exit();

2640

2642}

2643

2644

2645

2646

2647

2648

2649

2650

2651

2652

2653

2654

2655

2656

2657

2658

2659

2660

2661

2662

2663

2664

2665

2666

2667

2668

2669

2670

2671

2672

2673

2674

2675

2676

2677

2678

2679

2680

2681

2682

2683

2684StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(

2685 ParsedStmtContext StmtCtx, bool ReadDirectiveWithinMetadirective) {

2686 if (!ReadDirectiveWithinMetadirective)

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

2688 "Not an OpenMP directive!");

2693 : ConsumeAnnotationToken();

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

2696 Diag(Tok, diag::err_omp_unknown_directive);

2698 }

2699

2701

2702 bool IsExecutable = [&]() {

2703 if (DKind == OMPD_error)

2704 return true;

2705 auto Res = getDirectiveCategory(DKind);

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

2707 }();

2708

2709 if (IsExecutable) {

2710 Directive = ParseOpenMPExecutableDirective(

2711 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);

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

2714 }

2715

2716 switch (DKind) {

2717 case OMPD_nothing:

2719

2720

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

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

2724 else

2725 skipUntilPragmaOpenMPEnd(DKind);

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

2727 ConsumeAnnotationToken();

2728

2730 case OMPD_metadirective: {

2733

2734

2735

2736

2737 TentativeParsingAction TPA(*this);

2739

2741 tok::annot_pragma_openmp_end);

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

2744 ? OMPC_unknown

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

2747

2748

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

2750 getOpenMPClauseName(CKind).data()))

2752

2754 if (CKind == OMPC_when) {

2755

2756 parseOMPContextSelectors(Loc, TI);

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

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

2759 TPA.Commit();

2761 }

2762

2763

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

2766 else {

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

2768 TPA.Commit();

2770 }

2771 }

2772

2773 int paren = 0;

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

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

2776 paren++;

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

2778 paren--;

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

2780 Diag(Tok, diag::err_omp_expected_punc)

2781 << getOpenMPClauseName(CKind) << 0;

2782 TPA.Commit();

2784 }

2786 }

2787

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

2789 T.consumeClose();

2790

2791 VariantMatchInfo VMI;

2793

2794 VMIs.push_back(VMI);

2795 }

2796

2797 TPA.Revert();

2798

2799

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

2801 [this, Loc](StringRef ISATrait) {

2802

2803

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

2805 };

2807 nullptr,

2809

2810

2811 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);

2812

2813 int Idx = 0;

2814

2815

2816

2817

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

2819

2820 if (Idx++ != BestIdx) {

2822 T.consumeOpen();

2823 int paren = 0;

2824

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

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

2827 paren++;

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

2829 paren--;

2831 }

2832

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

2834 T.consumeClose();

2835 continue;

2836 }

2837

2839 ? OMPC_unknown

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

2842

2843

2844 T.consumeOpen();

2845

2846

2847 if (CKind == OMPC_when) {

2849

2850 parseOMPContextSelectors(Loc, TI);

2851

2852

2854 }

2855

2856

2857

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

2859 SkipUntil(tok::annot_pragma_openmp_end);

2860 break;

2861 }

2862

2863

2864 Directive = ParseOpenMPDeclarativeOrExecutableDirective(

2865 StmtCtx,

2866 true);

2867 break;

2868 }

2869 break;

2870 }

2871 case OMPD_threadprivate: {

2872

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

2874 ParsedStmtContext()) {

2875 Diag(Tok, diag::err_omp_immediate_directive)

2876 << getOpenMPDirectiveName(DKind) << 0;

2877 }

2879 DeclDirectiveListParserHelper Helper(this, DKind);

2880 if (!ParseOpenMPSimpleVarList(DKind, Helper,

2881 false)) {

2882 skipUntilPragmaOpenMPEnd(DKind);

2884 Loc, Helper.getIdentifiers());

2886 }

2887 SkipUntil(tok::annot_pragma_openmp_end);

2888 break;

2889 }

2890 case OMPD_allocate: {

2891

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

2893 ParsedStmtContext()) {

2894 Diag(Tok, diag::err_omp_immediate_directive)

2895 << getOpenMPDirectiveName(DKind) << 0;

2896 }

2898 DeclDirectiveListParserHelper Helper(this, DKind);

2899 if (!ParseOpenMPSimpleVarList(DKind, Helper,

2900 false)) {

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

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

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

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

2909 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,

2910 !SeenClauses[unsigned(CKind)]);

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

2913 SeenClauses[unsigned(CKind)] = true;

2914 if (Clause != nullptr)

2915 Clauses.push_back(Clause);

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

2918 break;

2919 }

2920

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

2924 }

2925 skipUntilPragmaOpenMPEnd(DKind);

2926 }

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

2930 }

2931 SkipUntil(tok::annot_pragma_openmp_end);

2932 break;

2933 }

2934 case OMPD_declare_reduction:

2937 ParseOpenMPDeclareReductionDirective(AS_none)) {

2938 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);

2941 } else {

2942 SkipUntil(tok::annot_pragma_openmp_end);

2943 }

2944 break;

2945 case OMPD_declare_mapper: {

2948 ParseOpenMPDeclareMapperDirective(AS_none)) {

2949

2950 ConsumeAnnotationToken();

2952 } else {

2953 SkipUntil(tok::annot_pragma_openmp_end);

2954 }

2955 break;

2956 }

2957 case OMPD_declare_target: {

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

2961 if (HasClauses)

2962 ParseOMPDeclareTargetClauses(DTCI);

2963 bool HasImplicitMappings =

2965

2966 if (HasImplicitMappings) {

2967 Diag(Tok, diag::err_omp_unexpected_directive)

2968 << 1 << getOpenMPDirectiveName(DKind);

2969 SkipUntil(tok::annot_pragma_openmp_end);

2970 break;

2971 }

2972

2973

2975

2977 break;

2978 }

2979 case OMPD_declare_simd:

2980 case OMPD_begin_declare_target:

2981 case OMPD_end_declare_target:

2982 case OMPD_requires:

2983 case OMPD_begin_declare_variant:

2984 case OMPD_end_declare_variant:

2985 case OMPD_declare_variant:

2986 Diag(Tok, diag::err_omp_unexpected_directive)

2987 << 1 << getOpenMPDirectiveName(DKind);

2988 SkipUntil(tok::annot_pragma_openmp_end);

2989 break;

2990 case OMPD_assume: {

2992 Directive = ParseOpenMPInformationalDirective(

2993 StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);

2995 "Informational directive remains unprocessed");

2997 }

2998 case OMPD_unknown:

2999 default:

3000 Diag(Tok, diag::err_omp_unknown_directive);

3001 SkipUntil(tok::annot_pragma_openmp_end);

3002 break;

3003 }

3005}

3006

3007

3008

3009

3010

3011bool Parser::ParseOpenMPSimpleVarList(

3014 &Callback,

3015 bool AllowScopeSpecifier) {

3016

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

3019 getOpenMPDirectiveName(Kind).data()))

3020 return true;

3021 bool IsCorrect = true;

3022 bool NoIdentIsFound = true;

3023

3024

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

3028

3029 Token PrevTok = Tok;

3030 NoIdentIsFound = false;

3031

3033 ParseOptionalCXXScopeSpecifier(SS, nullptr,

3034 false, false)) {

3035 IsCorrect = false;

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

3039 false, false, false,

3040 false, false, nullptr, Name)) {

3041 IsCorrect = false;

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

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

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

3046 IsCorrect = false;

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

3050 << tok::identifier

3052 } else {

3054 }

3055

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

3058 }

3059 }

3060

3061 if (NoIdentIsFound) {

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

3063 IsCorrect = false;

3064 }

3065

3066

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

3068

3069 return !IsCorrect;

3070}

3071

3072OMPClause *Parser::ParseOpenMPSizesClause() {

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

3076 ValExprs))

3077 return nullptr;

3078

3080 OpenLoc, CloseLoc);

3081}

3082

3083OMPClause *Parser::ParseOpenMPPermutationClause() {

3086 if (ParseOpenMPExprListClause(OMPC_permutation, ClauseNameLoc, OpenLoc,

3087 CloseLoc, ArgExprs,

3088 true))

3089 return nullptr;

3090

3092 OpenLoc, CloseLoc);

3093}

3094

3098

3099

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

3102 return nullptr;

3104 do {

3106 Token Replacement;

3109 ? ParseCXXIdExpression()

3110 : tryParseCXXIdExpression(SS, false,

3111 Replacement);

3112 if (Allocator.isInvalid()) {

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

3115 break;

3116 }

3118 D.Allocator = Allocator.get();

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

3121 tok::annot_pragma_openmp_end);

3122 T.consumeOpen();

3125 T.consumeClose();

3126 if (AllocatorTraits.isInvalid()) {

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

3129 break;

3130 }

3131 D.AllocatorTraits = AllocatorTraits.get();

3132 D.LParenLoc = T.getOpenLocation();

3133 D.RParenLoc = T.getCloseLocation();

3134 }

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

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

3137

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

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

3141 T.consumeClose();

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

3144}

3145

3146

3147

3148

3149

3150

3151

3152

3153

3154

3155

3156

3157

3158

3159

3160

3161

3162

3163

3164

3165

3168 OMPClauseKind = CKind;

3170 bool ErrorFound = false;

3171 bool WrongDirective = false;

3172

3173 if (CKind != OMPC_unknown &&

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

3175 Diag(Tok, diag::err_omp_unexpected_clause)

3176 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);

3177 ErrorFound = true;

3178 WrongDirective = true;

3179 }

3180

3181 switch (CKind) {

3182 case OMPC_final:

3183 case OMPC_num_threads:

3184 case OMPC_safelen:

3185 case OMPC_simdlen:

3186 case OMPC_collapse:

3187 case OMPC_ordered:

3188 case OMPC_priority:

3189 case OMPC_grainsize:

3190 case OMPC_num_tasks:

3191 case OMPC_hint:

3192 case OMPC_allocator:

3193 case OMPC_depobj:

3194 case OMPC_detach:

3195 case OMPC_novariants:

3196 case OMPC_nocontext:

3197 case OMPC_filter:

3198 case OMPC_partial:

3199 case OMPC_align:

3200 case OMPC_message:

3201 case OMPC_ompx_dyn_cgroup_mem:

3202

3203

3204

3205

3206

3207

3208

3209

3210

3211

3212

3213

3214

3215

3216

3217

3218

3219

3220

3221

3222

3223

3224

3225

3226

3227

3228

3229 if (!FirstClause) {

3230 Diag(Tok, diag::err_omp_more_one_clause)

3231 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;

3232 ErrorFound = true;

3233 }

3234

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

3237 Clause = ParseOpenMPClause(CKind, WrongDirective);

3238 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)

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

3240 else

3241 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);

3242 break;

3243 case OMPC_fail:

3244 case OMPC_default:

3245 case OMPC_proc_bind:

3246 case OMPC_atomic_default_mem_order:

3247 case OMPC_at:

3248 case OMPC_severity:

3249 case OMPC_bind:

3250

3251

3252

3253

3254

3255

3256

3257

3258

3259

3260

3261

3262

3263 if (!FirstClause) {

3264 Diag(Tok, diag::err_omp_more_one_clause)

3265 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;

3266 ErrorFound = true;

3267 }

3268

3269 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);

3270 break;

3271 case OMPC_device:

3272 case OMPC_schedule:

3273 case OMPC_dist_schedule:

3274 case OMPC_defaultmap:

3275 case OMPC_order:

3276

3277

3278

3279

3280

3281

3282

3283

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

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

3286 Diag(Tok, diag::err_omp_more_one_clause)

3287 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;

3288 ErrorFound = true;

3289 }

3290 [[fallthrough]];

3291 case OMPC_if:

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

3293 break;

3294 case OMPC_holds:

3295 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);

3296 break;

3297 case OMPC_nowait:

3298 case OMPC_untied:

3299 case OMPC_mergeable:

3300 case OMPC_read:

3301 case OMPC_write:

3302 case OMPC_capture:

3303 case OMPC_compare:

3304 case OMPC_seq_cst:

3305 case OMPC_acq_rel:

3306 case OMPC_acquire:

3307 case OMPC_release:

3308 case OMPC_relaxed:

3309 case OMPC_weak:

3310 case OMPC_threads:

3311 case OMPC_simd:

3312 case OMPC_nogroup:

3313 case OMPC_unified_address:

3314 case OMPC_unified_shared_memory:

3315 case OMPC_reverse_offload:

3316 case OMPC_dynamic_allocators:

3317 case OMPC_full:

3318

3319

3320

3321

3322

3323

3324 if (!FirstClause) {

3325 Diag(Tok, diag::err_omp_more_one_clause)

3326 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;

3327 ErrorFound = true;

3328 }

3329

3330 Clause = ParseOpenMPClause(CKind, WrongDirective);

3331 break;

3332 case OMPC_update:

3333 if (!FirstClause) {

3334 Diag(Tok, diag::err_omp_more_one_clause)

3335 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;

3336 ErrorFound = true;

3337 }

3338

3339 Clause = (DKind == OMPD_depobj)

3340 ? ParseOpenMPSimpleClause(CKind, WrongDirective)

3341 : ParseOpenMPClause(CKind, WrongDirective);

3342 break;

3343 case OMPC_num_teams:

3344 case OMPC_thread_limit:

3345 if (!FirstClause) {

3346 Diag(Tok, diag::err_omp_more_one_clause)

3347 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;

3348 ErrorFound = true;

3349 }

3350 [[fallthrough]];

3351 case OMPC_private:

3352 case OMPC_firstprivate:

3353 case OMPC_lastprivate:

3354 case OMPC_shared:

3355 case OMPC_reduction:

3356 case OMPC_task_reduction:

3357 case OMPC_in_reduction:

3358 case OMPC_linear:

3359 case OMPC_aligned:

3360 case OMPC_copyin:

3361 case OMPC_copyprivate:

3362 case OMPC_flush:

3363 case OMPC_depend:

3364 case OMPC_map:

3365 case OMPC_to:

3366 case OMPC_from:

3367 case OMPC_use_device_ptr:

3368 case OMPC_use_device_addr:

3369 case OMPC_is_device_ptr:

3370 case OMPC_has_device_addr:

3371 case OMPC_allocate:

3372 case OMPC_nontemporal:

3373 case OMPC_inclusive:

3374 case OMPC_exclusive:

3375 case OMPC_affinity:

3376 case OMPC_doacross:

3377 case OMPC_enter:

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

3379 CKind == OMPC_depend)

3380 Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);

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

3382 break;

3383 case OMPC_sizes:

3384 if (!FirstClause) {

3385 Diag(Tok, diag::err_omp_more_one_clause)

3386 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;

3387 ErrorFound = true;

3388 }

3389

3390 Clause = ParseOpenMPSizesClause();

3391 break;

3392 case OMPC_permutation:

3393 if (!FirstClause) {

3394 Diag(Tok, diag::err_omp_more_one_clause)

3395 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;

3396 ErrorFound = true;

3397 }

3398 Clause = ParseOpenMPPermutationClause();

3399 break;

3400 case OMPC_uses_allocators:

3401 Clause = ParseOpenMPUsesAllocatorClause(DKind);

3402 break;

3403 case OMPC_destroy:

3404 if (DKind != OMPD_interop) {

3405 if (!FirstClause) {

3406 Diag(Tok, diag::err_omp_more_one_clause)

3407 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;

3408 ErrorFound = true;

3409 }

3410 Clause = ParseOpenMPClause(CKind, WrongDirective);

3411 break;

3412 }

3413 [[fallthrough]];

3414 case OMPC_init:

3415 case OMPC_use:

3416 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);

3417 break;

3418 case OMPC_device_type:

3419 case OMPC_unknown:

3420 skipUntilPragmaOpenMPEnd(DKind);

3421 break;

3422 case OMPC_threadprivate:

3423 case OMPC_uniform:

3424 case OMPC_match:

3425 if (!WrongDirective)

3426 Diag(Tok, diag::err_omp_unexpected_clause)

3427 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);

3429 break;

3430 case OMPC_absent:

3431 case OMPC_contains: {

3437 T.consumeOpen();

3438 do {

3440 if (DK == OMPD_unknown) {

3441 skipUntilPragmaOpenMPEnd(OMPD_assume);

3442 Diag(Tok, diag::err_omp_unexpected_clause)

3443 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);

3444 break;

3445 }

3447 DKVec.push_back(DK);

3449 } else {

3450 Diag(Tok, diag::err_omp_unexpected_clause)

3451 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);

3452 }

3455 T.consumeClose();

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

3458 break;

3459 }

3460 case OMPC_no_openmp:

3461 case OMPC_no_openmp_routines:

3462 case OMPC_no_parallelism: {

3463 if (!FirstClause) {

3464 Diag(Tok, diag::err_omp_more_one_clause)

3465 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;

3466 ErrorFound = true;

3467 }

3471 break;

3472 }

3473 case OMPC_ompx_attribute:

3474 Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);

3475 break;

3476 case OMPC_ompx_bare:

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

3478

3479

3480

3481

3482 Diag(Tok, diag::err_omp_unexpected_clause)

3483 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);

3484 ErrorFound = true;

3485 WrongDirective = true;

3486 }

3487 if (WrongDirective)

3488 Diag(Tok, diag::note_ompx_bare_clause)

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

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

3491 Diag(Tok, diag::err_omp_unexpected_clause_extension_only)

3492 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);

3493 ErrorFound = true;

3494 }

3495 Clause = ParseOpenMPClause(CKind, WrongDirective);

3496 break;

3497 default:

3498 break;

3499 }

3500 return ErrorFound ? nullptr : Clause;

3501}

3502

3503

3504

3505

3508 bool IsAddressOfOperand) {

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

3512

3515 ParseCastExpression(AnyCastExpr, IsAddressOfOperand, NotTypeCast));

3518

3519

3521 if (T.consumeClose())

3522 RLoc = T.getCloseLocation();

3523

3524 return Val;

3525}

3526

3527

3528

3529

3530

3531

3532

3533

3534

3535

3536

3537

3538

3539

3540

3541

3542

3543

3544

3545

3546

3547

3548

3549

3550

3551

3552

3553

3554

3555

3556

3557

3558

3559

3560

3561

3562

3563

3564

3565

3566

3567

3568

3569

3570

3572 bool ParseOnly) {

3576

3578

3580 return nullptr;

3581

3582 if (ParseOnly)

3583 return nullptr;

3585 LLoc, RLoc);

3586}

3587

3588

3589

3590

3591

3592bool Parser::ParseOpenMPIndirectClause(

3596

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

3598 if (ParseOnly)

3599 return false;

3601 return true;

3602 }

3603

3607 return false;

3608

3609 if (ParseOnly)

3610 return false;

3611

3616 if (Ret.isInvalid())

3617 return false;

3618 llvm::APSInt Result;

3621 if (Ret.isInvalid())

3622 return false;

3624 return true;

3625 }

3626 return false;

3627}

3628

3629

3630

3631bool Parser::ParseOMPInteropInfo(OMPInteropInfo &InteropInfo,

3634 bool HasError = false;

3635 bool IsTarget = false;

3636 bool IsTargetSync = false;

3637

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

3639

3640 bool PreferTypeAllowed = Kind == OMPC_init &&

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

3642 !IsTargetSync;

3644

3645

3646

3647 if (IsTarget)

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

3649 IsTarget = true;

3652 if (IsTargetSync)

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

3654 IsTargetSync = true;

3657 PreferTypeAllowed) {

3660 tok::annot_pragma_openmp_end);

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

3662 HasError = true;

3663

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

3666 ExprResult LHS = ParseCastExpression(AnyCastExpr);

3670 false);

3673 } else {

3674 HasError = true;

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

3677 }

3678

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

3681 }

3682 PT.consumeClose();

3683 } else {

3684 HasError = true;

3685 Diag(Tok, diag::err_omp_expected_interop_type);

3687 }

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

3689 break;

3691 }

3692

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

3694 Diag(Tok, diag::err_omp_expected_interop_type);

3695 HasError = true;

3696 }

3697

3698 if (Kind == OMPC_init) {

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

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

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

3703 }

3704

3705

3706

3707 InteropInfo.IsTarget = IsTarget;

3709

3710 return HasError;

3711}

3712

3713

3714

3715

3716

3717

3718

3719

3720

3721

3722

3723

3724

3725

3726

3727

3728

3729

3730

3731

3732

3733

3734

3735

3737 bool ParseOnly) {

3739

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

3742 getOpenMPClauseName(Kind).data()))

3743 return nullptr;

3744

3745 bool InteropError = false;

3747 if (Kind == OMPC_init)

3748 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);

3749

3750

3754 if (!InteropVarExpr.isUsable()) {

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

3757 }

3758

3759

3761 if (T.consumeClose())

3762 RLoc = T.getCloseLocation();

3763

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

3765 return nullptr;

3766

3767 if (Kind == OMPC_init)

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

3770 RLoc);

3771 if (Kind == OMPC_use)

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

3774

3775 if (Kind == OMPC_destroy)

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

3778

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

3780}

3781

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

3784

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

3787 getOpenMPClauseName(OMPC_ompx_attribute).data()))

3788 return nullptr;

3789

3791 ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);

3792

3793

3794 if (T.consumeClose())

3795 return nullptr;

3796

3797 if (ParseOnly)

3798 return nullptr;

3799

3801 for (const ParsedAttr &PA : ParsedAttrs) {

3802 switch (PA.getKind()) {

3803 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:

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

3805 continue;

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

3808 Attrs.push_back(A);

3809 continue;

3810 case ParsedAttr::AT_AMDGPUWavesPerEU:

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

3812 !PA.checkAtMostNumArgs(Actions, 2))

3813 continue;

3815 PA, PA.getArgAsExpr(0),

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

3817 Attrs.push_back(A);

3818 continue;

3819 case ParsedAttr::AT_CUDALaunchBounds:

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

3821 !PA.checkAtMostNumArgs(Actions, 2))

3822 continue;

3824 PA, PA.getArgAsExpr(0),

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

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

3827 Attrs.push_back(A);

3828 continue;

3829 default:

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

3831 continue;

3832 };

3833 }

3834

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

3837}

3838

3839

3840

3841

3842

3843

3844

3845

3846

3847

3848

3849

3850

3851

3852

3853

3855 bool ParseOnly) {

3857 if (!Val || ParseOnly)

3858 return nullptr;

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

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

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

3862 OMP_DEFAULT_firstprivate)) {

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

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

3865 OMP_DEFAULT_private

3866 ? OMPC_private

3867 : OMPC_firstprivate)

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

3869 return nullptr;

3870 }

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

3873}

3874

3875

3876

3877

3878

3879

3880

3881

3882

3883

3884

3885

3886

3887

3888

3889

3890

3891

3892

3893

3894

3895

3896

3897

3898

3899

3900

3904

3905 if (ParseOnly)

3906 return nullptr;

3908}

3909

3910

3911

3912

3913

3914

3915

3916

3917

3918

3919

3920

3921

3922

3923

3924

3925

3928 bool ParseOnly) {

3931

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

3934 getOpenMPClauseName(Kind).data()))

3935 return nullptr;

3936

3940 if (Kind == OMPC_schedule) {

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

3942 Arg.resize(NumberOfElements);

3943 KLoc.resize(NumberOfElements);

3950

3951 Arg[Modifier1] = KindModifier;

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

3954 Tok.isNot(tok::annot_pragma_openmp_end))

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

3957

3962 ? KindModifier

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

3966 Tok.isNot(tok::annot_pragma_openmp_end))

3968 }

3969

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

3972 else

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

3976 }

3977 Arg[ScheduleKind] = KindModifier;

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

3980 Tok.isNot(tok::annot_pragma_openmp_end))

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

3983 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||

3984 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&

3985 Tok.is(tok::comma))

3987 } else if (Kind == OMPC_dist_schedule) {

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

3992 Tok.isNot(tok::annot_pragma_openmp_end))

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

3996 } else if (Kind == OMPC_defaultmap) {

3997

4000

4001

4002

4005 Arg.push_back(Modifier);

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

4008 Tok.isNot(tok::annot_pragma_openmp_end))

4010

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

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

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

4016

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

4021 Tok.isNot(tok::annot_pragma_openmp_end))

4023 } else {

4026 }

4027 } else if (Kind == OMPC_order) {

4028 enum { Modifier, OrderKind, NumberOfElements };

4029 Arg.resize(NumberOfElements);

4030 KLoc.resize(NumberOfElements);

4036

4037 Arg[Modifier] = KindModifier;

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

4040 Tok.isNot(tok::annot_pragma_openmp_end))

4042

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

4045 else

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

4049 }

4050 Arg[OrderKind] = KindModifier;

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

4053 Tok.isNot(tok::annot_pragma_openmp_end))

4055 } else if (Kind == OMPC_device) {

4056

4059

4064

4066 } else {

4068 KLoc.emplace_back();

4069 }

4070 } else if (Kind == OMPC_grainsize) {

4071

4078 Arg.push_back(Modifier);

4080

4082

4084 } else {

4085 if (Modifier == OMPC_GRAINSIZE_strict) {

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

4087

4089 }

4091 KLoc.emplace_back();

4092 }

4093 } else {

4095 KLoc.emplace_back();

4096 }

4097 } else if (Kind == OMPC_num_tasks) {

4098

4105 Arg.push_back(Modifier);

4107

4109

4111 } else {

4112 if (Modifier == OMPC_NUMTASKS_strict) {

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

4114

4116 }

4118 KLoc.emplace_back();

4119 }

4120 } else {

4122 KLoc.emplace_back();

4123 }

4124 } else {

4125 assert(Kind == OMPC_if);

4127 TentativeParsingAction TPA(*this);

4129 Arg.push_back(DK);

4130 if (DK != OMPD_unknown) {

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

4133 TPA.Commit();

4135 } else {

4136 TPA.Revert();

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

4138 }

4139 } else {

4140 TPA.Revert();

4141 }

4142 }

4143

4144 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||

4145 (Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||

4146 Kind == OMPC_if || Kind == OMPC_device ||

4147 Kind == OMPC_grainsize || Kind == OMPC_num_tasks;

4148 if (NeedAnExpression) {

4152 Val =

4154 }

4155

4156

4158 if (T.consumeClose())

4159 RLoc = T.getCloseLocation();

4160

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

4162 return nullptr;

4163

4164 if (ParseOnly)

4165 return nullptr;

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

4168}

4169

4172 if (ReductionIdScopeSpec.isEmpty()) {

4174 switch (P.getCurToken().getKind()) {

4175 case tok:➕

4176 OOK = OO_Plus;

4177 break;

4178 case tok:➖

4179 OOK = OO_Minus;

4180 break;

4181 case tok:⭐

4182 OOK = OO_Star;

4183 break;

4184 case tok::amp:

4185 OOK = OO_Amp;

4186 break;

4187 case tok::pipe:

4188 OOK = OO_Pipe;

4189 break;

4190 case tok::caret:

4191 OOK = OO_Caret;

4192 break;

4193 case tok::ampamp:

4194 OOK = OO_AmpAmp;

4195 break;

4196 case tok::pipepipe:

4197 OOK = OO_PipePipe;

4198 break;

4199 default:

4200 break;

4201 }

4206 return false;

4207 }

4208 }

4209 return P.ParseUnqualifiedId(

4210 ReductionIdScopeSpec, nullptr,

4211 false, false,

4212 false,

4213 false,

4214 false, nullptr, ReductionId);

4215}

4216

4217

4218

4220 Token Tok = P.getCurToken();

4221 if (!Tok.is(tok::identifier))

4223

4227 OMPC_map, PP.getSpelling(Tok), P.getLangOpts()));

4228 return TypeModifier;

4229}

4230

4231

4233

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

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

4238 return true;

4239 }

4240

4242 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,

4243 nullptr,

4244 false,

4245 false);

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

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

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

4250 return true;

4251 }

4256

4257 return T.consumeClose();

4258}

4259

4261

4262

4263

4264

4265

4266

4268 bool HasMapType = false;

4270 StringRef PreMapName = "";

4271 while (getCurToken().isNot(tok::colon)) {

4274 if (TypeModifier == OMPC_MAP_MODIFIER_always ||

4275 TypeModifier == OMPC_MAP_MODIFIER_close ||

4276 TypeModifier == OMPC_MAP_MODIFIER_present ||

4277 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {

4278 Data.MapTypeModifiers.push_back(TypeModifier);

4283 << "map type modifier";

4285 } else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {

4286 Data.MapTypeModifiers.push_back(TypeModifier);

4290 return true;

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

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

4294 << "map type modifier";

4295

4297 if (!HasMapType) {

4298 HasMapType = true;

4299 Data.ExtraModifier = MapKind;

4303 } else {

4304 Diag(Tok, diag::err_omp_more_one_map_type);

4305 Diag(PreMapLoc, diag::note_previous_map_type_specified_here)

4306 << PreMapName;

4307 }

4309 } else {

4310

4311

4312

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

4314 Diag(Tok, diag::err_omp_map_type_modifier_missing);

4316 continue;

4317 }

4318

4321 break;

4322 } else {

4323 return false;

4324 }

4325 }

4326

4327 Diag(Tok, diag::err_omp_unknown_map_type_modifier)

4329 : 0)

4332 }

4335 }

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

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

4338 Diag(Tok, diag::err_omp_unknown_map_type);

4340 } else {

4342 }

4343 }

4344 return false;

4345}

4346

4347

4348

4350 Token Tok = P.getCurToken();

4351

4352 if (!Tok.isOneOf(tok::identifier, tok::kw_delete))

4355 unsigned MapType =

4357 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||

4358 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||

4359 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)

4362}

4363

4364

4365

4366

4368 Token Tok = P.getCurToken();

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

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

4371 return;

4372 }

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

4376 P.ConsumeToken();

4377}

4378

4379

4380

4381ExprResult Parser::ParseOpenMPIteratorsExpr() {

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

4383 "Expected 'iterator' token.");

4385

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

4389

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

4393

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

4396

4399 T.skipToEnd();

4401 }

4402 IteratorType = TR.get();

4403 }

4404

4405

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

4411 } else {

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

4413 }

4414

4415

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

4419 else

4420 Diag(Tok, diag::err_omp_expected_equal_in_iterator);

4421

4422

4424

4426 ExprResult LHS = ParseCastExpression(AnyCastExpr);

4430 false);

4431

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

4435

4436

4438 LHS = ParseCastExpression(AnyCastExpr);

4442 false);

4443

4446

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

4448

4450

4452 LHS = ParseCastExpression(AnyCastExpr);

4456 false);

4457 }

4458

4459

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

4461 Diag(Tok, diag::err_omp_expected_punc_after_iterator);

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

4464

4466 D.DeclIdent = II;

4467 D.DeclIdentLoc = IdLoc;

4468 D.Type = IteratorType;

4469 D.AssignLoc = AssignLoc;

4470 D.ColonLoc = ColonLoc;

4471 D.SecColonLoc = SecColonLoc;

4472 D.Range.Begin = Begin.get();

4473 D.Range.End = End.get();

4474 D.Range.Step = Step.get();

4475 }

4476

4477

4479 if (T.consumeClose())

4480 RLoc = T.getCloseLocation();

4481

4483 LLoc, RLoc, Data);

4484}

4485

4489

4490

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

4492 return false;

4493

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

4496

4497 if (Data.ExtraModifier == OMPC_DEPEND_outallmemory ||

4498 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)

4499 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);

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

4501 Data.ExtraModifier != OMPC_DEPEND_inout)

4502 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);

4503 else

4504 Data.ExtraModifier = Data.ExtraModifier == OMPC_DEPEND_out

4505 ? OMPC_DEPEND_outallmemory

4506 : OMPC_DEPEND_inoutallmemory;

4508 return true;

4509 }

4510 return false;

4511}

4512

4513

4514

4517 ExprResult Tail = P.ParseAssignmentExpression();

4518 Sema &Actions = P.getActions();

4520 false);

4522 Data.DepModOrTailExpr = Tail.get();

4523 Token CurTok = P.getCurToken();

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

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

4526 }

4527 return true;

4528 }

4529 return false;

4530}

4531

4532

4533

4534

4538 const Token &Tok = P.getCurToken();

4543 bool AllocatorSeen = false;

4544 bool AlignSeen = false;

4548

4549

4550 if (P.getLangOpts().OpenMP < 51)

4551 return P.ParseAssignmentExpression();

4552

4553

4554

4555

4556

4557

4559 return P.ParseAssignmentExpression();

4560

4561 do {

4562 P.ConsumeToken();

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

4564 switch (CurrentModifier) {

4565 case OMPC_ALLOCATE_allocator: {

4566 if (AllocatorSeen) {

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

4569 << getOpenMPClauseName(Kind);

4570 } else {

4571 Data.AllocClauseModifiers.push_back(CurrentModifier);

4572 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);

4573 }

4575 tok::annot_pragma_openmp_end);

4577 Tail = P.ParseAssignmentExpression();

4579 AllocatorSeen = true;

4580 break;

4581 }

4582 case OMPC_ALLOCATE_align: {

4583 if (AlignSeen) {

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

4586 << getOpenMPClauseName(Kind);

4587 } else {

4588 Data.AllocClauseModifiers.push_back(CurrentModifier);

4589 Data.AllocClauseModifiersLoc.push_back(CurrentModifierLoc);

4590 }

4591 Val = P.ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);

4593 Data.AllocateAlignment = Val.get();

4594 AlignSeen = true;

4595 break;

4596 }

4597 default:

4598 llvm_unreachable("Unexpected allocate modifier");

4599 }

4600 } else {

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

4602 }

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

4604 break;

4605 P.ConsumeToken();

4609

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

4612 break;

4613 }

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

4615 return Tail;

4616}

4617

4618

4624 bool InvalidReductionId = false;

4625 bool IsInvalidMapperModifier = false;

4626

4627

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

4630 getOpenMPClauseName(Kind).data()))

4631 return true;

4632

4633 bool HasIterator = false;

4634 bool InvalidIterator = false;

4635 bool NeedRParenForLinear = false;

4637 tok::annot_pragma_openmp_end);

4638

4639 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||

4640 Kind == OMPC_in_reduction) {

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

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

4645

4646 Data.ExtraModifier =

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

4652 }

4655 ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,

4656 nullptr,

4657 false,

4658 false);

4660 *this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);

4661 if (InvalidReductionId) {

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

4664 }

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

4667 else

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

4669 if (!InvalidReductionId)

4670 Data.ReductionOrMapperId =

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

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

4675

4676

4677

4678

4679

4680

4681 HasIterator = true;

4683 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();

4684 Data.DepModOrTailExpr = IteratorRes.get();

4685

4686 ExpectAndConsume(tok::comma);

4687 }

4688 }

4689

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

4696 (Kind == OMPC_doacross &&

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

4700 } else {

4702

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

4704 Data.ExtraModifier == OMPC_DEPEND_source) {

4705

4706 T.consumeClose();

4707 return false;

4708 }

4709 }

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

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

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

4714 : diag::warn_pragma_expected_colon)

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

4716 }

4717 if (Kind == OMPC_doacross) {

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

4720 Data.ExtraModifier = Data.ExtraModifier == OMPC_DOACROSS_source

4721 ? OMPC_DOACROSS_source_omp_cur_iteration

4722 : OMPC_DOACROSS_sink_omp_cur_iteration;

4724 }

4725 if (Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {

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

4727 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)

4728 << getOpenMPClauseName(Kind) << 0 << 0;

4730 return false;

4731 } else {

4734 uint64_t Value = 0;

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

4737 Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)

4738 << getOpenMPClauseName(Kind) << 0 << 0;

4740 return false;

4741 }

4742 }

4743 }

4744 if (Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {

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

4746 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)

4747 << getOpenMPClauseName(Kind) << 1 << 1;

4749 return false;

4750 }

4751 }

4752

4753 if (Kind == OMPC_doacross &&

4754 (Data.ExtraModifier == OMPC_DOACROSS_source ||

4755 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||

4756 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {

4757

4758 T.consumeClose();

4759 return false;

4760 }

4761 }

4762 } else if (Kind == OMPC_linear) {

4763

4764 Data.ExtraModifier = OMPC_LINEAR_val;

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

4766 Data.ExtraModifier =

4770 NeedRParenForLinear = true;

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

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

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

4775 }

4776 } else if (Kind == OMPC_lastprivate) {

4777

4779

4780

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

4784 Data.ExtraModifier =

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

4790 }

4791 } else if (Kind == OMPC_map) {

4792

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

4794 HasIterator = true;

4796 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);

4798 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();

4799 Data.IteratorExpr = IteratorRes.get();

4800

4801 ExpectAndConsume(tok::comma);

4803 Diag(Tok, diag::err_omp_unknown_map_type_modifier)

4806 InvalidIterator = true;

4807 }

4808 }

4809

4811

4812

4813

4814

4817

4818

4819 TentativeParsingAction TPA(*this);

4820 bool ColonPresent = false;

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

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

4824 ColonPresent = true;

4825 }

4826 TPA.Revert();

4827

4828

4829 if (ColonPresent) {

4831 Diag(Tok, diag::err_omp_map_modifier_specification_list);

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

4835 else

4837 }

4839 Data.ExtraModifier = OMPC_MAP_tofrom;

4841 if (DKind == OMPD_target_enter_data)

4842 Data.ExtraModifier = OMPC_MAP_to;

4843 else if (DKind == OMPD_target_exit_data)

4844 Data.ExtraModifier = OMPC_MAP_from;

4845 }

4846 Data.IsMapTypeImplicit = true;

4847 }

4848

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

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

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

4856 break;

4857 Data.MotionModifiers.push_back(Modifier);

4860 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {

4862 if (IsInvalidMapperModifier)

4863 break;

4864 }

4865

4867 break;

4868

4869

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

4872 }

4873 if (Data.MotionModifiers.empty() && Tok.isNot(tok::colon)) {

4874 if (!IsInvalidMapperModifier) {

4876 Diag(Tok, diag::warn_pragma_expected_colon) << ")";

4877 else

4878 Diag(Tok, diag::warn_pragma_expected_colon) << "motion modifier";

4879 }

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

4882 }

4883

4884

4885 if ((Data.MotionModifiers.empty() || getLangOpts().OpenMP >= 51) &&

4886 Tok.is(tok::colon))

4888 } else if (Kind == OMPC_allocate ||

4889 (Kind == OMPC_affinity && Tok.is(tok::identifier) &&

4891

4892

4894 TentativeParsingAction TPA(*this);

4895

4896

4897

4899 if (Kind == OMPC_allocate) {

4901 } else {

4902 HasIterator = true;

4904 Tail = ParseOpenMPIteratorsExpr();

4905 }

4908 false);

4909 if (Tail.isUsable() || Data.AllocateAlignment) {

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

4911 Data.DepModOrTailExpr = Tail.isUsable() ? Tail.get() : nullptr;

4913 TPA.Commit();

4914 } else {

4915

4916 TPA.Revert();

4917 if (Kind == OMPC_allocate && Data.AllocClauseModifiers.size()) {

4918 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,

4920 Diag(Tok, diag::err_modifier_expected_colon) << "allocate clause";

4921 }

4922 }

4923 } else {

4924

4925

4926 TPA.Revert();

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

4929 }

4930 } else if (Kind == OMPC_adjust_args) {

4931

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

4938 Diag(Tok, diag::err_omp_unknown_adjust_args_op);

4940 } else {

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

4944 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,

4945 "adjust-op");

4946 }

4947 }

4948

4949 bool IsComma =

4950 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&

4951 Kind != OMPC_in_reduction && Kind != OMPC_depend &&

4952 Kind != OMPC_doacross && Kind != OMPC_map && Kind != OMPC_adjust_args) ||

4953 (Kind == OMPC_reduction && !InvalidReductionId) ||

4957 (Kind == OMPC_adjust_args &&

4959 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);

4960 while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&

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

4965

4969 Vars.push_back(VarExpr.get());

4970 } else {

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

4973 }

4974 }

4975

4976 IsComma = Tok.is(tok::comma);

4977 if (IsComma)

4979 else if (Tok.isNot(tok::r_paren) &&

4980 Tok.isNot(tok::annot_pragma_openmp_end) &&

4981 (!MayHaveTail || Tok.isNot(tok::colon)))

4982 Diag(Tok, diag::err_omp_expected_punc)

4983 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)

4984 : getOpenMPClauseName(Kind))

4985 << (Kind == OMPC_flush);

4986 }

4987

4988

4989 if (NeedRParenForLinear)

4991

4992

4993 const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);

4994 bool StepFound = false;

4995 bool ModifierFound = false;

4996 if (MustHaveTail) {

4999

5000 if (getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {

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

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

5003

5004

5009

5010 if (LinKind == OMPC_LINEAR_step) {

5011 if (StepFound)

5012 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;

5013

5015 tok::annot_pragma_openmp_end);

5017

5019 Diag(StepModifierLoc, diag::err_expected_lparen_after) << "step";

5020

5021

5023 if (StepFound)

5024 Data.StepModifierLoc = StepModifierLoc;

5025

5026

5028 } else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {

5029 if (ModifierFound)

5030 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;

5031

5032 Data.ExtraModifier = LinKind;

5034 ModifierFound = true;

5035 } else {

5037 }

5038 } else {

5039

5041 }

5042

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

5045 if (Tok.is(tok::r_paren) || Tok.is(tok::annot_pragma_openmp_end))

5046 break;

5047 }

5048 if (!StepFound && !ModifierFound)

5049 Diag(ELoc, diag::err_expected_expression);

5050 } else {

5051

5054 false);

5056 Data.DepModOrTailExpr = Tail.get();

5057 else

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

5060 }

5061 }

5062

5063

5065 if (T.consumeClose())

5066 Data.RLoc = T.getCloseLocation();

5067

5068 if (HasIterator)

5070 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&

5071 Vars.empty()) ||

5072 (MustHaveTail && Data.DepModOrTailExpr && StepFound) ||

5073 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;

5074}

5075

5076

5077

5078

5079

5080

5081

5082

5083

5084

5085

5086

5087

5088

5089

5090

5091

5092

5093

5094

5095

5096

5097

5098

5099

5100

5101

5102

5103

5104

5105

5106

5107

5108

5109

5110

5111

5112

5113

5114

5115

5116

5117

5118

5119

5120

5121

5122

5123

5124

5125

5126

5127

5128

5129

5130

5131

5132

5133

5134

5135

5138 bool ParseOnly) {

5143

5145 return nullptr;

5146

5147 if (ParseOnly)

5148 return nullptr;

5151}

5152

5153bool Parser::ParseOpenMPExprListClause(OpenMPClauseKind Kind,

5158 bool ReqIntConst) {

5159 assert(getOpenMPClauseName(Kind) == PP.getSpelling(Tok) &&

5160 "Expected parsing to start at clause name");

5162

5163

5165 if (T.consumeOpen()) {

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

5167 return true;

5168 }

5169

5170

5171 do {

5175

5176 T.skipToEnd();

5177 return true;

5178 }

5179 Exprs.push_back(Val.get());

5181

5182 bool Result = T.consumeClose();

5183 OpenLoc = T.getOpenLocation();

5184 CloseLoc = T.getCloseLocation();

5186}

Defines the clang::ASTContext interface.

This file defines OpenMP AST classes for clauses.

Defines some OpenMP-specific enums and functions.

static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P)

static OpenMPMapModifierKind isMapModifier(Parser &P)

Checks if the token is a valid map-type-modifier.

static std::optional< SimpleClauseData > parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind)

static unsigned getOpenMPDirectiveKindEx(StringRef S)

static bool checkExtensionProperty(Parser &P, SourceLocation Loc, OMPTraitProperty &TIProperty, OMPTraitSelector &TISelector, llvm::StringMap< SourceLocation > &Seen)

static ExprResult parseOpenMPAllocateClauseModifiers(Parser &P, OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data)

Parse 'allocate' clause modifiers.

static DeclarationName parseOpenMPReductionId(Parser &P)

static ExprResult parseContextScore(Parser &P)

Parse optional 'score' '(' ')' ':'.

static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)

static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data, OpenMPClauseKind CKind, SourceLocation ELoc)

Parse step size expression.

static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data)

Parse map-type in map clause.

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.

static OpenMPMapClauseKind isMapType(Parser &P)

Checks if the token is a valid map-type.

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.

This file defines OpenMP AST classes for executable directives and clauses.

Defines the clang::TokenKind enum and support functions.

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.

ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed.

Captures information about "declaration specifiers".

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.

Information about one declarator, including the parsed type information and the identifier.

RAII object that enters a new expression evaluation context.

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.

One of these records is kept for each identifier that is lexed.

bool isStr(const char(&Str)[StrLen]) const

Return true if this is the identifier for the specified string.

StringRef getName() const

Return the actual identifier string.

IdentifierInfo & get(StringRef Name)

Return the identifier token info for the specified named identifier.

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.

Wrapper for void* pointer.

RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing,...

ParsedAttr - Represents a syntactic attribute.

static const ParsedAttributesView & none()

ParsedAttributes - A collection of parsed attributes.

Introduces zero or more scopes for parsing.

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.

TypeResult ParseTypeName(SourceRange *Range=nullptr, DeclaratorContext Context=DeclaratorContext::TypeName, AccessSpecifier AS=AS_none, Decl **OwnedType=nullptr, ParsedAttributes *Attrs=nullptr)

ParseTypeName type-name: [C99 6.7.6] specifier-qualifier-list abstract-declarator[opt].

DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

bool parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data)

Parses map-type-modifiers in map clause.

SourceLocation ConsumeToken()

ConsumeToken - Consume the current 'peek token' and lex the next one.

void EnterScope(unsigned ScopeFlags)

EnterScope - Start a new scope.

bool parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data)

Parses the mapper modifier in map, to, and from clauses.

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.

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 ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)

Parse an expr that doesn't include (top-level) commas.

ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc, bool IsAddressOfOperand=false)

Parses simple expression in parens for single-expression clauses of OpenMP constructs.

const LangOptions & getLangOpts() const

ExprResult ParseExpression(TypeCastState isTypeCast=NotTypeCast)

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'.

const Token & NextToken()

NextToken - This peeks ahead one token and returns it without consuming it.

A class for parsing a DeclSpec.

Activates OpenMP parsing mode to preseve OpenMP specific annotation tokens.

void enterVariableInit(SourceLocation Tok, Decl *D)

Engages in a tight little dance with the lexer to efficiently preprocess tokens.

void EnterToken(const Token &Tok, bool IsReinject)

Enters a token in the token stream to be lexed next.

const Token & LookAhead(unsigned N)

Peeks ahead N tokens and returns that token without consuming any tokens.

bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value)

Parses a simple integer literal to get its numeric value.

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 isCodeCompletionReached() const

Returns true if code-completion is enabled and we have hit the code-completion point.

A (possibly-)qualified type.

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.

Scope - A scope is a transient data structure that is used while parsing the program.

@ 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.

AMDGPUWavesPerEUAttr * CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)

Create an AMDGPUWavesPerEUAttr attribute.

AMDGPUFlatWorkGroupSizeAttr * CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)

Create an AMDGPUWavesPerEUAttr attribute.

QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, ArrayRef< Expr * > Args, SourceLocation OpenParLoc, bool Braced)

void CodeCompleteInitializer(Scope *S, Decl *D)

DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)

Called at the end of '#pragma omp declare reduction'.

void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)

Finish current declare reduction construct initializer.

OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)

Called on well-formed 'use' clause.

void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)

Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...

OMPClause * ActOnOpenMPDirectivePresenceClause(OpenMPClauseKind CK, llvm::ArrayRef< OpenMPDirectiveKind > DKVec, SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc)

Called on well-formed 'absent' or 'contains' clauses.

void StartOpenMPClause(OpenMPClauseKind K)

Start analysis of clauses.

ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)

Build the mapper variable of '#pragma omp declare mapper'.

StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)

Called on well-formed '#pragma omp error'.

DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)

Called on well-formed '#pragma omp requires'.

OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)

OMPClause * ActOnOpenMPPermutationClause(ArrayRef< Expr * > PermExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)

Called on well-form 'permutation' clause after parsing its arguments.

OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)

Called on well-formed 'destroy' clause.

VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)

Initialize declare reduction construct initializer.

void ActOnOpenMPEndAssumesDirective()

Called on well-formed '#pragma omp end assumes'.

QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)

Check if the specified type is allowed to be used in 'omp declare reduction' construct.

DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)

Called on well-formed '#pragma omp allocate'.

OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)

bool isInOpenMPDeclareVariantScope() const

Can we exit an OpenMP declare variant scope at the moment.

TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)

Check variable declaration in 'omp declare mapper' construct.

ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)

OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)

Called on well-formed 'uses_allocators' clause.

StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)

End of OpenMP region.

DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)

Called on start of '#pragma omp declare reduction'.

void ActOnOpenMPEndDeclareVariant()

Handle a omp end declare variant.

void EndOpenMPDSABlock(Stmt *CurDirective)

Called on end of data sharing attribute block.

OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)

Called on well-form 'sizes' clause.

bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)

Called on the start of target region i.e. '#pragma omp declare target'.

StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)

void EndOpenMPClause()

End analysis of clauses.

bool isInOpenMPAssumeScope() const

Check if there is an active global omp begin assumes directive.

QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)

Check if the specified type is allowed to be used in 'omp declare mapper' construct.

std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)

Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...

StmtResult ActOnOpenMPInformationalDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc)

Process an OpenMP informational directive.

OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)

OMPClause * ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK, SourceLocation Loc, SourceLocation RLoc)

OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)

Called on well-formed 'init' clause.

void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)

Initialize declare reduction construct initializer.

bool isInOpenMPDeclareTargetContext() const

Return true inside OpenMP declare target region.

OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)

void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)

Called on start of new data sharing attribute block.

void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)

Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.

void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)

Finish current declare reduction construct initializer.

DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)

Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.

OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)

Called on a well-formed 'ompx_attribute' clause.

DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)

Called on well-formed '#pragma omp threadprivate'.

void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)

Initialization of captured region for OpenMP region.

NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)

Searches for the provided declaration name for OpenMP declare target directive.

void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)

Called on well-formed '#pragma omp [begin] assume[s]'.

void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)

Handle a omp begin declare variant.

StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)

Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...

const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()

Called at the end of target region i.e. '#pragma omp end declare target'.

OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)

DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)

Called on start of '#pragma omp declare mapper'.

RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...

A RAII object to enter scope of a compound statement.

Sema - This implements semantic analysis and AST building for C.

Scope * getCurScope() const

Retrieve the parser's current scope.

ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)

CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...

ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)

VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...

void ActOnReenterFunctionContext(Scope *S, Decl *D)

Push the parameters of D, which must be a function, into scope.

void FinalizeDeclaration(Decl *D)

FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform any semantic actions neces...

DeclarationNameInfo GetNameForDeclarator(Declarator &D)

GetNameForDeclarator - Determine the full declaration name for the given Declarator.

ASTContext & getASTContext() const

ExprResult ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val)

SemaCodeCompletion & CodeCompletion()

DeclContext * getCurLexicalContext() const

DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef< Decl * > Group)

BuildDeclaratorGroup - convert a list of declarations into a declaration group, performing any necess...

DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name)

Retrieves the declaration name from a parsed unqualified-id.

void ActOnInitializerError(Decl *Dcl)

ActOnInitializerError - Given that there was an error parsing an initializer for the given declaratio...

@ Unevaluated

The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...

StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)

void ActOnUninitializedDecl(Decl *dcl)

void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)

AddInitializerToDecl - Adds the initializer Init to the declaration dcl.

CUDALaunchBoundsAttr * CreateLaunchBoundsAttr(const AttributeCommonInfo &CI, Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks)

Create an CUDALaunchBoundsAttr attribute.

StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)

ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})

Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...

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.

SourceLocation getBegin() const

StringLiteral - This represents a string literal expression, e.g.

Token - This structure provides full information about a lexed token.

IdentifierInfo * getIdentifierInfo() const

bool isAnyIdentifier() const

Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...

SourceLocation getEndLoc() const

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 isOneOf(tok::TokenKind K1, tok::TokenKind K2) const

bool isNot(tok::TokenKind K) const

bool isAnnotation() const

Return true if this is any of tok::annot_* kind tokens.

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.

Directive - Abstract class representing a parsed verify directive.

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.

TypeSpecifierType

Specifies the kind of type.

OverloadedOperatorKind

Enumeration specifying the different kinds of C++ overloaded operators.

@ OO_None

Not an overloaded operator.

llvm::omp::Directive OpenMPDirectiveKind

OpenMP directives.

@ 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.

bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)

OpenMPDeviceType

OpenMP device type for 'device_type' clause.

@ OMPC_DEVICE_TYPE_unknown

@ OMPC_SCHEDULE_MODIFIER_unknown

llvm::omp::Clause OpenMPClauseKind

OpenMP clauses.

const char * getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type)

bool operator<(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)

Checks if the specified directive is a target code offload directive.

@ Property

The type of a property.

@ Result

The result type of a method or function.

@ OMPC_LASTPRIVATE_unknown

OpenMPGrainsizeClauseModifier

unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str, const LangOptions &LangOpts)

OpenMPNumTasksClauseModifier

ActionResult< Expr * > ExprResult

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

bool operator!=(CanQual< T > x, CanQual< U > y)

@ 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".

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.

const FunctionProtoType * T

OpenMPMapModifierKind

OpenMP modifier kind for 'map' clause.

@ OMPC_MAP_MODIFIER_unknown

AccessSpecifier

A C++ access specifier (public, private, protected), plus the special value "none" which means differ...

bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)

Checks if the specified directive is a taskloop directive.

OpenMPMapClauseKind

OpenMP mapping kind for 'map' clause.

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

llvm::SmallVector< OMPTraitProperty, 1 > Properties

llvm::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.

Data structure for iterator expression.

Data used for processing a list of variables in OpenMP clauses.

Data for list of allocators.

Clang specific specialization of the OMPContext to lookup target features.