20 #include "llvm/ADT/PointerIntPair.h"
22 using namespace clang;
42 OMPD_distribute_parallel,
43 OMPD_teams_distribute_parallel,
44 OMPD_target_teams_distribute_parallel
47 class ThreadprivateListParserHelper final {
52 ThreadprivateListParserHelper(
Parser *
P) : P(P) {}
55 P->getActions().ActOnOpenMPIdExpression(
P->getCurScope(), SS, NameInfo);
57 Identifiers.push_back(Res.
get());
70 return llvm::StringSwitch<unsigned>(
S)
71 .Case(
"cancellation", OMPD_cancellation)
72 .Case(
"data", OMPD_data)
73 .Case(
"declare", OMPD_declare)
74 .Case(
"end", OMPD_end)
75 .Case(
"enter", OMPD_enter)
76 .Case(
"exit", OMPD_exit)
77 .Case(
"point", OMPD_point)
78 .Case(
"reduction", OMPD_reduction)
79 .Case(
"update", OMPD_update)
87 static const unsigned F[][3] = {
88 { OMPD_cancellation, OMPD_point, OMPD_cancellation_point },
89 { OMPD_declare, OMPD_reduction, OMPD_declare_reduction },
90 { OMPD_declare, OMPD_simd, OMPD_declare_simd },
91 { OMPD_declare, OMPD_target, OMPD_declare_target },
92 { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel },
93 { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for },
94 { OMPD_distribute_parallel_for, OMPD_simd,
95 OMPD_distribute_parallel_for_simd },
96 { OMPD_distribute, OMPD_simd, OMPD_distribute_simd },
97 { OMPD_end, OMPD_declare, OMPD_end_declare },
98 { OMPD_end_declare, OMPD_target, OMPD_end_declare_target },
99 { OMPD_target, OMPD_data, OMPD_target_data },
100 { OMPD_target, OMPD_enter, OMPD_target_enter },
101 { OMPD_target, OMPD_exit, OMPD_target_exit },
102 { OMPD_target, OMPD_update, OMPD_target_update },
103 { OMPD_target_enter, OMPD_data, OMPD_target_enter_data },
104 { OMPD_target_exit, OMPD_data, OMPD_target_exit_data },
105 { OMPD_for, OMPD_simd, OMPD_for_simd },
106 { OMPD_parallel, OMPD_for, OMPD_parallel_for },
107 { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd },
108 { OMPD_parallel, OMPD_sections, OMPD_parallel_sections },
109 { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd },
110 { OMPD_target, OMPD_parallel, OMPD_target_parallel },
111 { OMPD_target, OMPD_simd, OMPD_target_simd },
112 { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for },
113 { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd },
114 { OMPD_teams, OMPD_distribute, OMPD_teams_distribute },
115 { OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd },
116 { OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel },
117 { OMPD_teams_distribute_parallel, OMPD_for, OMPD_teams_distribute_parallel_for },
118 { OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd },
119 { OMPD_target, OMPD_teams, OMPD_target_teams },
120 { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute },
121 { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel },
122 { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd },
123 { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for },
124 { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd }
126 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
135 for (
unsigned i = 0; i < llvm::array_lengthof(F); ++i) {
136 if (DKind != F[i][0])
147 if (SDKind == F[i][1]) {
152 return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
161 bool WithOperator =
false;
162 if (Tok.
is(tok::kw_operator)) {
192 case tok::identifier:
197 P.
Diag(Tok.
getLocation(), diag::err_omp_expected_reduction_identifier);
198 P.
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
205 : DeclNames.getCXXOperatorName(OOK);
222 if (T.expectAndConsume(diag::err_expected_lparen_after,
229 if (Name.
isEmpty() && Tok.
is(tok::annot_pragma_openmp_end))
233 bool IsCorrect = !ExpectAndConsume(tok::colon);
235 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
238 IsCorrect = IsCorrect && !Name.
isEmpty();
240 if (Tok.
is(tok::colon) || Tok.
is(tok::annot_pragma_openmp_end)) {
245 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
257 if (!ReductionType.isNull()) {
258 ReductionTypes.push_back(
259 std::make_pair(ReductionType, Range.
getBegin()));
262 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
266 if (Tok.
is(tok::colon) || Tok.
is(tok::annot_pragma_openmp_end))
270 if (ExpectAndConsume(tok::comma)) {
272 if (Tok.
is(tok::annot_pragma_openmp_end)) {
277 }
while (Tok.
isNot(tok::annot_pragma_openmp_end));
279 if (ReductionTypes.empty()) {
284 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
288 if (ExpectAndConsume(tok::colon))
291 if (Tok.
is(tok::annot_pragma_openmp_end)) {
301 unsigned I = 0,
E = ReductionTypes.size();
302 for (
auto *D : DRD.get()) {
303 TentativeParsingAction TPA(*
this);
310 D->getLocation(),
true);
314 Tok.
isNot(tok::annot_pragma_openmp_end)) {
319 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.
isUsable();
321 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
323 if (Tok.
is(tok::identifier) &&
334 tok::annot_pragma_openmp_end);
336 !T.expectAndConsume(diag::err_expected_lparen_after,
"initializer") &&
338 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
347 D, InitializerResult.
get());
349 Tok.
isNot(tok::annot_pragma_openmp_end)) {
355 !T.consumeClose() && IsCorrect && !InitializerResult.
isInvalid();
377 class FNContextRAII final {
382 bool HasTemplateScope =
false;
383 bool HasFunScope =
false;
384 FNContextRAII() =
delete;
385 FNContextRAII(
const FNContextRAII &) =
delete;
386 FNContextRAII &operator=(
const FNContextRAII &) =
delete;
403 if (HasTemplateScope)
404 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
411 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
418 if (HasTemplateScope)
441 bool IsError =
false;
442 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
443 if (Tok.
isNot(tok::identifier))
445 OMPDeclareSimdDeclAttr::BranchStateTy Out;
447 StringRef ClauseName = II->
getName();
449 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
450 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
451 P.
Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
453 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
459 }
else if (ClauseName.equals(
"simdlen")) {
461 P.
Diag(Tok, diag::err_omp_more_one_clause)
473 CKind == OMPC_linear) {
475 auto *Vars = &Uniforms;
476 if (CKind == OMPC_aligned)
478 else if (CKind == OMPC_linear)
485 if (CKind == OMPC_aligned)
486 Alignments.append(Aligneds.size() - Alignments.size(), Data.
TailExpr);
487 else if (CKind == OMPC_linear) {
490 Data.
LinKind = OMPC_LINEAR_val;
491 LinModifiers.append(Linears.size() - LinModifiers.size(),
493 Steps.append(Linears.size() - Steps.size(), Data.
TailExpr);
500 if (Tok.
is(tok::comma))
511 PP.EnterTokenStream(Toks,
true);
513 ConsumeAnyToken(
true);
515 FNContextRAII FnContext(*
this, Ptr);
516 OMPDeclareSimdDeclAttr::BranchStateTy BS =
517 OMPDeclareSimdDeclAttr::BS_Undefined;
527 Alignments, Linears, LinModifiers, Steps);
529 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
530 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
532 while (Tok.
isNot(tok::annot_pragma_openmp_end))
538 return Actions.ActOnOpenMPDeclareSimdDirective(
539 Ptr, BS, Simdlen.
get(), Uniforms, Aligneds, Alignments, Linears,
563 assert(Tok.
is(tok::annot_pragma_openmp) &&
"Not an OpenMP directive!");
570 case OMPD_threadprivate: {
572 ThreadprivateListParserHelper Helper(
this);
573 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper,
true)) {
576 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
577 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
582 ConsumeAnnotationToken();
583 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
584 Helper.getIdentifiers());
588 case OMPD_declare_reduction:
590 if (
auto Res = ParseOpenMPDeclareReductionDirective(AS)) {
593 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
594 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
596 while (Tok.
isNot(tok::annot_pragma_openmp_end))
600 ConsumeAnnotationToken();
604 case OMPD_declare_simd: {
611 while(Tok.
isNot(tok::annot_pragma_openmp_end)) {
619 if (Tok.
is(tok::annot_pragma_openmp))
620 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
621 else if (Tok.
isNot(tok::r_brace) && !isEofOrEom()) {
625 MaybeParseCXX11Attributes(Attrs);
627 Ptr = ParseExternalDeclaration(Attrs, &PDS);
630 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
634 Diag(Loc, diag::err_omp_decl_in_declare_simd);
637 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
639 case OMPD_declare_target: {
641 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
644 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
645 OMPDeclareTargetDeclAttr::MapTypeTy MT =
646 OMPDeclareTargetDeclAttr::MT_To;
647 if (Tok.
is(tok::identifier)) {
649 StringRef ClauseName = II->
getName();
651 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName,
653 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
659 auto Callback = [
this, MT, &SameDirectiveDecls](
661 Actions.ActOnOpenMPDeclareTargetName(
getCurScope(), SS, NameInfo, MT,
664 if (ParseOpenMPSimpleVarList(OMPD_declare_target,
Callback,
true))
668 if (Tok.
is(tok::comma))
679 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
683 while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target &&
685 ParsedAttributesWithRange attrs(AttrFactory);
686 MaybeParseCXX11Attributes(attrs);
687 ParseExternalDeclaration(attrs);
689 TentativeParsingAction TPA(*
this);
690 ConsumeAnnotationToken();
692 if (DKind != OMPD_end_declare_target)
699 if (DKind == OMPD_end_declare_target) {
701 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
702 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
709 Diag(Tok, diag::err_expected_end_declare_target);
710 Diag(DTLoc, diag::note_matching) <<
"'#pragma omp declare target'";
712 Actions.ActOnFinishOpenMPDeclareTargetDirective();
716 Diag(Tok, diag::err_omp_unknown_directive);
734 case OMPD_parallel_for:
735 case OMPD_parallel_for_simd:
736 case OMPD_parallel_sections:
740 case OMPD_cancellation_point:
742 case OMPD_target_data:
743 case OMPD_target_enter_data:
744 case OMPD_target_exit_data:
745 case OMPD_target_parallel:
746 case OMPD_target_parallel_for:
748 case OMPD_taskloop_simd:
749 case OMPD_distribute:
750 case OMPD_end_declare_target:
751 case OMPD_target_update:
752 case OMPD_distribute_parallel_for:
753 case OMPD_distribute_parallel_for_simd:
754 case OMPD_distribute_simd:
755 case OMPD_target_parallel_for_simd:
756 case OMPD_target_simd:
757 case OMPD_teams_distribute:
758 case OMPD_teams_distribute_simd:
759 case OMPD_teams_distribute_parallel_for_simd:
760 case OMPD_teams_distribute_parallel_for:
761 case OMPD_target_teams:
762 case OMPD_target_teams_distribute:
763 case OMPD_target_teams_distribute_parallel_for:
764 case OMPD_target_teams_distribute_parallel_for_simd:
765 case OMPD_target_teams_distribute_simd:
766 Diag(Tok, diag::err_omp_unexpected_directive)
770 while (Tok.
isNot(tok::annot_pragma_openmp_end))
809 StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
810 AllowedConstructsKind Allowed) {
811 assert(Tok.
is(tok::annot_pragma_openmp) &&
"Not an OpenMP directive!");
816 unsigned ScopeFlags =
824 bool HasAssociatedStatement =
true;
825 bool FlushHasClause =
false;
828 case OMPD_threadprivate: {
829 if (Allowed != ACK_Any) {
830 Diag(Tok, diag::err_omp_immediate_directive)
834 ThreadprivateListParserHelper Helper(
this);
835 if (!ParseOpenMPSimpleVarList(OMPD_threadprivate, Helper,
false)) {
838 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
839 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
844 Loc, Helper.getIdentifiers());
845 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.
getLocation());
850 case OMPD_declare_reduction:
852 if (
auto Res = ParseOpenMPDeclareReductionDirective(
AS_none)) {
855 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
856 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
858 while (Tok.
isNot(tok::annot_pragma_openmp_end))
862 Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.
getLocation());
868 FlushHasClause =
true;
877 case OMPD_cancellation_point:
879 case OMPD_target_enter_data:
880 case OMPD_target_exit_data:
881 case OMPD_target_update:
882 if (Allowed == ACK_StatementsOpenMPNonStandalone) {
883 Diag(Tok, diag::err_omp_immediate_directive)
886 HasAssociatedStatement =
false;
898 case OMPD_parallel_for:
899 case OMPD_parallel_for_simd:
900 case OMPD_parallel_sections:
907 case OMPD_target_data:
908 case OMPD_target_parallel:
909 case OMPD_target_parallel_for:
911 case OMPD_taskloop_simd:
912 case OMPD_distribute:
913 case OMPD_distribute_parallel_for:
914 case OMPD_distribute_parallel_for_simd:
915 case OMPD_distribute_simd:
916 case OMPD_target_parallel_for_simd:
917 case OMPD_target_simd:
918 case OMPD_teams_distribute:
919 case OMPD_teams_distribute_simd:
920 case OMPD_teams_distribute_parallel_for_simd:
921 case OMPD_teams_distribute_parallel_for:
922 case OMPD_target_teams:
923 case OMPD_target_teams_distribute:
924 case OMPD_target_teams_distribute_parallel_for:
925 case OMPD_target_teams_distribute_parallel_for_simd:
926 case OMPD_target_teams_distribute_simd: {
929 if (DKind == OMPD_critical) {
931 tok::annot_pragma_openmp_end);
932 if (!T.consumeOpen()) {
938 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
942 }
else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
944 if (Tok.
isNot(tok::annot_pragma_openmp_end))
952 ParseScope OMPDirectiveScope(
this, ScopeFlags);
953 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
955 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
959 : FlushHasClause ? OMPC_flush
961 Actions.StartOpenMPClause(CKind);
962 FlushHasClause =
false;
964 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
965 FirstClauses[CKind].setInt(
true);
967 FirstClauses[CKind].setPointer(Clause);
968 Clauses.push_back(Clause);
972 if (Tok.
is(tok::comma))
974 Actions.EndOpenMPClause();
979 ConsumeAnnotationToken();
984 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
985 if (Allowed == ACK_StatementsOpenMPNonStandalone) {
986 Diag(Loc, diag::err_omp_immediate_directive)
990 HasAssociatedStatement =
false;
994 if (HasAssociatedStatement) {
997 Actions.ActOnOpenMPRegionStart(DKind,
getCurScope());
998 Actions.ActOnStartOfCompoundStmt();
1000 AssociatedStmt = ParseStatement();
1001 Actions.ActOnFinishOfCompoundStmt();
1002 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1004 Directive = Actions.ActOnOpenMPExecutableDirective(
1005 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1009 Actions.EndOpenMPDSABlock(Directive.get());
1010 OMPDirectiveScope.Exit();
1013 case OMPD_declare_simd:
1014 case OMPD_declare_target:
1015 case OMPD_end_declare_target:
1016 Diag(Tok, diag::err_omp_unexpected_directive)
1018 SkipUntil(tok::annot_pragma_openmp_end);
1021 Diag(Tok, diag::err_omp_unknown_directive);
1022 SkipUntil(tok::annot_pragma_openmp_end);
1032 bool Parser::ParseOpenMPSimpleVarList(
1036 bool AllowScopeSpecifier) {
1039 if (T.expectAndConsume(diag::err_expected_lparen_after,
1042 bool IsCorrect =
true;
1043 bool NoIdentIsFound =
true;
1046 while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end)) {
1051 Token PrevTok = Tok;
1052 NoIdentIsFound =
false;
1054 if (AllowScopeSpecifier &&
getLangOpts().CPlusPlus &&
1055 ParseOptionalCXXScopeSpecifier(SS,
nullptr,
false)) {
1057 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1060 TemplateKWLoc, Name)) {
1062 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1064 }
else if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren) &&
1065 Tok.
isNot(tok::annot_pragma_openmp_end)) {
1067 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1073 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
1076 if (Tok.
is(tok::comma)) {
1081 if (NoIdentIsFound) {
1082 Diag(Tok, diag::err_expected) << tok::identifier;
1087 IsCorrect = !T.consumeClose() && IsCorrect;
1110 bool ErrorFound =
false;
1120 case OMPC_num_threads:
1126 case OMPC_num_teams:
1127 case OMPC_thread_limit:
1129 case OMPC_grainsize:
1130 case OMPC_num_tasks:
1153 Diag(Tok, diag::err_omp_more_one_clause)
1158 if (CKind == OMPC_ordered && PP.
LookAhead(0).
isNot(tok::l_paren))
1159 Clause = ParseOpenMPClause(CKind);
1161 Clause = ParseOpenMPSingleExprClause(CKind);
1164 case OMPC_proc_bind:
1171 Diag(Tok, diag::err_omp_more_one_clause)
1176 Clause = ParseOpenMPSimpleClause(CKind);
1179 case OMPC_dist_schedule:
1180 case OMPC_defaultmap:
1186 Diag(Tok, diag::err_omp_more_one_clause)
1193 Clause = ParseOpenMPSingleExprWithArgClause(CKind);
1197 case OMPC_mergeable:
1211 Diag(Tok, diag::err_omp_more_one_clause)
1216 Clause = ParseOpenMPClause(CKind);
1219 case OMPC_firstprivate:
1220 case OMPC_lastprivate:
1222 case OMPC_reduction:
1223 case OMPC_task_reduction:
1227 case OMPC_copyprivate:
1233 case OMPC_use_device_ptr:
1234 case OMPC_is_device_ptr:
1235 Clause = ParseOpenMPVarListClause(DKind, CKind);
1238 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1249 return ErrorFound ?
nullptr : Clause;
1258 if (T.
expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
1265 Val = Actions.ActOnFinishFullExpr(Val.
get(), ELoc);
1315 return Actions.ActOnOpenMPSingleExprClause(Kind, Val.
get(), Loc, LLoc, RLoc);
1331 if (T.expectAndConsume(diag::err_expected_lparen_after,
1338 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1339 Tok.
isNot(tok::annot_pragma_openmp_end))
1345 return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc,
1379 return Actions.ActOnOpenMPClause(Kind, Loc, Tok.
getLocation());
1401 if (T.expectAndConsume(diag::err_expected_lparen_after,
1408 if (Kind == OMPC_schedule) {
1409 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
1410 Arg.resize(NumberOfElements);
1411 KLoc.resize(NumberOfElements);
1419 Arg[Modifier1] = KindModifier;
1421 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1422 Tok.
isNot(tok::annot_pragma_openmp_end))
1424 if (Tok.
is(tok::comma)) {
1433 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1434 Tok.
isNot(tok::annot_pragma_openmp_end))
1438 if (Tok.
is(tok::colon))
1441 Diag(Tok, diag::warn_pragma_expected_colon) <<
"schedule modifier";
1445 Arg[ScheduleKind] = KindModifier;
1447 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1448 Tok.
isNot(tok::annot_pragma_openmp_end))
1450 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
1451 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
1452 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
1454 DelimLoc = ConsumeAnyToken();
1455 }
else if (Kind == OMPC_dist_schedule) {
1459 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1460 Tok.
isNot(tok::annot_pragma_openmp_end))
1462 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.
is(tok::comma))
1463 DelimLoc = ConsumeAnyToken();
1464 }
else if (Kind == OMPC_defaultmap) {
1469 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1470 Tok.
isNot(tok::annot_pragma_openmp_end))
1473 if (Tok.
is(tok::colon))
1476 Diag(Tok, diag::warn_pragma_expected_colon) <<
"defaultmap modifier";
1481 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1482 Tok.
isNot(tok::annot_pragma_openmp_end))
1485 assert(Kind == OMPC_if);
1487 TentativeParsingAction TPA(*
this);
1502 bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.
isValid()) ||
1503 (Kind == OMPC_dist_schedule && DelimLoc.
isValid()) ||
1505 if (NeedAnExpression) {
1509 Val = Actions.ActOnFinishFullExpr(Val.
get(), ELoc);
1515 if (NeedAnExpression && Val.
isInvalid())
1518 return Actions.ActOnOpenMPSingleExprWithArgClause(
1519 Kind, Arg, Val.
get(), Loc, T.getOpenLocation(), KLoc, DelimLoc,
1520 T.getCloseLocation());
1526 if (ReductionIdScopeSpec.
isEmpty()) {
1567 nullptr, TemplateKWLoc, ReductionId);
1576 bool InvalidReductionId =
false;
1577 bool MapTypeModifierSpecified =
false;
1585 bool NeedRParenForLinear =
false;
1587 tok::annot_pragma_openmp_end);
1589 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction) {
1596 UnqualifiedReductionId);
1597 if (InvalidReductionId) {
1598 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1601 if (Tok.
is(tok::colon))
1604 Diag(Tok, diag::warn_pragma_expected_colon) <<
"reduction identifier";
1605 if (!InvalidReductionId)
1607 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
1608 }
else if (Kind == OMPC_depend) {
1617 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
1622 if (DKind == OMPD_ordered && Data.
DepKind == OMPC_DEPEND_source) {
1628 if (Tok.
is(tok::colon))
1631 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
1632 : diag::warn_pragma_expected_colon)
1633 <<
"dependency type";
1635 }
else if (Kind == OMPC_linear) {
1637 if (Tok.
is(tok::identifier) && PP.
LookAhead(0).
is(tok::l_paren)) {
1642 NeedRParenForLinear =
true;
1644 }
else if (Kind == OMPC_map) {
1650 auto &&IsMapClauseModifierToken = [](
const Token &Tok) ->
bool {
1651 return Tok.
isOneOf(tok::identifier, tok::kw_delete);
1658 IsMapClauseModifierToken(Tok)
1663 bool ColonExpected =
false;
1665 if (IsMapClauseModifierToken(Tok)) {
1668 Diag(Tok, diag::err_omp_unknown_map_type);
1669 else if (Data.
MapType == OMPC_MAP_always)
1670 Diag(Tok, diag::err_omp_map_type_missing);
1673 if (IsMapClauseModifierToken(PP.
LookAhead(1)) &&
1677 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1680 MapTypeModifierSpecified =
true;
1686 IsMapClauseModifierToken(Tok)
1691 Data.
MapType == OMPC_MAP_always)
1692 Diag(Tok, diag::err_omp_unknown_map_type);
1695 Data.
MapType = OMPC_MAP_tofrom;
1698 }
else if (IsMapClauseModifierToken(PP.
LookAhead(0))) {
1702 Diag(Tok, diag::err_omp_unknown_map_type_modifier);
1705 MapTypeModifierSpecified =
true;
1710 IsMapClauseModifierToken(Tok)
1715 Data.
MapType == OMPC_MAP_always)
1716 Diag(Tok, diag::err_omp_unknown_map_type);
1719 Data.
MapType = OMPC_MAP_tofrom;
1723 Data.
MapType = OMPC_MAP_tofrom;
1727 Data.
MapType = OMPC_MAP_tofrom;
1731 if (Tok.
is(tok::colon))
1733 else if (ColonExpected)
1734 Diag(Tok, diag::warn_pragma_expected_colon) <<
"map type";
1737 bool IsComma = (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
1738 Kind != OMPC_depend && Kind != OMPC_map) ||
1739 (Kind == OMPC_reduction && !InvalidReductionId) ||
1741 (!MapTypeModifierSpecified ||
1744 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
1745 while (IsComma || (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::colon) &&
1746 Tok.
isNot(tok::annot_pragma_openmp_end))) {
1752 Vars.push_back(VarExpr.
get());
1754 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1758 IsComma = Tok.
is(tok::comma);
1761 else if (Tok.
isNot(tok::r_paren) &&
1762 Tok.
isNot(tok::annot_pragma_openmp_end) &&
1763 (!MayHaveTail || Tok.
isNot(tok::colon)))
1764 Diag(Tok, diag::err_omp_expected_punc)
1767 << (Kind == OMPC_flush);
1771 if (NeedRParenForLinear)
1775 const bool MustHaveTail = MayHaveTail && Tok.
is(tok::colon);
1780 Tail = Actions.ActOnFinishFullExpr(Tail.
get(), ELoc);
1784 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1792 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
1793 (MustHaveTail && !Data.
TailExpr) || InvalidReductionId)
1844 OpenMPVarListDataTy Data;
1849 return Actions.ActOnOpenMPVarListClause(
1850 Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.
getLocation(),
1851 Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind,
1852 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.
Decl - This represents one declaration (or definition), e.g.
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.
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
Token - This structure provides full information about a lexed token.
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, ParsedType ObjectType, SourceLocation &TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
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
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
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
bool isTemplateDecl() const
returns true if this declaration is a template
This is the scope of OpenMP executable directive.
CXXScopeSpec ReductionIdScopeSpec
OpenMPClauseKind
OpenMP clauses.
DeclContext * getDeclContext()
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 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