19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/StringSwitch.h"
29enum class OpenACCDirectiveKindEx {
30 Invalid =
static_cast<int>(OpenACCDirectiveKind::Invalid),
41OpenACCDirectiveKindEx getOpenACCDirectiveKind(
Token Tok) {
42 if (!Tok.
is(tok::identifier))
43 return OpenACCDirectiveKindEx::Invalid;
45 llvm::StringSwitch<OpenACCDirectiveKind>(
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);
64 if (DirKind != OpenACCDirectiveKind::Invalid)
65 return static_cast<OpenACCDirectiveKindEx
>(DirKind);
67 return llvm::StringSwitch<OpenACCDirectiveKindEx>(
69 .Case(
"enter", OpenACCDirectiveKindEx::Enter)
70 .Case(
"exit", OpenACCDirectiveKindEx::Exit)
71 .Default(OpenACCDirectiveKindEx::Invalid);
78 if (Tok.
is(tok::kw_auto))
79 return OpenACCClauseKind::Auto;
82 if (Tok.
is(tok::kw_default))
83 return OpenACCClauseKind::Default;
86 if (Tok.
is(tok::kw_if))
87 return OpenACCClauseKind::If;
90 if (Tok.
is(tok::kw_private))
91 return OpenACCClauseKind::Private;
94 if (Tok.
is(tok::kw_delete))
95 return OpenACCClauseKind::Delete;
97 if (!Tok.
is(tok::identifier))
98 return OpenACCClauseKind::Invalid;
100 return llvm::StringSwitch<OpenACCClauseKind>(
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);
158 if (!Tok.
is(tok::identifier))
159 return OpenACCAtomicKind::Invalid;
160 return llvm::StringSwitch<OpenACCAtomicKind>(
162 .Case(
"read", OpenACCAtomicKind::Read)
163 .Case(
"write", OpenACCAtomicKind::Write)
164 .Case(
"update", OpenACCAtomicKind::Update)
165 .Case(
"capture", OpenACCAtomicKind::Capture)
166 .Default(OpenACCAtomicKind::Invalid);
170 if (!Tok.
is(tok::identifier))
171 return OpenACCDefaultClauseKind::Invalid;
173 return llvm::StringSwitch<OpenACCDefaultClauseKind>(
175 .Case(
"none", OpenACCDefaultClauseKind::None)
176 .Case(
"present", OpenACCDefaultClauseKind::Present)
177 .Default(OpenACCDefaultClauseKind::Invalid);
180enum class OpenACCSpecialTokenKind {
192bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind,
Token Tok) {
193 if (Tok.
is(tok::kw_static) && Kind == OpenACCSpecialTokenKind::Static)
196 if (!Tok.
is(tok::identifier))
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:
219 llvm_unreachable(
"Unknown 'Kind' Passed");
226 if (Tok.
is(tok::identifier))
241template <
typename DirOrClauseTy>
242bool tryParseAndConsumeSpecialTokenKind(
Parser &
P, OpenACCSpecialTokenKind Kind,
243 DirOrClauseTy DirOrClause) {
244 Token IdentTok =
P.getCurToken();
247 if (isTokenIdentifierOrKeyword(
P, IdentTok) &&
P.NextToken().is(tok::colon)) {
251 if (!isOpenACCSpecialToken(Kind, IdentTok)) {
252 P.Diag(IdentTok, diag::err_acc_invalid_tag_kind)
254 << std::is_same_v<DirOrClauseTy, OpenACCClauseKind>;
265 if (!Tok.
is(tok::identifier))
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:
284 case OpenACCDirectiveKind::ParallelLoop:
285 case OpenACCDirectiveKind::SerialLoop:
286 case OpenACCDirectiveKind::KernelsLoop:
287 case OpenACCDirectiveKind::EnterData:
288 case OpenACCDirectiveKind::ExitData:
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:
310 llvm_unreachable(
"Unknown 'Kind' Passed");
317 if (
P.NextToken().isNot(tok::colon)) {
318 P.Diag(
P.getCurToken(), diag::err_acc_expected_reduction_operator);
319 return OpenACCReductionOperator::Invalid;
321 Token ReductionKindTok =
P.getCurToken();
326 switch (ReductionKindTok.
getKind()) {
328 return OpenACCReductionOperator::Addition;
330 return OpenACCReductionOperator::Multiplication;
332 return OpenACCReductionOperator::BitwiseAnd;
334 return OpenACCReductionOperator::BitwiseOr;
336 return OpenACCReductionOperator::BitwiseXOr;
338 return OpenACCReductionOperator::And;
340 return OpenACCReductionOperator::Or;
341 case tok::identifier:
343 return OpenACCReductionOperator::Max;
345 return OpenACCReductionOperator::Min;
348 P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator);
349 return OpenACCReductionOperator::Invalid;
351 llvm_unreachable(
"Reduction op token kind not caught by 'default'?");
356bool expectIdentifierOrKeyword(
Parser &
P) {
357 Token Tok =
P.getCurToken();
359 if (isTokenIdentifierOrKeyword(
P, Tok))
362 P.Diag(
P.getCurToken(), diag::err_expected) << tok::identifier;
367ParseOpenACCEnterExitDataDirective(
Parser &
P,
Token FirstTok,
368 OpenACCDirectiveKindEx ExtDirKind) {
369 Token SecondTok =
P.getCurToken();
372 P.Diag(FirstTok, diag::err_acc_invalid_directive)
374 return OpenACCDirectiveKind::Invalid;
381 if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) {
382 if (!SecondTok.
is(tok::identifier))
383 P.Diag(SecondTok, diag::err_expected) << tok::identifier;
385 P.Diag(FirstTok, diag::err_acc_invalid_directive)
388 return OpenACCDirectiveKind::Invalid;
391 return ExtDirKind == OpenACCDirectiveKindEx::Enter
392 ? OpenACCDirectiveKind::EnterData
393 : OpenACCDirectiveKind::ExitData;
397 Token AtomicClauseToken =
P.getCurToken();
401 return OpenACCAtomicKind::Update;
408 if (AtomicKind == OpenACCAtomicKind::Invalid)
409 return OpenACCAtomicKind::Update;
417 Token FirstTok =
P.getCurToken();
421 if (FirstTok.
isNot(tok::identifier)) {
422 P.Diag(FirstTok, diag::err_acc_missing_directive);
424 if (
P.getCurToken().isNot(tok::annot_pragma_openacc_end))
427 return OpenACCDirectiveKind::Invalid;
432 OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok);
440 if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) {
442 case OpenACCDirectiveKindEx::Invalid: {
443 P.Diag(FirstTok, diag::err_acc_invalid_directive)
445 return OpenACCDirectiveKind::Invalid;
447 case OpenACCDirectiveKindEx::Enter:
448 case OpenACCDirectiveKindEx::Exit:
449 return ParseOpenACCEnterExitDataDirective(
P, FirstTok, ExDirKind);
458 Token SecondTok =
P.getCurToken();
460 isOpenACCDirectiveKind(OpenACCDirectiveKind::Loop, SecondTok)) {
466 case OpenACCDirectiveKind::Parallel:
468 return OpenACCDirectiveKind::ParallelLoop;
469 case OpenACCDirectiveKind::Serial:
471 return OpenACCDirectiveKind::SerialLoop;
472 case OpenACCDirectiveKind::Kernels:
474 return OpenACCDirectiveKind::KernelsLoop;
481enum ClauseParensKind {
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;
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;
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;
549 llvm_unreachable(
"Unhandled clause kind");
554 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional;
559 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required;
566void SkipUntilEndOfDirective(
Parser &
P) {
567 while (
P.getCurToken().isNot(tok::annot_pragma_openacc_end))
574 case OpenACCDirectiveKind::EnterData:
575 case OpenACCDirectiveKind::ExitData:
576 case OpenACCDirectiveKind::Wait:
577 case OpenACCDirectiveKind::Init:
578 case OpenACCDirectiveKind::Shutdown:
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:
591 llvm_unreachable(
"Unhandled directive->assoc stmt");
596 case OpenACCDirectiveKind::Parallel:
597 case OpenACCDirectiveKind::Serial:
598 case OpenACCDirectiveKind::Kernels:
599 case OpenACCDirectiveKind::ParallelLoop:
600 case OpenACCDirectiveKind::SerialLoop:
601 case OpenACCDirectiveKind::KernelsLoop:
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:
614 case OpenACCDirectiveKind::Invalid:
615 llvm_unreachable(
"Shouldn't be creating a scope for an invalid construct");
624Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() {
625 return {
nullptr, OpenACCParseCanContinue::Can};
628Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() {
629 return {
nullptr, OpenACCParseCanContinue::Cannot};
632Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(
OpenACCClause *Clause) {
633 return {Clause, OpenACCParseCanContinue::Can};
636ExprResult Parser::ParseOpenACCConditionExpr() {
661 bool FirstClause =
true;
662 while (
getCurToken().isNot(tok::annot_pragma_openacc_end)) {
668 OpenACCClauseParseResult
Result = ParseOpenACCClause(Clauses, DirKind);
670 Clauses.push_back(Clause);
671 }
else if (
Result.getInt() == OpenACCParseCanContinue::Cannot) {
674 SkipUntilEndOfDirective(*
this);
681Parser::OpenACCIntExprParseResult
689 return {ER, OpenACCParseCanContinue::Cannot};
695 return {ER, OpenACCParseCanContinue::Can};
698 OpenACCParseCanContinue::Can};
704 OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK,
Loc);
706 if (!CurResult.first.isUsable() &&
707 CurResult.second == OpenACCParseCanContinue::Cannot) {
708 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
713 IntExprs.push_back(CurResult.first.get());
716 ExpectAndConsume(tok::comma);
718 CurResult = ParseOpenACCIntExpr(DK, CK,
Loc);
720 if (!CurResult.first.isUsable() &&
721 CurResult.second == OpenACCParseCanContinue::Cannot) {
722 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
726 IntExprs.push_back(CurResult.first.get());
740bool Parser::ParseOpenACCDeviceTypeList(
743 if (expectIdentifierOrKeyword(*
this)) {
744 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
752 ExpectAndConsume(tok::comma);
754 if (expectIdentifierOrKeyword(*
this)) {
755 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
776 tok::annot_pragma_openacc_end)) {
794bool Parser::ParseOpenACCSizeExprList(
796 ExprResult SizeExpr = ParseOpenACCSizeExpr(CK);
798 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
803 SizeExprs.push_back(SizeExpr.
get());
806 ExpectAndConsume(tok::comma);
808 SizeExpr = ParseOpenACCSizeExpr(CK);
810 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
814 SizeExprs.push_back(SizeExpr.
get());
825Parser::OpenACCGangArgRes Parser::ParseOpenACCGangArg(
SourceLocation GangLoc) {
827 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static,
getCurToken()) &&
836 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim,
getCurToken()) &&
847 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num,
getCurToken()) &&
861bool Parser::ParseOpenACCGangArgList(
865 Parser::OpenACCGangArgRes Res = ParseOpenACCGangArg(GangLoc);
866 if (!Res.second.isUsable()) {
867 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
872 GKs.push_back(Res.first);
873 IntExprs.push_back(Res.second.get());
876 ExpectAndConsume(tok::comma);
878 Res = ParseOpenACCGangArg(GangLoc);
879 if (!Res.second.isUsable()) {
880 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
885 GKs.push_back(Res.first);
886 IntExprs.push_back(Res.second.get());
896Parser::OpenACCClauseParseResult
901 if (expectIdentifierOrKeyword(*
this))
902 return OpenACCCannotContinue();
909 return OpenACCCannotContinue();
915 return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc);
918Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
923 tok::annot_pragma_openacc_end);
926 if (ClauseHasRequiredParens(DirKind, ClauseKind)) {
927 if (
Parens.expectAndConsume()) {
931 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
933 return OpenACCCanContinue();
937 switch (ClauseKind) {
941 if (expectIdentifierOrKeyword(*
this)) {
943 return OpenACCCanContinue();
949 getOpenACCDefaultClauseKind(DefKindTok);
952 Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
954 return OpenACCCanContinue();
961 ExprResult CondExpr = ParseOpenACCConditionExpr();
967 return OpenACCCanContinue();
975 bool IsReadOnly = tryParseAndConsumeSpecialTokenKind(
976 *
this, OpenACCSpecialTokenKind::ReadOnly, ClauseKind);
988 bool IsZero = tryParseAndConsumeSpecialTokenKind(
989 *
this, OpenACCSpecialTokenKind::Zero, ClauseKind);
1011 ParseOpenACCVarList(ClauseKind);
1032 bool HasForce = tryParseAndConsumeSpecialTokenKind(
1033 *
this, OpenACCSpecialTokenKind::Force, ClauseKind);
1038 return OpenACCCanContinue();
1047 return OpenACCCanContinue();
1054 ExprResult BindArg = ParseOpenACCBindClauseArgument();
1057 return OpenACCCanContinue();
1068 return OpenACCCanContinue();
1078 ClauseKind, ClauseLoc)
1082 return OpenACCCanContinue();
1101 }
else if (!ParseOpenACCDeviceTypeList(Archs)) {
1105 return OpenACCCanContinue();
1113 return OpenACCCanContinue();
1120 llvm_unreachable(
"Not a required parens type?");
1125 if (
Parens.consumeClose())
1126 return OpenACCCannotContinue();
1128 }
else if (ClauseHasOptionalParens(DirKind, ClauseKind)) {
1129 if (!
Parens.consumeOpen()) {
1131 switch (ClauseKind) {
1134 ExprResult CondExpr = ParseOpenACCConditionExpr();
1140 return OpenACCCanContinue();
1146 tryParseAndConsumeSpecialTokenKind(*
this,
1149 ? OpenACCSpecialTokenKind::Length
1150 : OpenACCSpecialTokenKind::Num,
1153 ClauseKind, ClauseLoc)
1157 return OpenACCCanContinue();
1171 return OpenACCCanContinue();
1178 if (ParseOpenACCGangArgList(ClauseLoc, GKs, IntExprs)) {
1180 return OpenACCCanContinue();
1182 ParsedClause.
setGangDetails(std::move(GKs), std::move(IntExprs));
1186 OpenACCWaitParseInfo Info =
1187 ParseOpenACCWaitArgument(ClauseLoc,
1191 return OpenACCCanContinue();
1195 std::move(Info.QueueIdExprs));
1199 llvm_unreachable(
"Not an optional parens type?");
1202 if (
Parens.consumeClose())
1203 return OpenACCCannotContinue();
1212 return OpenACCSuccess(
1223Parser::OpenACCIntExprParseResult
1226 return ParseOpenACCIntExpr(DK, CK,
Loc);
1233Parser::OpenACCWaitParseInfo
1235 OpenACCWaitParseInfo
Result;
1237 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) &&
1244 OpenACCIntExprParseResult Res = ParseOpenACCIntExpr(
1249 if (Res.first.isInvalid() &&
1250 Res.second == OpenACCParseCanContinue::Cannot) {
1255 if (ExpectAndConsume(tok::colon)) {
1260 Result.DevNumExpr = Res.first.get();
1264 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) &&
1276 bool FirstArg =
true;
1279 if (ExpectAndConsume(tok::comma)) {
1286 OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument(
1292 if (Res.first.isInvalid() &&
1293 Res.second == OpenACCParseCanContinue::Cannot) {
1298 if (Res.first.isUsable())
1299 Result.QueueIdExprs.push_back(Res.first.get());
1305ExprResult Parser::ParseOpenACCIDExpression() {
1308 Res = ParseCXXIdExpression(
true);
1313 if (Tok.
isNot(tok::identifier)) {
1314 Diag(Tok, diag::err_expected) << tok::identifier;
1335ExprResult Parser::ParseOpenACCBindClauseArgument() {
1351 return ParseOpenACCIDExpression();
1362 OpenACCArraySectionRAII ArraySections(*
this);
1366 return {Res, OpenACCParseCanContinue::Cannot};
1370 return {Res, OpenACCParseCanContinue::Can};
1374 return {Res, OpenACCParseCanContinue::Can};
1380 auto [Res, CanContinue] = ParseOpenACCVar(CK);
1382 Vars.push_back(Res.
get());
1383 }
else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1389 ExpectAndConsume(tok::comma);
1391 auto [Res, CanContinue] = ParseOpenACCVar(CK);
1394 Vars.push_back(Res.
get());
1395 }
else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1407void Parser::ParseOpenACCCacheVarList() {
1416 if (tryParseAndConsumeSpecialTokenKind(*
this,
1417 OpenACCSpecialTokenKind::ReadOnly,
1428Parser::OpenACCDirectiveParseInfo
1429Parser::ParseOpenACCDirective() {
1433 Parser::OpenACCWaitParseInfo WaitInfo;
1441 ParseOpenACCAtomicKind(*
this);
1446 tok::annot_pragma_openacc_end);
1448 if (!
T.consumeOpen()) {
1451 Diag(
T.getOpenLocation(), diag::err_acc_invalid_open_paren);
1457 ExprResult RoutineName = ParseOpenACCIDExpression();
1467 ParseOpenACCCacheVarList();
1474 WaitInfo = ParseOpenACCWaitArgument(DirLoc,
true);
1475 if (WaitInfo.Failed)
1485 Diag(Tok, diag::err_expected) << tok::l_paren;
1489 OpenACCDirectiveParseInfo ParseInfo{DirKind,
1492 T.getOpenLocation(),
1493 T.getCloseLocation(),
1496 WaitInfo.getAllExprs(),
1497 ParseOpenACCClauseList(DirKind)};
1499 assert(Tok.
is(tok::annot_pragma_openacc_end) &&
1500 "Didn't parse all OpenACC Clauses");
1501 ParseInfo.EndLoc = ConsumeAnnotationToken();
1502 assert(ParseInfo.EndLoc.isValid() &&
1503 "Terminating annotation token not present");
1510 assert(Tok.
is(tok::annot_pragma_openacc) &&
"expected OpenACC Start Token");
1514 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1516 if (
getActions().OpenACC().ActOnStartDeclDirective(DirInfo.DirKind,
1526 assert(Tok.
is(tok::annot_pragma_openacc) &&
"expected OpenACC Start Token");
1530 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1531 if (
getActions().OpenACC().ActOnStartStmtDirective(
1532 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses))
1536 if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) {
1538 getActions().OpenACC(), DirInfo.DirKind, DirInfo.DirLoc, {},
1541 ParseScope ACCScope(
this, getOpenACCScopeFlags(DirInfo.DirKind));
1544 DirInfo.StartLoc, DirInfo.DirKind, DirInfo.Clauses, ParseStatement());
1548 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1549 DirInfo.MiscLoc, DirInfo.Exprs, DirInfo.RParenLoc, DirInfo.EndLoc,
1550 DirInfo.Clauses, AssocStmt);
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.