clang: lib/Parse/ParseOpenACC.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
20#include "llvm/ADT/StringRef.h"
21#include "llvm/ADT/StringSwitch.h"
22
23using namespace clang;
24using namespace llvm;
25
26namespace {
27
28
29
30enum class OpenACCDirectiveKindEx {
32
33 Enter,
34 Exit,
35};
36
37
38
39
40
41
42OpenACCDirectiveKindEx getOpenACCDirectiveKind(Token Tok) {
43 if (.is(tok::identifier))
44 return OpenACCDirectiveKindEx::Invalid;
46 llvm::StringSwitch(
47 Tok.getIdentifierInfo()->getName())
64
66 return static_cast<OpenACCDirectiveKindEx>(DirKind);
67
68 return llvm::StringSwitch(
69 Tok.getIdentifierInfo()->getName())
70 .Case("enter", OpenACCDirectiveKindEx::Enter)
71 .Case("exit", OpenACCDirectiveKindEx::Exit)
72 .Default(OpenACCDirectiveKindEx::Invalid);
73}
74
75
77
78
79 if (Tok.is(tok::kw_auto))
81
82
83 if (Tok.is(tok::kw_default))
85
86
87 if (Tok.is(tok::kw_if))
89
90
91 if (Tok.is(tok::kw_private))
93
94
95 if (Tok.is(tok::kw_delete))
97
98 if (.is(tok::identifier))
100
101 return llvm::StringSwitch(
102 Tok.getIdentifierInfo()->getName())
154}
155
156
157
159 if (.is(tok::identifier))
161 return llvm::StringSwitch(
162 Tok.getIdentifierInfo()->getName())
168}
169
171 if (.is(tok::identifier))
173
174 return llvm::StringSwitch(
175 Tok.getIdentifierInfo()->getName())
179}
180
181enum class OpenACCSpecialTokenKind {
182 ReadOnly,
183 DevNum,
184 Queues,
186 Force,
188 Length,
191};
192
193bool isOpenACCSpecialToken(OpenACCSpecialTokenKind Kind, Token Tok) {
194 if (Tok.is(tok::kw_static) && Kind == OpenACCSpecialTokenKind::Static)
195 return true;
196
197 if (.is(tok::identifier))
198 return false;
199
200 switch (Kind) {
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");
219 }
220 llvm_unreachable("Unknown 'Kind' Passed");
221}
222
223
224
225
226bool isTokenIdentifierOrKeyword(Parser &P, Token Tok) {
227 if (Tok.is(tok::identifier))
228 return true;
229
230 if (.isAnnotation() && Tok.getIdentifierInfo() &&
232 return true;
233
234 return false;
235}
236
237
238
239
240
241
242template
243bool tryParseAndConsumeSpecialTokenKind(Parser &P, OpenACCSpecialTokenKind Kind,
244 DirOrClauseTy DirOrClause) {
246
247
248 if (isTokenIdentifierOrKeyword(P, IdentTok) && P.NextToken().is(tok::colon)) {
251
252 if (!isOpenACCSpecialToken(Kind, IdentTok)) {
253 P.Diag(IdentTok, diag::err_acc_invalid_tag_kind)
255 << std::is_same_v<DirOrClauseTy, OpenACCClauseKind>;
256 return false;
257 }
258
259 return true;
260 }
261
262 return false;
263}
264
266 if (.is(tok::identifier))
267 return false;
268
269 switch (Kind) {
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");
284
290 return false;
291
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");
309 return false;
310 }
311 llvm_unreachable("Unknown 'Kind' Passed");
312}
313
315
316
317
319 P.Diag(P.getCurToken(), diag::err_acc_expected_reduction_operator);
321 }
323
326
327 switch (ReductionKindTok.getKind()) {
328 case tok:➕
330 case tok:⭐
332 case tok::amp:
334 case tok::pipe:
336 case tok::caret:
338 case tok::ampamp:
340 case tok::pipepipe:
342 case tok::identifier:
347 [[fallthrough]];
348 default:
349 P.Diag(ReductionKindTok, diag::err_acc_invalid_reduction_operator);
351 }
352 llvm_unreachable("Reduction op token kind not caught by 'default'?");
353}
354
355
356
357bool expectIdentifierOrKeyword(Parser &P) {
359
360 if (isTokenIdentifierOrKeyword(P, Tok))
361 return false;
362
363 P.Diag(P.getCurToken(), diag::err_expected) << tok::identifier;
364 return true;
365}
366
368ParseOpenACCEnterExitDataDirective(Parser &P, Token FirstTok,
369 OpenACCDirectiveKindEx ExtDirKind) {
371
373 P.Diag(FirstTok, diag::err_acc_invalid_directive)
376 }
377
378
379
381
383 if (!SecondTok.is(tok::identifier))
384 P.Diag(SecondTok, diag::err_expected) << tok::identifier;
385 else
386 P.Diag(FirstTok, diag::err_acc_invalid_directive)
390 }
391
392 return ExtDirKind == OpenACCDirectiveKindEx::Enter
395}
396
399
400
403
404 OpenACCAtomicKind AtomicKind = getOpenACCAtomicKind(AtomicClauseToken);
405
406
407
408
411
412 return AtomicKind;
413}
414
415
418
419
420
421 if (FirstTok.isNot(tok::identifier)) {
422 P.Diag(FirstTok, diag::err_acc_missing_directive);
423
426
428 }
429
431
432 OpenACCDirectiveKindEx ExDirKind = getOpenACCDirectiveKind(FirstTok);
433
434
435
436
437
438
439
440 if (ExDirKind >= OpenACCDirectiveKindEx::Invalid) {
441 switch (ExDirKind) {
442 case OpenACCDirectiveKindEx::Invalid: {
443 P.Diag(FirstTok, diag::err_acc_invalid_directive)
446 }
447 case OpenACCDirectiveKindEx::Enter:
448 case OpenACCDirectiveKindEx::Exit:
449 return ParseOpenACCEnterExitDataDirective(P, FirstTok, ExDirKind);
450 }
451 }
452
454
455
456
457
461 switch (DirKind) {
462 default:
463
464
465 break;
475 }
476 }
477
478 return DirKind;
479}
480
481enum ClauseParensKind {
485};
486
489 switch (Kind) {
492 : ClauseParensKind::Optional;
498 return ClauseParensKind::Optional;
499
538 return ClauseParensKind::Required;
539
541 llvm_unreachable("Shortloop shouldn't be generated in clang");
549 return ClauseParensKind::None;
550 }
551 llvm_unreachable("Unhandled clause kind");
552}
553
556 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Optional;
557}
558
561 return getClauseParensKind(DirKind, Kind) == ClauseParensKind::Required;
562}
563
564
565
566
567
568void SkipUntilEndOfDirective(Parser &P) {
571}
572
574 switch (DirKind) {
576
577
588 return false;
599 return true;
600 }
601 llvm_unreachable("Unhandled directive->assoc stmt");
602}
603
605 switch (DirKind) {
609
610
616
617
636 return 0;
638 llvm_unreachable("Shouldn't be creating a scope for an invalid construct");
639 }
640 llvm_unreachable("Shouldn't be creating a scope for an invalid construct");
641}
642
643}
644
645Parser::OpenACCClauseParseResult Parser::OpenACCCanContinue() {
646 return {nullptr, OpenACCParseCanContinue::Can};
647}
648
649Parser::OpenACCClauseParseResult Parser::OpenACCCannotContinue() {
650 return {nullptr, OpenACCParseCanContinue::Cannot};
651}
652
653Parser::OpenACCClauseParseResult Parser::OpenACCSuccess(OpenACCClause *Clause) {
654 return {Clause, OpenACCParseCanContinue::Can};
655}
656
657ExprResult Parser::ParseOpenACCConditionExpr() {
658
659
660
661
663
665 return ER;
666
667 Sema::ConditionResult R =
670
672}
673
675
676
677 {
678 RevertingTentativeParsingAction TPA{*this};
679
680 while (isTokenIdentifierOrKeyword(*this, getCurToken()) &&
684 }
685
686 if (!isTokenIdentifierOrKeyword(*this, getCurToken()) ||
688
690 }
691 }
692
693 auto GetModKind = [](Token T) {
694 return StringSwitch(T.getIdentifierInfo()->getName())
702 };
703
705 auto ConsumeModKind = [&]() {
708
711 << diag::ACCModifier::Unknown << IdentToken.getIdentifierInfo() << CK;
714 << diag::ACCModifier::Duplicate << IdentToken.getIdentifierInfo()
715 << CK;
716 else
717 CurModList |= NewKind;
718
719
721
723 };
724
725
726
728 ConsumeModKind();
729
730
731
732 ConsumeModKind();
733
734 return CurModList;
735}
736
739 SmallVector<OpenACCClause *> Clauses;
740 bool FirstClause = true;
742
743 if (!FirstClause && getCurToken().is(tok::comma))
745 FirstClause = false;
746
747 OpenACCClauseParseResult Result = ParseOpenACCClause(Clauses, DirKind);
748 if (OpenACCClause *Clause = Result.getPointer()) {
749 Clauses.push_back(Clause);
750 } else if (Result.getInt() == OpenACCParseCanContinue::Cannot) {
751
752
753 SkipUntilEndOfDirective(*this);
754 return Clauses;
755 }
756 }
757 return Clauses;
758}
759
760Parser::OpenACCIntExprParseResult
764
765
766
768 return {ER, OpenACCParseCanContinue::Cannot};
769
771 OpenACCParseCanContinue::Can};
772}
773
777 OpenACCIntExprParseResult CurResult = ParseOpenACCIntExpr(DK, CK, Loc);
778
779 if (!CurResult.first.isUsable() &&
780 CurResult.second == OpenACCParseCanContinue::Cannot) {
781 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
783 return true;
784 }
785
786 IntExprs.push_back(CurResult.first.get());
787
788 while (().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
789 ExpectAndConsume(tok::comma);
790
791 CurResult = ParseOpenACCIntExpr(DK, CK, Loc);
792
793 if (!CurResult.first.isUsable() &&
794 CurResult.second == OpenACCParseCanContinue::Cannot) {
795 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
797 return true;
798 }
799 IntExprs.push_back(CurResult.first.get());
800 }
801 return false;
802}
803
804bool Parser::ParseOpenACCDeviceTypeList(
806
807 if (expectIdentifierOrKeyword(*this)) {
808 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
810 return true;
811 }
814
815 while (().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
816 ExpectAndConsume(tok::comma);
817
818 if (expectIdentifierOrKeyword(*this)) {
819 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
821 return true;
822 }
825 }
826 return false;
827}
828
830
831
834 tok::annot_pragma_openacc_end)) {
837 }
838
840
842 return SizeExpr;
843
846 SizeExpr.get());
847
848 return SizeExpr;
849}
850
851bool Parser::ParseOpenACCSizeExprList(
853 ExprResult SizeExpr = ParseOpenACCSizeExpr(CK);
855 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
857 return true;
858 }
859
860 SizeExprs.push_back(SizeExpr.get());
861
862 while (().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
863 ExpectAndConsume(tok::comma);
864
865 SizeExpr = ParseOpenACCSizeExpr(CK);
867 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
869 return true;
870 }
871 SizeExprs.push_back(SizeExpr.get());
872 }
873 return false;
874}
875
876Parser::OpenACCGangArgRes Parser::ParseOpenACCGangArg(SourceLocation GangLoc) {
877
878 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Static, getCurToken()) &&
880
885 }
886
887 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Dim, getCurToken()) &&
891
892
895 }
896
897 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Num, getCurToken()) &&
901
902 }
903
904
907 .first;
909}
910
911bool Parser::ParseOpenACCGangArgList(
914
915 Parser::OpenACCGangArgRes Res = ParseOpenACCGangArg(GangLoc);
916 if (!Res.second.isUsable()) {
917 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
919 return true;
920 }
921
922 GKs.push_back(Res.first);
923 IntExprs.push_back(Res.second.get());
924
925 while (().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
926 ExpectAndConsume(tok::comma);
927
928 Res = ParseOpenACCGangArg(GangLoc);
929 if (!Res.second.isUsable()) {
930 SkipUntil(tok::r_paren, tok::annot_pragma_openacc_end,
932 return true;
933 }
934
935 GKs.push_back(Res.first);
936 IntExprs.push_back(Res.second.get());
937 }
938 return false;
939}
940
941namespace {
942bool isUnsupportedExtensionClause(Token Tok) {
943 if (.is(tok::identifier))
944 return false;
945
947}
948}
949
950Parser::OpenACCClauseParseResult
953
954
955 if (expectIdentifierOrKeyword(*this))
956 return OpenACCCannotContinue();
957
959
960 if (isUnsupportedExtensionClause(getCurToken())) {
961 Diag(getCurToken(), diag::warn_acc_unsupported_extension_clause)
963
964
965
968 tok::annot_pragma_openacc_end);
969
970 if (.consumeOpen())
972
973 return OpenACCCanContinue();
977 return OpenACCCannotContinue();
978 }
979
980
982
983 return ParseOpenACCClauseParams(ExistingClauses, DirKind, Kind, ClauseLoc);
984}
985
986Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
991 tok::annot_pragma_openacc_end);
992 SemaOpenACC::OpenACCParsedClause ParsedClause(DirKind, ClauseKind, ClauseLoc);
993
994 if (ClauseHasRequiredParens(DirKind, ClauseKind)) {
995 if (Parens.expectAndConsume()) {
996
997
998
999 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openacc_end,
1001 return OpenACCCanContinue();
1002 }
1003 ParsedClause.setLParenLoc(Parens.getOpenLocation());
1004
1005 switch (ClauseKind) {
1008
1009 if (expectIdentifierOrKeyword(*this)) {
1011 return OpenACCCanContinue();
1012 }
1013
1015
1017 getOpenACCDefaultClauseKind(DefKindTok);
1018
1020 Diag(DefKindTok, diag::err_acc_invalid_default_clause_kind);
1022 return OpenACCCanContinue();
1023 }
1024
1025 ParsedClause.setDefaultDetails(DefKind);
1026 break;
1027 }
1029 ExprResult CondExpr = ParseOpenACCConditionExpr();
1030 ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get()
1031 : nullptr);
1032
1035 return OpenACCCanContinue();
1036 }
1037
1038 break;
1039 }
1053 ParsedClause.setVarListDetails(ParseOpenACCVarList(DirKind, ClauseKind),
1054 ModList);
1055 break;
1056 }
1058
1059
1061 ParsedClause.setReductionDetails(
1062 Op, ParseOpenACCVarList(DirKind, ClauseKind));
1063 break;
1064 }
1066
1067
1068
1070 [[fallthrough]];
1084 ParsedClause.setVarListDetails(ParseOpenACCVarList(DirKind, ClauseKind),
1086 break;
1088 bool HasForce = tryParseAndConsumeSpecialTokenKind(
1089 *this, OpenACCSpecialTokenKind::Force, ClauseKind);
1093 return OpenACCCanContinue();
1094 }
1095
1099
1102 return OpenACCCanContinue();
1103 }
1104
1105 ParsedClause.setCollapseDetails(HasForce, LoopCount.get());
1106 break;
1107 }
1109 ParsedClause.setBindDetails(ParseOpenACCBindClauseArgument());
1110
1111
1112 if (std::holds_alternativestd::monostate(
1113 ParsedClause.getBindDetails())) {
1115 return OpenACCCanContinue();
1116 }
1117 break;
1118 }
1120 llvm::SmallVector<Expr *> IntExprs;
1121
1124 IntExprs)) {
1126 return OpenACCCanContinue();
1127 }
1128 ParsedClause.setIntExprDetails(std::move(IntExprs));
1129 break;
1130 }
1136 ClauseKind, ClauseLoc)
1137 .first;
1140 return OpenACCCanContinue();
1141 }
1142
1143 ParsedClause.setIntExprDetails(IntExpr.get());
1144 break;
1145 }
1148 llvm::SmallVector Archs;
1150
1151
1152 ParsedClause.setDeviceTypeDetails(
1154 } else if (!ParseOpenACCDeviceTypeList(Archs)) {
1155 ParsedClause.setDeviceTypeDetails(std::move(Archs));
1156 } else {
1158 return OpenACCCanContinue();
1159 }
1160 break;
1161 }
1163 llvm::SmallVector<Expr *> SizeExprs;
1166 return OpenACCCanContinue();
1167 }
1168
1169 ParsedClause.setIntExprDetails(std::move(SizeExprs));
1170 break;
1171 }
1172 default:
1173 llvm_unreachable("Not a required parens type?");
1174 }
1175
1176 ParsedClause.setEndLoc(getCurToken().getLocation());
1177
1178 if (Parens.consumeClose())
1179 return OpenACCCannotContinue();
1180
1181 } else if (ClauseHasOptionalParens(DirKind, ClauseKind)) {
1182 if (.consumeOpen()) {
1183 ParsedClause.setLParenLoc(Parens.getOpenLocation());
1184 switch (ClauseKind) {
1187 ExprResult CondExpr = ParseOpenACCConditionExpr();
1188 ParsedClause.setConditionDetails(CondExpr.isUsable() ? CondExpr.get()
1189 : nullptr);
1190
1193 return OpenACCCanContinue();
1194 }
1195 break;
1196 }
1199 tryParseAndConsumeSpecialTokenKind(*this,
1200 ClauseKind ==
1202 ? OpenACCSpecialTokenKind::Length
1203 : OpenACCSpecialTokenKind::Num,
1204 ClauseKind);
1206 ClauseKind, ClauseLoc)
1207 .first;
1210 return OpenACCCanContinue();
1211 }
1212 ParsedClause.setIntExprDetails(IntExpr.get());
1213 break;
1214 }
1219 .first;
1220 ParsedClause.setIntExprDetails(AsyncArg.isUsable() ? AsyncArg.get()
1221 : nullptr);
1224 return OpenACCCanContinue();
1225 }
1226 break;
1227 }
1229 llvm::SmallVector GKs;
1230 llvm::SmallVector<Expr *> IntExprs;
1231 if (ParseOpenACCGangArgList(ClauseLoc, GKs, IntExprs)) {
1233 return OpenACCCanContinue();
1234 }
1235 ParsedClause.setGangDetails(std::move(GKs), std::move(IntExprs));
1236 break;
1237 }
1239 OpenACCWaitParseInfo Info =
1240 ParseOpenACCWaitArgument(ClauseLoc,
1241 false);
1242 if (Info.Failed) {
1244 return OpenACCCanContinue();
1245 }
1246
1247 ParsedClause.setWaitDetails(Info.DevNumExpr, Info.QueuesLoc,
1248 std::move(Info.QueueIdExprs));
1249 break;
1250 }
1251 default:
1252 llvm_unreachable("Not an optional parens type?");
1253 }
1254 ParsedClause.setEndLoc(getCurToken().getLocation());
1255 if (Parens.consumeClose())
1256 return OpenACCCannotContinue();
1257 } else {
1258
1259
1260 ParsedClause.setEndLoc(ClauseLoc);
1261 }
1262 } else {
1263 ParsedClause.setEndLoc(ClauseLoc);
1264 }
1265 return OpenACCSuccess(
1266 Actions.OpenACC().ActOnClause(ExistingClauses, ParsedClause));
1267}
1268
1269Parser::OpenACCIntExprParseResult
1272 return ParseOpenACCIntExpr(DK, CK, Loc);
1273}
1274
1275Parser::OpenACCWaitParseInfo
1276Parser::ParseOpenACCWaitArgument(SourceLocation Loc, bool IsDirective) {
1277 OpenACCWaitParseInfo Result;
1278
1279 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::DevNum, Tok) &&
1281
1283
1285
1286 OpenACCIntExprParseResult Res = ParseOpenACCIntExpr(
1290 Loc);
1291 if (Res.first.isInvalid() &&
1292 Res.second == OpenACCParseCanContinue::Cannot) {
1293 Result.Failed = true;
1295 }
1296
1297 if (ExpectAndConsume(tok::colon)) {
1298 Result.Failed = true;
1300 }
1301
1302 Result.DevNumExpr = Res.first.get();
1303 }
1304
1305
1306 if (isOpenACCSpecialToken(OpenACCSpecialTokenKind::Queues, Tok) &&
1308
1310
1312 }
1313
1314
1315
1316
1317
1318
1319
1320 OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument(
1324 Loc);
1325
1326 if (Res.first.isInvalid() &&
1327 Res.second == OpenACCParseCanContinue::Cannot) {
1328 Result.Failed = true;
1330 }
1331
1332 if (Res.first.isUsable())
1333 Result.QueueIdExprs.push_back(Res.first.get());
1334
1335 while (().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
1336 if (ExpectAndConsume(tok::comma)) {
1337 Result.Failed = true;
1339 }
1340
1341 OpenACCIntExprParseResult Res = ParseOpenACCAsyncArgument(
1345 Loc);
1346
1347 if (Res.first.isInvalid() &&
1348 Res.second == OpenACCParseCanContinue::Cannot) {
1349 Result.Failed = true;
1351 }
1352
1353 if (Res.first.isUsable())
1354 Result.QueueIdExprs.push_back(Res.first.get());
1355 }
1356
1358}
1359
1360ExprResult Parser::ParseOpenACCIDExpression() {
1363 Res = ParseCXXIdExpression(true);
1364 } else {
1365
1366
1367
1368 if (Tok.isNot(tok::identifier)) {
1369 Diag(Tok, diag::err_expected) << tok::identifier;
1371 }
1372
1375 CXXScopeSpec ScopeSpec;
1376 SourceLocation TemplateKWLoc;
1378
1379
1380
1381
1382 Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, TemplateKWLoc,
1383 Name, false,
1384 false);
1385 }
1386
1387 return Res;
1388}
1389
1390std::variant<std::monostate, clang::StringLiteral *, IdentifierInfo *>
1391Parser::ParseOpenACCBindClauseArgument() {
1392
1393
1394
1395
1396
1397
1400 return std::monostate{};
1401 }
1402
1406 return II;
1407 }
1408
1411 return std::monostate{};
1412 }
1413
1415 false, true);
1417 return std::monostate{};
1419}
1420
1421Parser::OpenACCVarParseResult Parser::ParseOpenACCVar(OpenACCDirectiveKind DK,
1423 OpenACCArraySectionRAII ArraySections(*this);
1424
1427
1430 return {Res, OpenACCParseCanContinue::Cannot};
1431 }
1432
1434 return {Res, OpenACCParseCanContinue::Can};
1435}
1436
1439 llvm::SmallVector<Expr *> Vars;
1440
1441 auto [Res, CanContinue] = ParseOpenACCVar(DK, CK);
1443 Vars.push_back(Res.get());
1444 } else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1446 return Vars;
1447 }
1448
1449 while (().isOneOf(tok::r_paren, tok::annot_pragma_openacc_end)) {
1450 ExpectAndConsume(tok::comma);
1451
1452 auto [Res, CanContinue] = ParseOpenACCVar(DK, CK);
1453
1455 Vars.push_back(Res.get());
1456 } else if (CanContinue == OpenACCParseCanContinue::Cannot) {
1458 return Vars;
1459 }
1460 }
1461 return Vars;
1462}
1463
1464Parser::OpenACCCacheParseInfo Parser::ParseOpenACCCacheVarList() {
1465
1466
1468 return {};
1469
1470 OpenACCCacheParseInfo CacheInfo;
1471
1473
1474
1475
1476 if (tryParseAndConsumeSpecialTokenKind(*this,
1477 OpenACCSpecialTokenKind::ReadOnly,
1479 CacheInfo.ReadOnlyLoc = ReadOnlyLoc;
1480
1481
1482
1485
1486 return CacheInfo;
1487}
1488
1489Parser::OpenACCDirectiveParseInfo
1490Parser::ParseOpenACCDirective() {
1491 SourceLocation StartLoc = ConsumeAnnotationToken();
1494 Parser::OpenACCWaitParseInfo WaitInfo;
1495 Parser::OpenACCCacheParseInfo CacheInfo;
1498
1500
1501
1502
1503
1505 AtomicKind = ParseOpenACCAtomicKind(*this);
1506
1507
1508
1510 tok::annot_pragma_openacc_end);
1511
1512 if (.consumeOpen()) {
1513 switch (DirKind) {
1514 default:
1515 Diag(T.getOpenLocation(), diag::err_acc_invalid_open_paren);
1516 T.skipToEnd();
1517 break;
1519
1520
1521 RoutineName = ParseOpenACCIDExpression();
1522
1523
1524 if (!RoutineName.isUsable()) {
1525 T.skipToEnd();
1526 } else {
1527 T.consumeClose();
1528 RoutineName =
1530 }
1531 break;
1532 }
1534 CacheInfo = ParseOpenACCCacheVarList();
1535
1536
1537 T.consumeClose();
1538 break;
1540
1541 WaitInfo = ParseOpenACCWaitArgument(DirLoc, true);
1542 if (WaitInfo.Failed)
1543 T.skipToEnd();
1544 else
1545 T.consumeClose();
1546 break;
1547 }
1549
1550
1551
1552 Diag(Tok, diag::err_expected) << tok::l_paren;
1553 }
1554
1555
1556 OpenACCDirectiveParseInfo ParseInfo{DirKind,
1557 StartLoc,
1558 DirLoc,
1559 T.getOpenLocation(),
1560 T.getCloseLocation(),
1561 SourceLocation{},
1563 ? WaitInfo.QueuesLoc
1564 : CacheInfo.ReadOnlyLoc),
1565 AtomicKind,
1566 {},
1567 {}};
1568
1570 ParseInfo.Exprs = WaitInfo.getAllExprs();
1572 ParseInfo.Exprs = std::move(CacheInfo.Vars);
1574 ParseInfo.Exprs = llvm::SmallVector<Expr *>(1, RoutineName.get());
1575
1576 ParseInfo.Clauses = ParseOpenACCClauseList(DirKind);
1577
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");
1583
1584 return ParseInfo;
1585}
1586
1589 Decl *TagDecl, OpenACCDirectiveParseInfo &DirInfo) {
1591
1593 if (DirInfo.LParenLoc.isInvalid()) {
1594 if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
1596
1597
1598
1600 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
1601 MaybeParseCXX11Attributes(Attrs);
1602 ParsingDeclSpec PDS(*this);
1603 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
1604 }
1605
1606
1607
1608
1609 } else {
1610 Ptr = ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType,
1611 TagDecl);
1612 }
1613 }
1614 }
1615
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));
1621}
1622
1624Parser::ParseOpenACCAfterRoutineStmt(OpenACCDirectiveParseInfo &DirInfo) {
1626
1627
1628
1630
1631
1632
1633
1634 if (DirInfo.LParenLoc.isInvalid()) {
1636 NextStmt = ParseStatement();
1637 }
1638
1640 DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1641 DirInfo.Exprs.empty() ? nullptr : DirInfo.Exprs.front(),
1642 DirInfo.RParenLoc, DirInfo.Clauses, DirInfo.EndLoc, NextStmt.get());
1643}
1644
1648 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
1649
1651
1652 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1653
1654 if (getActions().OpenACC().ActOnStartDeclDirective(
1655 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses))
1656 return nullptr;
1657
1659 return ParseOpenACCAfterRoutineDecl(AS, Attrs, TagType, TagDecl, DirInfo);
1660
1662 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1663 DirInfo.RParenLoc, DirInfo.EndLoc, DirInfo.Clauses));
1664}
1665
1667 assert(Tok.is(tok::annot_pragma_openacc) && "expected OpenACC Start Token");
1668
1670
1671 OpenACCDirectiveParseInfo DirInfo = ParseOpenACCDirective();
1672 if (getActions().OpenACC().ActOnStartStmtDirective(
1673 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.Clauses))
1675
1677 return ParseOpenACCAfterRoutineStmt(DirInfo);
1678
1680 if (doesDirectiveHaveAssociatedStmt(DirInfo.DirKind)) {
1682 getActions().OpenACC(), DirInfo.DirKind, DirInfo.DirLoc, {},
1683 DirInfo.Clauses);
1685 ParseScope ACCScope(this, getOpenACCScopeFlags(DirInfo.DirKind));
1686
1688 DirInfo.StartLoc, DirInfo.DirKind, DirInfo.AtomicKind, DirInfo.Clauses,
1689 ParseStatement());
1690 }
1691
1693 DirInfo.DirKind, DirInfo.StartLoc, DirInfo.DirLoc, DirInfo.LParenLoc,
1694 DirInfo.MiscLoc, DirInfo.Exprs, DirInfo.AtomicKind, DirInfo.RParenLoc,
1695 DirInfo.EndLoc, DirInfo.Clauses, AssocStmt);
1696}
static Decl::Kind getKind(const Decl *D)
bool Optional
Is optional and can be removed.
bool is(tok::TokenKind Kind) const
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.
Definition ParseOpenACC.cpp:1646
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
ExprResult ParseConstantExpression()
StmtResult ParseOpenACCDirectiveStmt()
Definition ParseOpenACC.cpp:1666
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)
@ None
The alignment was not explicit in code.
ActionResult< Expr * > ExprResult
@ Parens
New-expression has a C++98 paren-delimited initializer.
ActionResult< Stmt * > StmtResult
Diagnostic wrappers for TextAPI types for error reporting.