20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/StringSwitch.h"
30enum class OpenACCDirectiveKindEx {
42OpenACCDirectiveKindEx getOpenACCDirectiveKind(
Token Tok) {
43 if (!
Tok.is(tok::identifier))
44 return OpenACCDirectiveKindEx::Invalid;
46 llvm::StringSwitch<OpenACCDirectiveKind>(
47 Tok.getIdentifierInfo()->getName())
66 return static_cast<OpenACCDirectiveKindEx
>(DirKind);
68 return llvm::StringSwitch<OpenACCDirectiveKindEx>(
69 Tok.getIdentifierInfo()->getName())
70 .Case(
"enter", OpenACCDirectiveKindEx::Enter)
71 .Case(
"exit", OpenACCDirectiveKindEx::Exit)
72 .Default(OpenACCDirectiveKindEx::Invalid);
79 if (
Tok.is(tok::kw_auto))
83 if (
Tok.is(tok::kw_default))
87 if (
Tok.is(tok::kw_if))
91 if (
Tok.is(tok::kw_private))
95 if (
Tok.is(tok::kw_delete))
98 if (!
Tok.is(tok::identifier))
101 return llvm::StringSwitch<OpenACCClauseKind>(
102 Tok.getIdentifierInfo()->getName())
159 if (!
Tok.is(tok::identifier))
161 return llvm::StringSwitch<OpenACCAtomicKind>(
162 Tok.getIdentifierInfo()->getName())
171 if (!
Tok.is(tok::identifier))
174 return llvm::StringSwitch<OpenACCDefaultClauseKind>(
175 Tok.getIdentifierInfo()->getName())
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:
202 return Tok.getIdentifierInfo()->isStr(
"readonly");
203 case OpenACCSpecialTokenKind::DevNum:
204 return Tok.getIdentifierInfo()->isStr(
"devnum");
205 case OpenACCSpecialTokenKind::Queues:
206 return Tok.getIdentifierInfo()->isStr(
"queues");
207 case OpenACCSpecialTokenKind::Zero:
208 return Tok.getIdentifierInfo()->isStr(
"zero");
209 case OpenACCSpecialTokenKind::Force:
210 return Tok.getIdentifierInfo()->isStr(
"force");
211 case OpenACCSpecialTokenKind::Num:
212 return Tok.getIdentifierInfo()->isStr(
"num");
213 case OpenACCSpecialTokenKind::Length:
214 return Tok.getIdentifierInfo()->isStr(
"length");
215 case OpenACCSpecialTokenKind::Dim:
216 return Tok.getIdentifierInfo()->isStr(
"dim");
217 case OpenACCSpecialTokenKind::Static:
218 return Tok.getIdentifierInfo()->isStr(
"static");
220 llvm_unreachable(
"Unknown 'Kind' Passed");
227 if (
Tok.is(tok::identifier))
230 if (!
Tok.isAnnotation() &&
Tok.getIdentifierInfo() &&
242template <
typename DirOrClauseTy>
243bool tryParseAndConsumeSpecialTokenKind(
Parser &P, OpenACCSpecialTokenKind Kind,
244 DirOrClauseTy DirOrClause) {
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))
271 return Tok.getIdentifierInfo()->isStr(
"parallel");
273 return Tok.getIdentifierInfo()->isStr(
"serial");
275 return Tok.getIdentifierInfo()->isStr(
"kernels");
277 return Tok.getIdentifierInfo()->isStr(
"data");
279 return Tok.getIdentifierInfo()->isStr(
"host_data");
281 return Tok.getIdentifierInfo()->isStr(
"loop");
283 return Tok.getIdentifierInfo()->isStr(
"cache");
293 return Tok.getIdentifierInfo()->isStr(
"atomic");
295 return Tok.getIdentifierInfo()->isStr(
"routine");
297 return Tok.getIdentifierInfo()->isStr(
"declare");
299 return Tok.getIdentifierInfo()->isStr(
"init");
301 return Tok.getIdentifierInfo()->isStr(
"shutdown");
303 return Tok.getIdentifierInfo()->isStr(
"set");
305 return Tok.getIdentifierInfo()->isStr(
"update");
307 return Tok.getIdentifierInfo()->isStr(
"wait");
311 llvm_unreachable(
"Unknown 'Kind' Passed");
327 switch (ReductionKindTok.
getKind()) {
342 case tok::identifier:
349 P.
Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator);
352 llvm_unreachable(
"Reduction op token kind not caught by 'default'?");
357bool expectIdentifierOrKeyword(
Parser &P) {
360 if (isTokenIdentifierOrKeyword(P,
Tok))
368ParseOpenACCEnterExitDataDirective(
Parser &P,
Token FirstTok,
369 OpenACCDirectiveKindEx ExtDirKind) {
373 P.
Diag(FirstTok, diag::err_acc_invalid_directive)
383 if (!SecondTok.
is(tok::identifier))
384 P.
Diag(SecondTok, diag::err_expected) << tok::identifier;
386 P.
Diag(FirstTok, diag::err_acc_invalid_directive)
392 return ExtDirKind == OpenACCDirectiveKindEx::Enter
421 if (FirstTok.
isNot(tok::identifier)) {
422 P.
Diag(FirstTok, diag::err_acc_missing_directive);
432 OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok);
440 if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) {
442 case OpenACCDirectiveKindEx::Invalid: {
443 P.
Diag(FirstTok, diag::err_acc_invalid_directive)
447 case OpenACCDirectiveKindEx::Enter:
448 case OpenACCDirectiveKindEx::Exit:
449 return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind);
481enum ClauseParensKind {
492 : ClauseParensKind::Optional;
498 return ClauseParensKind::Optional;
538 return ClauseParensKind::Required;
541 llvm_unreachable(
"Shortloop shouldn't be generated in clang");
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) {
601 llvm_unreachable(
"Unhandled directive->assoc stmt");
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() {
667 Sema::ConditionResult R =
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;
739 SmallVector<OpenACCClause *> Clauses;
740 bool FirstClause =
true;
747 OpenACCClauseParseResult
Result = ParseOpenACCClause(Clauses, DirKind);
748 if (OpenACCClause *Clause =
Result.getPointer()) {
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);
992 SemaOpenACC::OpenACCParsedClause ParsedClause(DirKind, ClauseKind, ClauseLoc);
994 if (ClauseHasRequiredParens(DirKind, ClauseKind)) {
995 if (
Parens.expectAndConsume()) {
999 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
1001 return OpenACCCanContinue();
1003 ParsedClause.setLParenLoc(
Parens.getOpenLocation());
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();
1025 ParsedClause.setDefaultDetails(DefKind);
1029 ExprResult CondExpr = ParseOpenACCConditionExpr();
1030 ParsedClause.setConditionDetails(CondExpr.
isUsable() ? CondExpr.
get()
1035 return OpenACCCanContinue();
1053 ParsedClause.setVarListDetails(ParseOpenACCVarList(DirKind, ClauseKind),
1061 ParsedClause.setReductionDetails(
1062 Op, ParseOpenACCVarList(DirKind, ClauseKind));
1084 ParsedClause.setVarListDetails(ParseOpenACCVarList(DirKind, ClauseKind),
1088 bool HasForce = tryParseAndConsumeSpecialTokenKind(
1089 *
this, OpenACCSpecialTokenKind::Force, ClauseKind);
1093 return OpenACCCanContinue();
1102 return OpenACCCanContinue();
1105 ParsedClause.setCollapseDetails(HasForce, LoopCount.
get());
1109 ParsedClause.setBindDetails(ParseOpenACCBindClauseArgument());
1112 if (std::holds_alternative<std::monostate>(
1113 ParsedClause.getBindDetails())) {
1115 return OpenACCCanContinue();
1120 llvm::SmallVector<Expr *> IntExprs;
1126 return OpenACCCanContinue();
1128 ParsedClause.setIntExprDetails(std::move(IntExprs));
1136 ClauseKind, ClauseLoc)
1140 return OpenACCCanContinue();
1143 ParsedClause.setIntExprDetails(IntExpr.
get());
1148 llvm::SmallVector<IdentifierLoc> Archs;
1152 ParsedClause.setDeviceTypeDetails(
1154 }
else if (!ParseOpenACCDeviceTypeList(Archs)) {
1155 ParsedClause.setDeviceTypeDetails(std::move(Archs));
1158 return OpenACCCanContinue();
1163 llvm::SmallVector<Expr *> SizeExprs;
1166 return OpenACCCanContinue();
1169 ParsedClause.setIntExprDetails(std::move(SizeExprs));
1173 llvm_unreachable(
"Not a required parens type?");
1176 ParsedClause.setEndLoc(
getCurToken().getLocation());
1178 if (
Parens.consumeClose())
1179 return OpenACCCannotContinue();
1181 }
else if (ClauseHasOptionalParens(DirKind, ClauseKind)) {
1182 if (!
Parens.consumeOpen()) {
1183 ParsedClause.setLParenLoc(
Parens.getOpenLocation());
1184 switch (ClauseKind) {
1187 ExprResult CondExpr = ParseOpenACCConditionExpr();
1188 ParsedClause.setConditionDetails(CondExpr.
isUsable() ? CondExpr.
get()
1193 return OpenACCCanContinue();
1199 tryParseAndConsumeSpecialTokenKind(*
this,
1202 ? OpenACCSpecialTokenKind::Length
1203 : OpenACCSpecialTokenKind::Num,
1206 ClauseKind, ClauseLoc)
1210 return OpenACCCanContinue();
1212 ParsedClause.setIntExprDetails(IntExpr.
get());
1220 ParsedClause.setIntExprDetails(AsyncArg.
isUsable() ? AsyncArg.
get()
1224 return OpenACCCanContinue();
1229 llvm::SmallVector<OpenACCGangKind> GKs;
1230 llvm::SmallVector<Expr *> IntExprs;
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();
1247 ParsedClause.setWaitDetails(Info.DevNumExpr, Info.QueuesLoc,
1248 std::move(Info.QueueIdExprs));
1252 llvm_unreachable(
"Not an optional parens type?");
1254 ParsedClause.setEndLoc(
getCurToken().getLocation());
1255 if (
Parens.consumeClose())
1256 return OpenACCCannotContinue();
1260 ParsedClause.setEndLoc(ClauseLoc);
1263 ParsedClause.setEndLoc(ClauseLoc);
1265 return OpenACCSuccess(
1266 Actions.OpenACC().ActOnClause(ExistingClauses, ParsedClause));
1269Parser::OpenACCIntExprParseResult
1272 return ParseOpenACCIntExpr(DK, CK, Loc);
1275Parser::OpenACCWaitParseInfo
1276Parser::ParseOpenACCWaitArgument(
SourceLocation Loc,
bool IsDirective) {
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;
1375 CXXScopeSpec ScopeSpec;
1376 SourceLocation TemplateKWLoc;
1382 Res = Actions.ActOnIdExpression(
getCurScope(), ScopeSpec, TemplateKWLoc,
1390std::variant<std::monostate, clang::StringLiteral *, IdentifierInfo *>
1391Parser::ParseOpenACCBindClauseArgument() {
1400 return std::monostate{};
1411 return std::monostate{};
1417 return std::monostate{};
1423 OpenACCArraySectionRAII ArraySections(*
this);
1430 return {Res, OpenACCParseCanContinue::Cannot};
1434 return {Res, OpenACCParseCanContinue::Can};
1439 llvm::SmallVector<Expr *> Vars;
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() {
1491 SourceLocation StartLoc = ConsumeAnnotationToken();
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);
1574 ParseInfo.Exprs = llvm::SmallVector<Expr *>(1, RoutineName.
get());
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()) {
1600 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
1601 MaybeParseCXX11Attributes(Attrs);
1602 ParsingDeclSpec PDS(*
this);
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.
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...
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.
static OpaquePtr make(DeclGroupRef 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.
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
ExprResult ParseConstantExpression()
StmtResult ParseOpenACCDirectiveStmt()
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Scope * getCurScope() const
friend class ParsingOpenACCDirectiveRAII
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.
friend class BalancedDelimiterTracker
@ 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...
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'.
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'.
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.
void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc)
Specify that this unqualified-id was parsed as an identifier.
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.
@ Invalid
Invalid Reduction Clause Kind.
OpenACCClauseKind
Represents the kind of an OpenACC clause.
@ Auto
'auto' clause, allowed on 'loop' directives.
@ 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.
@ NoHost
'nohost' clause, allowed on 'routine' directives.
@ 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'.
@ Shortloop
'shortloop' is represented in the ACC.td file, but isn't present in the standard.
@ 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',...
@ Seq
'seq' clause, allowed on 'loop' and 'routine' directives.
@ 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.
@ Independent
'independent' clause, allowed on 'loop' directives.
@ NumWorkers
'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs...
@ IfPresent
'if_present' clause, allowed on 'host_data' and 'update' directives.
@ 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'.
@ Finalize
'finalize' clause, allowed on 'exit data' directive.
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
@ Invalid
Not a valid option.
@ Present
'present' option.
@ Result
The result type of a method or function.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
ActionResult< Expr * > ExprResult
@ Parens
New-expression has a C++98 paren-delimited initializer.
ActionResult< Stmt * > StmtResult
Diagnostic wrappers for TextAPI types for error reporting.