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

1

2

3

4

5

6

7

8

9

10

11

12

19#include "llvm/ADT/StringRef.h"

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

21

22using namespace clang;

23using namespace llvm;

24

25namespace {

26

27

28

29enum class OpenACCDirectiveKindEx {

30 Invalid = static_cast<int>(OpenACCDirectiveKind::Invalid),

31

32 Enter,

33 Exit,

34};

35

36

37

38

39

40

41OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) {

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

43 return OpenACCDirectiveKindEx::Invalid;

45 llvm::StringSwitch(

47 .Case("parallel", OpenACCDirectiveKind::Parallel)

48 .Case("serial", OpenACCDirectiveKind::Serial)

49 .Case("kernels", OpenACCDirectiveKind::Kernels)

50 .Case("data", OpenACCDirectiveKind::Data)

51 .Case("host_data", OpenACCDirectiveKind::HostData)

52 .Case("loop", OpenACCDirectiveKind::Loop)

53 .Case("cache", OpenACCDirectiveKind::Cache)

54 .Case("atomic", OpenACCDirectiveKind::Atomic)

55 .Case("routine", OpenACCDirectiveKind::Routine)

56 .Case("declare", OpenACCDirectiveKind::Declare)

57 .Case("init", OpenACCDirectiveKind::Init)

58 .Case("shutdown", OpenACCDirectiveKind::Shutdown)

59 .Case("set", OpenACCDirectiveKind::Set)

60 .Case("update", OpenACCDirectiveKind::Update)

61 .Case("wait", OpenACCDirectiveKind::Wait)

62 .Default(OpenACCDirectiveKind::Invalid);

63

64 if (DirKind != OpenACCDirectiveKind::Invalid)

65 return static_cast<OpenACCDirectiveKindEx>(DirKind);

66

67 return llvm::StringSwitch(

69 .Case("enter", OpenACCDirectiveKindEx::Enter)

70 .Case("exit", OpenACCDirectiveKindEx::Exit)

71 .Default(OpenACCDirectiveKindEx::Invalid);

72}

73

74

76

77

78 if (Tok.is(tok::kw_auto))

79 return OpenACCClauseKind::Auto;

80

81

82 if (Tok.is(tok::kw_default))

83 return OpenACCClauseKind::Default;

84

85

86 if (Tok.is(tok::kw_if))

87 return OpenACCClauseKind::If;

88

89

90 if (Tok.is(tok::kw_private))

91 return OpenACCClauseKind::Private;

92

93

94 if (Tok.is(tok::kw_delete))

95 return OpenACCClauseKind::Delete;

96

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

98 return OpenACCClauseKind::Invalid;

99

100 return llvm::StringSwitch(

102 .Case("async", OpenACCClauseKind::Async)

103 .Case("attach", OpenACCClauseKind::Attach)

104 .Case("auto", OpenACCClauseKind::Auto)

105 .Case("bind", OpenACCClauseKind::Bind)

106 .Case("create", OpenACCClauseKind::Create)

107 .Case("pcreate", OpenACCClauseKind::PCreate)

108 .Case("present_or_create", OpenACCClauseKind::PresentOrCreate)

109 .Case("collapse", OpenACCClauseKind::Collapse)

110 .Case("copy", OpenACCClauseKind::Copy)

111 .Case("pcopy", OpenACCClauseKind::PCopy)

112 .Case("present_or_copy", OpenACCClauseKind::PresentOrCopy)

113 .Case("copyin", OpenACCClauseKind::CopyIn)

114 .Case("pcopyin", OpenACCClauseKind::PCopyIn)

115 .Case("present_or_copyin", OpenACCClauseKind::PresentOrCopyIn)

116 .Case("copyout", OpenACCClauseKind::CopyOut)

117 .Case("pcopyout", OpenACCClauseKind::PCopyOut)

118 .Case("present_or_copyout", OpenACCClauseKind::PresentOrCopyOut)

119 .Case("default", OpenACCClauseKind::Default)

120 .Case("default_async", OpenACCClauseKind::DefaultAsync)

121 .Case("delete", OpenACCClauseKind::Delete)

122 .Case("detach", OpenACCClauseKind::Detach)

123 .Case("device", OpenACCClauseKind::Device)

124 .Case("device_num", OpenACCClauseKind::DeviceNum)

125 .Case("device_resident", OpenACCClauseKind::DeviceResident)

126 .Case("device_type", OpenACCClauseKind::DeviceType)

127 .Case("deviceptr", OpenACCClauseKind::DevicePtr)

128 .Case("dtype", OpenACCClauseKind::DType)

129 .Case("finalize", OpenACCClauseKind::Finalize)

130 .Case("firstprivate", OpenACCClauseKind::FirstPrivate)

131 .Case("gang", OpenACCClauseKind::Gang)

132 .Case("host", OpenACCClauseKind::Host)

133 .Case("if", OpenACCClauseKind::If)

134 .Case("if_present", OpenACCClauseKind::IfPresent)

135 .Case("independent", OpenACCClauseKind::Independent)

136 .Case("link", OpenACCClauseKind::Link)

137 .Case("no_create", OpenACCClauseKind::NoCreate)

138 .Case("num_gangs", OpenACCClauseKind::NumGangs)

139 .Case("num_workers", OpenACCClauseKind::NumWorkers)

140 .Case("nohost", OpenACCClauseKind::NoHost)

141 .Case("present", OpenACCClauseKind::Present)

142 .Case("private", OpenACCClauseKind::Private)

143 .Case("reduction", OpenACCClauseKind::Reduction)

144 .Case("self", OpenACCClauseKind::Self)

145 .Case("seq", OpenACCClauseKind::Seq)

146 .Case("tile", OpenACCClauseKind::Tile)

147 .Case("use_device", OpenACCClauseKind::UseDevice)

148 .Case("vector", OpenACCClauseKind::Vector)

149 .Case("vector_length", OpenACCClauseKind::VectorLength)

150 .Case("wait", OpenACCClauseKind::Wait)

151 .Case("worker", OpenACCClauseKind::Worker)

152 .Default(OpenACCClauseKind::Invalid);

153}

154

155

156

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

159 return OpenACCAtomicKind::Invalid;

160 return llvm::StringSwitch(

162 .Case("read", OpenACCAtomicKind::Read)

163 .Case("write", OpenACCAtomicKind::Write)

164 .Case("update", OpenACCAtomicKind::Update)

165 .Case("capture", OpenACCAtomicKind::Capture)

166 .Default(OpenACCAtomicKind::Invalid);

167}

168

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

171 return OpenACCDefaultClauseKind::Invalid;

172

173 return llvm::StringSwitch(

175 .Case("none", OpenACCDefaultClauseKind::None)

176 .Case("present", OpenACCDefaultClauseKind::Present)

177 .Default(OpenACCDefaultClauseKind::Invalid);

178}

179

180enum class OpenACCSpecialTokenKind {

181 ReadOnly,

182 DevNum,

183 Queues,

185 Force,

187 Length,

190};

191

192bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) {

193 if (Tok.is(tok::kw_static) && Kind == OpenACCSpecialTokenKind::Static)

194 return true;

195

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

197 return false;

198

199 switch (Kind) {

200 case OpenACCSpecialTokenKind::ReadOnly:

202 case OpenACCSpecialTokenKind::DevNum:

204 case OpenACCSpecialTokenKind::Queues:

206 case OpenACCSpecialTokenKind::Zero:

208 case OpenACCSpecialTokenKind::Force:

210 case OpenACCSpecialTokenKind::Num:

212 case OpenACCSpecialTokenKind::Length:

214 case OpenACCSpecialTokenKind::Dim:

216 case OpenACCSpecialTokenKind::Static:

218 }

219 llvm_unreachable("Unknown 'Kind' Passed");

220}

221

222

223

224

225bool isTokenIdentifierOrKeyword(Parser &P, Token Tok) {

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

227 return true;

228

231 return true;

232

233 return false;

234}

235

236

237

238

239

240

241template

242bool tryParseAndConsumeSpecialTokenKind(Parser &P, OpenACCSpecialTokenKind Kind,

243 DirOrClauseTy DirOrClause) {

244 Token IdentTok = P.getCurToken();

245

246

247 if (isTokenIdentifierOrKeyword(P, IdentTok) && P.NextToken().is(tok::colon)) {

248 P.ConsumeToken();

249 P.ConsumeToken();

250

251 if (!isOpenACCSpecialToken(Kind, IdentTok)) {

252 P.Diag(IdentTok, diag::err_acc_invalid_tag_kind)

254 << std::is_same_v<DirOrClauseTy, OpenACCClauseKind>;

255 return false;

256 }

257

258 return true;

259 }

260

261 return false;

262}

263

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

266 return false;

267

268 switch (Kind) {

269 case OpenACCDirectiveKind::Parallel:

271 case OpenACCDirectiveKind::Serial:

273 case OpenACCDirectiveKind::Kernels:

275 case OpenACCDirectiveKind::Data:

277 case OpenACCDirectiveKind::HostData:

279 case OpenACCDirectiveKind::Loop:

281 case OpenACCDirectiveKind::Cache:

283

284 case OpenACCDirectiveKind::ParallelLoop:

285 case OpenACCDirectiveKind::SerialLoop:

286 case OpenACCDirectiveKind::KernelsLoop:

287 case OpenACCDirectiveKind::EnterData:

288 case OpenACCDirectiveKind::ExitData:

289 return false;

290

291 case OpenACCDirectiveKind::Atomic:

293 case OpenACCDirectiveKind::Routine:

295 case OpenACCDirectiveKind::Declare:

297 case OpenACCDirectiveKind::Init:

299 case OpenACCDirectiveKind::Shutdown:

301 case OpenACCDirectiveKind::Set:

303 case OpenACCDirectiveKind::Update:

305 case OpenACCDirectiveKind::Wait:

307 case OpenACCDirectiveKind::Invalid:

308 return false;

309 }

310 llvm_unreachable("Unknown 'Kind' Passed");

311}

312

314

315

316

317 if (P.NextToken().isNot(tok::colon)) {

318 P.Diag(P.getCurToken(), diag::err_acc_expected_reduction_operator);

319 return OpenACCReductionOperator::Invalid;

320 }

321 Token ReductionKindTok = P.getCurToken();

322

323 P.ConsumeToken();

324 P.ConsumeToken();

325

326 switch (ReductionKindTok.getKind()) {

327 case tok:➕

328 return OpenACCReductionOperator::Addition;

329 case tok:⭐

330 return OpenACCReductionOperator::Multiplication;

331 case tok::amp:

332 return OpenACCReductionOperator::BitwiseAnd;

333 case tok::pipe:

334 return OpenACCReductionOperator::BitwiseOr;

335 case tok::caret:

336 return OpenACCReductionOperator::BitwiseXOr;

337 case tok::ampamp:

338 return OpenACCReductionOperator::And;

339 case tok::pipepipe:

340 return OpenACCReductionOperator::Or;

341 case tok::identifier:

343 return OpenACCReductionOperator::Max;

345 return OpenACCReductionOperator::Min;

346 [[fallthrough]];

347 default:

348 P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator);

349 return OpenACCReductionOperator::Invalid;

350 }

351 llvm_unreachable("Reduction op token kind not caught by 'default'?");

352}

353

354

355

356bool expectIdentifierOrKeyword(Parser &P) {

357 Token Tok = P.getCurToken();

358

359 if (isTokenIdentifierOrKeyword(P, Tok))

360 return false;

361

362 P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;

363 return true;

364}

365

367ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok,

368 OpenACCDirectiveKindEx ExtDirKind) {

369 Token SecondTok = P.getCurToken();

370

372 P.Diag(FirstTok, diag::err_acc_invalid_directive)

374 return OpenACCDirectiveKind::Invalid;

375 }

376

377

378

379 P.ConsumeAnyToken();

380

381 if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) {

382 if (!SecondTok.is(tok::identifier))

383 P.Diag(SecondTok, diag::err_expected) << tok::identifier;

384 else

385 P.Diag(FirstTok, diag::err_acc_invalid_directive)

388 return OpenACCDirectiveKind::Invalid;

389 }

390

391 return ExtDirKind == OpenACCDirectiveKindEx::Enter

392 ? OpenACCDirectiveKind::EnterData

393 : OpenACCDirectiveKind::ExitData;

394}

395

397 Token AtomicClauseToken = P.getCurToken();

398

399

401 return OpenACCAtomicKind::Update;

402

403 OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseToken);

404

405

406

407

408 if (AtomicKind == OpenACCAtomicKind::Invalid)

409 return OpenACCAtomicKind::Update;

410

411 P.ConsumeToken();

412 return AtomicKind;

413}

414

415

417 Token FirstTok = P.getCurToken();

418

419

420

421 if (FirstTok.isNot(tok::identifier)) {

422 P.Diag(FirstTok, diag::err_acc_missing_directive);

423

424 if (P.getCurToken().isNot(tok::annot_pragma_openacc_end))

425 P.ConsumeAnyToken();

426

427 return OpenACCDirectiveKind::Invalid;

428 }

429

430 P.ConsumeToken();

431

432 OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok);

433

434

435

436

437

438

439

440 if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) {

441 switch (ExDirKind) {

442 case OpenACCDirectiveKindEx::Invalid: {

443 P.Diag(FirstTok, diag::err_acc_invalid_directive)

445 return OpenACCDirectiveKind::Invalid;

446 }

447 case OpenACCDirectiveKindEx::Enter:

448 case OpenACCDirectiveKindEx::Exit:

449 return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind);

450 }

451 }

452

454

455

456

457

458 Token SecondTok = P.getCurToken();

460 isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, SecondTok)) {

461 switch (DirKind) {

462 default:

463

464

465 break;

466 case OpenACCDirectiveKind::Parallel:

467 P.ConsumeToken();

468 return OpenACCDirectiveKind::ParallelLoop;

469 case OpenACCDirectiveKind::Serial:

470 P.ConsumeToken();

471 return OpenACCDirectiveKind::SerialLoop;

472 case OpenACCDirectiveKind::Kernels:

473 P.ConsumeToken();

474 return OpenACCDirectiveKind::KernelsLoop;

475 }

476 }

477

478 return DirKind;

479}

480

481enum ClauseParensKind {

485};

486

489 switch (Kind) {

490 case OpenACCClauseKind::Self:

491 return DirKind == OpenACCDirectiveKind::Update ? ClauseParensKind::Required

492 : ClauseParensKind::Optional;

493 case OpenACCClauseKind::Async:

494 case OpenACCClauseKind::Worker:

495 case OpenACCClauseKind::Vector:

496 case OpenACCClauseKind::Gang:

497 case OpenACCClauseKind::Wait:

498 return ClauseParensKind::Optional;

499

500 case OpenACCClauseKind::Default:

501 case OpenACCClauseKind::If:

502 case OpenACCClauseKind::Create:

503 case OpenACCClauseKind::PCreate:

504 case OpenACCClauseKind::PresentOrCreate:

505 case OpenACCClauseKind::Copy:

506 case OpenACCClauseKind::PCopy:

507 case OpenACCClauseKind::PresentOrCopy:

508 case OpenACCClauseKind::CopyIn:

509 case OpenACCClauseKind::PCopyIn:

510 case OpenACCClauseKind::PresentOrCopyIn:

511 case OpenACCClauseKind::CopyOut:

512 case OpenACCClauseKind::PCopyOut:

513 case OpenACCClauseKind::PresentOrCopyOut:

514 case OpenACCClauseKind::UseDevice:

515 case OpenACCClauseKind::NoCreate:

516 case OpenACCClauseKind::Present:

517 case OpenACCClauseKind::DevicePtr:

518 case OpenACCClauseKind::Attach:

519 case OpenACCClauseKind::Detach:

520 case OpenACCClauseKind::Private:

521 case OpenACCClauseKind::FirstPrivate:

522 case OpenACCClauseKind::Delete:

523 case OpenACCClauseKind::DeviceResident:

524 case OpenACCClauseKind::Device:

525 case OpenACCClauseKind::Link:

526 case OpenACCClauseKind::Host:

527 case OpenACCClauseKind::Reduction:

528 case OpenACCClauseKind::Collapse:

529 case OpenACCClauseKind::Bind:

530 case OpenACCClauseKind::VectorLength:

531 case OpenACCClauseKind::NumGangs:

532 case OpenACCClauseKind::NumWorkers:

533 case OpenACCClauseKind::DeviceNum:

534 case OpenACCClauseKind::DefaultAsync:

535 case OpenACCClauseKind::DeviceType:

536 case OpenACCClauseKind::DType:

537 case OpenACCClauseKind::Tile:

538 return ClauseParensKind::Required;

539

540 case OpenACCClauseKind::Auto:

541 case OpenACCClauseKind::Finalize:

542 case OpenACCClauseKind::IfPresent:

543 case OpenACCClauseKind::Independent:

544 case OpenACCClauseKind::Invalid:

545 case OpenACCClauseKind::NoHost:

546 case OpenACCClauseKind::Seq:

547 return ClauseParensKind::None;

548 }

549 llvm_unreachable("Unhandled clause kind");

550}

551

554 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional;

555}

556

559 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required;

560}

561

562

563

564

565

566void SkipUntilEndOfDirective(Parser &P) {

567 while (P.getCurToken().isNot(tok::annot_pragma_openacc_end))

568 P.ConsumeAnyToken();

569}

570

572 switch (DirKind) {

573 default:

574 case OpenACCDirectiveKind::EnterData:

575 case OpenACCDirectiveKind::ExitData:

576 case OpenACCDirectiveKind::Wait:

577 case OpenACCDirectiveKind::Init:

578 case OpenACCDirectiveKind::Shutdown:

579 return false;

580 case OpenACCDirectiveKind::Parallel:

581 case OpenACCDirectiveKind::Serial:

582 case OpenACCDirectiveKind::Kernels:

583 case OpenACCDirectiveKind::ParallelLoop:

584 case OpenACCDirectiveKind::SerialLoop:

585 case OpenACCDirectiveKind::KernelsLoop:

586 case OpenACCDirectiveKind::Loop:

587 case OpenACCDirectiveKind::Data:

588 case OpenACCDirectiveKind::HostData:

589 return true;

590 }

591 llvm_unreachable("Unhandled directive->assoc stmt");

592}

593

595 switch (DirKind) {

596 case OpenACCDirectiveKind::Parallel:

597 case OpenACCDirectiveKind::Serial:

598 case OpenACCDirectiveKind::Kernels:

599 case OpenACCDirectiveKind::ParallelLoop:

600 case OpenACCDirectiveKind::SerialLoop:

601 case OpenACCDirectiveKind::KernelsLoop:

602

603

606 case OpenACCDirectiveKind::Data:

607 case OpenACCDirectiveKind::EnterData:

608 case OpenACCDirectiveKind::ExitData:

609 case OpenACCDirectiveKind::HostData:

610 case OpenACCDirectiveKind::Wait:

611 case OpenACCDirectiveKind::Init:

612 case OpenACCDirectiveKind::Shutdown:

613 return 0;

614 case OpenACCDirectiveKind::Invalid:

615 llvm_unreachable("Shouldn't be creating a scope for an invalid construct");

616 default:

617 break;

618 }

619 return 0;

620}

621

622}

623

624Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() {

625 return {nullptr, OpenACCParseCanContinue::Can};

626}

627

628Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() {

629 return {nullptr, OpenACCParseCanContinue::Cannot};

630}

631

632Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) {

633 return {Clause, OpenACCParseCanContinue::Can};

634}

635

636ExprResult Parser::ParseOpenACCConditionExpr() {

637

638

639

640

642

644 return ER;

645

649

651}

652

653

654

655

656

657

661 bool FirstClause = true;

662 while (getCurToken().isNot(tok::annot_pragma_openacc_end)) {

663

664 if (!FirstClause && getCurToken().is(tok::comma))

666 FirstClause = false;

667

668 OpenACCClauseParseResult Result = ParseOpenACCClause(Clauses, DirKind);

670 Clauses.push_back(Clause);

671 } else if (Result.getInt() == OpenACCParseCanContinue::Cannot) {

672

673

674 SkipUntilEndOfDirective(*this);

675 return Clauses;

676 }

677 }

678 return Clauses;

679}

680

681Parser::OpenACCIntExprParseResult

685

686

687

689 return {ER, OpenACCParseCanContinue::Cannot};

690

691

692

695 return {ER, OpenACCParseCanContinue::Can};

696

698 OpenACCParseCanContinue::Can};

699}

700

704 OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc);

705

706 if (!CurResult.first.isUsable() &&

707 CurResult.second == OpenACCParseCanContinue::Cannot) {

708 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,

710 return true;

711 }

712

713 IntExprs.push_back(CurResult.first.get());

714

715 while (getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {

716 ExpectAndConsume(tok::comma);

717

718 CurResult = ParseOpenACCIntExpr(DK, CK, Loc);

719

720 if (!CurResult.first.isUsable() &&

721 CurResult.second == OpenACCParseCanContinue::Cannot) {

722 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,

724 return true;

725 }

726 IntExprs.push_back(CurResult.first.get());

727 }

728 return false;

729}

730

731

732

733

734

735

736

737

738

739

740bool Parser::ParseOpenACCDeviceTypeList(

741 llvm::SmallVector<std::pair<IdentifierInfo *, SourceLocation>> &Archs) {

742

743 if (expectIdentifierOrKeyword(*this)) {

744 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,

746 return true;

747 }

750

751 while (getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {

752 ExpectAndConsume(tok::comma);

753

754 if (expectIdentifierOrKeyword(*this)) {

755 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,

757 return true;

758 }

761 }

762 return false;

763}

764

765

766

767

768

769

770

772

773

776 tok::annot_pragma_openacc_end)) {

779 }

780

783

785 return SizeExpr;

786

789 SizeExpr.get());

790

791 return SizeExpr;

792}

793

794bool Parser::ParseOpenACCSizeExprList(

796 ExprResult SizeExpr = ParseOpenACCSizeExpr(CK);

798 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,

800 return true;

801 }

802

803 SizeExprs.push_back(SizeExpr.get());

804

805 while (getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {

806 ExpectAndConsume(tok::comma);

807

808 SizeExpr = ParseOpenACCSizeExpr(CK);

810 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,

812 return true;

813 }

814 SizeExprs.push_back(SizeExpr.get());

815 }

816 return false;

817}

818

819

820

821

822

823

824

825Parser::OpenACCGangArgRes Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {

826

827 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static, getCurToken()) &&

829

834 }

835

836 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim, getCurToken()) &&

840

841

845 }

846

847 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) &&

851

852 }

853

854

857 .first;

859}

860

861bool Parser::ParseOpenACCGangArgList(

864

865 Parser::OpenACCGangArgRes Res = ParseOpenACCGangArg(GangLoc);

866 if (!Res.second.isUsable()) {

867 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,

869 return true;

870 }

871

872 GKs.push_back(Res.first);

873 IntExprs.push_back(Res.second.get());

874

875 while (getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {

876 ExpectAndConsume(tok::comma);

877

878 Res = ParseOpenACCGangArg(GangLoc);

879 if (!Res.second.isUsable()) {

880 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,

882 return true;

883 }

884

885 GKs.push_back(Res.first);

886 IntExprs.push_back(Res.second.get());

887 }

888 return false;

889}

890

891

892

893

894

895

896Parser::OpenACCClauseParseResult

899

900

901 if (expectIdentifierOrKeyword(*this))

902 return OpenACCCannotContinue();

903

905

909 return OpenACCCannotContinue();

910 }

911

912

914

915 return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc);

916}

917

918Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(

923 tok::annot_pragma_openacc_end);

925

926 if (ClauseHasRequiredParens(DirKind, ClauseKind)) {

927 if (Parens.expectAndConsume()) {

928

929

930

931 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,

933 return OpenACCCanContinue();

934 }

936

937 switch (ClauseKind) {

940

941 if (expectIdentifierOrKeyword(*this)) {

943 return OpenACCCanContinue();

944 }

945

947

949 getOpenACCDefaultClauseKind(DefKindTok);

950

952 Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);

954 return OpenACCCanContinue();

955 }

956

958 break;

959 }

961 ExprResult CondExpr = ParseOpenACCConditionExpr();

963 : nullptr);

964

967 return OpenACCCanContinue();

968 }

969

970 break;

971 }

975 bool IsReadOnly = tryParseAndConsumeSpecialTokenKind(

976 *this, OpenACCSpecialTokenKind::ReadOnly, ClauseKind);

978 IsReadOnly,

979 false);

980 break;

981 }

988 bool IsZero = tryParseAndConsumeSpecialTokenKind(

989 *this, OpenACCSpecialTokenKind::Zero, ClauseKind);

991 false, IsZero);

992 break;

993 }

995

996

999 break;

1000 }

1002

1003

1004

1006 [[fallthrough]];

1010 false, false);

1011 break;

1014 ParseOpenACCVarList(ClauseKind);

1015 break;

1022 false, false);

1023 break;

1032 false, false);

1033 break;

1035 bool HasForce = tryParseAndConsumeSpecialTokenKind(

1036 *this, OpenACCSpecialTokenKind::Force, ClauseKind);

1041 return OpenACCCanContinue();

1042 }

1043

1047

1050 return OpenACCCanContinue();

1051 }

1052

1054 break;

1055 }

1057 ExprResult BindArg = ParseOpenACCBindClauseArgument();

1060 return OpenACCCanContinue();

1061 }

1062 break;

1063 }

1066

1069 IntExprs)) {

1071 return OpenACCCanContinue();

1072 }

1074 break;

1075 }

1081 ClauseKind, ClauseLoc)

1082 .first;

1085 return OpenACCCanContinue();

1086 }

1087

1089 break;

1090 }

1095

1096

1098 } else if (!ParseOpenACCDeviceTypeList(Archs)) {

1100 } else {

1102 return OpenACCCanContinue();

1103 }

1104 break;

1105 }

1110 return OpenACCCanContinue();

1111 }

1112

1114 break;

1115 }

1116 default:

1117 llvm_unreachable("Not a required parens type?");

1118 }

1119

1121

1122 if (Parens.consumeClose())

1123 return OpenACCCannotContinue();

1124

1125 } else if (ClauseHasOptionalParens(DirKind, ClauseKind)) {

1126 if (Parens.consumeOpen()) {

1128 switch (ClauseKind) {

1131 ExprResult CondExpr = ParseOpenACCConditionExpr();

1133 : nullptr);

1134

1137 return OpenACCCanContinue();

1138 }

1139 break;

1140 }

1143 tryParseAndConsumeSpecialTokenKind(*this,

1144 ClauseKind ==

1146 ? OpenACCSpecialTokenKind::Length

1147 : OpenACCSpecialTokenKind::Num,

1148 ClauseKind);

1150 ClauseKind, ClauseLoc)

1151 .first;

1154 return OpenACCCanContinue();

1155 }

1157 break;

1158 }

1163 .first;

1165 : nullptr);

1168 return OpenACCCanContinue();

1169 }

1170 break;

1171 }

1175 if (ParseOpenACCGangArgList(ClauseLoc, GKs, IntExprs)) {

1177 return OpenACCCanContinue();

1178 }

1179 ParsedClause.setGangDetails(std::move(GKs), std::move(IntExprs));

1180 break;

1181 }

1183 OpenACCWaitParseInfo Info =

1184 ParseOpenACCWaitArgument(ClauseLoc,

1185 false);

1186 if (Info.Failed) {

1188 return OpenACCCanContinue();

1189 }

1190

1191 ParsedClause.setWaitDetails(Info.DevNumExpr, Info.QueuesLoc,

1192 std::move(Info.QueueIdExprs));

1193 break;

1194 }

1195 default:

1196 llvm_unreachable("Not an optional parens type?");

1197 }

1199 if (Parens.consumeClose())

1200 return OpenACCCannotContinue();

1201 } else {

1202

1203

1204 ParsedClause.setEndLoc(ClauseLoc);

1205 }

1206 } else {

1207 ParsedClause.setEndLoc(ClauseLoc);

1208 }

1209 return OpenACCSuccess(

1211}

1212

1213

1214

1215

1216

1217

1218

1219

1220Parser::OpenACCIntExprParseResult

1223 return ParseOpenACCIntExpr(DK, CK, Loc);

1224}

1225

1226

1227

1228

1229

1230Parser::OpenACCWaitParseInfo

1231Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {

1232 OpenACCWaitParseInfo Result;

1233

1234 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) &&

1236

1238

1240

1241 OpenACCIntExprParseResult Res = ParseOpenACCIntExpr(

1246 if (Res.first.isInvalid() &&

1247 Res.second == OpenACCParseCanContinue::Cannot) {

1248 Result.Failed = true;

1250 }

1251

1252 if (ExpectAndConsume(tok::colon)) {

1253 Result.Failed = true;

1255 }

1256

1257 Result.DevNumExpr = Res.first.get();

1258 }

1259

1260

1261 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) &&

1263

1265

1267 }

1268

1269

1270

1271

1272

1273 bool FirstArg = true;

1274 while (getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {

1275 if (!FirstArg) {

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

1277 Result.Failed = true;

1279 }

1280 }

1281 FirstArg = false;

1282

1283 OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument(

1288

1289 if (Res.first.isInvalid() &&

1290 Res.second == OpenACCParseCanContinue::Cannot) {

1291 Result.Failed = true;

1293 }

1294

1295 if (Res.first.isUsable())

1296 Result.QueueIdExprs.push_back(Res.first.get());

1297 }

1298

1300}

1301

1302ExprResult Parser::ParseOpenACCIDExpression() {

1305 Res = ParseCXXIdExpression(true);

1306 } else {

1307

1308

1309

1310 if (Tok.isNot(tok::identifier)) {

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

1313 }

1314

1320

1321

1322

1323

1325 Name, false,

1326 false);

1327 }

1328

1330}

1331

1332ExprResult Parser::ParseOpenACCBindClauseArgument() {

1333

1334

1335

1336

1337

1338

1342 }

1343

1346 false, true));

1347

1348 return ParseOpenACCIDExpression();

1349}

1350

1351

1352

1353

1354

1355

1356

1357

1358Parser::OpenACCVarParseResult Parser::ParseOpenACCVar(OpenACCClauseKind CK) {

1359 OpenACCArraySectionRAII ArraySections(*this);

1360

1363 return {Res, OpenACCParseCanContinue::Cannot};

1364

1367 return {Res, OpenACCParseCanContinue::Can};

1368

1370

1371 return {Res, OpenACCParseCanContinue::Can};

1372}

1373

1376

1377 auto [Res, CanContinue] = ParseOpenACCVar(CK);

1379 Vars.push_back(Res.get());

1380 } else if (CanContinue == OpenACCParseCanContinue::Cannot) {

1382 return Vars;

1383 }

1384

1385 while (getCurToken().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {

1386 ExpectAndConsume(tok::comma);

1387

1388 auto [Res, CanContinue] = ParseOpenACCVar(CK);

1389

1391 Vars.push_back(Res.get());

1392 } else if (CanContinue == OpenACCParseCanContinue::Cannot) {

1394 return Vars;

1395 }

1396 }

1397 return Vars;

1398}

1399

1400

1401

1402

1403

1404void Parser::ParseOpenACCCacheVarList() {

1405

1406

1408 return;

1409

1410

1411

1412

1413 if (tryParseAndConsumeSpecialTokenKind(*this,

1414 OpenACCSpecialTokenKind::ReadOnly,

1416

1417

1418 }

1419

1420

1421

1423}

1424

1425Parser::OpenACCDirectiveParseInfo

1426Parser::ParseOpenACCDirective() {

1430 Parser::OpenACCWaitParseInfo WaitInfo;

1431

1433

1434

1435

1436

1438 ParseOpenACCAtomicKind(*this);

1439

1440

1441

1443 tok::annot_pragma_openacc_end);

1444

1445 if (T.consumeOpen()) {

1446 switch (DirKind) {

1447 default:

1448 Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren);

1449 T.skipToEnd();

1450 break;

1452

1453

1454 ExprResult RoutineName = ParseOpenACCIDExpression();

1455

1456

1458 T.skipToEnd();

1459 else

1460 T.consumeClose();

1461 break;

1462 }

1464 ParseOpenACCCacheVarList();

1465

1466

1467 T.consumeClose();

1468 break;

1470

1471 WaitInfo = ParseOpenACCWaitArgument(DirLoc, true);

1472 if (WaitInfo.Failed)

1473 T.skipToEnd();

1474 else

1475 T.consumeClose();

1476 break;

1477 }

1479

1480

1481

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

1483 }

1484

1485

1486 OpenACCDirectiveParseInfo ParseInfo{DirKind,

1487 StartLoc,

1488 DirLoc,

1489 T.getOpenLocation(),

1490 T.getCloseLocation(),

1492 WaitInfo.QueuesLoc,

1493 WaitInfo.getAllExprs(),

1494 ParseOpenACCClauseList(DirKind)};

1495

1496 assert(Tok.is(tok::annot_pragma_openacc_end) &&

1497 "Didn't parse all OpenACC Clauses");

1498 ParseInfo.EndLoc = ConsumeAnnotationToken();

1499 assert(ParseInfo.EndLoc.isValid() &&

1500 "Terminating annotation token not present");

1501

1502 return ParseInfo;

1503}

1504

1505

1507 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");

1508

1510

1511 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();

1512

1513 if (getActions().OpenACC().ActOnStartDeclDirective(DirInfo.DirKind,

1514 DirInfo.StartLoc))

1515 return nullptr;

1516

1517

1519}

1520

1521

1523 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");

1524

1526

1527 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();

1528 if (getActions().OpenACC().ActOnStartStmtDirective(

1529 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses))

1531

1533 if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) {

1535 getActions().OpenACC(), DirInfo.DirKind, DirInfo.DirLoc, {},

1536 DirInfo.Clauses);

1538 ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind));

1539

1541 DirInfo.StartLoc, DirInfo.DirKind, DirInfo.Clauses, ParseStatement());

1542 }

1543

1545 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,

1546 DirInfo.MiscLoc, DirInfo.Exprs, DirInfo.RParenLoc, DirInfo.EndLoc,

1547 DirInfo.Clauses, AssocStmt);

1548}

static Decl::Kind getKind(const Decl *D)

Defines some OpenACC-specific enums and functions.

static constexpr bool isOneOf()

This file declares semantic analysis for OpenACC constructs and clauses.

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.

SourceLocation getExprLoc() const LLVM_READONLY

getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...

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

bool isKeyword(const LangOptions &LangOpts) const

Return true if this token is a keyword in the specified language.

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.

Wrapper for void* pointer.

static OpaquePtr make(PtrTy P)

This is the base type for all OpenACC Clauses.

ParseScope - Introduces a new scope for parsing.

Parser - This implements a parser for the C family of languages.

DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

SourceLocation ConsumeToken()

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

DeclGroupPtrTy ParseOpenACCDirectiveDecl()

Placeholder for now, should just ignore the directives after emitting a diagnostic.

Sema & getActions() const

ExprResult ParseConstantExpression()

StmtResult ParseOpenACCDirectiveStmt()

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

ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)

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

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.

ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral=false)

const Token & NextToken()

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

Activates OpenACC parsing mode to preseve OpenACC specific annotation tokens.

@ ContinueScope

This is a while, do, for, which can have continue statements embedded into it.

@ OpenACCComputeConstructScope

This is the scope of an OpenACC Compute Construct, which restricts jumping into/out of it.

@ BreakScope

This is a while, do, switch, for, etc that can have break statements embedded into it.

Helper type for the registration/assignment of constructs that need to 'know' about their parent cons...

A type to represent all the data for an OpenACC Clause that has been parsed, but not yet created/sema...

void setLParenLoc(SourceLocation EndLoc)

void setConditionDetails(Expr *ConditionExpr)

void setCollapseDetails(bool IsForce, Expr *LoopCount)

void setGangDetails(ArrayRef< OpenACCGangKind > GKs, ArrayRef< Expr * > IntExprs)

void setReductionDetails(OpenACCReductionOperator Op, llvm::SmallVector< Expr * > &&VarList)

void setDefaultDetails(OpenACCDefaultClauseKind DefKind)

void setVarListDetails(ArrayRef< Expr * > VarList, bool IsReadOnly, bool IsZero)

void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc, llvm::SmallVector< Expr * > &&IntExprs)

void setEndLoc(SourceLocation EndLoc)

void setIntExprDetails(ArrayRef< Expr * > IntExprs)

void setDeviceTypeDetails(llvm::SmallVector< DeviceTypeArgument > &&Archs)

ExprResult ActOnVar(OpenACCClauseKind CK, Expr *VarExpr)

Called when encountering a 'var' for OpenACC, ensures it is actually a declaration reference to a var...

ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, SourceLocation Loc, Expr *IntExpr)

Called when encountering an 'int-expr' for OpenACC, and manages conversions and diagnostics to 'int'.

OpenACCClause * ActOnClause(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCParsedClause &Clause)

Called after parsing an OpenACC Clause so that it can be checked.

StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef< Expr * > Exprs, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses, StmtResult AssocStmt)

Called after the directive has been completely parsed, including the declaration group or associated ...

void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc)

Called after the construct has been parsed, but clauses haven't been parsed.

ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)

StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, OpenACCDirectiveKind K, ArrayRef< const OpenACCClause * > Clauses, StmtResult AssocStmt)

Called when we encounter an associated statement for our construct, this should check legality of the...

@ Boolean

A boolean condition, from 'if', 'while', 'for', or 'do'.

ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, CorrectionCandidateCallback *CCC=nullptr, bool IsInlineAsmIdentifier=false, Token *KeywordReplacement=nullptr)

ConditionResult ActOnCondition(Scope *S, SourceLocation Loc, Expr *SubExpr, ConditionKind CK, bool MissingOK=false)

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

Encodes a location in the source.

SourceLocation getBeginLoc() const LLVM_READONLY

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

IdentifierInfo * getIdentifierInfo() 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 isNot(tok::TokenKind K) const

bool isAnnotation() const

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

Represents a C++ unqualified-id that has been parsed.

bool Zero(InterpState &S, CodePtr OpPC)

bool isStringLiteral(TokenKind K)

Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.

bool isAnnotation(TokenKind K)

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

The JSON file list parser is used to communicate input to InstallAPI.

OpenACCClauseKind

Represents the kind of an OpenACC clause.

@ Bind

'bind' clause, allowed on routine constructs.

@ Gang

'gang' clause, allowed on 'loop' and Combined constructs.

@ Wait

'wait' clause, allowed on Compute, Data, 'update', and Combined constructs.

@ DevicePtr

'deviceptr' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.

@ PCopyOut

'copyout' clause alias 'pcopyout'. Preserved for diagnostic purposes.

@ VectorLength

'vector_length' clause, allowed on 'parallel', 'kernels', 'parallel loop', and 'kernels loop' constru...

@ Async

'async' clause, allowed on Compute, Data, 'update', 'wait', and Combined constructs.

@ PresentOrCreate

'create' clause alias 'present_or_create'.

@ Collapse

'collapse' clause, allowed on 'loop' and Combined constructs.

@ PresentOrCopy

'copy' clause alias 'present_or_copy'. Preserved for diagnostic purposes.

@ DeviceNum

'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.

@ Private

'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...

@ Invalid

Represents an invalid clause, for the purposes of parsing.

@ Vector

'vector' clause, allowed on 'loop', Combined, and 'routine' directives.

@ Copy

'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.

@ Worker

'worker' clause, allowed on 'loop', Combined, and 'routine' directives.

@ Create

'create' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...

@ DeviceType

'device_type' clause, allowed on Compute, 'data', 'init', 'shutdown', 'set', update',...

@ DefaultAsync

'default_async' clause, allowed on 'set' construct.

@ Attach

'attach' clause, allowed on Compute and Combined constructs, plus 'data' and 'enter data'.

@ NumGangs

'num_gangs' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs.

@ If

'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...

@ Default

'default' clause, allowed on parallel, serial, kernel (and compound) constructs.

@ UseDevice

'use_device' clause, allowed on 'host_data' construct.

@ NoCreate

'no_create' clause, allowed on allowed on Compute and Combined constructs, plus 'data'.

@ PresentOrCopyOut

'copyout' clause alias 'present_or_copyout'.

@ Link

'link' clause, allowed on 'declare' construct.

@ Reduction

'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.

@ Self

'self' clause, allowed on Compute and Combined Constructs, plus 'update'.

@ CopyOut

'copyout' clause, allowed on Compute and Combined constructs, plus 'data', 'exit data',...

@ FirstPrivate

'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop', and 'serial loop' constructs...

@ Host

'host' clause, allowed on 'update' construct.

@ PCopy

'copy' clause alias 'pcopy'. Preserved for diagnostic purposes.

@ Tile

'tile' clause, allowed on 'loop' and Combined constructs.

@ PCopyIn

'copyin' clause alias 'pcopyin'. Preserved for diagnostic purposes.

@ DeviceResident

'device_resident' clause, allowed on the 'declare' construct.

@ PCreate

'create' clause alias 'pcreate'. Preserved for diagnostic purposes.

@ Present

'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.

@ DType

'dtype' clause, an alias for 'device_type', stored separately for diagnostic purposes.

@ CopyIn

'copyin' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...

@ Device

'device' clause, allowed on the 'update' construct.

@ NumWorkers

'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs...

@ Detach

'detach' clause, allowed on the 'exit data' construct.

@ Delete

'delete' clause, allowed on the 'exit data' construct.

@ PresentOrCopyIn

'copyin' clause alias 'present_or_copyin'.

@ Invalid

Not a valid option.

@ Result

The result type of a method or function.

const FunctionProtoType * T

@ None

The alignment was not explicit in code.

@ Parens

New-expression has a C++98 paren-delimited initializer.

Diagnostic wrappers for TextAPI types for error reporting.