21 #include "llvm/ADT/PointerIntPair.h"
23 using namespace clang;
43 OMPD_distribute_parallel
46 class ThreadprivateListParserHelper final {
51 ThreadprivateListParserHelper(
Parser *
P) : P(P) {}
54 P->getActions().ActOnOpenMPIdExpression(
P->getCurScope(), SS, NameInfo);
56 Identifiers.push_back(Res.
get());
69 return llvm::StringSwitch<unsigned>(
S)
70 .Case(
"cancellation", OMPD_cancellation)
71 .Case(
"data", OMPD_data)
72 .Case(
"declare", OMPD_declare)
73 .Case(
"end", OMPD_end)
74 .Case(
"enter", OMPD_enter)
75 .Case(
"exit", OMPD_exit)
76 .Case(
"point", OMPD_point)
77 .Case(
"reduction", OMPD_reduction)
78 .Case(
"update", OMPD_update)
86 static const unsigned F[][3] = {
87 { OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
88 { OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
89 { OMPD_declare, OMPD_simd, OMPD_declare_simd },
90 { OMPD_declare, OMPD_target, OMPD_declare_target },
91 { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel },
92 { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for },
93 { OMPD_distribute_parallel_for, OMPD_simd,
94 OMPD_distribute_parallel_for_simd },
95 { OMPD_distribute, OMPD_simd, OMPD_distribute_simd },
96 { OMPD_end, OMPD_declare, OMPD_end_declare },
97 { OMPD_end_declare, OMPD_target, OMPD_end_declare_target },
98 { OMPD_target, OMPD_data, OMPD_target_data },
99 { OMPD_target, OMPD_enter, OMPD_target_enter },
100 { OMPD_target, OMPD_exit, OMPD_target_exit },
101 { OMPD_target, OMPD_update, OMPD_target_update },
102 { OMPD_target_enter, OMPD_data, OMPD_target_enter_data },
103 { OMPD_target_exit, OMPD_data, OMPD_target_exit_data },
104 { OMPD_for, OMPD_simd, OMPD_for_simd },
105 { OMPD_parallel, OMPD_for, OMPD_parallel_for },
106 { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
107 { OMPD_parallel, OMPD_sections, OMPD_parallel_sections },
108 { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd },
109 { OMPD_target, OMPD_parallel, OMPD_target_parallel },
110 { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for },
111 { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd }
113 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
122 for (
unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
123 if (DKind != F[i][0])
134 if (SDKind == F[i][1]) {
139 return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
148 bool WithOperator =
false;
149 if (Tok.
is(tok::kw_operator)) {
179 case tok::identifier:
183 P.
Diag(Tok.
getLocation(), diag::err_omp_expected_reduction_identifier);
184 P.
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
191 : DeclNames.getCXXOperatorName(OOK);
208 if (T.expectAndConsume(diag::err_expected_lparen_after,
215 if (Name.
isEmpty() && Tok.
is(tok::annot_pragma_openmp_end))
219 bool IsCorrect = !ExpectAndConsume(tok::colon);
221 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
224 IsCorrect = IsCorrect && !Name.
isEmpty();
226 if (Tok.
is(tok::colon) || Tok.
is(tok::annot_pragma_openmp_end)) {
231 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
243 if (!ReductionType.isNull()) {
244 ReductionTypes.push_back(
245 std::make_pair(ReductionType, Range.
getBegin()));
248 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
252 if (Tok.
is(tok::colon) || Tok.
is(tok::annot_pragma_openmp_end))
256 if (ExpectAndConsume(tok::comma)) {
258 if (Tok.
is(tok::annot_pragma_openmp_end)) {
263 }
while (Tok.
isNot(tok::annot_pragma_openmp_end));
265 if (ReductionTypes.empty()) {
270 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
274 if (ExpectAndConsume(tok::colon))
277 if (Tok.
is(tok::annot_pragma_openmp_end)) {
287 unsigned I = 0,
E = ReductionTypes.size();
288 for (
auto *D : DRD.get()) {
289 TentativeParsingAction TPA(*
this);
296 D->getLocation(),
true);
300 Tok.
isNot(tok::annot_pragma_openmp_end)) {
305 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.
isUsable();
307 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
309 if (Tok.
is(tok::identifier) &&
320 tok::annot_pragma_openmp_end);
322 !T.expectAndConsume(diag::err_expected_lparen_after,
"initializer") &&
324 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
333 D, InitializerResult.
get());
335 Tok.
isNot(tok::annot_pragma_openmp_end)) {
341 !T.consumeClose() && IsCorrect && !InitializerResult.
isInvalid();
363 class FNContextRAII final {
368 bool HasTemplateScope =
false;
369 bool HasFunScope =
false;
370 FNContextRAII() =
delete;
371 FNContextRAII(
const FNContextRAII &) =
delete;
372 FNContextRAII &operator=(
const FNContextRAII &) =
delete;
378 RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
386 HasTemplateScope = D->isTemplateDecl();
389 if (HasTemplateScope)
390 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
393 HasFunScope = D->isFunctionOrFunctionTemplate();
397 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
404 if (HasTemplateScope)
427 bool IsError =
false;
428 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
429 if (Tok.
isNot(tok::identifier))
431 OMPDeclareSimdDeclAttr::BranchStateTy Out;
433 StringRef ClauseName = II->
getName();
435 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
436 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
437 P.
Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
439 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
445 }
else if (ClauseName.equals(
"simdlen")) {
447 P.
Diag(Tok, diag::err_omp_more_one_clause)
459 CKind == OMPC_linear) {
461 auto *Vars = &Uniforms;
462 if (CKind == OMPC_aligned)
464 else if (CKind == OMPC_linear)
471 if (CKind == OMPC_aligned)
472 Alignments.append(Aligneds.size() - Alignments.size(), Data.
TailExpr);
473 else if (CKind == OMPC_linear) {
476 Data.
LinKind = OMPC_LINEAR_val;
477 LinModifiers.append(Linears.size() - LinModifiers.size(),
479 Steps.append(Linears.size() - Steps.size(), Data.
TailExpr);
486 if (Tok.
is(tok::comma))
497 PP.EnterTokenStream(Toks,
true);
499 ConsumeAnyToken(
true);
501 FNContextRAII FnContext(*
this, Ptr);
502 OMPDeclareSimdDeclAttr::BranchStateTy BS =
503 OMPDeclareSimdDeclAttr::BS_Undefined;
513 Alignments, Linears, LinModifiers, Steps);
515 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
516 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
518 while (Tok.
isNot(tok::annot_pragma_openmp_end))
524 return Actions.ActOnOpenMPDeclareSimdDirective(
525 Ptr, BS, Simdlen.
get(), Uniforms, Aligneds, Alignments, Linears,
549 assert(Tok.
is(tok::annot_pragma_openmp) &&
"Not an OpenMP directive!");
556 case OMPD_threadprivate: {
558 ThreadprivateListParserHelper Helper(
this);
559 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper,
true)) {
562 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
563 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
569 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
570 Helper.getIdentifiers());
574 case OMPD_declare_reduction:
576 if (
auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
579 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
580 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
582 while (Tok.
isNot(tok::annot_pragma_openmp_end))
590 case OMPD_declare_simd: {
597 while(Tok.
isNot(tok::annot_pragma_openmp_end)) {
605 if (Tok.
is(tok::annot_pragma_openmp))
606 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
607 else if (Tok.
isNot(tok::r_brace) && !isEofOrEom()) {
611 MaybeParseCXX11Attributes(Attrs);
612 MaybeParseMicrosoftAttributes(Attrs);
614 Ptr = ParseExternalDeclaration(Attrs, &PDS);
617 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
621 Diag(Loc, diag::err_omp_decl_in_declare_simd);
624 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
626 case OMPD_declare_target: {
628 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
631 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
632 OMPDeclareTargetDeclAttr::MapTypeTy MT =
633 OMPDeclareTargetDeclAttr::MT_To;
634 if (Tok.
is(tok::identifier)) {
636 StringRef ClauseName = II->
getName();
638 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
640 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
646 auto Callback = [
this, MT, &SameDirectiveDecls](
648 Actions.ActOnOpenMPDeclareTargetName(
getCurScope(), SS, NameInfo, MT,
651 if (ParseOpenMPSimpleVarList(OMPD_declare_target,
Callback,
true))
655 if (Tok.
is(tok::comma))
666 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
670 while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
672 ParsedAttributesWithRange attrs(AttrFactory);
673 MaybeParseCXX11Attributes(attrs);
674 MaybeParseMicrosoftAttributes(attrs);
675 ParseExternalDeclaration(attrs);
677 TentativeParsingAction TPA(*
this);
680 if (DKind != OMPD_end_declare_target)
687 if (DKind == OMPD_end_declare_target) {
689 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
690 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
697 Diag(Tok, diag::err_expected_end_declare_target);
698 Diag(DTLoc, diag::note_matching) <<
"'#pragma omp declare target'";
700 Actions.ActOnFinishOpenMPDeclareTargetDirective();
704 Diag(Tok, diag::err_omp_unknown_directive);
722 case OMPD_parallel_for:
723 case OMPD_parallel_for_simd:
724 case OMPD_parallel_sections:
728 case OMPD_cancellation_point:
730 case OMPD_target_data:
731 case OMPD_target_enter_data:
732 case OMPD_target_exit_data:
733 case OMPD_target_parallel:
734 case OMPD_target_parallel_for:
736 case OMPD_taskloop_simd:
737 case OMPD_distribute:
738 case OMPD_end_declare_target:
739 case OMPD_target_update:
740 case OMPD_distribute_parallel_for:
741 case OMPD_distribute_parallel_for_simd:
742 case OMPD_distribute_simd:
743 case OMPD_target_parallel_for_simd:
744 Diag(Tok, diag::err_omp_unexpected_directive)
748 while (Tok.
isNot(tok::annot_pragma_openmp_end))
780 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
781 AllowedContsructsKind Allowed) {
782 assert(Tok.
is(tok::annot_pragma_openmp) &&
"Not an OpenMP directive!");
787 unsigned ScopeFlags =
795 bool HasAssociatedStatement =
true;
796 bool FlushHasClause =
false;
799 case OMPD_threadprivate: {
800 if (Allowed != ACK_Any) {
801 Diag(Tok, diag::err_omp_immediate_directive)
805 ThreadprivateListParserHelper Helper(
this);
806 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper,
false)) {
809 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
810 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
815 Loc, Helper.getIdentifiers());
816 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.
getLocation());
821 case OMPD_declare_reduction:
823 if (
auto Res = ParseOpenMPDeclareReductionDirective(
AS_none)) {
826 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
827 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
829 while (Tok.
isNot(tok::annot_pragma_openmp_end))
833 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.
getLocation());
839 FlushHasClause =
true;
847 case OMPD_cancellation_point:
849 case OMPD_target_enter_data:
850 case OMPD_target_exit_data:
851 case OMPD_target_update:
852 if (Allowed == ACK_StatementsOpenMPNonStandalone) {
853 Diag(Tok, diag::err_omp_immediate_directive)
856 HasAssociatedStatement =
false;
867 case OMPD_parallel_for:
868 case OMPD_parallel_for_simd:
869 case OMPD_parallel_sections:
876 case OMPD_target_data:
877 case OMPD_target_parallel:
878 case OMPD_target_parallel_for:
880 case OMPD_taskloop_simd:
881 case OMPD_distribute:
882 case OMPD_distribute_parallel_for:
883 case OMPD_distribute_parallel_for_simd:
884 case OMPD_distribute_simd:
885 case OMPD_target_parallel_for_simd: {
888 if (DKind == OMPD_critical) {
890 tok::annot_pragma_openmp_end);
891 if (!T.consumeOpen()) {
897 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
901 }
else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
903 if (Tok.
isNot(tok::annot_pragma_openmp_end))
911 ParseScope OMPDirectiveScope(
this, ScopeFlags);
912 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
914 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
918 : FlushHasClause ? OMPC_flush
920 Actions.StartOpenMPClause(CKind);
921 FlushHasClause =
false;
923 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
924 FirstClauses[CKind].setInt(
true);
926 FirstClauses[CKind].setPointer(Clause);
927 Clauses.push_back(Clause);
931 if (Tok.
is(tok::comma))
933 Actions.EndOpenMPClause();
943 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
944 if (Allowed == ACK_StatementsOpenMPNonStandalone) {
945 Diag(Loc, diag::err_omp_immediate_directive)
949 HasAssociatedStatement =
false;
953 if (HasAssociatedStatement) {
956 Actions.ActOnOpenMPRegionStart(DKind,
getCurScope());
957 Actions.ActOnStartOfCompoundStmt();
959 AssociatedStmt = ParseStatement();
960 Actions.ActOnFinishOfCompoundStmt();
961 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
963 Directive = Actions.ActOnOpenMPExecutableDirective(
964 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
968 Actions.EndOpenMPDSABlock(Directive.get());
969 OMPDirectiveScope.Exit();
972 case OMPD_declare_simd:
973 case OMPD_declare_target:
974 case OMPD_end_declare_target:
975 Diag(Tok, diag::err_omp_unexpected_directive)
980 Diag(Tok, diag::err_omp_unknown_directive);
991 bool Parser::ParseOpenMPSimpleVarList(
995 bool AllowScopeSpecifier) {
998 if (T.expectAndConsume(diag::err_expected_lparen_after,
1001 bool IsCorrect =
true;
1002 bool NoIdentIsFound =
true;
1005 while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end)) {
1010 Token PrevTok = Tok;
1011 NoIdentIsFound =
false;
1013 if (AllowScopeSpecifier &&
getLangOpts().CPlusPlus &&
1014 ParseOptionalCXXScopeSpecifier(SS,
nullptr,
false)) {
1016 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1019 TemplateKWLoc, Name)) {
1021 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1023 }
else if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren) &&
1024 Tok.
isNot(tok::annot_pragma_openmp_end)) {
1026 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1032 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1035 if (Tok.
is(tok::comma)) {
1040 if (NoIdentIsFound) {
1041 Diag(Tok, diag::err_expected) << tok::identifier;
1046 IsCorrect = !T.consumeClose() && IsCorrect;
1069 bool ErrorFound =
false;
1079 case OMPC_num_threads:
1085 case OMPC_num_teams:
1086 case OMPC_thread_limit:
1088 case OMPC_grainsize:
1089 case OMPC_num_tasks:
1112 Diag(Tok, diag::err_omp_more_one_clause)
1117 if (CKind == OMPC_ordered && PP.
LookAhead(0).
isNot(tok::l_paren))
1118 Clause = ParseOpenMPClause(CKind);
1120 Clause = ParseOpenMPSingleExprClause(CKind);
1123 case OMPC_proc_bind:
1130 Diag(Tok, diag::err_omp_more_one_clause)
1135 Clause = ParseOpenMPSimpleClause(CKind);
1138 case OMPC_dist_schedule:
1139 case OMPC_defaultmap:
1145 Diag(Tok, diag::err_omp_more_one_clause)
1151 Clause = ParseOpenMPSingleExprWithArgClause(CKind);
1155 case OMPC_mergeable:
1169 Diag(Tok, diag::err_omp_more_one_clause)
1174 Clause = ParseOpenMPClause(CKind);
1177 case OMPC_firstprivate:
1178 case OMPC_lastprivate:
1180 case OMPC_reduction:
1184 case OMPC_copyprivate:
1190 case OMPC_use_device_ptr:
1191 case OMPC_is_device_ptr:
1192 Clause = ParseOpenMPVarListClause(DKind, CKind);
1195 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1206 return ErrorFound ?
nullptr : Clause;
1215 if (T.
expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1222 Val = Actions.ActOnFinishFullExpr(Val.
get(), ELoc);
1272 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.
get(), Loc, LLoc, RLoc);
1288 if (T.expectAndConsume(diag::err_expected_lparen_after,
1295 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1296 Tok.
isNot(tok::annot_pragma_openmp_end))
1302 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
1336 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.
getLocation());
1358 if (T.expectAndConsume(diag::err_expected_lparen_after,
1365 if (Kind == OMPC_schedule) {
1366 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1367 Arg.resize(NumberOfElements);
1368 KLoc.resize(NumberOfElements);
1376 Arg[Modifier1] = KindModifier;
1378 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1379 Tok.
isNot(tok::annot_pragma_openmp_end))
1381 if (Tok.
is(tok::comma)) {
1390 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1391 Tok.
isNot(tok::annot_pragma_openmp_end))
1395 if (Tok.
is(tok::colon))
1398 Diag(Tok, diag::warn_pragma_expected_colon) <<
"schedule modifier";
1402 Arg[ScheduleKind] = KindModifier;
1404 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1405 Tok.
isNot(tok::annot_pragma_openmp_end))
1407 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1408 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1409 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1411 DelimLoc = ConsumeAnyToken();
1412 }
else if (Kind == OMPC_dist_schedule) {
1416 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1417 Tok.
isNot(tok::annot_pragma_openmp_end))
1419 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.
is(tok::comma))
1420 DelimLoc = ConsumeAnyToken();
1421 }
else if (Kind == OMPC_defaultmap) {
1426 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1427 Tok.
isNot(tok::annot_pragma_openmp_end))
1430 if (Tok.
is(tok::colon))
1433 Diag(Tok, diag::warn_pragma_expected_colon) <<
"defaultmap modifier";
1438 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1439 Tok.
isNot(tok::annot_pragma_openmp_end))
1442 assert(Kind == OMPC_if);
1447 if (Tok.
is(tok::colon))
1450 Diag(Tok, diag::warn_pragma_expected_colon)
1451 <<
"directive name modifier";
1455 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.
isValid()) ||
1456 (Kind == OMPC_dist_schedule && DelimLoc.
isValid()) ||
1458 if (NeedAnExpression) {
1462 Val = Actions.ActOnFinishFullExpr(Val.
get(), ELoc);
1468 if (NeedAnExpression && Val.
isInvalid())
1471 return Actions.ActOnOpenMPSingleExprWithArgClause(
1472 Kind, Arg, Val.
get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
1473 T.getCloseLocation());
1479 if (ReductionIdScopeSpec.
isEmpty()) {
1519 TemplateKWLoc, ReductionId);
1528 bool InvalidReductionId =
false;
1529 bool MapTypeModifierSpecified =
false;
1537 bool NeedRParenForLinear =
false;
1539 tok::annot_pragma_openmp_end);
1541 if (Kind == OMPC_reduction) {
1548 UnqualifiedReductionId);
1549 if (InvalidReductionId) {
1550 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1553 if (Tok.
is(tok::colon))
1556 Diag(Tok, diag::warn_pragma_expected_colon) <<
"reduction identifier";
1557 if (!InvalidReductionId)
1559 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
1560 }
else if (Kind == OMPC_depend) {
1569 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1574 if (DKind == OMPD_ordered && Data.
DepKind == OMPC_DEPEND_source) {
1580 if (Tok.
is(tok::colon))
1583 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
1584 : diag::warn_pragma_expected_colon)
1585 <<
"dependency type";
1587 }
else if (Kind == OMPC_linear) {
1589 if (Tok.
is(tok::identifier) && PP.
LookAhead(0).
is(tok::l_paren)) {
1594 NeedRParenForLinear =
true;
1596 }
else if (Kind == OMPC_map) {
1602 auto &&IsMapClauseModifierToken = [](
const Token &Tok) ->
bool {
1603 return Tok.
isOneOf(tok::identifier, tok::kw_delete);
1610 IsMapClauseModifierToken(Tok)
1615 bool ColonExpected =
false;
1617 if (IsMapClauseModifierToken(Tok)) {
1620 Diag(Tok, diag::err_omp_unknown_map_type);
1621 else if (Data.
MapType == OMPC_MAP_always)
1622 Diag(Tok, diag::err_omp_map_type_missing);
1625 if (IsMapClauseModifierToken(PP.
LookAhead(1)) &&
1629 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1632 MapTypeModifierSpecified =
true;
1638 IsMapClauseModifierToken(Tok)
1643 Data.
MapType == OMPC_MAP_always)
1644 Diag(Tok, diag::err_omp_unknown_map_type);
1647 Data.
MapType = OMPC_MAP_tofrom;
1651 Data.
MapType = OMPC_MAP_tofrom;
1655 Data.
MapType = OMPC_MAP_tofrom;
1659 if (Tok.
is(tok::colon))
1661 else if (ColonExpected)
1662 Diag(Tok, diag::warn_pragma_expected_colon) <<
"map type";
1666 (Kind != OMPC_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
1667 (Kind == OMPC_reduction && !InvalidReductionId) ||
1669 (!MapTypeModifierSpecified ||
1672 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
1673 while (IsComma || (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::colon) &&
1674 Tok.
isNot(tok::annot_pragma_openmp_end))) {
1680 Vars.push_back(VarExpr.
get());
1682 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1686 IsComma = Tok.
is(tok::comma);
1689 else if (Tok.
isNot(tok::r_paren) &&
1690 Tok.
isNot(tok::annot_pragma_openmp_end) &&
1691 (!MayHaveTail || Tok.
isNot(tok::colon)))
1692 Diag(Tok, diag::err_omp_expected_punc)
1695 << (Kind == OMPC_flush);
1699 if (NeedRParenForLinear)
1703 const bool MustHaveTail = MayHaveTail && Tok.
is(tok::colon);
1708 Tail = Actions.ActOnFinishFullExpr(Tail.
get(), ELoc);
1712 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1720 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
1721 (MustHaveTail && !Data.
TailExpr) || InvalidReductionId)
1770 OpenMPVarListDataTy Data;
1775 return Actions.ActOnOpenMPVarListClause(
1776 Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.
getLocation(),
1777 Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
1778 Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit,
OpenMPDependClauseKind DepKind
SourceLocation getCloseLocation() const
Defines the clang::ASTContext interface.
ParseScope - Introduces a new scope for parsing.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
DeclarationNameInfo ReductionId
DeclContext * getCurLexicalContext() const
const Token & getCurToken() const
const LangOptions & getLangOpts() const
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
The base class of the type hierarchy.
This indicates that the scope corresponds to a function, which means that labels are set here...
bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind)
static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P)
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
void ActOnExitFunctionContext()
Wrapper for void* pointer.
Parser - This implements a parser for the C family of languages.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
SourceLocation DepLinMapLoc
void EnterToken(const Token &Tok)
Enters a token in the token stream to be lexed next.
TypeSpecifierType
Specifies the kind of type.
bool isAnyIdentifier() const
Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing...
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed...
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
bool isEmpty() const
No scope specifier.
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 ...
OpenMPLinearClauseKind LinKind
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation >> ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
Base wrapper for a particular "section" of type source info.
RecordDecl - Represents a struct/union/class.
const char * getOpenMPClauseName(OpenMPClauseKind Kind)
One of these records is kept for each identifier that is lexed.
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Token - This structure provides full information about a lexed token.
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ...
VerifyDiagnosticConsumer::Directive Directive
Represents a C++ unqualified-id that has been parsed.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer)
Finish current declare reduction construct initializer.
void ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
static bool parseDeclareSimdClauses(Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, SmallVectorImpl< Expr * > &Uniforms, SmallVectorImpl< Expr * > &Aligneds, SmallVectorImpl< Expr * > &Alignments, SmallVectorImpl< Expr * > &Linears, SmallVectorImpl< unsigned > &LinModifiers, SmallVectorImpl< Expr * > &Steps)
Parses clauses for 'declare simd' directive.
OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str)
Represents a C++ nested-name-specifier or a global scope specifier.
tok::TokenKind getKind() const
detail::InMemoryDirectory::const_iterator I
Sema - This implements semantic analysis and AST building for C.
A RAII object to enter scope of a compound statement.
DeclarationNameTable DeclarationNames
TypeResult ParseTypeName(SourceRange *Range=nullptr, Declarator::TheContext Context=Declarator::TypeNameContext, AccessSpecifier AS=AS_none, Decl **OwnedType=nullptr, ParsedAttributes *Attrs=nullptr)
ParseTypeName type-name: [C99 6.7.6] specifier-qualifier-list abstract-declarator[opt].
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
OpenMPMapClauseKind MapTypeModifier
StringRef getName() const
Return the actual identifier string.
bool isEmpty() const
Evaluates true when this declaration name is empty.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
MatchFinder::MatchCallback * Callback
This is the scope of OpenMP executable directive.
CXXScopeSpec ReductionIdScopeSpec
OpenMPClauseKind
OpenMP clauses.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
bool isNot(tok::TokenKind K) const
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
ExprResult ActOnFinishFullExpr(Expr *Expr)
A class for parsing a DeclSpec.
Encodes a location in the source.
OpenMPDependClauseKind
OpenMP attributes for 'depend' clause.
SourceLocation getEndLoc() const
bool isValid() const
Return true if this is a valid SourceLocation object.
ASTContext & getASTContext() const
static unsigned getOpenMPDirectiveKindEx(StringRef S)
OpenMPDirectiveKind
OpenMP directives.
Scope * getCurScope() const
This is a basic class for representing single OpenMP clause.
Preprocessor & getPreprocessor() const
SourceLocation getBegin() const
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)) {...
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, ParsedType ObjectType, SourceLocation &TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
Sema & getActions() const
bool expectAndConsume(unsigned DiagID=diag::err_expected, const char *Msg="", tok::TokenKind SkipToTok=tok::unknown)
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
This is the scope of some OpenMP simd directive.
This is a scope that corresponds to the template parameters of a C++ template.
DeclarationName - The name of a declaration.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
Data used for parsing list of variables in OpenMP clauses.
detail::InMemoryDirectory::const_iterator E
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
static const TST TST_unspecified
Not an overloaded operator.
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str)
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
This file defines OpenMP AST classes for executable directives and clauses.
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
ActionResult< Stmt * > StmtResult
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)
Parse an expr that doesn't include (top-level) commas.
OpenMPDirectiveKind getOpenMPDirectiveKind(llvm::StringRef Str)
const char * getOpenMPDirectiveName(OpenMPDirectiveKind Kind)
This is a scope that can contain a declaration.
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
static DeclarationName parseOpenMPReductionId(Parser &P)
This is the scope of some OpenMP loop directive.
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, OpenMPVarListDataTy &Data)
Parses clauses with list.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
A trivial tuple used to represent a source range.
NamedDecl - This represents a decl with a name.
Directive - Abstract class representing a parsed verify directive.
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
OpenMPMapClauseKind MapType
Stop skipping at specified token, but don't skip the token itself.
IdentifierInfo * getIdentifierInfo() const