20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/StringSwitch.h"
30enum class OpenACCDirectiveKindEx {
31 Invalid =
static_cast<int>(OpenACCDirectiveKind::Invalid),
42OpenACCDirectiveKindEx getOpenACCDirectiveKind(
Token Tok) {
43 if (!Tok.
is(tok::identifier))
44 return OpenACCDirectiveKindEx::Invalid;
46 llvm::StringSwitch<OpenACCDirectiveKind>(
48 .Case(
"parallel", OpenACCDirectiveKind::Parallel)
49 .Case(
"serial", OpenACCDirectiveKind::Serial)
50 .Case(
"kernels", OpenACCDirectiveKind::Kernels)
51 .Case(
"data", OpenACCDirectiveKind::Data)
52 .Case(
"host_data", OpenACCDirectiveKind::HostData)
53 .Case(
"loop", OpenACCDirectiveKind::Loop)
54 .Case(
"cache", OpenACCDirectiveKind::Cache)
55 .Case(
"atomic", OpenACCDirectiveKind::Atomic)
56 .Case(
"routine", OpenACCDirectiveKind::Routine)
57 .Case(
"declare", OpenACCDirectiveKind::Declare)
58 .Case(
"init", OpenACCDirectiveKind::Init)
59 .Case(
"shutdown", OpenACCDirectiveKind::Shutdown)
60 .Case(
"set", OpenACCDirectiveKind::Set)
61 .Case(
"update", OpenACCDirectiveKind::Update)
62 .Case(
"wait", OpenACCDirectiveKind::Wait)
63 .Default(OpenACCDirectiveKind::Invalid);
65 if (DirKind != OpenACCDirectiveKind::Invalid)
66 return static_cast<OpenACCDirectiveKindEx
>(DirKind);
68 return llvm::StringSwitch<OpenACCDirectiveKindEx>(
70 .Case(
"enter", OpenACCDirectiveKindEx::Enter)
71 .Case(
"exit", OpenACCDirectiveKindEx::Exit)
72 .Default(OpenACCDirectiveKindEx::Invalid);
79 if (Tok.
is(tok::kw_auto))
80 return OpenACCClauseKind::Auto;
83 if (Tok.
is(tok::kw_default))
84 return OpenACCClauseKind::Default;
87 if (Tok.
is(tok::kw_if))
88 return OpenACCClauseKind::If;
91 if (Tok.
is(tok::kw_private))
92 return OpenACCClauseKind::Private;
95 if (Tok.
is(tok::kw_delete))
96 return OpenACCClauseKind::Delete;
98 if (!Tok.
is(tok::identifier))
99 return OpenACCClauseKind::Invalid;
101 return llvm::StringSwitch<OpenACCClauseKind>(
103 .Case(
"async", OpenACCClauseKind::Async)
104 .Case(
"attach", OpenACCClauseKind::Attach)
105 .Case(
"auto", OpenACCClauseKind::Auto)
106 .Case(
"bind", OpenACCClauseKind::Bind)
107 .Case(
"create", OpenACCClauseKind::Create)
108 .Case(
"pcreate", OpenACCClauseKind::PCreate)
109 .Case(
"present_or_create", OpenACCClauseKind::PresentOrCreate)
110 .Case(
"collapse", OpenACCClauseKind::Collapse)
111 .Case(
"copy", OpenACCClauseKind::Copy)
112 .Case(
"pcopy", OpenACCClauseKind::PCopy)
113 .Case(
"present_or_copy", OpenACCClauseKind::PresentOrCopy)
114 .Case(
"copyin", OpenACCClauseKind::CopyIn)
115 .Case(
"pcopyin", OpenACCClauseKind::PCopyIn)
116 .Case(
"present_or_copyin", OpenACCClauseKind::PresentOrCopyIn)
117 .Case(
"copyout", OpenACCClauseKind::CopyOut)
118 .Case(
"pcopyout", OpenACCClauseKind::PCopyOut)
119 .Case(
"present_or_copyout", OpenACCClauseKind::PresentOrCopyOut)
120 .Case(
"default", OpenACCClauseKind::Default)
121 .Case(
"default_async", OpenACCClauseKind::DefaultAsync)
122 .Case(
"delete", OpenACCClauseKind::Delete)
123 .Case(
"detach", OpenACCClauseKind::Detach)
124 .Case(
"device", OpenACCClauseKind::Device)
125 .Case(
"device_num", OpenACCClauseKind::DeviceNum)
126 .Case(
"device_resident", OpenACCClauseKind::DeviceResident)
127 .Case(
"device_type", OpenACCClauseKind::DeviceType)
128 .Case(
"deviceptr", OpenACCClauseKind::DevicePtr)
129 .Case(
"dtype", OpenACCClauseKind::DType)
130 .Case(
"finalize", OpenACCClauseKind::Finalize)
131 .Case(
"firstprivate", OpenACCClauseKind::FirstPrivate)
132 .Case(
"gang", OpenACCClauseKind::Gang)
133 .Case(
"host", OpenACCClauseKind::Host)
134 .Case(
"if", OpenACCClauseKind::If)
135 .Case(
"if_present", OpenACCClauseKind::IfPresent)
136 .Case(
"independent", OpenACCClauseKind::Independent)
137 .Case(
"link", OpenACCClauseKind::Link)
138 .Case(
"no_create", OpenACCClauseKind::NoCreate)
139 .Case(
"num_gangs", OpenACCClauseKind::NumGangs)
140 .Case(
"num_workers", OpenACCClauseKind::NumWorkers)
141 .Case(
"nohost", OpenACCClauseKind::NoHost)
142 .Case(
"present", OpenACCClauseKind::Present)
143 .Case(
"private", OpenACCClauseKind::Private)
144 .Case(
"reduction", OpenACCClauseKind::Reduction)
145 .Case(
"self", OpenACCClauseKind::Self)
146 .Case(
"seq", OpenACCClauseKind::Seq)
147 .Case(
"tile", OpenACCClauseKind::Tile)
148 .Case(
"use_device", OpenACCClauseKind::UseDevice)
149 .Case(
"vector", OpenACCClauseKind::Vector)
150 .Case(
"vector_length", OpenACCClauseKind::VectorLength)
151 .Case(
"wait", OpenACCClauseKind::Wait)
152 .Case(
"worker", OpenACCClauseKind::Worker)
153 .Default(OpenACCClauseKind::Invalid);
159 if (!Tok.
is(tok::identifier))
160 return OpenACCAtomicKind::None;
161 return llvm::StringSwitch<OpenACCAtomicKind>(
163 .Case(
"read", OpenACCAtomicKind::Read)
164 .Case(
"write", OpenACCAtomicKind::Write)
165 .Case(
"update", OpenACCAtomicKind::Update)
166 .Case(
"capture", OpenACCAtomicKind::Capture)
167 .Default(OpenACCAtomicKind::None);
171 if (!Tok.
is(tok::identifier))
172 return OpenACCDefaultClauseKind::Invalid;
174 return llvm::StringSwitch<OpenACCDefaultClauseKind>(
176 .Case(
"none", OpenACCDefaultClauseKind::None)
177 .Case(
"present", OpenACCDefaultClauseKind::Present)
178 .Default(OpenACCDefaultClauseKind::Invalid);
181enum class OpenACCSpecialTokenKind {
193bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind,
Token Tok) {
194 if (Tok.
is(tok::kw_static) && Kind == OpenACCSpecialTokenKind::Static)
197 if (!Tok.
is(tok::identifier))
201 case OpenACCSpecialTokenKind::ReadOnly:
203 case OpenACCSpecialTokenKind::DevNum:
205 case OpenACCSpecialTokenKind::Queues:
207 case OpenACCSpecialTokenKind::Zero:
209 case OpenACCSpecialTokenKind::Force:
211 case OpenACCSpecialTokenKind::Num:
213 case OpenACCSpecialTokenKind::Length:
215 case OpenACCSpecialTokenKind::Dim:
217 case OpenACCSpecialTokenKind::Static:
220 llvm_unreachable(
"Unknown 'Kind' Passed");
227 if (Tok.
is(tok::identifier))
242template <
typename DirOrClauseTy>
243bool tryParseAndConsumeSpecialTokenKind(
Parser &
P, OpenACCSpecialTokenKind Kind,
244 DirOrClauseTy DirOrClause) {
245 Token IdentTok =
P.getCurToken();
248 if (isTokenIdentifierOrKeyword(
P, IdentTok) &&
P.NextToken().is(tok::colon)) {
252 if (!isOpenACCSpecialToken(Kind, IdentTok)) {
253 P.Diag(IdentTok, diag::err_acc_invalid_tag_kind)
255 << std::is_same_v<DirOrClauseTy, OpenACCClauseKind>;
266 if (!Tok.
is(tok::identifier))
270 case OpenACCDirectiveKind::Parallel:
272 case OpenACCDirectiveKind::Serial:
274 case OpenACCDirectiveKind::Kernels:
276 case OpenACCDirectiveKind::Data:
278 case OpenACCDirectiveKind::HostData:
280 case OpenACCDirectiveKind::Loop:
282 case OpenACCDirectiveKind::Cache:
285 case OpenACCDirectiveKind::ParallelLoop:
286 case OpenACCDirectiveKind::SerialLoop:
287 case OpenACCDirectiveKind::KernelsLoop:
288 case OpenACCDirectiveKind::EnterData:
289 case OpenACCDirectiveKind::ExitData:
292 case OpenACCDirectiveKind::Atomic:
294 case OpenACCDirectiveKind::Routine:
296 case OpenACCDirectiveKind::Declare:
298 case OpenACCDirectiveKind::Init:
300 case OpenACCDirectiveKind::Shutdown:
302 case OpenACCDirectiveKind::Set:
304 case OpenACCDirectiveKind::Update:
306 case OpenACCDirectiveKind::Wait:
308 case OpenACCDirectiveKind::Invalid:
311 llvm_unreachable(
"Unknown 'Kind' Passed");
318 if (
P.NextToken().isNot(tok::colon)) {
319 P.Diag(
P.getCurToken(), diag::err_acc_expected_reduction_operator);
320 return OpenACCReductionOperator::Invalid;
322 Token ReductionKindTok =
P.getCurToken();
327 switch (ReductionKindTok.
getKind()) {
329 return OpenACCReductionOperator::Addition;
331 return OpenACCReductionOperator::Multiplication;
333 return OpenACCReductionOperator::BitwiseAnd;
335 return OpenACCReductionOperator::BitwiseOr;
337 return OpenACCReductionOperator::BitwiseXOr;
339 return OpenACCReductionOperator::And;
341 return OpenACCReductionOperator::Or;
342 case tok::identifier:
344 return OpenACCReductionOperator::Max;
346 return OpenACCReductionOperator::Min;
349 P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator);
350 return OpenACCReductionOperator::Invalid;
352 llvm_unreachable(
"Reduction op token kind not caught by 'default'?");
357bool expectIdentifierOrKeyword(
Parser &
P) {
358 Token Tok =
P.getCurToken();
360 if (isTokenIdentifierOrKeyword(
P, Tok))
363 P.Diag(
P.getCurToken(), diag::err_expected) << tok::identifier;
368ParseOpenACCEnterExitDataDirective(
Parser &
P,
Token FirstTok,
369 OpenACCDirectiveKindEx ExtDirKind) {
370 Token SecondTok =
P.getCurToken();
373 P.Diag(FirstTok, diag::err_acc_invalid_directive)
375 return OpenACCDirectiveKind::Invalid;
382 if (!isOpenACCDirectiveKind(OpenACCDirectiveKind::Data, SecondTok)) {
383 if (!SecondTok.
is(tok::identifier))
384 P.Diag(SecondTok, diag::err_expected) << tok::identifier;
386 P.Diag(FirstTok, diag::err_acc_invalid_directive)
389 return OpenACCDirectiveKind::Invalid;
392 return ExtDirKind == OpenACCDirectiveKindEx::Enter
393 ? OpenACCDirectiveKind::EnterData
394 : OpenACCDirectiveKind::ExitData;
398 Token AtomicClauseToken =
P.getCurToken();
402 return OpenACCAtomicKind::None;
409 if (AtomicKind != OpenACCAtomicKind::None)
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::Shortloop:
541 llvm_unreachable(
"Shortloop shouldn't be generated in clang");
542 case OpenACCClauseKind::Auto:
543 case OpenACCClauseKind::Finalize:
544 case OpenACCClauseKind::IfPresent:
545 case OpenACCClauseKind::Independent:
546 case OpenACCClauseKind::Invalid:
547 case OpenACCClauseKind::NoHost:
548 case OpenACCClauseKind::Seq:
549 return ClauseParensKind::None;
551 llvm_unreachable(
"Unhandled clause kind");
556 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional;
561 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required;
568void SkipUntilEndOfDirective(
Parser &
P) {
569 while (
P.getCurToken().isNot(tok::annot_pragma_openacc_end))
575 case OpenACCDirectiveKind::Routine:
578 case OpenACCDirectiveKind::Cache:
579 case OpenACCDirectiveKind::Declare:
580 case OpenACCDirectiveKind::Set:
581 case OpenACCDirectiveKind::EnterData:
582 case OpenACCDirectiveKind::ExitData:
583 case OpenACCDirectiveKind::Wait:
584 case OpenACCDirectiveKind::Init:
585 case OpenACCDirectiveKind::Shutdown:
586 case OpenACCDirectiveKind::Update:
587 case OpenACCDirectiveKind::Invalid:
589 case OpenACCDirectiveKind::Parallel:
590 case OpenACCDirectiveKind::Serial:
591 case OpenACCDirectiveKind::Kernels:
592 case OpenACCDirectiveKind::ParallelLoop:
593 case OpenACCDirectiveKind::SerialLoop:
594 case OpenACCDirectiveKind::KernelsLoop:
595 case OpenACCDirectiveKind::Loop:
596 case OpenACCDirectiveKind::Data:
597 case OpenACCDirectiveKind::HostData:
598 case OpenACCDirectiveKind::Atomic:
601 llvm_unreachable(
"Unhandled directive->assoc stmt");
606 case OpenACCDirectiveKind::Parallel:
607 case OpenACCDirectiveKind::Serial:
608 case OpenACCDirectiveKind::Kernels:
613 case OpenACCDirectiveKind::ParallelLoop:
614 case OpenACCDirectiveKind::SerialLoop:
615 case OpenACCDirectiveKind::KernelsLoop:
621 case OpenACCDirectiveKind::Loop:
623 case OpenACCDirectiveKind::Data:
624 case OpenACCDirectiveKind::EnterData:
625 case OpenACCDirectiveKind::ExitData:
626 case OpenACCDirectiveKind::HostData:
627 case OpenACCDirectiveKind::Wait:
628 case OpenACCDirectiveKind::Init:
629 case OpenACCDirectiveKind::Shutdown:
630 case OpenACCDirectiveKind::Cache:
631 case OpenACCDirectiveKind::Atomic:
632 case OpenACCDirectiveKind::Declare:
633 case OpenACCDirectiveKind::Routine:
634 case OpenACCDirectiveKind::Set:
635 case OpenACCDirectiveKind::Update:
637 case OpenACCDirectiveKind::Invalid:
638 llvm_unreachable(
"Shouldn't be creating a scope for an invalid construct");
640 llvm_unreachable(
"Shouldn't be creating a scope for an invalid construct");
645Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() {
646 return {
nullptr, OpenACCParseCanContinue::Can};
649Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() {
650 return {
nullptr, OpenACCParseCanContinue::Cannot};
653Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(
OpenACCClause *Clause) {
654 return {Clause, OpenACCParseCanContinue::Can};
657ExprResult Parser::ParseOpenACCConditionExpr() {
678 RevertingTentativeParsingAction TPA{*
this};
680 while (isTokenIdentifierOrKeyword(*
this,
getCurToken()) &&
686 if (!isTokenIdentifierOrKeyword(*
this,
getCurToken()) ||
693 auto GetModKind = [](
Token T) {
694 return StringSwitch<OpenACCModifierKind>(
T.getIdentifierInfo()->getName())
705 auto ConsumeModKind = [&]() {
717 CurModList |= NewKind;
740 bool FirstClause =
true;
741 while (
getCurToken().isNot(tok::annot_pragma_openacc_end)) {
747 OpenACCClauseParseResult
Result = ParseOpenACCClause(Clauses, DirKind);
749 Clauses.push_back(Clause);
750 }
else if (
Result.getInt() == OpenACCParseCanContinue::Cannot) {
753 SkipUntilEndOfDirective(*
this);
760Parser::OpenACCIntExprParseResult
768 return {ER, OpenACCParseCanContinue::Cannot};
771 OpenACCParseCanContinue::Can};
777 OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK,
Loc);
779 if (!CurResult.first.isUsable() &&
780 CurResult.second == OpenACCParseCanContinue::Cannot) {
781 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
786 IntExprs.push_back(CurResult.first.get());
789 ExpectAndConsume(tok::comma);
791 CurResult = ParseOpenACCIntExpr(DK, CK,
Loc);
793 if (!CurResult.first.isUsable() &&
794 CurResult.second == OpenACCParseCanContinue::Cannot) {
795 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
799 IntExprs.push_back(CurResult.first.get());
804bool Parser::ParseOpenACCDeviceTypeList(
807 if (expectIdentifierOrKeyword(*
this)) {
808 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
816 ExpectAndConsume(tok::comma);
818 if (expectIdentifierOrKeyword(*
this)) {
819 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
834 tok::annot_pragma_openacc_end)) {
851bool Parser::ParseOpenACCSizeExprList(
853 ExprResult SizeExpr = ParseOpenACCSizeExpr(CK);
855 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
860 SizeExprs.push_back(SizeExpr.
get());
863 ExpectAndConsume(tok::comma);
865 SizeExpr = ParseOpenACCSizeExpr(CK);
867 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
871 SizeExprs.push_back(SizeExpr.
get());
876Parser::OpenACCGangArgRes Parser::ParseOpenACCGangArg(
SourceLocation GangLoc) {
878 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static,
getCurToken()) &&
887 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim,
getCurToken()) &&
897 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num,
getCurToken()) &&
911bool Parser::ParseOpenACCGangArgList(
915 Parser::OpenACCGangArgRes Res = ParseOpenACCGangArg(GangLoc);
916 if (!Res.second.isUsable()) {
917 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
922 GKs.push_back(Res.first);
923 IntExprs.push_back(Res.second.get());
926 ExpectAndConsume(tok::comma);
928 Res = ParseOpenACCGangArg(GangLoc);
929 if (!Res.second.isUsable()) {
930 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
935 GKs.push_back(Res.first);
936 IntExprs.push_back(Res.second.get());
942bool isUnsupportedExtensionClause(
Token Tok) {
943 if (!Tok.
is(tok::identifier))
950Parser::OpenACCClauseParseResult
955 if (expectIdentifierOrKeyword(*
this))
956 return OpenACCCannotContinue();
968 tok::annot_pragma_openacc_end);
970 if (!
Parens.consumeOpen())
973 return OpenACCCanContinue();
977 return OpenACCCannotContinue();
983 return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc);
986Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
991 tok::annot_pragma_openacc_end);
994 if (ClauseHasRequiredParens(DirKind, ClauseKind)) {
995 if (
Parens.expectAndConsume()) {
999 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
1001 return OpenACCCanContinue();
1005 switch (ClauseKind) {
1009 if (expectIdentifierOrKeyword(*
this)) {
1011 return OpenACCCanContinue();
1017 getOpenACCDefaultClauseKind(DefKindTok);
1020 Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
1022 return OpenACCCanContinue();
1029 ExprResult CondExpr = ParseOpenACCConditionExpr();
1035 return OpenACCCanContinue();
1062 Op, ParseOpenACCVarList(DirKind, ClauseKind));
1088 bool HasForce = tryParseAndConsumeSpecialTokenKind(
1089 *
this, OpenACCSpecialTokenKind::Force, ClauseKind);
1093 return OpenACCCanContinue();
1102 return OpenACCCanContinue();
1112 if (std::holds_alternative<std::monostate>(
1115 return OpenACCCanContinue();
1126 return OpenACCCanContinue();
1136 ClauseKind, ClauseLoc)
1140 return OpenACCCanContinue();
1154 }
else if (!ParseOpenACCDeviceTypeList(Archs)) {
1158 return OpenACCCanContinue();
1166 return OpenACCCanContinue();
1173 llvm_unreachable(
"Not a required parens type?");
1178 if (
Parens.consumeClose())
1179 return OpenACCCannotContinue();
1181 }
else if (ClauseHasOptionalParens(DirKind, ClauseKind)) {
1182 if (!
Parens.consumeOpen()) {
1184 switch (ClauseKind) {
1187 ExprResult CondExpr = ParseOpenACCConditionExpr();
1193 return OpenACCCanContinue();
1199 tryParseAndConsumeSpecialTokenKind(*
this,
1202 ? OpenACCSpecialTokenKind::Length
1203 : OpenACCSpecialTokenKind::Num,
1206 ClauseKind, ClauseLoc)
1210 return OpenACCCanContinue();
1224 return OpenACCCanContinue();
1231 if (ParseOpenACCGangArgList(ClauseLoc, GKs, IntExprs)) {
1233 return OpenACCCanContinue();
1235 ParsedClause.
setGangDetails(std::move(GKs), std::move(IntExprs));
1239 OpenACCWaitParseInfo Info =
1240 ParseOpenACCWaitArgument(ClauseLoc,
1244 return OpenACCCanContinue();
1248 std::move(Info.QueueIdExprs));
1252 llvm_unreachable(
"Not an optional parens type?");
1255 if (
Parens.consumeClose())
1256 return OpenACCCannotContinue();
1265 return OpenACCSuccess(
1269Parser::OpenACCIntExprParseResult
1272 return ParseOpenACCIntExpr(DK, CK,
Loc);
1275Parser::OpenACCWaitParseInfo
1277 OpenACCWaitParseInfo
Result;
1279 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) &&
1286 OpenACCIntExprParseResult Res = ParseOpenACCIntExpr(
1291 if (Res.first.isInvalid() &&
1292 Res.second == OpenACCParseCanContinue::Cannot) {
1297 if (ExpectAndConsume(tok::colon)) {
1302 Result.DevNumExpr = Res.first.get();
1306 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) &&
1320 OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument(
1326 if (Res.first.isInvalid() &&
1327 Res.second == OpenACCParseCanContinue::Cannot) {
1332 if (Res.first.isUsable())
1333 Result.QueueIdExprs.push_back(Res.first.get());
1336 if (ExpectAndConsume(tok::comma)) {
1341 OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument(
1347 if (Res.first.isInvalid() &&
1348 Res.second == OpenACCParseCanContinue::Cannot) {
1353 if (Res.first.isUsable())
1354 Result.QueueIdExprs.push_back(Res.first.get());
1360ExprResult Parser::ParseOpenACCIDExpression() {
1363 Res = ParseCXXIdExpression(
true);
1368 if (Tok.
isNot(tok::identifier)) {
1369 Diag(Tok, diag::err_expected) << tok::identifier;
1390std::variant<std::monostate, clang::StringLiteral *, IdentifierInfo *>
1391Parser::ParseOpenACCBindClauseArgument() {
1400 return std::monostate{};
1411 return std::monostate{};
1417 return std::monostate{};
1418 return cast<StringLiteral>(Res.
get());
1423 OpenACCArraySectionRAII ArraySections(*
this);
1430 return {Res, OpenACCParseCanContinue::Cannot};
1434 return {Res, OpenACCParseCanContinue::Can};
1441 auto [Res, CanContinue] = ParseOpenACCVar(DK, CK);
1443 Vars.push_back(Res.
get());
1444 }
else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1450 ExpectAndConsume(tok::comma);
1452 auto [Res, CanContinue] = ParseOpenACCVar(DK, CK);
1455 Vars.push_back(Res.
get());
1456 }
else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1464Parser::OpenACCCacheParseInfo Parser::ParseOpenACCCacheVarList() {
1470 OpenACCCacheParseInfo CacheInfo;
1476 if (tryParseAndConsumeSpecialTokenKind(*
this,
1477 OpenACCSpecialTokenKind::ReadOnly,
1479 CacheInfo.ReadOnlyLoc = ReadOnlyLoc;
1489Parser::OpenACCDirectiveParseInfo
1490Parser::ParseOpenACCDirective() {
1494 Parser::OpenACCWaitParseInfo WaitInfo;
1495 Parser::OpenACCCacheParseInfo CacheInfo;
1505 AtomicKind = ParseOpenACCAtomicKind(*
this);
1510 tok::annot_pragma_openacc_end);
1512 if (!
T.consumeOpen()) {
1515 Diag(
T.getOpenLocation(), diag::err_acc_invalid_open_paren);
1521 RoutineName = ParseOpenACCIDExpression();
1534 CacheInfo = ParseOpenACCCacheVarList();
1541 WaitInfo = ParseOpenACCWaitArgument(DirLoc,
true);
1542 if (WaitInfo.Failed)
1552 Diag(Tok, diag::err_expected) << tok::l_paren;
1556 OpenACCDirectiveParseInfo ParseInfo{DirKind,
1559 T.getOpenLocation(),
1560 T.getCloseLocation(),
1563 ? WaitInfo.QueuesLoc
1564 : CacheInfo.ReadOnlyLoc),
1570 ParseInfo.Exprs = WaitInfo.getAllExprs();
1572 ParseInfo.Exprs = std::move(CacheInfo.Vars);
1576 ParseInfo.Clauses = ParseOpenACCClauseList(DirKind);
1578 assert(Tok.
is(tok::annot_pragma_openacc_end) &&
1579 "Didn't parse all OpenACC Clauses");
1580 ParseInfo.EndLoc = ConsumeAnnotationToken();
1581 assert(ParseInfo.EndLoc.isValid() &&
1582 "Terminating annotation token not present");
1589 Decl *
TagDecl, OpenACCDirectiveParseInfo &DirInfo) {
1593 if (DirInfo.LParenLoc.isInvalid()) {
1594 if (Tok.
isNot(tok::r_brace) && !isEofOrEom()) {
1601 MaybeParseCXX11Attributes(Attrs);
1603 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
1610 Ptr = ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs,
TagType,
1617 getActions().OpenACC().ActOnEndRoutineDeclDirective(
1618 DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1619 DirInfo.Exprs.empty() ?
nullptr : DirInfo.Exprs.front(),
1620 DirInfo.RParenLoc, DirInfo.Clauses, DirInfo.EndLoc, Ptr));
1624Parser::ParseOpenACCAfterRoutineStmt(OpenACCDirectiveParseInfo &DirInfo) {
1634 if (DirInfo.LParenLoc.isInvalid()) {
1636 NextStmt = ParseStatement();
1640 DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1641 DirInfo.Exprs.empty() ?
nullptr : DirInfo.Exprs.front(),
1642 DirInfo.RParenLoc, DirInfo.Clauses, DirInfo.EndLoc, NextStmt.
get());
1648 assert(Tok.
is(tok::annot_pragma_openacc) &&
"expected OpenACC Start Token");
1652 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1654 if (
getActions().OpenACC().ActOnStartDeclDirective(
1655 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses))
1659 return ParseOpenACCAfterRoutineDecl(AS, Attrs,
TagType,
TagDecl, DirInfo);
1662 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1663 DirInfo.RParenLoc, DirInfo.EndLoc, DirInfo.Clauses));
1667 assert(Tok.
is(tok::annot_pragma_openacc) &&
"expected OpenACC Start Token");
1671 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1672 if (
getActions().OpenACC().ActOnStartStmtDirective(
1673 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses))
1677 return ParseOpenACCAfterRoutineStmt(DirInfo);
1680 if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) {
1682 getActions().OpenACC(), DirInfo.DirKind, DirInfo.DirLoc, {},
1685 ParseScope ACCScope(
this, getOpenACCScopeFlags(DirInfo.DirKind));
1688 DirInfo.StartLoc, DirInfo.DirKind, DirInfo.AtomicKind, DirInfo.Clauses,
1693 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1694 DirInfo.MiscLoc, DirInfo.Exprs, DirInfo.AtomicKind, DirInfo.RParenLoc,
1695 DirInfo.EndLoc, 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.
static const TST TST_unspecified
Decl - This represents one declaration (or definition), e.g.
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.
A simple pair of identifier info and location.
Wrapper for void* pointer.
static OpaquePtr make(PtrTy P)
This is the base type for all OpenACC Clauses.
ParsedAttributes - A collection of parsed attributes.
ParseScope - Introduces a new scope for parsing.
Parser - This implements a parser for the C family of languages.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
ExprResult ParseStringLiteralExpression(bool AllowUserDefinedLiteral=false)
ParseStringLiteralExpression - This handles the various token types that form string literals,...
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
Sema & getActions() const
DeclGroupPtrTy ParseOpenACCDirectiveDecl(AccessSpecifier &AS, ParsedAttributes &Attrs, DeclSpec::TST TagType, Decl *TagDecl)
Parse OpenACC directive on a declaration.
ExprResult ParseConstantExpression()
StmtResult ParseOpenACCDirectiveStmt()
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
const LangOptions & getLangOpts() const
ExprResult ParseExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)
Simple precedence-based parser for binary/ternary operators.
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
ExprResult ParseAssignmentExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)
Parse an expr that doesn't include (top-level) commas.
A class for parsing a DeclSpec.
Activates OpenACC parsing mode to preseve OpenACC specific annotation tokens.
@ OpenACCLoopConstructScope
This is the scope of an OpenACC Loop/Combined construct, which is used to determine whether a 'cache'...
@ 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 setVarListDetails(ArrayRef< Expr * > VarList, OpenACCModifierKind ModKind)
void setLParenLoc(SourceLocation EndLoc)
void setConditionDetails(Expr *ConditionExpr)
void setCollapseDetails(bool IsForce, Expr *LoopCount)
void setGangDetails(ArrayRef< OpenACCGangKind > GKs, ArrayRef< Expr * > IntExprs)
std::variant< std::monostate, clang::StringLiteral *, IdentifierInfo * > getBindDetails() const
void setReductionDetails(OpenACCReductionOperator Op, llvm::SmallVector< Expr * > &&VarList)
void setDefaultDetails(OpenACCDefaultClauseKind DefKind)
void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc, llvm::SmallVector< Expr * > &&IntExprs)
void setEndLoc(SourceLocation EndLoc)
void setIntExprDetails(ArrayRef< Expr * > IntExprs)
void setBindDetails(std::variant< std::monostate, clang::StringLiteral *, IdentifierInfo * > Arg)
void setDeviceTypeDetails(llvm::SmallVector< DeviceTypeArgument > &&Archs)
ExprResult ActOnRoutineName(Expr *RoutineName)
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.
void ActOnInvalidParseVar()
Called only if the parse of a 'var' was invalid, else 'ActOnVar' should be called.
StmtResult ActOnEndRoutineStmtDirective(SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *ReferencedFunc, SourceLocation RParenLoc, ArrayRef< const OpenACCClause * > Clauses, SourceLocation EndLoc, Stmt *NextStmt)
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, OpenACCDirectiveKind K, OpenACCAtomicKind AtKind, ArrayRef< const OpenACCClause * > Clauses, StmtResult AssocStmt)
Called when we encounter an associated statement for our construct, this should check legality of the...
ExprResult ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK, Expr *VarExpr)
Called when encountering a 'var' for OpenACC, ensures it is actually a declaration reference to a var...
void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc)
Called after the construct has been parsed, but clauses haven't been parsed.
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
void ActOnStartParseVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK)
Called right before a 'var' is parsed, so we can set the state for parsing a 'cache' var.
StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef< Expr * > Exprs, OpenACCAtomicKind AK, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses, StmtResult AssocStmt)
Called after the directive has been completely parsed, including the declaration group or associated ...
@ 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)
Encodes a location in the source.
SourceLocation getBeginLoc() const LLVM_READONLY
Represents the declaration of a struct/union/class/enum.
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 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.
TypeSpecifierType
Specifies the kind of type.
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'.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
@ Invalid
Not a valid option.
@ Result
The result type of a method or function.
const FunctionProtoType * T
@ Parens
New-expression has a C++98 paren-delimited initializer.
Diagnostic wrappers for TextAPI types for error reporting.