26#include "llvm/ADT/PointerIntPair.h"
27#include "llvm/ADT/StringSwitch.h"
28#include "llvm/ADT/UniqueVector.h"
29#include "llvm/Frontend/OpenMP/OMPAssume.h"
30#include "llvm/Frontend/OpenMP/OMPContext.h"
34using namespace llvm::omp;
41enum OpenMPDirectiveKindEx {
42 OMPD_cancellation = llvm::omp::Directive_enumSize + 1,
54 OMPD_distribute_parallel,
55 OMPD_teams_distribute_parallel,
56 OMPD_target_teams_distribute_parallel,
66struct OpenMPDirectiveKindExWrapper {
69 bool operator==(OpenMPDirectiveKindExWrapper
V)
const {
72 bool operator!=(OpenMPDirectiveKindExWrapper
V)
const {
83class DeclDirectiveListParserHelper final {
92 ExprResult Res =
P->getActions().OpenMP().ActOnOpenMPIdExpression(
93 P->getCurScope(), SS, NameInfo, Kind);
95 Identifiers.push_back(Res.
get());
104 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
105 if (DKind != OMPD_unknown)
108 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
109 .Case(
"cancellation", OMPD_cancellation)
110 .Case(
"data", OMPD_data)
111 .Case(
"declare", OMPD_declare)
112 .Case(
"end", OMPD_end)
113 .Case(
"enter", OMPD_enter)
114 .Case(
"exit", OMPD_exit)
115 .Case(
"point", OMPD_point)
116 .Case(
"reduction", OMPD_reduction)
117 .Case(
"update", OMPD_update)
118 .Case(
"mapper", OMPD_mapper)
119 .Case(
"variant", OMPD_variant)
120 .Case(
"begin", OMPD_begin)
121 .Default(OMPD_unknown);
128 static const OpenMPDirectiveKindExWrapper F[][3] = {
129 {OMPD_begin, OMPD_declare, OMPD_begin_declare},
130 {OMPD_begin, OMPD_assumes, OMPD_begin_assumes},
131 {OMPD_end, OMPD_declare, OMPD_end_declare},
132 {OMPD_end, OMPD_assumes, OMPD_end_assumes},
133 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
134 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
135 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
136 {OMPD_declare, OMPD_simd, OMPD_declare_simd},
137 {OMPD_declare, OMPD_target, OMPD_declare_target},
138 {OMPD_declare, OMPD_variant, OMPD_declare_variant},
139 {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},
140 {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
141 {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
142 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
143 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
144 {OMPD_distribute_parallel_for, OMPD_simd,
145 OMPD_distribute_parallel_for_simd},
146 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
147 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
148 {OMPD_target, OMPD_data, OMPD_target_data},
149 {OMPD_target, OMPD_enter, OMPD_target_enter},
150 {OMPD_target, OMPD_exit, OMPD_target_exit},
151 {OMPD_target, OMPD_update, OMPD_target_update},
152 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
153 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
154 {OMPD_for, OMPD_simd, OMPD_for_simd},
155 {OMPD_parallel, OMPD_for, OMPD_parallel_for},
156 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
157 {OMPD_parallel, OMPD_loop, OMPD_parallel_loop},
158 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
159 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
160 {OMPD_target, OMPD_parallel, OMPD_target_parallel},
161 {OMPD_target, OMPD_simd, OMPD_target_simd},
162 {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop},
163 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
164 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
165 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
166 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
167 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
168 {OMPD_teams_distribute_parallel, OMPD_for,
169 OMPD_teams_distribute_parallel_for},
170 {OMPD_teams_distribute_parallel_for, OMPD_simd,
171 OMPD_teams_distribute_parallel_for_simd},
172 {OMPD_teams, OMPD_loop, OMPD_teams_loop},
173 {OMPD_target, OMPD_teams, OMPD_target_teams},
174 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
175 {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop},
176 {OMPD_target_teams_distribute, OMPD_parallel,
177 OMPD_target_teams_distribute_parallel},
178 {OMPD_target_teams_distribute, OMPD_simd,
179 OMPD_target_teams_distribute_simd},
180 {OMPD_target_teams_distribute_parallel, OMPD_for,
181 OMPD_target_teams_distribute_parallel_for},
182 {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
183 OMPD_target_teams_distribute_parallel_for_simd},
184 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
185 {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop},
186 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
187 {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd},
188 {OMPD_parallel, OMPD_master, OMPD_parallel_master},
189 {OMPD_parallel, OMPD_masked, OMPD_parallel_masked},
190 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
191 {OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop},
192 {OMPD_parallel_master_taskloop, OMPD_simd,
193 OMPD_parallel_master_taskloop_simd},
194 {OMPD_parallel_masked_taskloop, OMPD_simd,
195 OMPD_parallel_masked_taskloop_simd}};
196 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
197 Token Tok =
P.getCurToken();
198 OpenMPDirectiveKindExWrapper DKind =
200 ?
static_cast<unsigned>(OMPD_unknown)
202 if (DKind == OMPD_unknown)
205 for (
const auto &I : F) {
209 Tok =
P.getPreprocessor().LookAhead(0);
210 OpenMPDirectiveKindExWrapper SDKind =
212 ?
static_cast<unsigned>(OMPD_unknown)
214 if (SDKind == OMPD_unknown)
217 if (SDKind == I[1]) {
222 return unsigned(DKind) < llvm::omp::Directive_enumSize
228 Token Tok =
P.getCurToken();
229 Sema &Actions =
P.getActions();
232 bool WithOperator =
false;
233 if (Tok.
is(tok::kw_operator)) {
235 Tok =
P.getCurToken();
263 case tok::identifier:
268 P.Diag(Tok.
getLocation(), diag::err_omp_expected_reduction_identifier);
269 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
276 : DeclNames.getCXXOperatorName(OOK);
293 if (
T.expectAndConsume(
294 diag::err_expected_lparen_after,
295 getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
301 if (Name.isEmpty() && Tok.
is(tok::annot_pragma_openmp_end))
305 bool IsCorrect = !ExpectAndConsume(tok::colon);
307 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
310 IsCorrect = IsCorrect && !Name.isEmpty();
312 if (Tok.
is(tok::colon) || Tok.
is(tok::annot_pragma_openmp_end)) {
317 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
329 if (!ReductionType.
isNull()) {
330 ReductionTypes.push_back(
334 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
338 if (Tok.
is(tok::colon) || Tok.
is(tok::annot_pragma_openmp_end))
342 if (ExpectAndConsume(tok::comma)) {
344 if (Tok.
is(tok::annot_pragma_openmp_end)) {
349 }
while (Tok.
isNot(tok::annot_pragma_openmp_end));
351 if (ReductionTypes.empty()) {
356 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
360 if (ExpectAndConsume(tok::colon))
363 if (Tok.
is(tok::annot_pragma_openmp_end)) {
375 unsigned I = 0, E = ReductionTypes.size();
376 for (
Decl *D : DRD.get()) {
377 TentativeParsingAction TPA(*
this);
386 D, CombinerResult.
get());
389 Tok.
isNot(tok::annot_pragma_openmp_end)) {
394 IsCorrect = !
T.consumeClose() && IsCorrect && CombinerResult.
isUsable();
396 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
398 if (Tok.
is(tok::identifier) &&
409 tok::annot_pragma_openmp_end);
411 !
T.expectAndConsume(diag::err_expected_lparen_after,
"initializer") &&
413 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
422 if (Tok.
is(tok::identifier) &&
425 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
432 D, InitializerResult.
get(), OmpPrivParm);
434 Tok.
isNot(tok::annot_pragma_openmp_end)) {
440 !
T.consumeClose() && IsCorrect && !InitializerResult.
isInvalid();
456void Parser::ParseOpenMPReductionInitializerForDecl(
VarDecl *OmpPrivParm) {
459 if (isTokenEqualOrEqualTypo()) {
462 if (Tok.
is(tok::code_completion)) {
473 if (
Init.isInvalid()) {
480 }
else if (Tok.
is(tok::l_paren)) {
488 auto RunSignatureHelp = [
this, OmpPrivParm, LParLoc, &Exprs]() {
492 OmpPrivParm->
getLocation(), Exprs, LParLoc,
false);
493 CalledSignatureHelp =
true;
494 return PreferredType;
496 if (ParseExpressionList(Exprs, [&] {
497 PreferredType.enterFunctionArgument(Tok.
getLocation(),
507 if (!
T.consumeClose())
508 RLoc =
T.getCloseLocation();
517 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
521 if (
Init.isInvalid()) {
542 bool IsCorrect =
true;
545 if (
T.expectAndConsume(diag::err_expected_lparen_after,
546 getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
555 if (Tok.
isNot(tok::identifier) && Tok.
isNot(tok::kw_default)) {
563 ExpectAndConsume(tok::colon);
570 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
589 IsCorrect &= !
T.consumeClose();
600 ParseScope OMPDirectiveScope(
this, ScopeFlags);
611 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
617 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
619 Clauses.push_back(Clause);
623 if (Tok.
is(tok::comma))
627 if (Clauses.empty()) {
628 Diag(Tok, diag::err_omp_expected_clause)
629 << getOpenMPDirectiveName(OMPD_declare_mapper);
635 OMPDirectiveScope.Exit();
649 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
651 ParseSpecifierQualifierList(DS, AS, DSC);
656 ParseDeclarator(DeclaratorInfo);
657 Range = DeclaratorInfo.getSourceRange();
658 if (DeclaratorInfo.getIdentifier() ==
nullptr) {
674class FNContextRAII final {
678 bool HasFunScope =
false;
679 FNContextRAII() =
delete;
680 FNContextRAII(
const FNContextRAII &) =
delete;
681 FNContextRAII &operator=(
const FNContextRAII &) =
delete;
688 Sema &Actions =
P.getActions();
696 P.ReenterTemplateScopes(Scopes, D);
708 P.getActions().ActOnExitFunctionContext();
727 const Token &Tok =
P.getCurToken();
728 bool IsError =
false;
729 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
730 if (Tok.
isNot(tok::identifier))
732 OMPDeclareSimdDeclAttr::BranchStateTy Out;
734 StringRef ClauseName = II->
getName();
736 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
737 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
738 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
740 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
746 }
else if (ClauseName ==
"simdlen") {
748 P.Diag(Tok, diag::err_omp_more_one_clause)
749 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
754 SimdLen =
P.ParseOpenMPParensExpr(ClauseName, RLoc);
759 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
760 CKind == OMPC_linear) {
763 if (CKind == OMPC_aligned) {
765 }
else if (CKind == OMPC_linear) {
766 Data.ExtraModifier = OMPC_LINEAR_val;
771 if (
P.ParseOpenMPVarList(OMPD_declare_simd,
772 getOpenMPClauseKind(ClauseName), *Vars,
Data))
774 if (CKind == OMPC_aligned) {
775 Alignments.append(Aligneds.size() - Alignments.size(),
776 Data.DepModOrTailExpr);
777 }
else if (CKind == OMPC_linear) {
778 assert(0 <=
Data.ExtraModifier &&
780 "Unexpected linear modifier.");
781 if (
P.getActions().OpenMP().CheckOpenMPLinearModifier(
783 Data.ExtraModifierLoc))
784 Data.ExtraModifier = OMPC_LINEAR_val;
785 LinModifiers.append(Linears.size() - LinModifiers.size(),
787 Steps.append(Linears.size() - Steps.size(),
Data.DepModOrTailExpr);
794 if (Tok.
is(tok::comma))
805 PP.EnterTokenStream(Toks,
true,
811 FNContextRAII FnContext(*
this, Ptr);
812 OMPDeclareSimdDeclAttr::BranchStateTy BS =
813 OMPDeclareSimdDeclAttr::BS_Undefined;
823 Alignments, Linears, LinModifiers, Steps);
824 skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
830 Ptr, BS, Simdlen.
get(), Uniforms, Aligneds, Alignments, Linears,
838 CONTEXT_SELECTOR_SET_LVL = 0,
839 CONTEXT_SELECTOR_LVL = 1,
840 CONTEXT_TRAIT_LVL = 2,
843static StringRef stringLiteralParser(
Parser &
P) {
844 ExprResult Res =
P.ParseStringLiteralExpression(
true);
848static StringRef getNameFromIdOrString(
Parser &
P,
Token &Tok,
850 if (Tok.
is(tok::identifier) || Tok.
is(tok::kw_for)) {
852 StringRef Name =
P.getPreprocessor().getSpelling(Tok, Buffer);
853 (void)
P.ConsumeToken();
858 return stringLiteralParser(
P);
861 diag::warn_omp_declare_variant_string_literal_or_identifier)
866static bool checkForDuplicates(
Parser &
P, StringRef Name,
868 llvm::StringMap<SourceLocation> &Seen,
870 auto Res = Seen.try_emplace(Name, NameLoc);
876 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
878 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
885 llvm::omp::TraitSet
Set,
887 llvm::StringMap<SourceLocation> &Seen) {
888 TIProperty.
Kind = TraitProperty::invalid;
891 StringRef Name = getNameFromIdOrString(*
this, Tok, CONTEXT_TRAIT_LVL);
894 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(
Set,
Selector);
899 TIProperty.
Kind = getOpenMPContextTraitPropertyKind(
Set,
Selector, Name);
900 if (TIProperty.
Kind != TraitProperty::invalid) {
901 if (checkForDuplicates(*
this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
902 TIProperty.
Kind = TraitProperty::invalid;
908 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
909 << Name << getOpenMPContextTraitSelectorName(
Selector)
910 << getOpenMPContextTraitSetName(
Set);
912 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
913 if (SetForName != TraitSet::invalid) {
914 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
915 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
916 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
917 << Name <<
"<selector-name>"
918 <<
"(<property-name>)";
921 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
922 if (SelectorForName != TraitSelector::invalid) {
923 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
924 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
925 bool AllowsTraitScore =
false;
926 bool RequiresProperty =
false;
927 isValidTraitSelectorForTraitSet(
928 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
929 AllowsTraitScore, RequiresProperty);
930 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
931 << getOpenMPContextTraitSetName(
932 getOpenMPContextTraitSetForSelector(SelectorForName))
933 << Name << (RequiresProperty ?
"(<property-name>)" :
"");
936 for (
const auto &PotentialSet :
937 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
939 TraitProperty PropertyForName =
940 getOpenMPContextTraitPropertyKind(PotentialSet,
Selector, Name);
941 if (PropertyForName == TraitProperty::invalid)
943 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
944 << getOpenMPContextTraitSetName(
945 getOpenMPContextTraitSetForProperty(PropertyForName))
946 << getOpenMPContextTraitSelectorName(
947 getOpenMPContextTraitSelectorForProperty(PropertyForName))
948 << (
"(" + Name +
")").str();
951 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
952 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(
Set,
Selector);
958 llvm::StringMap<SourceLocation> &Seen) {
959 assert(TISelector.
Kind ==
960 llvm::omp::TraitSelector::implementation_extension &&
961 "Only for extension properties, e.g., "
962 "`implementation={extension(PROPERTY)}`");
963 if (TIProperty.
Kind == TraitProperty::invalid)
966 if (TIProperty.
Kind ==
967 TraitProperty::implementation_extension_disable_implicit_base)
970 if (TIProperty.
Kind ==
971 TraitProperty::implementation_extension_allow_templates)
974 if (TIProperty.
Kind ==
975 TraitProperty::implementation_extension_bind_to_declaration)
980 llvm::omp::TraitProperty::implementation_extension_match_all ||
982 llvm::omp::TraitProperty::implementation_extension_match_any ||
984 llvm::omp::TraitProperty::implementation_extension_match_none);
987 if (IsMatchExtension(TIProperty)) {
989 if (IsMatchExtension(SeenProp)) {
990 P.Diag(
Loc, diag::err_omp_variant_ctx_second_match_extension);
991 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
994 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
995 << CONTEXT_TRAIT_LVL << SeenName;
1001 llvm_unreachable(
"Unknown extension property!");
1005 llvm::omp::TraitSet
Set,
1006 llvm::StringMap<SourceLocation> &Seen) {
1007 assert(TISelector.
Kind != TraitSelector::user_condition &&
1008 "User conditions are special properties not handled here!");
1012 parseOMPTraitPropertyKind(TIProperty,
Set, TISelector.
Kind, Seen);
1014 if (TISelector.
Kind == llvm::omp::TraitSelector::implementation_extension)
1017 TIProperty.
Kind = TraitProperty::invalid;
1020 if (TIProperty.
Kind == TraitProperty::invalid) {
1022 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1023 << CONTEXT_TRAIT_LVL;
1027 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.
Kind,
1036 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
1037 << getOpenMPContextTraitPropertyName(TIProperty.
Kind,
1039 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1040 << getOpenMPContextTraitSetName(
Set);
1041 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
1042 << getOpenMPContextTraitPropertyName(TIProperty.
Kind,
1044 << getOpenMPContextTraitSelectorName(
1045 getOpenMPContextTraitSelectorForProperty(TIProperty.
Kind))
1046 << getOpenMPContextTraitSetName(
1047 getOpenMPContextTraitSetForProperty(TIProperty.
Kind));
1048 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1049 << CONTEXT_TRAIT_LVL;
1053 llvm::omp::TraitSet
Set,
1054 llvm::StringMap<SourceLocation> &Seen) {
1055 TISelector.
Kind = TraitSelector::invalid;
1058 StringRef Name = getNameFromIdOrString(*
this, Tok, CONTEXT_SELECTOR_LVL);
1061 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(
Set);
1065 TISelector.
Kind = getOpenMPContextTraitSelectorKind(Name);
1066 if (TISelector.
Kind != TraitSelector::invalid) {
1067 if (checkForDuplicates(*
this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
1068 TISelector.
Kind = TraitSelector::invalid;
1073 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
1074 << Name << getOpenMPContextTraitSetName(
Set);
1076 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
1077 if (SetForName != TraitSet::invalid) {
1078 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1079 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
1080 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1081 << Name <<
"<selector-name>"
1082 <<
"<property-name>";
1085 for (
const auto &PotentialSet :
1086 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1087 TraitSet::device}) {
1088 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1089 PotentialSet, TraitSelector::invalid, Name);
1090 if (PropertyForName == TraitProperty::invalid)
1092 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1093 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
1094 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1095 << getOpenMPContextTraitSetName(
1096 getOpenMPContextTraitSetForProperty(PropertyForName))
1097 << getOpenMPContextTraitSelectorName(
1098 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1099 << (
"(" + Name +
")").str();
1102 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1103 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(
Set);
1110 StringRef SelectorName =
1111 P.getPreprocessor().getSpelling(
P.getCurToken(), Buffer);
1112 if (SelectorName !=
"score")
1114 (void)
P.ConsumeToken();
1116 ScoreExpr =
P.ParseOpenMPParensExpr(SelectorName, RLoc);
1118 if (
P.getCurToken().is(tok::colon))
1119 (
void)
P.ConsumeAnyToken();
1121 P.Diag(
P.getCurToken(), diag::warn_omp_declare_variant_expected)
1123 <<
"score expression";
1130void Parser::parseOMPContextSelector(
1132 llvm::StringMap<SourceLocation> &SeenSelectors) {
1133 unsigned short OuterPC = ParenCount;
1138 auto FinishSelector = [OuterPC,
this]() ->
void {
1141 while (!
SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
1142 tok::annot_pragma_openmp_end},
1145 if (Tok.
is(tok::r_paren) && OuterPC > ParenCount)
1146 (
void)ConsumeParen();
1147 if (OuterPC <= ParenCount) {
1151 if (!Tok.
is(tok::comma) && !Tok.
is(tok::r_paren)) {
1157 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1158 << CONTEXT_SELECTOR_LVL;
1162 parseOMPTraitSelectorKind(TISelector,
Set, SeenSelectors);
1163 if (TISelector.
Kind == TraitSelector::invalid)
1164 return FinishSelector();
1166 bool AllowsTraitScore =
false;
1167 bool RequiresProperty =
false;
1168 if (!isValidTraitSelectorForTraitSet(TISelector.
Kind,
Set, AllowsTraitScore,
1169 RequiresProperty)) {
1170 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
1171 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1172 << getOpenMPContextTraitSetName(
Set);
1173 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
1174 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1175 << getOpenMPContextTraitSetName(
1176 getOpenMPContextTraitSetForSelector(TISelector.
Kind))
1177 << RequiresProperty;
1178 return FinishSelector();
1181 if (!RequiresProperty) {
1183 {getOpenMPContextTraitPropertyForSelector(TISelector.
Kind),
1184 getOpenMPContextTraitSelectorName(TISelector.
Kind)});
1188 if (!Tok.
is(tok::l_paren)) {
1189 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
1190 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1191 << getOpenMPContextTraitSetName(
Set);
1192 return FinishSelector();
1195 if (TISelector.
Kind == TraitSelector::user_condition) {
1199 return FinishSelector();
1202 {TraitProperty::user_condition_unknown,
"<condition>"});
1207 tok::annot_pragma_openmp_end);
1209 (void)BDT.consumeOpen();
1214 if (!AllowsTraitScore && !Score.
isUnset()) {
1216 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1217 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1218 << getOpenMPContextTraitSetName(
Set) << Score.
get();
1220 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1221 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1222 << getOpenMPContextTraitSetName(
Set) <<
"<invalid>";
1230 llvm::StringMap<SourceLocation> SeenProperties;
1232 parseOMPContextProperty(TISelector,
Set, SeenProperties);
1239void Parser::parseOMPTraitSetKind(
OMPTraitSet &TISet,
1240 llvm::StringMap<SourceLocation> &Seen) {
1241 TISet.
Kind = TraitSet::invalid;
1244 StringRef Name = getNameFromIdOrString(*
this, Tok, CONTEXT_SELECTOR_SET_LVL);
1247 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1251 TISet.
Kind = getOpenMPContextTraitSetKind(Name);
1252 if (TISet.
Kind != TraitSet::invalid) {
1253 if (checkForDuplicates(*
this, Name, NameLoc, Seen,
1254 CONTEXT_SELECTOR_SET_LVL))
1255 TISet.
Kind = TraitSet::invalid;
1260 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
1262 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
1263 if (SelectorForName != TraitSelector::invalid) {
1264 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1265 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
1266 bool AllowsTraitScore =
false;
1267 bool RequiresProperty =
false;
1268 isValidTraitSelectorForTraitSet(
1269 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
1270 AllowsTraitScore, RequiresProperty);
1271 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1272 << getOpenMPContextTraitSetName(
1273 getOpenMPContextTraitSetForSelector(SelectorForName))
1274 << Name << (RequiresProperty ?
"(<property-name>)" :
"");
1277 for (
const auto &PotentialSet :
1278 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1279 TraitSet::device}) {
1280 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1281 PotentialSet, TraitSelector::invalid, Name);
1282 if (PropertyForName == TraitProperty::invalid)
1284 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1285 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
1286 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1287 << getOpenMPContextTraitSetName(
1288 getOpenMPContextTraitSetForProperty(PropertyForName))
1289 << getOpenMPContextTraitSelectorName(
1290 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1291 << (
"(" + Name +
")").str();
1294 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1295 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1301void Parser::parseOMPContextSelectorSet(
1302 OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
1303 auto OuterBC = BraceCount;
1308 auto FinishSelectorSet = [
this, OuterBC]() ->
void {
1311 while (!
SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
1312 tok::annot_pragma_openmp_end},
1315 if (Tok.
is(tok::r_brace) && OuterBC > BraceCount)
1316 (
void)ConsumeBrace();
1317 if (OuterBC <= BraceCount) {
1321 if (!Tok.
is(tok::comma) && !Tok.
is(tok::r_brace)) {
1327 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1328 << CONTEXT_SELECTOR_SET_LVL;
1331 parseOMPTraitSetKind(TISet, SeenSets);
1332 if (TISet.
Kind == TraitSet::invalid)
1333 return FinishSelectorSet();
1339 << (
"context set name \"" + getOpenMPContextTraitSetName(TISet.
Kind) +
1344 if (Tok.
is(tok::l_brace)) {
1345 (void)ConsumeBrace();
1349 << (
"'=' that follows the context set name \"" +
1350 getOpenMPContextTraitSetName(TISet.
Kind) +
"\"")
1354 llvm::StringMap<SourceLocation> SeenSelectors;
1357 parseOMPContextSelector(TISelector, TISet.
Kind, SeenSelectors);
1358 if (TISelector.
Kind != TraitSelector::invalid &&
1364 if (Tok.
is(tok::r_brace)) {
1365 (void)ConsumeBrace();
1369 << (
"context selectors for the context set \"" +
1370 getOpenMPContextTraitSetName(TISet.
Kind) +
"\"")
1379 llvm::StringMap<SourceLocation> SeenSets;
1382 parseOMPContextSelectorSet(TISet, SeenSets);
1383 if (TISet.
Kind != TraitSet::invalid && !TISet.
Selectors.empty())
1384 TI.
Sets.push_back(TISet);
1395 PP.EnterTokenStream(Toks,
true,
1401 FNContextRAII FnContext(*
this, Ptr);
1413 getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1416 if (!AssociatedFunction.
isUsable()) {
1417 if (!Tok.
is(tok::annot_pragma_openmp_end))
1421 (void)ConsumeAnnotationToken();
1426 Actions.
OpenMP().getOMPTraitInfoForSurroundingScope();
1435 if (Tok.
is(tok::annot_pragma_openmp_end)) {
1440 bool IsError =
false;
1441 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1445 if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
1454 IsError = parseOMPDeclareVariantMatchClause(
Loc, TI, ParentTI);
1456 case OMPC_adjust_args: {
1464 llvm::append_range(
Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing
1466 : AdjustNeedDevicePtr,
1470 case OMPC_append_args:
1471 if (!AppendArgs.empty()) {
1472 Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
1473 << getOpenMPDirectiveName(OMPD_declare_variant)
1474 << getOpenMPClauseName(CKind) << 0;
1480 IsError = parseOpenMPAppendArgs(AppendArgs);
1484 llvm_unreachable(
"Unexpected clause for declare variant.");
1491 (void)ConsumeAnnotationToken();
1495 if (Tok.
is(tok::comma))
1499 std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1501 Ptr, AssociatedFunction.
get(), TI, AppendArgs.size(),
1504 if (DeclVarData && !TI.
Sets.empty())
1506 DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
1507 AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc,
1511 (void)ConsumeAnnotationToken();
1514bool Parser::parseOpenMPAppendArgs(
1516 bool HasError =
false;
1519 if (
T.expectAndConsume(diag::err_expected_lparen_after,
1520 getOpenMPClauseName(OMPC_append_args).data()))
1528 tok::annot_pragma_openmp_end);
1529 if (IT.expectAndConsume(diag::err_expected_lparen_after,
"interop"))
1533 if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
1536 InteropInfos.push_back(InteropInfo);
1539 if (Tok.
is(tok::comma))
1542 if (!HasError && InteropInfos.empty()) {
1545 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1548 HasError =
T.consumeClose() || HasError;
1559 if (CKind != OMPC_match) {
1567 if (
T.expectAndConsume(diag::err_expected_lparen_after,
1568 getOpenMPClauseName(OMPC_match).data()))
1572 parseOMPContextSelectors(
Loc, TI);
1575 (void)
T.consumeClose();
1586 bool MergedSet =
false;
1588 if (
Set.Kind != ParentSet.
Kind)
1592 bool MergedSelector =
false;
1596 MergedSelector =
true;
1599 bool MergedProperty =
false;
1613 if (
Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1614 Diag(
Loc, diag::err_omp_declare_variant_nested_user_condition);
1615 }
else if (
Selector.ScoreOrCondition !=
1617 Diag(
Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1618 << getOpenMPContextTraitPropertyName(
1620 << getOpenMPContextTraitSelectorName(ParentSelector.
Kind)
1621 << getOpenMPContextTraitSetName(ParentSet.
Kind);
1624 if (!MergedProperty)
1625 Selector.Properties.push_back(ParentProperty);
1628 if (!MergedSelector)
1629 Set.Selectors.push_back(ParentSelector);
1633 TI.
Sets.push_back(ParentSet);
1650 llvm::omp::Clause_enumSize + 1>
1651 FirstClauses(llvm::omp::Clause_enumSize + 1);
1652 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1658 DKind, CKind, !FirstClauses[
unsigned(CKind)].getInt());
1659 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1661 FirstClauses[
unsigned(CKind)].setInt(
true);
1662 if (Clause !=
nullptr)
1663 Clauses.push_back(Clause);
1664 if (Tok.
is(tok::annot_pragma_openmp_end)) {
1669 if (Tok.
is(tok::comma))
1690 bool SkippedClauses =
false;
1692 auto SkipBraces = [&](llvm::StringRef Spelling,
bool IssueNote) {
1694 tok::annot_pragma_openmp_end);
1695 if (
T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
1698 if (IssueNote &&
T.getCloseLocation().isValid())
1699 Diag(
T.getCloseLocation(),
1700 diag::note_omp_assumption_clause_continue_here);
1706 auto MatchACMClause = [&](StringRef RawString) {
1707 llvm::StringSwitch<int> SS(RawString);
1708 unsigned ACMIdx = 0;
1709 for (
const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
1710 if (ACMI.StartsWith)
1711 SS.StartsWith(ACMI.Identifier, ACMIdx++);
1713 SS.Case(ACMI.Identifier, ACMIdx++);
1715 return SS.Default(-1);
1718 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1724 Idx = MatchACMClause(II->
getName());
1728 bool NextIsLPar = Tok.
is(tok::l_paren);
1731 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
1732 << llvm::omp::getOpenMPDirectiveName(DKind)
1733 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
1735 SkipBraces(II ? II->
getName() :
"",
true);
1736 SkippedClauses =
true;
1739 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
1740 if (ACMI.HasDirectiveList || ACMI.HasExpression) {
1743 SkippedClauses =
true;
1744 SkipBraces(II->
getName(),
false);
1750 diag::warn_omp_unknown_assumption_clause_without_args)
1752 SkipBraces(II->
getName(),
true);
1755 assert(II &&
"Expected an identifier clause!");
1756 std::string Assumption = II->
getName().str();
1757 if (ACMI.StartsWith)
1758 Assumption =
"ompx_" + Assumption.substr(ACMI.Identifier.size());
1760 Assumption =
"omp_" + Assumption;
1761 Assumptions.push_back(Assumption);
1772 Diag(
Loc, diag::err_expected_begin_assumes);
1786struct SimpleClauseData {
1798static std::optional<SimpleClauseData>
1800 const Token &Tok =
P.getCurToken();
1805 if (
T.expectAndConsume(diag::err_expected_lparen_after,
1806 getOpenMPClauseName(Kind).data()))
1807 return std::nullopt;
1810 Kind, Tok.
isAnnotation() ?
"" :
P.getPreprocessor().getSpelling(Tok),
1813 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1814 Tok.
isNot(tok::annot_pragma_openmp_end))
1815 P.ConsumeAnyToken();
1819 if (!
T.consumeClose())
1820 RLoc =
T.getCloseLocation();
1825void Parser::ParseOMPDeclareTargetClauses(
1828 bool RequiresToOrLinkOrIndirectClause =
false;
1829 bool HasToOrLinkOrIndirectClause =
false;
1830 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1831 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1832 bool HasIdentifier = Tok.
is(tok::identifier);
1833 if (HasIdentifier) {
1835 RequiresToOrLinkOrIndirectClause =
true;
1837 StringRef ClauseName = II->
getName();
1838 bool IsDeviceTypeClause =
1840 getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1842 bool IsIndirectClause =
getLangOpts().OpenMP >= 51 &&
1843 getOpenMPClauseKind(ClauseName) == OMPC_indirect;
1844 if (DTCI.
Indirect && IsIndirectClause) {
1845 Diag(Tok, diag::err_omp_more_one_clause)
1846 << getOpenMPDirectiveName(OMPD_declare_target)
1847 << getOpenMPClauseName(OMPC_indirect) << 0;
1850 bool IsToEnterOrLinkClause =
1851 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1852 assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
1857 if (
getLangOpts().OpenMP >= 52 && ClauseName ==
"to") {
1858 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
1861 if (
getLangOpts().OpenMP <= 51 && ClauseName ==
"enter") {
1862 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
1866 if (!IsDeviceTypeClause && !IsIndirectClause &&
1867 DTCI.
Kind == OMPD_begin_declare_target) {
1868 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1869 << ClauseName << (
getLangOpts().OpenMP >= 51 ? 3 : 0);
1872 if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
1874 ? diag::err_omp_declare_target_unexpected_clause_52
1875 : diag::err_omp_declare_target_unexpected_clause)
1883 if (IsToEnterOrLinkClause || IsIndirectClause)
1884 HasToOrLinkOrIndirectClause =
true;
1886 if (IsIndirectClause) {
1887 if (!ParseOpenMPIndirectClause(DTCI,
false))
1892 if (IsDeviceTypeClause) {
1893 std::optional<SimpleClauseData> DevTypeData =
1896 if (DeviceTypeLoc.
isValid()) {
1898 Diag(DevTypeData->Loc,
1899 diag::warn_omp_more_one_device_type_clause);
1903 case OMPC_DEVICE_TYPE_any:
1904 DTCI.
DT = OMPDeclareTargetDeclAttr::DT_Any;
1906 case OMPC_DEVICE_TYPE_host:
1907 DTCI.
DT = OMPDeclareTargetDeclAttr::DT_Host;
1909 case OMPC_DEVICE_TYPE_nohost:
1910 DTCI.
DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1913 llvm_unreachable(
"Unexpected device_type");
1915 DeviceTypeLoc = DevTypeData->Loc;
1922 if (DTCI.
Kind == OMPD_declare_target || HasIdentifier) {
1932 Diag(NameInfo.
getLoc(), diag::err_omp_declare_target_multiple)
1935 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1940 if (Tok.
is(tok::l_paren)) {
1942 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1945 if (!HasIdentifier && Tok.
isNot(tok::annot_pragma_openmp_end)) {
1948 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1949 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1954 if (Tok.
is(tok::comma))
1958 if (DTCI.
Indirect && DTCI.
DT != OMPDeclareTargetDeclAttr::DT_Any)
1959 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
1962 if (DTCI.
Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
1963 !HasToOrLinkOrIndirectClause)
1966 ? diag::err_omp_declare_target_missing_enter_or_link_clause
1967 : diag::err_omp_declare_target_missing_to_or_link_clause)
1976 if (Tok.
is(tok::annot_pragma_openmp_end))
1979 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1980 << getOpenMPDirectiveName(DKind);
1981 while (Tok.
isNot(tok::annot_pragma_openmp_end))
1990 bool SkipUntilOpenMPEnd) {
1991 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1993 if (FoundKind == ExpectedKind) {
1995 skipUntilPragmaOpenMPEnd(ExpectedKind);
1999 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
2001 Diag(BeginLoc, diag::note_matching)
2002 << (
"'#pragma omp " + getOpenMPDirectiveName(BeginKind) +
"'").str();
2003 if (SkipUntilOpenMPEnd)
2010 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
2014 if (Tok.
is(tok::annot_pragma_openmp_end))
2015 ConsumeAnnotationToken();
2057 assert(Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2058 "Not an OpenMP directive!");
2065 TentativeParsingAction TPA(*
this);
2066 Loc = ConsumeAnnotationToken();
2068 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
2073 Toks.push_back(Tok);
2074 while (Cnt && Tok.
isNot(tok::eof)) {
2076 if (Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
2078 else if (Tok.
is(tok::annot_pragma_openmp_end))
2080 Toks.push_back(Tok);
2085 auto *LP =
new LateParsedPragma(
this, AS);
2087 getCurrentClass().LateParsedDeclarations.push_back(LP);
2092 Loc = ConsumeAnnotationToken();
2097 case OMPD_threadprivate: {
2099 DeclDirectiveListParserHelper Helper(
this, DKind);
2100 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2102 skipUntilPragmaOpenMPEnd(DKind);
2104 ConsumeAnnotationToken();
2106 Loc, Helper.getIdentifiers());
2110 case OMPD_allocate: {
2112 DeclDirectiveListParserHelper Helper(
this, DKind);
2113 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2116 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2118 llvm::omp::Clause_enumSize + 1>
2119 FirstClauses(llvm::omp::Clause_enumSize + 1);
2120 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2126 OMPD_allocate, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2127 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2129 FirstClauses[
unsigned(CKind)].setInt(
true);
2130 if (Clause !=
nullptr)
2131 Clauses.push_back(Clause);
2132 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2137 if (Tok.
is(tok::comma))
2141 skipUntilPragmaOpenMPEnd(DKind);
2144 ConsumeAnnotationToken();
2146 Loc, Helper.getIdentifiers(), Clauses);
2150 case OMPD_requires: {
2154 llvm::omp::Clause_enumSize + 1>
2155 FirstClauses(llvm::omp::Clause_enumSize + 1);
2156 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2157 Diag(Tok, diag::err_omp_expected_clause)
2158 << getOpenMPDirectiveName(OMPD_requires);
2161 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2167 OMPD_requires, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2168 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2170 FirstClauses[
unsigned(CKind)].setInt(
true);
2171 if (Clause !=
nullptr)
2172 Clauses.push_back(Clause);
2173 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2178 if (Tok.
is(tok::comma))
2183 if (Clauses.empty()) {
2184 Diag(Tok, diag::err_omp_expected_clause)
2185 << getOpenMPDirectiveName(OMPD_requires);
2186 ConsumeAnnotationToken();
2189 ConsumeAnnotationToken();
2195 ParseOpenMPClauses(DKind, Clauses, StartLoc);
2202 case OMPD_begin_assumes:
2205 case OMPD_end_assumes:
2208 case OMPD_declare_reduction:
2210 if (
DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2211 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2213 ConsumeAnnotationToken();
2217 case OMPD_declare_mapper: {
2219 if (
DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
2221 ConsumeAnnotationToken();
2226 case OMPD_begin_declare_variant: {
2234 Actions.
OpenMP().getOMPTraitInfoForSurroundingScope();
2237 if (parseOMPDeclareVariantMatchClause(
Loc, TI, ParentTI)) {
2241 (void)ConsumeAnnotationToken();
2246 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
2250 VariantMatchInfo VMI;
2253 std::function<void(StringRef)> DiagUnknownTrait =
2254 [
this,
Loc](StringRef ISATrait) {
2257 Diag(
Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2260 ASTCtx, std::move(DiagUnknownTrait),
2264 if (isVariantApplicableInContext(VMI, OMPCtx,
true)) {
2270 unsigned Nesting = 1;
2276 if (DK == OMPD_end_declare_variant)
2278 else if (DK == OMPD_begin_declare_variant)
2280 if (!Nesting || isEofOrEom())
2285 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
2286 DK,
Loc, DKLoc,
true);
2291 case OMPD_end_declare_variant: {
2295 Diag(
Loc, diag::err_expected_begin_declare_variant);
2299 case OMPD_declare_variant:
2300 case OMPD_declare_simd: {
2306 Toks.push_back(Tok);
2308 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2309 Toks.push_back(Tok);
2312 Toks.push_back(Tok);
2316 if (Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
2317 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2319 }
else if (Tok.
isNot(tok::r_brace) && !isEofOrEom()) {
2324 MaybeParseCXX11Attributes(Attrs);
2326 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
2329 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs,
TagType, Tag);
2333 Diag(
Loc, diag::err_omp_decl_in_declare_simd_variant)
2334 << (DKind == OMPD_declare_simd ? 0 : 1);
2337 if (DKind == OMPD_declare_simd)
2338 return ParseOMPDeclareSimdClauses(Ptr, Toks,
Loc);
2339 assert(DKind == OMPD_declare_variant &&
2340 "Expected declare variant directive only");
2341 ParseOMPDeclareVariantClauses(Ptr, Toks,
Loc);
2344 case OMPD_begin_declare_target:
2345 case OMPD_declare_target: {
2347 bool HasClauses = Tok.
isNot(tok::annot_pragma_openmp_end);
2350 ParseOMPDeclareTargetClauses(DTCI);
2351 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
2358 if (HasImplicitMappings) {
2366 Decls.push_back(It.first);
2369 case OMPD_end_declare_target: {
2371 Diag(Tok, diag::err_omp_unexpected_directive)
2372 << 1 << getOpenMPDirectiveName(DKind);
2377 ParseOMPEndDeclareTargetDirective(DTCI.
Kind, DKind, DTCI.
Loc);
2381 Diag(Tok, diag::err_omp_unknown_directive);
2388 case OMPD_taskyield:
2391 case OMPD_taskgroup:
2403 case OMPD_parallel_for:
2404 case OMPD_parallel_for_simd:
2405 case OMPD_parallel_sections:
2406 case OMPD_parallel_master:
2407 case OMPD_parallel_masked:
2411 case OMPD_cancellation_point:
2413 case OMPD_target_data:
2414 case OMPD_target_enter_data:
2415 case OMPD_target_exit_data:
2416 case OMPD_target_parallel:
2417 case OMPD_target_parallel_for:
2419 case OMPD_taskloop_simd:
2420 case OMPD_master_taskloop:
2421 case OMPD_master_taskloop_simd:
2422 case OMPD_parallel_master_taskloop:
2423 case OMPD_parallel_master_taskloop_simd:
2424 case OMPD_masked_taskloop:
2425 case OMPD_masked_taskloop_simd:
2426 case OMPD_parallel_masked_taskloop:
2427 case OMPD_parallel_masked_taskloop_simd:
2428 case OMPD_distribute:
2429 case OMPD_target_update:
2430 case OMPD_distribute_parallel_for:
2431 case OMPD_distribute_parallel_for_simd:
2432 case OMPD_distribute_simd:
2433 case OMPD_target_parallel_for_simd:
2434 case OMPD_target_simd:
2436 case OMPD_teams_distribute:
2437 case OMPD_teams_distribute_simd:
2438 case OMPD_teams_distribute_parallel_for_simd:
2439 case OMPD_teams_distribute_parallel_for:
2440 case OMPD_target_teams:
2441 case OMPD_target_teams_distribute:
2442 case OMPD_target_teams_distribute_parallel_for:
2443 case OMPD_target_teams_distribute_parallel_for_simd:
2444 case OMPD_target_teams_distribute_simd:
2447 case OMPD_metadirective:
2449 case OMPD_teams_loop:
2450 case OMPD_target_teams_loop:
2451 case OMPD_parallel_loop:
2452 case OMPD_target_parallel_loop:
2453 Diag(Tok, diag::err_omp_unexpected_directive)
2454 << 1 << getOpenMPDirectiveName(DKind);
2459 while (Tok.
isNot(tok::annot_pragma_openmp_end))
2505StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2506 ParsedStmtContext StmtCtx,
bool ReadDirectiveWithinMetadirective) {
2507 if (!ReadDirectiveWithinMetadirective)
2508 assert(Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2509 "Not an OpenMP directive!");
2514 llvm::omp::Clause_enumSize + 1>
2515 FirstClauses(llvm::omp::Clause_enumSize + 1);
2520 : ConsumeAnnotationToken(),
2523 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2524 Diag(Tok, diag::err_omp_unknown_directive);
2531 bool HasAssociatedStatement =
true;
2538 if (ReadDirectiveWithinMetadirective && Tok.
is(tok::r_paren))
2539 while (Tok.
isNot(tok::annot_pragma_openmp_end))
2542 skipUntilPragmaOpenMPEnd(DKind);
2543 if (Tok.
is(tok::annot_pragma_openmp_end))
2544 ConsumeAnnotationToken();
2547 case OMPD_metadirective: {
2554 TentativeParsingAction TPA(*
this);
2558 tok::annot_pragma_openmp_end);
2559 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2566 if (
T.expectAndConsume(diag::err_expected_lparen_after,
2567 getOpenMPClauseName(CKind).data()))
2571 if (CKind == OMPC_when) {
2573 parseOMPContextSelectors(
Loc, TI);
2574 if (TI.
Sets.size() == 0) {
2575 Diag(Tok, diag::err_omp_expected_context_selector) <<
"when clause";
2581 if (Tok.
is(tok::colon))
2584 Diag(Tok, diag::err_omp_expected_colon) <<
"when clause";
2591 while (Tok.
isNot(tok::r_paren) || paren != 0) {
2592 if (Tok.
is(tok::l_paren))
2594 if (Tok.
is(tok::r_paren))
2596 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2597 Diag(Tok, diag::err_omp_expected_punc)
2598 << getOpenMPClauseName(CKind) << 0;
2605 if (Tok.
is(tok::r_paren))
2608 VariantMatchInfo VMI;
2611 VMIs.push_back(VMI);
2617 std::function<void(StringRef)> DiagUnknownTrait =
2618 [
this,
Loc](StringRef ISATrait) {
2621 Diag(
Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2628 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2635 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2637 if (Idx++ != BestIdx) {
2642 while (Tok.
isNot(tok::r_paren) || paren != 0) {
2643 if (Tok.
is(tok::l_paren))
2645 if (Tok.
is(tok::r_paren))
2650 if (Tok.
is(tok::r_paren))
2664 if (CKind == OMPC_when) {
2667 parseOMPContextSelectors(
Loc, TI);
2675 if (Tok.
is(tok::r_paren)) {
2676 SkipUntil(tok::annot_pragma_openmp_end);
2681 Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2688 case OMPD_threadprivate: {
2690 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2691 ParsedStmtContext()) {
2692 Diag(Tok, diag::err_omp_immediate_directive)
2693 << getOpenMPDirectiveName(DKind) << 0;
2696 DeclDirectiveListParserHelper Helper(
this, DKind);
2697 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2699 skipUntilPragmaOpenMPEnd(DKind);
2701 Loc, Helper.getIdentifiers());
2704 SkipUntil(tok::annot_pragma_openmp_end);
2707 case OMPD_allocate: {
2709 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2710 ParsedStmtContext()) {
2711 Diag(Tok, diag::err_omp_immediate_directive)
2712 << getOpenMPDirectiveName(DKind) << 0;
2715 DeclDirectiveListParserHelper Helper(
this, DKind);
2716 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2719 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2721 llvm::omp::Clause_enumSize + 1>
2722 FirstClauses(llvm::omp::Clause_enumSize + 1);
2723 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2729 OMPD_allocate, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2730 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2732 FirstClauses[
unsigned(CKind)].setInt(
true);
2733 if (Clause !=
nullptr)
2734 Clauses.push_back(Clause);
2735 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2740 if (Tok.
is(tok::comma))
2744 skipUntilPragmaOpenMPEnd(DKind);
2747 Loc, Helper.getIdentifiers(), Clauses);
2750 SkipUntil(tok::annot_pragma_openmp_end);
2753 case OMPD_declare_reduction:
2756 ParseOpenMPDeclareReductionDirective(
AS_none)) {
2757 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2761 SkipUntil(tok::annot_pragma_openmp_end);
2764 case OMPD_declare_mapper: {
2767 ParseOpenMPDeclareMapperDirective(
AS_none)) {
2769 ConsumeAnnotationToken();
2772 SkipUntil(tok::annot_pragma_openmp_end);
2779 case OMPD_taskyield:
2783 case OMPD_cancellation_point:
2785 case OMPD_target_enter_data:
2786 case OMPD_target_exit_data:
2787 case OMPD_target_update:
2789 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2790 ParsedStmtContext()) {
2791 Diag(Tok, diag::err_omp_immediate_directive)
2792 << getOpenMPDirectiveName(DKind) << 0;
2793 if (DKind == OMPD_error) {
2794 SkipUntil(tok::annot_pragma_openmp_end);
2798 HasAssociatedStatement =
false;
2812 case OMPD_parallel_for:
2813 case OMPD_parallel_for_simd:
2814 case OMPD_parallel_sections:
2815 case OMPD_parallel_master:
2816 case OMPD_parallel_masked:
2822 case OMPD_taskgroup:
2823 case OMPD_target_data:
2824 case OMPD_target_parallel:
2825 case OMPD_target_parallel_for:
2827 case OMPD_teams_loop:
2828 case OMPD_target_teams_loop:
2829 case OMPD_parallel_loop:
2830 case OMPD_target_parallel_loop:
2833 case OMPD_taskloop_simd:
2834 case OMPD_master_taskloop:
2835 case OMPD_masked_taskloop:
2836 case OMPD_master_taskloop_simd:
2837 case OMPD_masked_taskloop_simd:
2838 case OMPD_parallel_master_taskloop:
2839 case OMPD_parallel_masked_taskloop:
2840 case OMPD_parallel_master_taskloop_simd:
2841 case OMPD_parallel_masked_taskloop_simd:
2842 case OMPD_distribute:
2843 case OMPD_distribute_parallel_for:
2844 case OMPD_distribute_parallel_for_simd:
2845 case OMPD_distribute_simd:
2846 case OMPD_target_parallel_for_simd:
2847 case OMPD_target_simd:
2848 case OMPD_teams_distribute:
2849 case OMPD_teams_distribute_simd:
2850 case OMPD_teams_distribute_parallel_for_simd:
2851 case OMPD_teams_distribute_parallel_for:
2852 case OMPD_target_teams:
2853 case OMPD_target_teams_distribute:
2854 case OMPD_target_teams_distribute_parallel_for:
2855 case OMPD_target_teams_distribute_parallel_for_simd:
2856 case OMPD_target_teams_distribute_simd:
2861 bool ImplicitClauseAllowed =
false;
2862 if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2864 ImplicitClauseAllowed =
true;
2868 if (DKind == OMPD_critical) {
2870 tok::annot_pragma_openmp_end);
2871 if (!
T.consumeOpen()) {
2877 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2881 }
else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2883 if (Tok.
isNot(tok::annot_pragma_openmp_end))
2891 ParseScope OMPDirectiveScope(
this, ScopeFlags);
2895 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2898 if (ReadDirectiveWithinMetadirective && Tok.
is(tok::r_paren)) {
2899 while (Tok.
isNot(tok::annot_pragma_openmp_end))
2903 bool HasImplicitClause =
false;
2904 if (ImplicitClauseAllowed && Tok.
is(tok::l_paren)) {
2905 HasImplicitClause =
true;
2915 if (HasImplicitClause) {
2916 assert(CKind == OMPC_unknown &&
"Must be unknown implicit clause.");
2917 if (DKind == OMPD_flush) {
2920 assert(DKind == OMPD_depobj &&
2921 "Expected flush or depobj directives.");
2922 CKind = OMPC_depobj;
2926 ImplicitClauseAllowed =
false;
2928 HasImplicitClause =
false;
2930 DKind, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2931 FirstClauses[
unsigned(CKind)].setInt(
true);
2933 FirstClauses[
unsigned(CKind)].setPointer(Clause);
2934 Clauses.push_back(Clause);
2938 if (Tok.
is(tok::comma))
2945 ConsumeAnnotationToken();
2947 if (DKind == OMPD_ordered) {
2950 for (
auto CK : {OMPC_depend, OMPC_doacross}) {
2951 if (FirstClauses[
unsigned(CK)].getInt()) {
2952 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2953 ParsedStmtContext()) {
2954 Diag(
Loc, diag::err_omp_immediate_directive)
2955 << getOpenMPDirectiveName(DKind) << 1
2956 << getOpenMPClauseName(CK);
2958 HasAssociatedStatement =
false;
2963 if (DKind == OMPD_tile && !FirstClauses[
unsigned(OMPC_sizes)].getInt()) {
2964 Diag(
Loc, diag::err_omp_required_clause)
2965 << getOpenMPDirectiveName(OMPD_tile) <<
"sizes";
2969 if (HasAssociatedStatement) {
2978 AssociatedStmt = ParseStatement();
2987 }
else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2988 DKind == OMPD_target_exit_data) {
2997 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.
get(),
Loc,
3002 OMPDirectiveScope.Exit();
3005 case OMPD_declare_target: {
3007 bool HasClauses = Tok.
isNot(tok::annot_pragma_openmp_end);
3010 ParseOMPDeclareTargetClauses(DTCI);
3011 bool HasImplicitMappings =
3014 if (HasImplicitMappings) {
3015 Diag(Tok, diag::err_omp_unexpected_directive)
3016 << 1 << getOpenMPDirectiveName(DKind);
3017 SkipUntil(tok::annot_pragma_openmp_end);
3027 case OMPD_declare_simd:
3028 case OMPD_begin_declare_target:
3029 case OMPD_end_declare_target:
3031 case OMPD_begin_declare_variant:
3032 case OMPD_end_declare_variant:
3033 case OMPD_declare_variant:
3034 Diag(Tok, diag::err_omp_unexpected_directive)
3035 << 1 << getOpenMPDirectiveName(DKind);
3036 SkipUntil(tok::annot_pragma_openmp_end);
3040 Diag(Tok, diag::err_omp_unknown_directive);
3041 SkipUntil(tok::annot_pragma_openmp_end);
3051bool Parser::ParseOpenMPSimpleVarList(
3055 bool AllowScopeSpecifier) {
3058 if (
T.expectAndConsume(diag::err_expected_lparen_after,
3059 getOpenMPDirectiveName(Kind).data()))
3061 bool IsCorrect =
true;
3062 bool NoIdentIsFound =
true;
3065 while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end)) {
3069 Token PrevTok = Tok;
3070 NoIdentIsFound =
false;
3073 ParseOptionalCXXScopeSpecifier(SS,
nullptr,
3076 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3079 false,
false,
false,
3080 false,
false,
nullptr, Name)) {
3082 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3084 }
else if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren) &&
3085 Tok.
isNot(tok::annot_pragma_openmp_end)) {
3087 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3096 if (Tok.
is(tok::comma)) {
3101 if (NoIdentIsFound) {
3102 Diag(Tok, diag::err_expected) << tok::identifier;
3107 IsCorrect = !
T.consumeClose() && IsCorrect;
3112OMPClause *Parser::ParseOpenMPSizesClause() {
3115 if (ParseOpenMPExprListClause(OMPC_sizes, ClauseNameLoc, OpenLoc, CloseLoc,
3129 if (
T.expectAndConsume(diag::err_expected_lparen_after,
"uses_allocator"))
3137 ? ParseCXXIdExpression()
3138 : tryParseCXXIdExpression(SS,
false,
3140 if (Allocator.isInvalid()) {
3141 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3147 if (Tok.
is(tok::l_paren)) {
3149 tok::annot_pragma_openmp_end);
3155 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3163 if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren))
3164 Diag(Tok, diag::err_omp_expected_punc) <<
"uses_allocators" << 0;
3166 if (Tok.
is(tok::comma))
3168 }
while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end));
3171 Loc,
T.getOpenLocation(),
T.getCloseLocation(),
Data);
3196 OMPClauseKind = CKind;
3198 bool ErrorFound =
false;
3199 bool WrongDirective =
false;
3201 if (CKind != OMPC_unknown &&
3202 !isAllowedClauseForDirective(DKind, CKind,
getLangOpts().OpenMP)) {
3203 Diag(Tok, diag::err_omp_unexpected_clause)
3204 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3206 WrongDirective =
true;
3211 case OMPC_num_threads:
3216 case OMPC_num_teams:
3217 case OMPC_thread_limit:
3219 case OMPC_grainsize:
3220 case OMPC_num_tasks:
3222 case OMPC_allocator:
3225 case OMPC_novariants:
3226 case OMPC_nocontext:
3231 case OMPC_ompx_dyn_cgroup_mem:
3260 Diag(Tok, diag::err_omp_more_one_clause)
3261 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3265 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3267 Clause = ParseOpenMPClause(CKind, WrongDirective);
3268 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
3269 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3271 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3275 case OMPC_proc_bind:
3276 case OMPC_atomic_default_mem_order:
3294 Diag(Tok, diag::err_omp_more_one_clause)
3295 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3299 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3303 case OMPC_dist_schedule:
3304 case OMPC_defaultmap:
3314 if ((
getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3315 (CKind != OMPC_order ||
getLangOpts().OpenMP >= 51) && !FirstClause) {
3316 Diag(Tok, diag::err_omp_more_one_clause)
3317 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3322 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3326 case OMPC_mergeable:
3340 case OMPC_unified_address:
3341 case OMPC_unified_shared_memory:
3342 case OMPC_reverse_offload:
3343 case OMPC_dynamic_allocators:
3352 Diag(Tok, diag::err_omp_more_one_clause)
3353 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3357 Clause = ParseOpenMPClause(CKind, WrongDirective);
3361 Diag(Tok, diag::err_omp_more_one_clause)
3362 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3366 Clause = (DKind == OMPD_depobj)
3367 ? ParseOpenMPSimpleClause(CKind, WrongDirective)
3368 : ParseOpenMPClause(CKind, WrongDirective);
3371 case OMPC_firstprivate:
3372 case OMPC_lastprivate:
3374 case OMPC_reduction:
3375 case OMPC_task_reduction:
3376 case OMPC_in_reduction:
3380 case OMPC_copyprivate:
3386 case OMPC_use_device_ptr:
3387 case OMPC_use_device_addr:
3388 case OMPC_is_device_ptr:
3389 case OMPC_has_device_addr:
3391 case OMPC_nontemporal:
3392 case OMPC_inclusive:
3393 case OMPC_exclusive:
3397 if (
getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
3398 CKind == OMPC_depend)
3399 Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
3400 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3404 Diag(Tok, diag::err_omp_more_one_clause)
3405 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3409 Clause = ParseOpenMPSizesClause();
3411 case OMPC_uses_allocators:
3412 Clause = ParseOpenMPUsesAllocatorClause(DKind);
3415 if (DKind != OMPD_interop) {
3417 Diag(Tok, diag::err_omp_more_one_clause)
3418 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3421 Clause = ParseOpenMPClause(CKind, WrongDirective);
3427 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3429 case OMPC_device_type:
3431 skipUntilPragmaOpenMPEnd(DKind);
3433 case OMPC_threadprivate:
3436 if (!WrongDirective)
3437 Diag(Tok, diag::err_omp_unexpected_clause)
3438 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3441 case OMPC_ompx_attribute:
3442 Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
3444 case OMPC_ompx_bare:
3446 Diag(Tok, diag::note_ompx_bare_clause)
3447 << getOpenMPClauseName(CKind) <<
"target teams";
3448 if (!ErrorFound && !
getLangOpts().OpenMPExtensions) {
3449 Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
3450 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3453 Clause = ParseOpenMPClause(CKind, WrongDirective);
3458 return ErrorFound ? nullptr : Clause;
3466 bool IsAddressOfOperand) {
3468 if (
T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3473 ParseCastExpression(AnyCastExpr, IsAddressOfOperand,
NotTypeCast));
3479 if (!
T.consumeClose())
3480 RLoc =
T.getCloseLocation();
3547bool Parser::ParseOpenMPIndirectClause(
3552 if (Tok.
isNot(tok::l_paren)) {
3571 if (
Ret.isInvalid())
3576 if (
Ret.isInvalid())
3589 bool HasError =
false;
3590 bool IsTarget =
false;
3591 bool IsTargetSync =
false;
3593 while (Tok.
is(tok::identifier)) {
3595 bool PreferTypeAllowed =
Kind == OMPC_init &&
3603 Diag(Tok, diag::warn_omp_more_one_interop_type) <<
"target";
3608 Diag(Tok, diag::warn_omp_more_one_interop_type) <<
"targetsync";
3609 IsTargetSync =
true;
3612 PreferTypeAllowed) {
3615 tok::annot_pragma_openmp_end);
3616 if (PT.expectAndConsume(diag::err_expected_lparen_after,
"prefer_type"))
3619 while (Tok.
isNot(tok::r_paren)) {
3621 ExprResult LHS = ParseCastExpression(AnyCastExpr);
3630 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3634 if (Tok.
is(tok::comma))
3640 Diag(Tok, diag::err_omp_expected_interop_type);
3643 if (!Tok.
is(tok::comma))
3648 if (!HasError && !IsTarget && !IsTargetSync) {
3649 Diag(Tok, diag::err_omp_expected_interop_type);
3653 if (Kind == OMPC_init) {
3654 if (Tok.
isNot(tok::colon) && (IsTarget || IsTargetSync))
3655 Diag(Tok, diag::warn_pragma_expected_colon) <<
"interop types";
3656 if (Tok.
is(tok::colon))
3696 if (
T.expectAndConsume(diag::err_expected_lparen_after,
3697 getOpenMPClauseName(Kind).data()))
3700 bool InteropError =
false;
3702 if (Kind == OMPC_init)
3703 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3710 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3716 if (!
T.consumeClose())
3717 RLoc =
T.getCloseLocation();
3719 if (ParseOnly || !InteropVarExpr.
isUsable() || InteropError)
3722 if (Kind == OMPC_init)
3724 InteropVarExpr.
get(), InteropInfo,
Loc,
T.getOpenLocation(), VarLoc,
3726 if (Kind == OMPC_use)
3728 InteropVarExpr.
get(),
Loc,
T.getOpenLocation(), VarLoc, RLoc);
3730 if (Kind == OMPC_destroy)
3732 InteropVarExpr.
get(),
Loc,
T.getOpenLocation(), VarLoc, RLoc);
3734 llvm_unreachable(
"Unexpected interop variable clause.");
3737OMPClause *Parser::ParseOpenMPOMPXAttributesClause(
bool ParseOnly) {
3741 if (
T.expectAndConsume(diag::err_expected_lparen_after,
3742 getOpenMPClauseName(OMPC_ompx_attribute).data()))
3746 ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
3749 if (
T.consumeClose())
3757 switch (PA.getKind()) {
3758 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
3759 if (!PA.checkExactlyNumArgs(Actions, 2))
3762 PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
3765 case ParsedAttr::AT_AMDGPUWavesPerEU:
3766 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3767 !PA.checkAtMostNumArgs(Actions, 2))
3770 PA, PA.getArgAsExpr(0),
3771 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) :
nullptr))
3774 case ParsedAttr::AT_CUDALaunchBounds:
3775 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3776 !PA.checkAtMostNumArgs(Actions, 2))
3779 PA, PA.getArgAsExpr(0),
3780 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) :
nullptr,
3781 PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) :
nullptr))
3785 Diag(
Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
3791 Attrs,
Loc,
T.getOpenLocation(),
T.getCloseLocation());
3812 if (!Val || ParseOnly)
3814 if (
getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3815 (
static_cast<DefaultKind
>(Val->Type) == OMP_DEFAULT_private ||
3816 static_cast<DefaultKind
>(Val->Type) ==
3817 OMP_DEFAULT_firstprivate)) {
3818 Diag(Val->LOpen, diag::err_omp_invalid_dsa)
3819 << getOpenMPClauseName(
static_cast<DefaultKind
>(Val->Type) ==
3822 : OMPC_firstprivate)
3823 << getOpenMPClauseName(OMPC_default) <<
"5.1";
3827 Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
3888 if (
T.expectAndConsume(diag::err_expected_lparen_after,
3889 getOpenMPClauseName(Kind).data()))
3895 if (Kind == OMPC_schedule) {
3896 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
3897 Arg.resize(NumberOfElements);
3898 KLoc.resize(NumberOfElements);
3906 Arg[Modifier1] = KindModifier;
3908 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3909 Tok.
isNot(tok::annot_pragma_openmp_end))
3911 if (Tok.
is(tok::comma)) {
3920 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3921 Tok.
isNot(tok::annot_pragma_openmp_end))
3925 if (Tok.
is(tok::colon))
3928 Diag(Tok, diag::warn_pragma_expected_colon) <<
"schedule modifier";
3932 Arg[ScheduleKind] = KindModifier;
3934 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3935 Tok.
isNot(tok::annot_pragma_openmp_end))
3937 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
3938 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
3939 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
3942 }
else if (Kind == OMPC_dist_schedule) {
3946 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3947 Tok.
isNot(tok::annot_pragma_openmp_end))
3949 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.
is(tok::comma))
3951 }
else if (Kind == OMPC_defaultmap) {
3959 Arg.push_back(Modifier);
3961 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3962 Tok.
isNot(tok::annot_pragma_openmp_end))
3966 if (Tok.
is(tok::colon))
3969 Diag(Tok, diag::warn_pragma_expected_colon) <<
"defaultmap modifier";
3974 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3975 Tok.
isNot(tok::annot_pragma_openmp_end))
3981 }
else if (Kind == OMPC_order) {
3982 enum { Modifier, OrderKind, NumberOfElements };
3983 Arg.resize(NumberOfElements);
3984 KLoc.resize(NumberOfElements);
3991 Arg[Modifier] = KindModifier;
3993 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3994 Tok.
isNot(tok::annot_pragma_openmp_end))
3997 if (Tok.
is(tok::colon))
4000 Diag(Tok, diag::warn_pragma_expected_colon) <<
"order modifier";
4004 Arg[OrderKind] = KindModifier;
4006 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
4007 Tok.
isNot(tok::annot_pragma_openmp_end))
4009 }
else if (Kind == OMPC_device) {
4022 KLoc.emplace_back();
4024 }
else if (Kind == OMPC_grainsize) {
4032 Arg.push_back(Modifier);
4039 if (Modifier == OMPC_GRAINSIZE_strict) {
4040 Diag(Tok, diag::err_modifier_expected_colon) <<
"strict";
4045 KLoc.emplace_back();
4049 KLoc.emplace_back();
4051 }
else if (Kind == OMPC_num_tasks) {
4059 Arg.push_back(Modifier);
4066 if (Modifier == OMPC_NUMTASKS_strict) {
4067 Diag(Tok, diag::err_modifier_expected_colon) <<
"strict";
4072 KLoc.emplace_back();
4076 KLoc.emplace_back();
4079 assert(Kind == OMPC_if);
4081 TentativeParsingAction TPA(*
this);
4084 if (DK != OMPD_unknown) {
4091 Arg.back() =
unsigned(OMPD_unknown);
4098 bool NeedAnExpression = (
Kind == OMPC_schedule && DelimLoc.
isValid()) ||
4099 (Kind == OMPC_dist_schedule && DelimLoc.
isValid()) ||
4100 Kind == OMPC_if || Kind == OMPC_device ||
4101 Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
4102 if (NeedAnExpression) {
4112 if (!
T.consumeClose())
4113 RLoc =
T.getCloseLocation();
4115 if (NeedAnExpression && Val.
isInvalid())
4121 Kind, Arg, Val.
get(),
Loc,
T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4126 if (ReductionIdScopeSpec.
isEmpty()) {
4128 switch (
P.getCurToken().getKind()) {
4163 return P.ParseUnqualifiedId(
4164 ReductionIdScopeSpec,
nullptr,
4168 false,
nullptr, ReductionId);
4174 Token Tok =
P.getCurToken();
4175 if (!Tok.
is(tok::identifier))
4182 return TypeModifier;
4189 if (
T.expectAndConsume(diag::err_expected_lparen_after,
"mapper")) {
4190 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4196 ParseOptionalCXXScopeSpecifier(
Data.ReductionOrMapperIdScopeSpec,
4200 if (Tok.
isNot(tok::identifier) && Tok.
isNot(tok::kw_default)) {
4202 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4211 return T.consumeClose();
4222 bool HasMapType =
false;
4224 StringRef PreMapName =
"";
4228 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4229 TypeModifier == OMPC_MAP_MODIFIER_close ||
4230 TypeModifier == OMPC_MAP_MODIFIER_present ||
4231 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4232 Data.MapTypeModifiers.push_back(TypeModifier);
4237 <<
"map type modifier";
4239 }
else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4240 Data.MapTypeModifiers.push_back(TypeModifier);
4245 if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::colon) &&
4247 Diag(
Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4248 <<
"map type modifier";
4253 Data.ExtraModifier = MapKind;
4258 Diag(Tok, diag::err_omp_more_one_map_type);
4259 Diag(PreMapLoc, diag::note_previous_map_type_specified_here)
4267 if (Tok.
is(tok::comma)) {
4268 Diag(Tok, diag::err_omp_map_type_modifier_missing);
4281 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4291 if (!Tok.
is(tok::colon)) {
4292 Diag(Tok, diag::err_omp_unknown_map_type);
4304 Token Tok =
P.getCurToken();
4306 if (!Tok.
isOneOf(tok::identifier, tok::kw_delete))
4311 if (MapType == OMPC_MAP_to || MapType == OMPC_MAP_from ||
4312 MapType == OMPC_MAP_tofrom || MapType == OMPC_MAP_alloc ||
4313 MapType == OMPC_MAP_delete || MapType == OMPC_MAP_release)
4322 Token Tok =
P.getCurToken();
4323 if (Tok.
is(tok::colon)) {
4324 P.Diag(Tok, diag::err_omp_map_type_missing);
4329 P.Diag(Tok, diag::err_omp_unknown_map_type);
4335ExprResult Parser::ParseOpenMPIteratorsExpr() {
4336 assert(Tok.
is(tok::identifier) && PP.
getSpelling(Tok) ==
"iterator" &&
4337 "Expected 'iterator' token.");
4341 if (
T.expectAndConsume(diag::err_expected_lparen_after,
"iterator"))
4346 while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end)) {
4349 if (Tok.
isNot(tok::identifier) ||
NextToken().isNot(tok::equal)) {
4356 IteratorType = TR.
get();
4362 if (Tok.
is(tok::identifier)) {
4366 Diag(Tok, diag::err_expected_unqualified_id) << 0;
4371 if (Tok.
is(tok::equal))
4374 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4380 ExprResult LHS = ParseCastExpression(AnyCastExpr);
4387 if (Tok.
is(tok::colon))
4392 LHS = ParseCastExpression(AnyCastExpr);
4401 if (Tok.
is(tok::colon)) {
4406 LHS = ParseCastExpression(AnyCastExpr);
4414 if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren))
4415 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4416 if (Tok.
is(tok::comma))
4422 D.
Type = IteratorType;
4433 if (!
T.consumeClose())
4434 RLoc =
T.getCloseLocation();
4445 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4448 if (Tok.
is(tok::identifier) &&
4451 if (
Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4452 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4453 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4454 else if (
Data.ExtraModifier != OMPC_DEPEND_out &&
4455 Data.ExtraModifier != OMPC_DEPEND_inout)
4456 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4458 Data.ExtraModifier =
Data.ExtraModifier == OMPC_DEPEND_out
4459 ? OMPC_DEPEND_outallmemory
4460 : OMPC_DEPEND_inoutallmemory;
4472 Sema &Actions =
P.getActions();
4476 Data.DepModOrTailExpr = Tail.
get();
4477 Token CurTok =
P.getCurToken();
4478 if (CurTok.
isNot(tok::r_paren) && CurTok.
isNot(tok::comma)) {
4479 P.Diag(CurTok, diag::err_expected_punc) <<
"step expression";
4492 bool InvalidReductionId =
false;
4493 bool IsInvalidMapperModifier =
false;
4497 if (
T.expectAndConsume(diag::err_expected_lparen_after,
4498 getOpenMPClauseName(Kind).data()))
4501 bool HasIterator =
false;
4502 bool InvalidIterator =
false;
4503 bool NeedRParenForLinear =
false;
4505 tok::annot_pragma_openmp_end);
4507 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4508 Kind == OMPC_in_reduction) {
4510 if (Kind == OMPC_reduction &&
getLangOpts().OpenMP >= 50 &&
4511 (Tok.
is(tok::identifier) || Tok.
is(tok::kw_default)) &&
4514 Data.ExtraModifier =
4518 assert(Tok.
is(tok::comma) &&
"Expected comma.");
4523 ParseOptionalCXXScopeSpecifier(
Data.ReductionOrMapperIdScopeSpec,
4528 *
this,
Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4529 if (InvalidReductionId) {
4530 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4533 if (Tok.
is(tok::colon))
4536 Diag(Tok, diag::warn_pragma_expected_colon) <<
"reduction identifier";
4537 if (!InvalidReductionId)
4538 Data.ReductionOrMapperId =
4540 }
else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4542 if (Tok.
is(tok::identifier) && PP.
getSpelling(Tok) ==
"iterator") {
4551 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4552 Data.DepModOrTailExpr = IteratorRes.
get();
4554 ExpectAndConsume(tok::comma);
4564 (Kind == OMPC_doacross &&
4566 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4571 if (DKind == OMPD_ordered && Kind == OMPC_depend &&
4572 Data.ExtraModifier == OMPC_DEPEND_source) {
4578 if (Tok.
is(tok::colon)) {
4580 }
else if (Kind != OMPC_doacross || Tok.
isNot(tok::r_paren)) {
4581 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
4582 : diag::warn_pragma_expected_colon)
4583 << (Kind == OMPC_depend ?
"dependency type" :
"dependence-type");
4585 if (Kind == OMPC_doacross) {
4586 if (Tok.
is(tok::identifier) &&
4588 Data.ExtraModifier =
Data.ExtraModifier == OMPC_DOACROSS_source
4589 ? OMPC_DOACROSS_source_omp_cur_iteration
4590 : OMPC_DOACROSS_sink_omp_cur_iteration;
4593 if (
Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
4594 if (Tok.
isNot(tok::minus)) {
4595 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4596 << getOpenMPClauseName(Kind) << 0 << 0;
4603 if (Tok.
isNot(tok::numeric_constant) ||
4605 Diag(
Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
4606 << getOpenMPClauseName(Kind) << 0 << 0;
4612 if (
Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
4613 if (Tok.
isNot(tok::r_paren)) {
4614 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4615 << getOpenMPClauseName(Kind) << 1 << 1;
4621 if (Kind == OMPC_doacross &&
4622 (
Data.ExtraModifier == OMPC_DOACROSS_source ||
4623 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
4624 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
4630 }
else if (Kind == OMPC_linear) {
4632 Data.ExtraModifier = OMPC_LINEAR_val;
4633 if (Tok.
is(tok::identifier) && PP.
LookAhead(0).
is(tok::l_paren)) {
4634 Data.ExtraModifier =
4638 NeedRParenForLinear =
true;
4640 Diag(
Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
4641 <<
"linear-modifier(list)" << getOpenMPClauseName(Kind)
4642 <<
"linear(list: [linear-modifier,] step(step-size))";
4644 }
else if (Kind == OMPC_lastprivate) {
4651 Tok.
is(tok::identifier) && PP.
LookAhead(0).
is(tok::colon)) {
4652 Data.ExtraModifier =
4656 assert(Tok.
is(tok::colon) &&
"Expected colon.");
4659 }
else if (Kind == OMPC_map) {
4661 if (Tok.
is(tok::identifier) && PP.
getSpelling(Tok) ==
"iterator") {
4664 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
4666 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4667 Data.IteratorExpr = IteratorRes.
get();
4669 ExpectAndConsume(tok::comma);
4671 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4674 InvalidIterator =
true;
4687 TentativeParsingAction TPA(*
this);
4688 bool ColonPresent =
false;
4689 if (
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4691 if (Tok.
is(tok::colon))
4692 ColonPresent =
true;
4699 Diag(Tok, diag::err_omp_map_modifier_specification_list);
4701 if (
getLangOpts().OpenMP < 60 && !IsInvalidMapperModifier)
4707 Data.ExtraModifier = OMPC_MAP_tofrom;
4709 if (DKind == OMPD_target_enter_data)
4710 Data.ExtraModifier = OMPC_MAP_to;
4711 else if (DKind == OMPD_target_exit_data)
4712 Data.ExtraModifier = OMPC_MAP_from;
4714 Data.IsMapTypeImplicit =
true;
4717 if (Tok.
is(tok::colon))
4719 }
else if (Kind == OMPC_to || Kind == OMPC_from) {
4720 while (Tok.
is(tok::identifier)) {
4725 Data.MotionModifiers.push_back(Modifier);
4728 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
4730 if (IsInvalidMapperModifier)
4738 if (Tok.
is(tok::comma))
4741 if (!
Data.MotionModifiers.empty() && Tok.
isNot(tok::colon)) {
4742 if (!IsInvalidMapperModifier) {
4744 Diag(Tok, diag::warn_pragma_expected_colon) <<
")";
4746 Diag(Tok, diag::warn_pragma_expected_colon) <<
"motion modifier";
4748 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4756 }
else if (Kind == OMPC_allocate ||
4757 (Kind == OMPC_affinity && Tok.
is(tok::identifier) &&
4761 TentativeParsingAction TPA(*
this);
4766 if (Kind == OMPC_allocate) {
4771 Tail = ParseOpenMPIteratorsExpr();
4777 if (Tok.
is(tok::colon)) {
4778 Data.DepModOrTailExpr = Tail.
get();
4789 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4792 }
else if (Kind == OMPC_adjust_args) {
4800 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4804 if (Tok.
is(tok::colon))
4806 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
4812 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
4813 Kind != OMPC_in_reduction && Kind != OMPC_depend &&
4814 Kind != OMPC_doacross && Kind != OMPC_map) ||
4815 (Kind == OMPC_reduction && !InvalidReductionId) ||
4819 (Kind == OMPC_adjust_args &&
4821 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
4822 while (IsComma || (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::colon) &&
4823 Tok.
isNot(tok::annot_pragma_openmp_end))) {
4831 Vars.push_back(VarExpr.
get());
4833 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4838 IsComma = Tok.
is(tok::comma);
4841 else if (Tok.
isNot(tok::r_paren) &&
4842 Tok.
isNot(tok::annot_pragma_openmp_end) &&
4843 (!MayHaveTail || Tok.
isNot(tok::colon)))
4844 Diag(Tok, diag::err_omp_expected_punc)
4845 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
4846 : getOpenMPClauseName(Kind))
4847 << (Kind == OMPC_flush);
4851 if (NeedRParenForLinear)
4856 const bool MustHaveTail = MayHaveTail && Tok.
is(tok::colon);
4857 bool StepFound =
false;
4858 bool ModifierFound =
false;
4863 if (
getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
4864 while (Tok.
isNot(tok::r_paren)) {
4865 if (Tok.
is(tok::identifier)) {
4873 if (LinKind == OMPC_LINEAR_step) {
4875 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
4878 tok::annot_pragma_openmp_end);
4882 Diag(StepModifierLoc, diag::err_expected_lparen_after) <<
"step";
4887 Data.StepModifierLoc = StepModifierLoc;
4891 }
else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
4893 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
4895 Data.ExtraModifier = LinKind;
4897 ModifierFound =
true;
4906 if (Tok.
is(tok::comma))
4908 if (Tok.
is(tok::r_paren) || Tok.
is(tok::annot_pragma_openmp_end))
4911 if (!StepFound && !ModifierFound)
4912 Diag(ELoc, diag::err_expected_expression);
4919 Data.DepModOrTailExpr = Tail.
get();
4921 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4928 if (!
T.consumeClose())
4929 Data.RLoc =
T.getCloseLocation();
4933 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
4935 (MustHaveTail && !
Data.DepModOrTailExpr && StepFound) ||
4936 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
5019 assert(getOpenMPClauseName(Kind) == PP.
getSpelling(Tok) &&
5020 "Expected parsing to start at clause name");
5025 if (
T.consumeOpen()) {
5026 Diag(Tok, diag::err_expected) << tok::l_paren;
5039 Exprs.push_back(Val.
get());
5042 bool Result =
T.consumeClose();
5043 OpenLoc =
T.getOpenLocation();
5044 CloseLoc =
T.getCloseLocation();
Defines the clang::ASTContext interface.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P)
static OpenMPMapModifierKind isMapModifier(Parser &P)
Checks if the token is a valid map-type-modifier.
static std::optional< SimpleClauseData > parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind)
static unsigned getOpenMPDirectiveKindEx(StringRef S)
static bool checkExtensionProperty(Parser &P, SourceLocation Loc, OMPTraitProperty &TIProperty, OMPTraitSelector &TISelector, llvm::StringMap< SourceLocation > &Seen)
static DeclarationName parseOpenMPReductionId(Parser &P)
static ExprResult parseContextScore(Parser &P)
Parse optional 'score' '(' <expr> ')' ':'.
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data, OpenMPClauseKind CKind, SourceLocation ELoc)
Parse step size expression.
static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data)
Parse map-type in map clause.
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.
static OpenMPMapClauseKind isMapType(Parser &P)
Checks if the token is a valid map-type.
This file declares facilities that support code completion.
This file declares semantic analysis for OpenMP constructs and clauses.
This file defines OpenMP AST classes for executable directives and clauses.
Defines the clang::TokenKind enum and support functions.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
DeclarationNameTable DeclarationNames
OMPTraitInfo & getNewOMPTraitInfo()
Return a new OMPTraitInfo object owned by this context.
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....
Represents a C++ nested-name-specifier or a global scope specifier.
bool isEmpty() const
No scope specifier.
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed.
Captures information about "declaration specifiers".
static const TST TST_unspecified
Decl - This represents one declaration (or definition), e.g.
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
SourceLocation getLocation() const
DeclContext * getDeclContext()
The name of a declaration.
Information about one declarator, including the parsed type information and the identifier.
RAII object that enters a new expression evaluation context.
bool isValueDependent() const
Determines whether the value of this expression depends on.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
One of these records is kept for each identifier that is lexed.
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.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
This represents a decl that may have a name.
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
This is a basic class for representing single OpenMP clause.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
llvm::SmallVector< OMPTraitSet, 2 > Sets
The outermost level of selector sets.
Wrapper for void* pointer.
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing,...
ParsedAttr - Represents a syntactic attribute.
static const ParsedAttributesView & none()
ParsedAttributes - A collection of parsed attributes.
Introduces zero or more scopes for parsing.
ParseScope - Introduces a new scope for parsing.
Parser - This implements a parser for the C family of languages.
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, SemaOpenMP::OpenMPVarListDataTy &Data)
Parses clauses with list.
TypeResult ParseTypeName(SourceRange *Range=nullptr, DeclaratorContext Context=DeclaratorContext::TypeName, AccessSpecifier AS=AS_none, Decl **OwnedType=nullptr, ParsedAttributes *Attrs=nullptr)
ParseTypeName type-name: [C99 6.7.6] specifier-qualifier-list abstract-declarator[opt].
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
bool parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses map-type-modifiers in map clause.
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
void EnterScope(unsigned ScopeFlags)
EnterScope - Start a new scope.
bool parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses the mapper modifier in map, to, and from clauses.
bool ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, SourceLocation *TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
ExprResult ParseConstantExpression()
bool TryConsumeToken(tok::TokenKind Expected)
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Scope * getCurScope() const
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...
const Token & getCurToken() const
void ExitScope()
ExitScope - Pop a scope off the scope stack.
ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)
Parse an expr that doesn't include (top-level) commas.
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc, bool IsAddressOfOperand=false)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
const LangOptions & getLangOpts() const
ExprResult ParseExpression(TypeCastState isTypeCast=NotTypeCast)
Simple precedence-based parser for binary/ternary operators.
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
bool ParseOpenMPReservedLocator(OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data, const LangOptions &LangOpts)
Parses a reserved locator like 'omp_all_memory'.
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
A class for parsing a DeclSpec.
Activates OpenMP parsing mode to preseve OpenMP specific annotation tokens.
void enterVariableInit(SourceLocation Tok, Decl *D)
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void EnterToken(const Token &Tok, bool IsReinject)
Enters a token in the token stream to be lexed next.
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value)
Parses a simple integer literal to get its numeric value.
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 isCodeCompletionReached() const
Returns true if code-completion is enabled and we have hit the code-completion point.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
The collection of all-type qualifiers we support.
Represents a struct/union/class.
Scope - A scope is a transient data structure that is used while parsing the program.
@ OpenMPDirectiveScope
This is the scope of OpenMP executable directive.
@ CompoundStmtScope
This is a compound statement scope.
@ OpenMPSimdDirectiveScope
This is the scope of some OpenMP simd directive.
@ FnScope
This indicates that the scope corresponds to a function, which means that labels are set here.
@ OpenMPLoopDirectiveScope
This is the scope of some OpenMP loop directive.
@ DeclScope
This is a scope that can contain a declaration.
Smart pointer class that efficiently represents Objective-C method names.
QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, ArrayRef< Expr * > Args, SourceLocation OpenParLoc, bool Braced)
void CodeCompleteInitializer(Scope *S, Decl *D)
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
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'.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind PrevMappedDirective=llvm::omp::OMPD_unknown)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare mapper'.
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
A RAII object to enter scope of a compound statement.
Sema - This implements semantic analysis and AST building for C.
Scope * getCurScope() const
Retrieve the parser's current scope.
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)
CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...
AMDGPUFlatWorkGroupSizeAttr * CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
void ActOnReenterFunctionContext(Scope *S, Decl *D)
Push the parameters of D, which must be a function, into scope.
void FinalizeDeclaration(Decl *D)
FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform any semantic actions neces...
DeclarationNameInfo GetNameForDeclarator(Declarator &D)
GetNameForDeclarator - Determine the full declaration name for the given Declarator.
AMDGPUWavesPerEUAttr * CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
ASTContext & getASTContext() const
ExprResult ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val)
SemaCodeCompletion & CodeCompletion()
DeclContext * getCurLexicalContext() const
DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef< Decl * > Group)
BuildDeclaratorGroup - convert a list of declarations into a declaration group, performing any necess...
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name)
Retrieves the declaration name from a parsed unqualified-id.
void ActOnInitializerError(Decl *Dcl)
ActOnInitializerError - Given that there was an error parsing an initializer for the given declaratio...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
CUDALaunchBoundsAttr * CreateLaunchBoundsAttr(const AttributeCommonInfo &CI, Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks)
Create an CUDALaunchBoundsAttr attribute.
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})
Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
StringLiteral - This represents a string literal expression, e.g.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
bool isAnyIdentifier() const
Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...
SourceLocation getEndLoc() 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 isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
bool isNot(tok::TokenKind K) const
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
Base wrapper for a particular "section" of type source info.
The base class of the type hierarchy.
QualType getCanonicalTypeInternal() const
Represents a C++ unqualified-id that has been parsed.
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
Represents a variable declaration or definition.
Directive - Abstract class representing a parsed verify directive.
Defines the clang::TargetInfo interface.
bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
bool isStringLiteral(TokenKind K)
Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.
The JSON file list parser is used to communicate input to InstallAPI.
TypeSpecifierType
Specifies the kind of type.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
@ OMPC_DEFAULTMAP_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ADJUST_ARGS_unknown
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
OpenMPDeviceType
OpenMP device type for 'device_type' clause.
@ OMPC_DEVICE_TYPE_unknown
@ OMPC_SCHEDULE_MODIFIER_unknown
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Property
The type of a property.
@ Result
The result type of a method or function.
@ OMPC_LASTPRIVATE_unknown
OpenMPGrainsizeClauseModifier
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str, const LangOptions &LangOpts)
OpenMPNumTasksClauseModifier
ActionResult< Expr * > ExprResult
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
@ OMPC_MOTION_MODIFIER_unknown
bool operator!=(CanQual< T > x, CanQual< U > y)
@ OMPC_DEFAULTMAP_unknown
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
const FunctionProtoType * T
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
llvm::SmallVector< Expr *, 4 > PreferTypes
llvm::omp::TraitProperty Kind
StringRef RawString
The raw string as we parsed it.
llvm::omp::TraitSelector Kind
llvm::SmallVector< OMPTraitProperty, 1 > Properties
llvm::SmallVector< OMPTraitSelector, 2 > Selectors
This structure contains most locations needed for by an OMPVarListClause.
std::optional< Expr * > Indirect
The directive with indirect clause.
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
SourceLocation Loc
The directive location.
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Data structure for iterator expression.
SourceLocation DeclIdentLoc
SourceLocation SecColonLoc
IdentifierInfo * DeclIdent
OMPIteratorExpr::IteratorRange Range
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * Allocator
Allocator.
Clang specific specialization of the OMPContext to lookup target features.