23#include "llvm/ADT/PointerIntPair.h"
24#include "llvm/ADT/StringSwitch.h"
25#include "llvm/ADT/UniqueVector.h"
26#include "llvm/Frontend/OpenMP/OMPAssume.h"
27#include "llvm/Frontend/OpenMP/OMPContext.h"
31using namespace llvm::omp;
38enum OpenMPDirectiveKindEx {
39 OMPD_cancellation = llvm::omp::Directive_enumSize + 1,
51 OMPD_distribute_parallel,
52 OMPD_teams_distribute_parallel,
53 OMPD_target_teams_distribute_parallel,
63struct OpenMPDirectiveKindExWrapper {
66 bool operator==(OpenMPDirectiveKindExWrapper
V)
const {
69 bool operator!=(OpenMPDirectiveKindExWrapper
V)
const {
80class DeclDirectiveListParserHelper final {
89 ExprResult Res =
P->getActions().ActOnOpenMPIdExpression(
90 P->getCurScope(), SS, NameInfo, Kind);
92 Identifiers.push_back(Res.
get());
101 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
102 if (DKind != OMPD_unknown)
105 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
106 .Case(
"cancellation", OMPD_cancellation)
107 .Case(
"data", OMPD_data)
108 .Case(
"declare", OMPD_declare)
109 .Case(
"end", OMPD_end)
110 .Case(
"enter", OMPD_enter)
111 .Case(
"exit", OMPD_exit)
112 .Case(
"point", OMPD_point)
113 .Case(
"reduction", OMPD_reduction)
114 .Case(
"update", OMPD_update)
115 .Case(
"mapper", OMPD_mapper)
116 .Case(
"variant", OMPD_variant)
117 .Case(
"begin", OMPD_begin)
118 .Default(OMPD_unknown);
125 static const OpenMPDirectiveKindExWrapper F[][3] = {
126 {OMPD_begin, OMPD_declare, OMPD_begin_declare},
127 {OMPD_begin, OMPD_assumes, OMPD_begin_assumes},
128 {OMPD_end, OMPD_declare, OMPD_end_declare},
129 {OMPD_end, OMPD_assumes, OMPD_end_assumes},
130 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
131 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
132 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
133 {OMPD_declare, OMPD_simd, OMPD_declare_simd},
134 {OMPD_declare, OMPD_target, OMPD_declare_target},
135 {OMPD_declare, OMPD_variant, OMPD_declare_variant},
136 {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},
137 {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
138 {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
139 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
140 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
141 {OMPD_distribute_parallel_for, OMPD_simd,
142 OMPD_distribute_parallel_for_simd},
143 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
144 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
145 {OMPD_target, OMPD_data, OMPD_target_data},
146 {OMPD_target, OMPD_enter, OMPD_target_enter},
147 {OMPD_target, OMPD_exit, OMPD_target_exit},
148 {OMPD_target, OMPD_update, OMPD_target_update},
149 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
150 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
151 {OMPD_for, OMPD_simd, OMPD_for_simd},
152 {OMPD_parallel, OMPD_for, OMPD_parallel_for},
153 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
154 {OMPD_parallel, OMPD_loop, OMPD_parallel_loop},
155 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
156 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
157 {OMPD_target, OMPD_parallel, OMPD_target_parallel},
158 {OMPD_target, OMPD_simd, OMPD_target_simd},
159 {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop},
160 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
161 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
162 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
163 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
164 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
165 {OMPD_teams_distribute_parallel, OMPD_for,
166 OMPD_teams_distribute_parallel_for},
167 {OMPD_teams_distribute_parallel_for, OMPD_simd,
168 OMPD_teams_distribute_parallel_for_simd},
169 {OMPD_teams, OMPD_loop, OMPD_teams_loop},
170 {OMPD_target, OMPD_teams, OMPD_target_teams},
171 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
172 {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop},
173 {OMPD_target_teams_distribute, OMPD_parallel,
174 OMPD_target_teams_distribute_parallel},
175 {OMPD_target_teams_distribute, OMPD_simd,
176 OMPD_target_teams_distribute_simd},
177 {OMPD_target_teams_distribute_parallel, OMPD_for,
178 OMPD_target_teams_distribute_parallel_for},
179 {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
180 OMPD_target_teams_distribute_parallel_for_simd},
181 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
182 {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop},
183 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
184 {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd},
185 {OMPD_parallel, OMPD_master, OMPD_parallel_master},
186 {OMPD_parallel, OMPD_masked, OMPD_parallel_masked},
187 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
188 {OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop},
189 {OMPD_parallel_master_taskloop, OMPD_simd,
190 OMPD_parallel_master_taskloop_simd},
191 {OMPD_parallel_masked_taskloop, OMPD_simd,
192 OMPD_parallel_masked_taskloop_simd}};
193 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
194 Token Tok =
P.getCurToken();
195 OpenMPDirectiveKindExWrapper DKind =
197 ?
static_cast<unsigned>(OMPD_unknown)
199 if (DKind == OMPD_unknown)
202 for (
const auto &I : F) {
206 Tok =
P.getPreprocessor().LookAhead(0);
207 OpenMPDirectiveKindExWrapper SDKind =
209 ?
static_cast<unsigned>(OMPD_unknown)
211 if (SDKind == OMPD_unknown)
214 if (SDKind == I[1]) {
219 return unsigned(DKind) < llvm::omp::Directive_enumSize
225 Token Tok =
P.getCurToken();
226 Sema &Actions =
P.getActions();
229 bool WithOperator =
false;
230 if (Tok.
is(tok::kw_operator)) {
232 Tok =
P.getCurToken();
260 case tok::identifier:
265 P.Diag(Tok.
getLocation(), diag::err_omp_expected_reduction_identifier);
266 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
273 : DeclNames.getCXXOperatorName(OOK);
290 if (T.expectAndConsume(
291 diag::err_expected_lparen_after,
292 getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
298 if (Name.isEmpty() && Tok.
is(tok::annot_pragma_openmp_end))
302 bool IsCorrect = !ExpectAndConsume(tok::colon);
304 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
307 IsCorrect = IsCorrect && !Name.isEmpty();
309 if (Tok.
is(tok::colon) || Tok.
is(tok::annot_pragma_openmp_end)) {
314 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
326 if (!ReductionType.
isNull()) {
327 ReductionTypes.push_back(
328 std::make_pair(ReductionType,
Range.getBegin()));
331 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
335 if (Tok.
is(tok::colon) || Tok.
is(tok::annot_pragma_openmp_end))
339 if (ExpectAndConsume(tok::comma)) {
341 if (Tok.
is(tok::annot_pragma_openmp_end)) {
346 }
while (Tok.
isNot(tok::annot_pragma_openmp_end));
348 if (ReductionTypes.empty()) {
353 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
357 if (ExpectAndConsume(tok::colon))
360 if (Tok.
is(tok::annot_pragma_openmp_end)) {
370 unsigned I = 0, E = ReductionTypes.size();
371 for (
Decl *D : DRD.get()) {
372 TentativeParsingAction TPA(*
this);
383 Tok.
isNot(tok::annot_pragma_openmp_end)) {
388 IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.
isUsable();
390 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
392 if (Tok.
is(tok::identifier) &&
403 tok::annot_pragma_openmp_end);
405 !T.expectAndConsume(diag::err_expected_lparen_after,
"initializer") &&
407 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
416 if (Tok.
is(tok::identifier) &&
419 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
426 D, InitializerResult.
get(), OmpPrivParm);
428 Tok.
isNot(tok::annot_pragma_openmp_end)) {
434 !T.consumeClose() && IsCorrect && !InitializerResult.
isInvalid();
450void Parser::ParseOpenMPReductionInitializerForDecl(
VarDecl *OmpPrivParm) {
453 if (isTokenEqualOrEqualTypo()) {
456 if (Tok.
is(tok::code_completion)) {
466 if (Init.isInvalid()) {
473 }
else if (Tok.
is(tok::l_paren)) {
481 auto RunSignatureHelp = [
this, OmpPrivParm, LParLoc, &Exprs]() {
484 OmpPrivParm->
getLocation(), Exprs, LParLoc,
false);
485 CalledSignatureHelp =
true;
486 return PreferredType;
488 if (ParseExpressionList(Exprs, [&] {
489 PreferredType.enterFunctionArgument(Tok.
getLocation(),
499 if (!T.consumeClose())
500 RLoc = T.getCloseLocation();
509 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
513 if (Init.isInvalid()) {
534 bool IsCorrect =
true;
537 if (T.expectAndConsume(diag::err_expected_lparen_after,
538 getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
547 if (Tok.
isNot(tok::identifier) && Tok.
isNot(tok::kw_default)) {
555 ExpectAndConsume(tok::colon);
562 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
581 IsCorrect &= !T.consumeClose();
592 ParseScope OMPDirectiveScope(
this, ScopeFlags);
601 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
607 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
609 Clauses.push_back(Clause);
613 if (Tok.
is(tok::comma))
617 if (Clauses.empty()) {
618 Diag(Tok, diag::err_omp_expected_clause)
619 << getOpenMPDirectiveName(OMPD_declare_mapper);
625 OMPDirectiveScope.Exit();
628 Range.getBegin(), VName, AS, MapperVarRef.
get(), Clauses);
639 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
641 ParseSpecifierQualifierList(DS, AS, DSC);
646 ParseDeclarator(DeclaratorInfo);
647 Range = DeclaratorInfo.getSourceRange();
648 if (DeclaratorInfo.getIdentifier() ==
nullptr) {
663class FNContextRAII final {
667 bool HasFunScope =
false;
668 FNContextRAII() =
delete;
669 FNContextRAII(
const FNContextRAII &) =
delete;
670 FNContextRAII &operator=(
const FNContextRAII &) =
delete;
677 Sema &Actions =
P.getActions();
685 P.ReenterTemplateScopes(Scopes, D);
697 P.getActions().ActOnExitFunctionContext();
716 const Token &Tok =
P.getCurToken();
717 bool IsError =
false;
718 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
719 if (Tok.
isNot(tok::identifier))
721 OMPDeclareSimdDeclAttr::BranchStateTy Out;
723 StringRef ClauseName = II->
getName();
725 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
726 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
727 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
729 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
735 }
else if (ClauseName.equals(
"simdlen")) {
737 P.Diag(Tok, diag::err_omp_more_one_clause)
738 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
743 SimdLen =
P.ParseOpenMPParensExpr(ClauseName, RLoc);
748 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
749 CKind == OMPC_linear) {
752 if (CKind == OMPC_aligned) {
754 }
else if (CKind == OMPC_linear) {
755 Data.ExtraModifier = OMPC_LINEAR_val;
760 if (
P.ParseOpenMPVarList(OMPD_declare_simd,
761 getOpenMPClauseKind(ClauseName), *Vars,
Data))
763 if (CKind == OMPC_aligned) {
764 Alignments.append(Aligneds.size() - Alignments.size(),
765 Data.DepModOrTailExpr);
766 }
else if (CKind == OMPC_linear) {
767 assert(0 <=
Data.ExtraModifier &&
769 "Unexpected linear modifier.");
770 if (
P.getActions().CheckOpenMPLinearModifier(
772 Data.ExtraModifierLoc))
773 Data.ExtraModifier = OMPC_LINEAR_val;
774 LinModifiers.append(Linears.size() - LinModifiers.size(),
776 Steps.append(Linears.size() - Steps.size(),
Data.DepModOrTailExpr);
783 if (Tok.
is(tok::comma))
794 PP.EnterTokenStream(Toks,
true,
800 FNContextRAII FnContext(*
this, Ptr);
801 OMPDeclareSimdDeclAttr::BranchStateTy BS =
802 OMPDeclareSimdDeclAttr::BS_Undefined;
812 Alignments, Linears, LinModifiers, Steps);
813 skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
819 Ptr, BS, Simdlen.
get(), Uniforms, Aligneds, Alignments, Linears,
827 CONTEXT_SELECTOR_SET_LVL = 0,
828 CONTEXT_SELECTOR_LVL = 1,
829 CONTEXT_TRAIT_LVL = 2,
832static StringRef stringLiteralParser(
Parser &
P) {
833 ExprResult Res =
P.ParseStringLiteralExpression(
true);
837static StringRef getNameFromIdOrString(
Parser &
P,
Token &Tok,
839 if (Tok.
is(tok::identifier) || Tok.
is(tok::kw_for)) {
841 StringRef Name =
P.getPreprocessor().getSpelling(Tok, Buffer);
842 (void)
P.ConsumeToken();
847 return stringLiteralParser(
P);
850 diag::warn_omp_declare_variant_string_literal_or_identifier)
855static bool checkForDuplicates(
Parser &
P, StringRef Name,
857 llvm::StringMap<SourceLocation> &Seen,
859 auto Res = Seen.try_emplace(Name, NameLoc);
865 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
867 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
874 llvm::omp::TraitSet Set,
876 llvm::StringMap<SourceLocation> &Seen) {
877 TIProperty.
Kind = TraitProperty::invalid;
880 StringRef Name = getNameFromIdOrString(*
this, Tok, CONTEXT_TRAIT_LVL);
883 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set,
Selector);
888 TIProperty.
Kind = getOpenMPContextTraitPropertyKind(Set,
Selector, Name);
889 if (TIProperty.
Kind != TraitProperty::invalid) {
890 if (checkForDuplicates(*
this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
891 TIProperty.
Kind = TraitProperty::invalid;
897 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
898 << Name << getOpenMPContextTraitSelectorName(
Selector)
899 << getOpenMPContextTraitSetName(Set);
901 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
902 if (SetForName != TraitSet::invalid) {
903 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
904 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
905 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
906 << Name <<
"<selector-name>"
907 <<
"(<property-name>)";
910 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
911 if (SelectorForName != TraitSelector::invalid) {
912 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
913 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
914 bool AllowsTraitScore =
false;
915 bool RequiresProperty =
false;
916 isValidTraitSelectorForTraitSet(
917 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
918 AllowsTraitScore, RequiresProperty);
919 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
920 << getOpenMPContextTraitSetName(
921 getOpenMPContextTraitSetForSelector(SelectorForName))
922 << Name << (RequiresProperty ?
"(<property-name>)" :
"");
925 for (
const auto &PotentialSet :
926 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
928 TraitProperty PropertyForName =
929 getOpenMPContextTraitPropertyKind(PotentialSet,
Selector, Name);
930 if (PropertyForName == TraitProperty::invalid)
932 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
933 << getOpenMPContextTraitSetName(
934 getOpenMPContextTraitSetForProperty(PropertyForName))
935 << getOpenMPContextTraitSelectorName(
936 getOpenMPContextTraitSelectorForProperty(PropertyForName))
937 << (
"(" + Name +
")").str();
940 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
941 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(Set,
Selector);
947 llvm::StringMap<SourceLocation> &Seen) {
948 assert(TISelector.
Kind ==
949 llvm::omp::TraitSelector::implementation_extension &&
950 "Only for extension properties, e.g., "
951 "`implementation={extension(PROPERTY)}`");
952 if (TIProperty.
Kind == TraitProperty::invalid)
955 if (TIProperty.
Kind ==
956 TraitProperty::implementation_extension_disable_implicit_base)
959 if (TIProperty.
Kind ==
960 TraitProperty::implementation_extension_allow_templates)
963 if (TIProperty.
Kind ==
964 TraitProperty::implementation_extension_bind_to_declaration)
969 llvm::omp::TraitProperty::implementation_extension_match_all ||
971 llvm::omp::TraitProperty::implementation_extension_match_any ||
973 llvm::omp::TraitProperty::implementation_extension_match_none);
976 if (IsMatchExtension(TIProperty)) {
978 if (IsMatchExtension(SeenProp)) {
979 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
980 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
983 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
984 << CONTEXT_TRAIT_LVL << SeenName;
990 llvm_unreachable(
"Unknown extension property!");
994 llvm::omp::TraitSet Set,
995 llvm::StringMap<SourceLocation> &Seen) {
996 assert(TISelector.
Kind != TraitSelector::user_condition &&
997 "User conditions are special properties not handled here!");
1001 parseOMPTraitPropertyKind(TIProperty, Set, TISelector.
Kind, Seen);
1003 if (TISelector.
Kind == llvm::omp::TraitSelector::implementation_extension)
1006 TIProperty.
Kind = TraitProperty::invalid;
1009 if (TIProperty.
Kind == TraitProperty::invalid) {
1011 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1012 << CONTEXT_TRAIT_LVL;
1016 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.
Kind,
1017 TISelector.
Kind, Set)) {
1025 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
1026 << getOpenMPContextTraitPropertyName(TIProperty.
Kind,
1028 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1029 << getOpenMPContextTraitSetName(Set);
1030 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
1031 << getOpenMPContextTraitPropertyName(TIProperty.
Kind,
1033 << getOpenMPContextTraitSelectorName(
1034 getOpenMPContextTraitSelectorForProperty(TIProperty.
Kind))
1035 << getOpenMPContextTraitSetName(
1036 getOpenMPContextTraitSetForProperty(TIProperty.
Kind));
1037 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1038 << CONTEXT_TRAIT_LVL;
1042 llvm::omp::TraitSet Set,
1043 llvm::StringMap<SourceLocation> &Seen) {
1044 TISelector.
Kind = TraitSelector::invalid;
1047 StringRef Name = getNameFromIdOrString(*
this, Tok, CONTEXT_SELECTOR_LVL);
1050 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1054 TISelector.
Kind = getOpenMPContextTraitSelectorKind(Name);
1055 if (TISelector.
Kind != TraitSelector::invalid) {
1056 if (checkForDuplicates(*
this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
1057 TISelector.
Kind = TraitSelector::invalid;
1062 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
1063 << Name << getOpenMPContextTraitSetName(Set);
1065 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
1066 if (SetForName != TraitSet::invalid) {
1067 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1068 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
1069 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1070 << Name <<
"<selector-name>"
1071 <<
"<property-name>";
1074 for (
const auto &PotentialSet :
1075 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1076 TraitSet::device}) {
1077 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1078 PotentialSet, TraitSelector::invalid, Name);
1079 if (PropertyForName == TraitProperty::invalid)
1081 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1082 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
1083 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1084 << getOpenMPContextTraitSetName(
1085 getOpenMPContextTraitSetForProperty(PropertyForName))
1086 << getOpenMPContextTraitSelectorName(
1087 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1088 << (
"(" + Name +
")").str();
1091 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1092 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(Set);
1099 StringRef SelectorName =
1100 P.getPreprocessor().getSpelling(
P.getCurToken(), Buffer);
1101 if (!SelectorName.equals(
"score"))
1103 (void)
P.ConsumeToken();
1105 ScoreExpr =
P.ParseOpenMPParensExpr(SelectorName, RLoc);
1107 if (
P.getCurToken().is(tok::colon))
1108 (
void)
P.ConsumeAnyToken();
1110 P.Diag(
P.getCurToken(), diag::warn_omp_declare_variant_expected)
1112 <<
"score expression";
1119void Parser::parseOMPContextSelector(
1121 llvm::StringMap<SourceLocation> &SeenSelectors) {
1122 unsigned short OuterPC = ParenCount;
1127 auto FinishSelector = [OuterPC,
this]() ->
void {
1130 while (!
SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
1131 tok::annot_pragma_openmp_end},
1134 if (Tok.
is(tok::r_paren) && OuterPC > ParenCount)
1135 (
void)ConsumeParen();
1136 if (OuterPC <= ParenCount) {
1140 if (!Tok.
is(tok::comma) && !Tok.
is(tok::r_paren)) {
1146 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1147 << CONTEXT_SELECTOR_LVL;
1151 parseOMPTraitSelectorKind(TISelector, Set, SeenSelectors);
1152 if (TISelector.
Kind == TraitSelector::invalid)
1153 return FinishSelector();
1155 bool AllowsTraitScore =
false;
1156 bool RequiresProperty =
false;
1157 if (!isValidTraitSelectorForTraitSet(TISelector.
Kind, Set, AllowsTraitScore,
1158 RequiresProperty)) {
1159 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
1160 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1161 << getOpenMPContextTraitSetName(Set);
1162 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
1163 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1164 << getOpenMPContextTraitSetName(
1165 getOpenMPContextTraitSetForSelector(TISelector.
Kind))
1166 << RequiresProperty;
1167 return FinishSelector();
1170 if (!RequiresProperty) {
1172 {getOpenMPContextTraitPropertyForSelector(TISelector.
Kind),
1173 getOpenMPContextTraitSelectorName(TISelector.
Kind)});
1177 if (!Tok.
is(tok::l_paren)) {
1178 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
1179 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1180 << getOpenMPContextTraitSetName(Set);
1181 return FinishSelector();
1184 if (TISelector.
Kind == TraitSelector::user_condition) {
1188 return FinishSelector();
1191 {TraitProperty::user_condition_unknown,
"<condition>"});
1196 tok::annot_pragma_openmp_end);
1198 (void)BDT.consumeOpen();
1203 if (!AllowsTraitScore && !Score.
isUnset()) {
1205 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1206 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1207 << getOpenMPContextTraitSetName(Set) << Score.
get();
1209 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1210 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1211 << getOpenMPContextTraitSetName(Set) <<
"<invalid>";
1219 llvm::StringMap<SourceLocation> SeenProperties;
1221 parseOMPContextProperty(TISelector, Set, SeenProperties);
1228void Parser::parseOMPTraitSetKind(
OMPTraitSet &TISet,
1229 llvm::StringMap<SourceLocation> &Seen) {
1230 TISet.
Kind = TraitSet::invalid;
1233 StringRef Name = getNameFromIdOrString(*
this, Tok, CONTEXT_SELECTOR_SET_LVL);
1236 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1240 TISet.
Kind = getOpenMPContextTraitSetKind(Name);
1241 if (TISet.
Kind != TraitSet::invalid) {
1242 if (checkForDuplicates(*
this, Name, NameLoc, Seen,
1243 CONTEXT_SELECTOR_SET_LVL))
1244 TISet.
Kind = TraitSet::invalid;
1249 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
1251 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
1252 if (SelectorForName != TraitSelector::invalid) {
1253 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1254 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
1255 bool AllowsTraitScore =
false;
1256 bool RequiresProperty =
false;
1257 isValidTraitSelectorForTraitSet(
1258 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
1259 AllowsTraitScore, RequiresProperty);
1260 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1261 << getOpenMPContextTraitSetName(
1262 getOpenMPContextTraitSetForSelector(SelectorForName))
1263 << Name << (RequiresProperty ?
"(<property-name>)" :
"");
1266 for (
const auto &PotentialSet :
1267 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1268 TraitSet::device}) {
1269 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1270 PotentialSet, TraitSelector::invalid, Name);
1271 if (PropertyForName == TraitProperty::invalid)
1273 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1274 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
1275 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1276 << getOpenMPContextTraitSetName(
1277 getOpenMPContextTraitSetForProperty(PropertyForName))
1278 << getOpenMPContextTraitSelectorName(
1279 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1280 << (
"(" + Name +
")").str();
1283 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1284 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1290void Parser::parseOMPContextSelectorSet(
1291 OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
1292 auto OuterBC = BraceCount;
1297 auto FinishSelectorSet = [
this, OuterBC]() ->
void {
1300 while (!
SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
1301 tok::annot_pragma_openmp_end},
1304 if (Tok.
is(tok::r_brace) && OuterBC > BraceCount)
1305 (
void)ConsumeBrace();
1306 if (OuterBC <= BraceCount) {
1310 if (!Tok.
is(tok::comma) && !Tok.
is(tok::r_brace)) {
1316 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1317 << CONTEXT_SELECTOR_SET_LVL;
1320 parseOMPTraitSetKind(TISet, SeenSets);
1321 if (TISet.
Kind == TraitSet::invalid)
1322 return FinishSelectorSet();
1328 << (
"context set name \"" + getOpenMPContextTraitSetName(TISet.
Kind) +
1333 if (Tok.
is(tok::l_brace)) {
1334 (void)ConsumeBrace();
1338 << (
"'=' that follows the context set name \"" +
1339 getOpenMPContextTraitSetName(TISet.
Kind) +
"\"")
1343 llvm::StringMap<SourceLocation> SeenSelectors;
1346 parseOMPContextSelector(TISelector, TISet.
Kind, SeenSelectors);
1347 if (TISelector.
Kind != TraitSelector::invalid &&
1353 if (Tok.
is(tok::r_brace)) {
1354 (void)ConsumeBrace();
1358 << (
"context selectors for the context set \"" +
1359 getOpenMPContextTraitSetName(TISet.
Kind) +
"\"")
1368 llvm::StringMap<SourceLocation> SeenSets;
1371 parseOMPContextSelectorSet(TISet, SeenSets);
1372 if (TISet.
Kind != TraitSet::invalid && !TISet.
Selectors.empty())
1373 TI.
Sets.push_back(TISet);
1384 PP.EnterTokenStream(Toks,
true,
1390 FNContextRAII FnContext(*
this, Ptr);
1402 getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1405 if (!AssociatedFunction.
isUsable()) {
1406 if (!Tok.
is(tok::annot_pragma_openmp_end))
1410 (void)ConsumeAnnotationToken();
1414 OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
1423 if (Tok.
is(tok::annot_pragma_openmp_end)) {
1428 bool IsError =
false;
1429 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1433 if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
1442 IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
1444 case OMPC_adjust_args: {
1452 llvm::append_range(
Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing
1454 : AdjustNeedDevicePtr,
1458 case OMPC_append_args:
1459 if (!AppendArgs.empty()) {
1460 Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
1461 << getOpenMPDirectiveName(OMPD_declare_variant)
1462 << getOpenMPClauseName(CKind) << 0;
1468 IsError = parseOpenMPAppendArgs(AppendArgs);
1472 llvm_unreachable(
"Unexpected clause for declare variant.");
1479 (void)ConsumeAnnotationToken();
1483 if (Tok.
is(tok::comma))
1487 std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1489 Ptr, AssociatedFunction.
get(), TI, AppendArgs.size(),
1492 if (DeclVarData && !TI.
Sets.empty())
1494 DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
1495 AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc,
1499 (void)ConsumeAnnotationToken();
1502bool Parser::parseOpenMPAppendArgs(
1504 bool HasError =
false;
1507 if (T.expectAndConsume(diag::err_expected_lparen_after,
1508 getOpenMPClauseName(OMPC_append_args).data()))
1516 tok::annot_pragma_openmp_end);
1517 if (IT.expectAndConsume(diag::err_expected_lparen_after,
"interop"))
1521 if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
1524 InteropInfos.push_back(InteropInfo);
1527 if (Tok.
is(tok::comma))
1530 if (!HasError && InteropInfos.empty()) {
1533 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1536 HasError = T.consumeClose() || HasError;
1540bool Parser::parseOMPDeclareVariantMatchClause(
SourceLocation Loc,
1547 if (CKind != OMPC_match) {
1555 if (T.expectAndConsume(diag::err_expected_lparen_after,
1556 getOpenMPClauseName(OMPC_match).data()))
1560 parseOMPContextSelectors(Loc, TI);
1563 (void)T.consumeClose();
1574 bool MergedSet =
false;
1580 bool MergedSelector =
false;
1584 MergedSelector =
true;
1587 bool MergedProperty =
false;
1601 if (
Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1602 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
1603 }
else if (
Selector.ScoreOrCondition !=
1605 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1606 << getOpenMPContextTraitPropertyName(
1608 << getOpenMPContextTraitSelectorName(ParentSelector.
Kind)
1609 << getOpenMPContextTraitSetName(ParentSet.
Kind);
1612 if (!MergedProperty)
1613 Selector.Properties.push_back(ParentProperty);
1616 if (!MergedSelector)
1617 Set.
Selectors.push_back(ParentSelector);
1621 TI.
Sets.push_back(ParentSet);
1638 llvm::omp::Clause_enumSize + 1>
1639 FirstClauses(llvm::omp::Clause_enumSize + 1);
1640 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1646 DKind, CKind, !FirstClauses[
unsigned(CKind)].getInt());
1647 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1649 FirstClauses[
unsigned(CKind)].setInt(
true);
1650 if (Clause !=
nullptr)
1651 Clauses.push_back(Clause);
1652 if (Tok.
is(tok::annot_pragma_openmp_end)) {
1657 if (Tok.
is(tok::comma))
1678 bool SkippedClauses =
false;
1680 auto SkipBraces = [&](llvm::StringRef Spelling,
bool IssueNote) {
1682 tok::annot_pragma_openmp_end);
1683 if (T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
1686 if (IssueNote && T.getCloseLocation().isValid())
1687 Diag(T.getCloseLocation(),
1688 diag::note_omp_assumption_clause_continue_here);
1694 auto MatchACMClause = [&](StringRef RawString) {
1695 llvm::StringSwitch<int> SS(RawString);
1696 unsigned ACMIdx = 0;
1697 for (
const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
1698 if (ACMI.StartsWith)
1699 SS.StartsWith(ACMI.Identifier, ACMIdx++);
1701 SS.Case(ACMI.Identifier, ACMIdx++);
1703 return SS.Default(-1);
1706 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1712 Idx = MatchACMClause(II->
getName());
1716 bool NextIsLPar = Tok.
is(tok::l_paren);
1719 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
1720 << llvm::omp::getOpenMPDirectiveName(DKind)
1721 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
1723 SkipBraces(II ? II->
getName() :
"",
true);
1724 SkippedClauses =
true;
1727 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
1728 if (ACMI.HasDirectiveList || ACMI.HasExpression) {
1731 SkippedClauses =
true;
1732 SkipBraces(II->
getName(),
false);
1738 diag::warn_omp_unknown_assumption_clause_without_args)
1740 SkipBraces(II->
getName(),
true);
1743 assert(II &&
"Expected an identifier clause!");
1744 std::string Assumption = II->
getName().str();
1745 if (ACMI.StartsWith)
1746 Assumption =
"ompx_" + Assumption.substr(ACMI.Identifier.size());
1748 Assumption =
"omp_" + Assumption;
1749 Assumptions.push_back(Assumption);
1759 Diag(Loc, diag::err_expected_begin_assumes);
1773struct SimpleClauseData {
1785static std::optional<SimpleClauseData>
1787 const Token &Tok =
P.getCurToken();
1793 getOpenMPClauseName(Kind).data()))
1794 return std::nullopt;
1797 Kind, Tok.
isAnnotation() ?
"" :
P.getPreprocessor().getSpelling(Tok),
1800 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1801 Tok.
isNot(tok::annot_pragma_openmp_end))
1802 P.ConsumeAnyToken();
1809 return SimpleClauseData(
Type, Loc, LOpen,
TypeLoc, RLoc);
1812void Parser::ParseOMPDeclareTargetClauses(
1813 Sema::DeclareTargetContextInfo &DTCI) {
1815 bool RequiresToOrLinkOrIndirectClause =
false;
1816 bool HasToOrLinkOrIndirectClause =
false;
1817 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1818 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1819 bool HasIdentifier = Tok.
is(tok::identifier);
1820 if (HasIdentifier) {
1822 RequiresToOrLinkOrIndirectClause =
true;
1824 StringRef ClauseName = II->
getName();
1825 bool IsDeviceTypeClause =
1827 getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1829 bool IsIndirectClause =
getLangOpts().OpenMP >= 51 &&
1830 getOpenMPClauseKind(ClauseName) == OMPC_indirect;
1831 if (DTCI.Indirect && IsIndirectClause) {
1832 Diag(Tok, diag::err_omp_more_one_clause)
1833 << getOpenMPDirectiveName(OMPD_declare_target)
1834 << getOpenMPClauseName(OMPC_indirect) << 0;
1837 bool IsToEnterOrLinkClause =
1838 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1839 assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
1844 if (
getLangOpts().OpenMP >= 52 && ClauseName ==
"to") {
1845 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
1848 if (
getLangOpts().OpenMP <= 51 && ClauseName ==
"enter") {
1849 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
1853 if (!IsDeviceTypeClause && !IsIndirectClause &&
1854 DTCI.Kind == OMPD_begin_declare_target) {
1855 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1856 << ClauseName << (
getLangOpts().OpenMP >= 51 ? 3 : 0);
1859 if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
1861 ? diag::err_omp_declare_target_unexpected_clause_52
1862 : diag::err_omp_declare_target_unexpected_clause)
1870 if (IsToEnterOrLinkClause || IsIndirectClause)
1871 HasToOrLinkOrIndirectClause =
true;
1873 if (IsIndirectClause) {
1874 if (!ParseOpenMPIndirectClause(DTCI,
false))
1879 if (IsDeviceTypeClause) {
1880 std::optional<SimpleClauseData> DevTypeData =
1883 if (DeviceTypeLoc.
isValid()) {
1885 Diag(DevTypeData->Loc,
1886 diag::warn_omp_more_one_device_type_clause);
1890 case OMPC_DEVICE_TYPE_any:
1891 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Any;
1893 case OMPC_DEVICE_TYPE_host:
1894 DTCI.DT = OMPDeclareTargetDeclAttr::DT_Host;
1896 case OMPC_DEVICE_TYPE_nohost:
1897 DTCI.DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1900 llvm_unreachable(
"Unexpected device_type");
1902 DeviceTypeLoc = DevTypeData->Loc;
1909 if (DTCI.Kind == OMPD_declare_target || HasIdentifier) {
1917 bool FirstMapping = DTCI.ExplicitlyMapped.try_emplace(ND, MI).second;
1919 Diag(NameInfo.
getLoc(), diag::err_omp_declare_target_multiple)
1922 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1927 if (Tok.
is(tok::l_paren)) {
1929 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1932 if (!HasIdentifier && Tok.
isNot(tok::annot_pragma_openmp_end)) {
1935 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1936 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1941 if (Tok.
is(tok::comma))
1945 if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
1946 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
1949 if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
1950 !HasToOrLinkOrIndirectClause)
1953 ? diag::err_omp_declare_target_missing_enter_or_link_clause
1954 : diag::err_omp_declare_target_missing_to_or_link_clause)
1963 if (Tok.
is(tok::annot_pragma_openmp_end))
1966 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1967 << getOpenMPDirectiveName(DKind);
1968 while (Tok.
isNot(tok::annot_pragma_openmp_end))
1977 bool SkipUntilOpenMPEnd) {
1978 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1980 if (FoundKind == ExpectedKind) {
1982 skipUntilPragmaOpenMPEnd(ExpectedKind);
1986 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1988 Diag(BeginLoc, diag::note_matching)
1989 << (
"'#pragma omp " + getOpenMPDirectiveName(BeginKind) +
"'").str();
1990 if (SkipUntilOpenMPEnd)
1997 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
2001 if (Tok.
is(tok::annot_pragma_openmp_end))
2002 ConsumeAnnotationToken();
2044 assert(Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2045 "Not an OpenMP directive!");
2052 TentativeParsingAction TPA(*
this);
2053 Loc = ConsumeAnnotationToken();
2055 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
2060 Toks.push_back(Tok);
2061 while (Cnt && Tok.
isNot(tok::eof)) {
2063 if (Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
2065 else if (Tok.
is(tok::annot_pragma_openmp_end))
2067 Toks.push_back(Tok);
2072 auto *LP =
new LateParsedPragma(
this, AS);
2074 getCurrentClass().LateParsedDeclarations.push_back(LP);
2079 Loc = ConsumeAnnotationToken();
2084 case OMPD_threadprivate: {
2086 DeclDirectiveListParserHelper Helper(
this, DKind);
2087 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2089 skipUntilPragmaOpenMPEnd(DKind);
2091 ConsumeAnnotationToken();
2093 Helper.getIdentifiers());
2097 case OMPD_allocate: {
2099 DeclDirectiveListParserHelper Helper(
this, DKind);
2100 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2103 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2105 llvm::omp::Clause_enumSize + 1>
2106 FirstClauses(llvm::omp::Clause_enumSize + 1);
2107 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2113 OMPD_allocate, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2114 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2116 FirstClauses[
unsigned(CKind)].setInt(
true);
2117 if (Clause !=
nullptr)
2118 Clauses.push_back(Clause);
2119 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2124 if (Tok.
is(tok::comma))
2128 skipUntilPragmaOpenMPEnd(DKind);
2131 ConsumeAnnotationToken();
2137 case OMPD_requires: {
2141 llvm::omp::Clause_enumSize + 1>
2142 FirstClauses(llvm::omp::Clause_enumSize + 1);
2143 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2144 Diag(Tok, diag::err_omp_expected_clause)
2145 << getOpenMPDirectiveName(OMPD_requires);
2148 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2154 OMPD_requires, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2155 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2157 FirstClauses[
unsigned(CKind)].setInt(
true);
2158 if (Clause !=
nullptr)
2159 Clauses.push_back(Clause);
2160 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2165 if (Tok.
is(tok::comma))
2170 if (Clauses.empty()) {
2171 Diag(Tok, diag::err_omp_expected_clause)
2172 << getOpenMPDirectiveName(OMPD_requires);
2173 ConsumeAnnotationToken();
2176 ConsumeAnnotationToken();
2182 ParseOpenMPClauses(DKind, Clauses, StartLoc);
2188 case OMPD_begin_assumes:
2191 case OMPD_end_assumes:
2194 case OMPD_declare_reduction:
2196 if (
DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2197 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2199 ConsumeAnnotationToken();
2203 case OMPD_declare_mapper: {
2205 if (
DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
2207 ConsumeAnnotationToken();
2212 case OMPD_begin_declare_variant: {
2219 OMPTraitInfo *ParentTI = Actions.getOMPTraitInfoForSurroundingScope();
2222 if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
2226 (void)ConsumeAnnotationToken();
2231 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
2235 VariantMatchInfo VMI;
2238 std::function<void(StringRef)> DiagUnknownTrait =
2239 [
this, Loc](StringRef ISATrait) {
2242 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2245 ASTCtx, std::move(DiagUnknownTrait),
2249 if (isVariantApplicableInContext(VMI, OMPCtx,
true)) {
2255 unsigned Nesting = 1;
2261 if (DK == OMPD_end_declare_variant)
2263 else if (DK == OMPD_begin_declare_variant)
2265 if (!Nesting || isEofOrEom())
2270 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
2271 DK, Loc, DKLoc,
true);
2276 case OMPD_end_declare_variant: {
2280 Diag(Loc, diag::err_expected_begin_declare_variant);
2284 case OMPD_declare_variant:
2285 case OMPD_declare_simd: {
2291 Toks.push_back(Tok);
2293 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2294 Toks.push_back(Tok);
2297 Toks.push_back(Tok);
2301 if (Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
2302 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2304 }
else if (Tok.
isNot(tok::r_brace) && !isEofOrEom()) {
2309 MaybeParseCXX11Attributes(Attrs);
2311 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
2314 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs,
TagType, Tag);
2318 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2319 << (DKind == OMPD_declare_simd ? 0 : 1);
2322 if (DKind == OMPD_declare_simd)
2323 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
2324 assert(DKind == OMPD_declare_variant &&
2325 "Expected declare variant directive only");
2326 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
2329 case OMPD_begin_declare_target:
2330 case OMPD_declare_target: {
2332 bool HasClauses = Tok.
isNot(tok::annot_pragma_openmp_end);
2333 Sema::DeclareTargetContextInfo DTCI(DKind, DTLoc);
2335 ParseOMPDeclareTargetClauses(DTCI);
2336 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
2338 (DTCI.ExplicitlyMapped.empty() && DTCI.Indirect);
2343 if (HasImplicitMappings) {
2350 for (
auto &It : DTCI.ExplicitlyMapped)
2351 Decls.push_back(It.first);
2354 case OMPD_end_declare_target: {
2356 Diag(Tok, diag::err_omp_unexpected_directive)
2357 << 1 << getOpenMPDirectiveName(DKind);
2360 const Sema::DeclareTargetContextInfo &DTCI =
2362 ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
2366 Diag(Tok, diag::err_omp_unknown_directive);
2373 case OMPD_taskyield:
2376 case OMPD_taskgroup:
2388 case OMPD_parallel_for:
2389 case OMPD_parallel_for_simd:
2390 case OMPD_parallel_sections:
2391 case OMPD_parallel_master:
2392 case OMPD_parallel_masked:
2396 case OMPD_cancellation_point:
2398 case OMPD_target_data:
2399 case OMPD_target_enter_data:
2400 case OMPD_target_exit_data:
2401 case OMPD_target_parallel:
2402 case OMPD_target_parallel_for:
2404 case OMPD_taskloop_simd:
2405 case OMPD_master_taskloop:
2406 case OMPD_master_taskloop_simd:
2407 case OMPD_parallel_master_taskloop:
2408 case OMPD_parallel_master_taskloop_simd:
2409 case OMPD_masked_taskloop:
2410 case OMPD_masked_taskloop_simd:
2411 case OMPD_parallel_masked_taskloop:
2412 case OMPD_parallel_masked_taskloop_simd:
2413 case OMPD_distribute:
2414 case OMPD_target_update:
2415 case OMPD_distribute_parallel_for:
2416 case OMPD_distribute_parallel_for_simd:
2417 case OMPD_distribute_simd:
2418 case OMPD_target_parallel_for_simd:
2419 case OMPD_target_simd:
2420 case OMPD_teams_distribute:
2421 case OMPD_teams_distribute_simd:
2422 case OMPD_teams_distribute_parallel_for_simd:
2423 case OMPD_teams_distribute_parallel_for:
2424 case OMPD_target_teams:
2425 case OMPD_target_teams_distribute:
2426 case OMPD_target_teams_distribute_parallel_for:
2427 case OMPD_target_teams_distribute_parallel_for_simd:
2428 case OMPD_target_teams_distribute_simd:
2431 case OMPD_metadirective:
2433 case OMPD_teams_loop:
2434 case OMPD_target_teams_loop:
2435 case OMPD_parallel_loop:
2436 case OMPD_target_parallel_loop:
2437 Diag(Tok, diag::err_omp_unexpected_directive)
2438 << 1 << getOpenMPDirectiveName(DKind);
2443 while (Tok.
isNot(tok::annot_pragma_openmp_end))
2489StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2490 ParsedStmtContext StmtCtx,
bool ReadDirectiveWithinMetadirective) {
2491 if (!ReadDirectiveWithinMetadirective)
2492 assert(Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2493 "Not an OpenMP directive!");
2498 llvm::omp::Clause_enumSize + 1>
2499 FirstClauses(llvm::omp::Clause_enumSize + 1);
2504 : ConsumeAnnotationToken(),
2507 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2508 Diag(Tok, diag::err_omp_unknown_directive);
2515 bool HasAssociatedStatement =
true;
2519 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2520 ParsedStmtContext())
2521 Diag(Tok, diag::err_omp_immediate_directive)
2522 << getOpenMPDirectiveName(DKind) << 0;
2524 skipUntilPragmaOpenMPEnd(DKind);
2525 if (Tok.
is(tok::annot_pragma_openmp_end))
2526 ConsumeAnnotationToken();
2528 case OMPD_metadirective: {
2535 TentativeParsingAction TPA(*
this);
2539 tok::annot_pragma_openmp_end);
2540 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2547 if (T.expectAndConsume(diag::err_expected_lparen_after,
2548 getOpenMPClauseName(CKind).data()))
2552 if (CKind == OMPC_when) {
2554 parseOMPContextSelectors(Loc, TI);
2555 if (TI.
Sets.size() == 0) {
2556 Diag(Tok, diag::err_omp_expected_context_selector) <<
"when clause";
2562 if (Tok.
is(tok::colon))
2565 Diag(Tok, diag::err_omp_expected_colon) <<
"when clause";
2572 while (Tok.
isNot(tok::r_paren) || paren != 0) {
2573 if (Tok.
is(tok::l_paren))
2575 if (Tok.
is(tok::r_paren))
2577 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2578 Diag(Tok, diag::err_omp_expected_punc)
2579 << getOpenMPClauseName(CKind) << 0;
2586 if (Tok.
is(tok::r_paren))
2589 VariantMatchInfo VMI;
2592 VMIs.push_back(VMI);
2598 std::function<void(StringRef)> DiagUnknownTrait =
2599 [
this, Loc](StringRef ISATrait) {
2602 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2609 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2616 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2618 if (Idx++ != BestIdx) {
2623 while (Tok.
isNot(tok::r_paren) || paren != 0) {
2624 if (Tok.
is(tok::l_paren))
2626 if (Tok.
is(tok::r_paren))
2631 if (Tok.
is(tok::r_paren))
2645 if (CKind == OMPC_when) {
2648 parseOMPContextSelectors(Loc, TI);
2656 if (Tok.
is(tok::r_paren)) {
2657 SkipUntil(tok::annot_pragma_openmp_end);
2662 Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2669 case OMPD_threadprivate: {
2671 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
2672 ParsedStmtContext()) {
2673 Diag(Tok, diag::err_omp_immediate_directive)
2674 << getOpenMPDirectiveName(DKind) << 0;
2677 DeclDirectiveListParserHelper Helper(
this, DKind);
2678 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2680 skipUntilPragmaOpenMPEnd(DKind);
2682 Loc, Helper.getIdentifiers());
2685 SkipUntil(tok::annot_pragma_openmp_end);
2688 case OMPD_allocate: {
2690 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
2691 ParsedStmtContext()) {
2692 Diag(Tok, diag::err_omp_immediate_directive)
2693 << getOpenMPDirectiveName(DKind) << 0;
2696 DeclDirectiveListParserHelper Helper(
this, DKind);
2697 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2700 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2702 llvm::omp::Clause_enumSize + 1>
2703 FirstClauses(llvm::omp::Clause_enumSize + 1);
2704 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2710 OMPD_allocate, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2711 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2713 FirstClauses[
unsigned(CKind)].setInt(
true);
2714 if (Clause !=
nullptr)
2715 Clauses.push_back(Clause);
2716 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2721 if (Tok.
is(tok::comma))
2725 skipUntilPragmaOpenMPEnd(DKind);
2728 Loc, Helper.getIdentifiers(), Clauses);
2731 SkipUntil(tok::annot_pragma_openmp_end);
2734 case OMPD_declare_reduction:
2737 ParseOpenMPDeclareReductionDirective(
AS_none)) {
2738 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2742 SkipUntil(tok::annot_pragma_openmp_end);
2745 case OMPD_declare_mapper: {
2748 ParseOpenMPDeclareMapperDirective(
AS_none)) {
2750 ConsumeAnnotationToken();
2753 SkipUntil(tok::annot_pragma_openmp_end);
2760 case OMPD_taskyield:
2764 case OMPD_cancellation_point:
2766 case OMPD_target_enter_data:
2767 case OMPD_target_exit_data:
2768 case OMPD_target_update:
2770 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2771 ParsedStmtContext()) {
2772 Diag(Tok, diag::err_omp_immediate_directive)
2773 << getOpenMPDirectiveName(DKind) << 0;
2774 if (DKind == OMPD_error) {
2775 SkipUntil(tok::annot_pragma_openmp_end);
2779 HasAssociatedStatement =
false;
2793 case OMPD_parallel_for:
2794 case OMPD_parallel_for_simd:
2795 case OMPD_parallel_sections:
2796 case OMPD_parallel_master:
2797 case OMPD_parallel_masked:
2803 case OMPD_taskgroup:
2804 case OMPD_target_data:
2805 case OMPD_target_parallel:
2806 case OMPD_target_parallel_for:
2808 case OMPD_teams_loop:
2809 case OMPD_target_teams_loop:
2810 case OMPD_parallel_loop:
2811 case OMPD_target_parallel_loop:
2813 case OMPD_taskloop_simd:
2814 case OMPD_master_taskloop:
2815 case OMPD_masked_taskloop:
2816 case OMPD_master_taskloop_simd:
2817 case OMPD_masked_taskloop_simd:
2818 case OMPD_parallel_master_taskloop:
2819 case OMPD_parallel_masked_taskloop:
2820 case OMPD_parallel_master_taskloop_simd:
2821 case OMPD_parallel_masked_taskloop_simd:
2822 case OMPD_distribute:
2823 case OMPD_distribute_parallel_for:
2824 case OMPD_distribute_parallel_for_simd:
2825 case OMPD_distribute_simd:
2826 case OMPD_target_parallel_for_simd:
2827 case OMPD_target_simd:
2828 case OMPD_teams_distribute:
2829 case OMPD_teams_distribute_simd:
2830 case OMPD_teams_distribute_parallel_for_simd:
2831 case OMPD_teams_distribute_parallel_for:
2832 case OMPD_target_teams:
2833 case OMPD_target_teams_distribute:
2834 case OMPD_target_teams_distribute_parallel_for:
2835 case OMPD_target_teams_distribute_parallel_for_simd:
2836 case OMPD_target_teams_distribute_simd:
2841 bool ImplicitClauseAllowed =
false;
2842 if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2844 ImplicitClauseAllowed =
true;
2848 if (DKind == OMPD_critical) {
2850 tok::annot_pragma_openmp_end);
2851 if (!T.consumeOpen()) {
2857 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2861 }
else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2863 if (Tok.
isNot(tok::annot_pragma_openmp_end))
2871 ParseScope OMPDirectiveScope(
this, ScopeFlags);
2874 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2877 if (ReadDirectiveWithinMetadirective && Tok.
is(tok::r_paren)) {
2878 while (Tok.
isNot(tok::annot_pragma_openmp_end))
2882 bool HasImplicitClause =
false;
2883 if (ImplicitClauseAllowed && Tok.
is(tok::l_paren)) {
2884 HasImplicitClause =
true;
2894 if (HasImplicitClause) {
2895 assert(CKind == OMPC_unknown &&
"Must be unknown implicit clause.");
2896 if (DKind == OMPD_flush) {
2899 assert(DKind == OMPD_depobj &&
2900 "Expected flush or depobj directives.");
2901 CKind = OMPC_depobj;
2905 ImplicitClauseAllowed =
false;
2907 HasImplicitClause =
false;
2909 DKind, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2910 FirstClauses[
unsigned(CKind)].setInt(
true);
2912 FirstClauses[
unsigned(CKind)].setPointer(Clause);
2913 Clauses.push_back(Clause);
2917 if (Tok.
is(tok::comma))
2924 ConsumeAnnotationToken();
2929 if (DKind == OMPD_ordered && FirstClauses[
unsigned(OMPC_depend)].getInt()) {
2930 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2931 ParsedStmtContext()) {
2932 Diag(Loc, diag::err_omp_immediate_directive)
2933 << getOpenMPDirectiveName(DKind) << 1
2934 << getOpenMPClauseName(OMPC_depend);
2936 HasAssociatedStatement =
false;
2939 if (DKind == OMPD_tile && !FirstClauses[
unsigned(OMPC_sizes)].getInt()) {
2940 Diag(Loc, diag::err_omp_required_clause)
2941 << getOpenMPDirectiveName(OMPD_tile) <<
"sizes";
2945 if (HasAssociatedStatement) {
2954 AssociatedStmt = ParseStatement();
2961 }
else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2962 DKind == OMPD_target_exit_data) {
2970 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.
get(), Loc,
2975 OMPDirectiveScope.Exit();
2978 case OMPD_declare_simd:
2979 case OMPD_declare_target:
2980 case OMPD_begin_declare_target:
2981 case OMPD_end_declare_target:
2983 case OMPD_begin_declare_variant:
2984 case OMPD_end_declare_variant:
2985 case OMPD_declare_variant:
2986 Diag(Tok, diag::err_omp_unexpected_directive)
2987 << 1 << getOpenMPDirectiveName(DKind);
2988 SkipUntil(tok::annot_pragma_openmp_end);
2992 Diag(Tok, diag::err_omp_unknown_directive);
2993 SkipUntil(tok::annot_pragma_openmp_end);
3003bool Parser::ParseOpenMPSimpleVarList(
3007 bool AllowScopeSpecifier) {
3010 if (T.expectAndConsume(diag::err_expected_lparen_after,
3011 getOpenMPDirectiveName(Kind).data()))
3013 bool IsCorrect =
true;
3014 bool NoIdentIsFound =
true;
3017 while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end)) {
3021 Token PrevTok = Tok;
3022 NoIdentIsFound =
false;
3025 ParseOptionalCXXScopeSpecifier(SS,
nullptr,
3028 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3031 false,
false,
false,
3032 false,
false,
nullptr, Name)) {
3034 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3036 }
else if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren) &&
3037 Tok.
isNot(tok::annot_pragma_openmp_end)) {
3039 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3048 if (Tok.
is(tok::comma)) {
3053 if (NoIdentIsFound) {
3054 Diag(Tok, diag::err_expected) << tok::identifier;
3059 IsCorrect = !T.consumeClose() && IsCorrect;
3064OMPClause *Parser::ParseOpenMPSizesClause() {
3069 if (T.consumeOpen()) {
3070 Diag(Tok, diag::err_expected) << tok::l_paren;
3081 ValExprs.push_back(Val.
get());
3083 if (Tok.
is(tok::r_paren) || Tok.
is(tok::annot_pragma_openmp_end))
3086 ExpectAndConsume(tok::comma);
3092 ValExprs, ClauseNameLoc, T.getOpenLocation(), T.getCloseLocation());
3101 if (T.expectAndConsume(diag::err_expected_lparen_after,
"uses_allocator"))
3107 if (Allocator.isInvalid()) {
3108 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3114 if (Tok.
is(tok::l_paren)) {
3116 tok::annot_pragma_openmp_end);
3122 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3130 if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren))
3131 Diag(Tok, diag::err_omp_expected_punc) <<
"uses_allocators" << 0;
3133 if (Tok.
is(tok::comma))
3135 }
while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end));
3138 T.getCloseLocation(),
Data);
3163 OMPClauseKind = CKind;
3165 bool ErrorFound =
false;
3166 bool WrongDirective =
false;
3168 if (CKind != OMPC_unknown &&
3169 !isAllowedClauseForDirective(DKind, CKind,
getLangOpts().OpenMP)) {
3170 Diag(Tok, diag::err_omp_unexpected_clause)
3171 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3173 WrongDirective =
true;
3178 case OMPC_num_threads:
3183 case OMPC_num_teams:
3184 case OMPC_thread_limit:
3186 case OMPC_grainsize:
3187 case OMPC_num_tasks:
3189 case OMPC_allocator:
3192 case OMPC_novariants:
3193 case OMPC_nocontext:
3198 case OMPC_ompx_dyn_cgroup_mem:
3227 Diag(Tok, diag::err_omp_more_one_clause)
3228 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3232 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3234 Clause = ParseOpenMPClause(CKind, WrongDirective);
3235 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
3236 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3238 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3241 case OMPC_proc_bind:
3242 case OMPC_atomic_default_mem_order:
3260 Diag(Tok, diag::err_omp_more_one_clause)
3261 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3265 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3269 case OMPC_dist_schedule:
3270 case OMPC_defaultmap:
3280 if ((
getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3281 (CKind != OMPC_order ||
getLangOpts().OpenMP >= 51) && !FirstClause) {
3282 Diag(Tok, diag::err_omp_more_one_clause)
3283 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3288 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3292 case OMPC_mergeable:
3305 case OMPC_unified_address:
3306 case OMPC_unified_shared_memory:
3307 case OMPC_reverse_offload:
3308 case OMPC_dynamic_allocators:
3317 Diag(Tok, diag::err_omp_more_one_clause)
3318 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3322 Clause = ParseOpenMPClause(CKind, WrongDirective);
3326 Diag(Tok, diag::err_omp_more_one_clause)
3327 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3331 Clause = (DKind == OMPD_depobj)
3332 ? ParseOpenMPSimpleClause(CKind, WrongDirective)
3333 : ParseOpenMPClause(CKind, WrongDirective);
3336 case OMPC_firstprivate:
3337 case OMPC_lastprivate:
3339 case OMPC_reduction:
3340 case OMPC_task_reduction:
3341 case OMPC_in_reduction:
3345 case OMPC_copyprivate:
3351 case OMPC_use_device_ptr:
3352 case OMPC_use_device_addr:
3353 case OMPC_is_device_ptr:
3354 case OMPC_has_device_addr:
3356 case OMPC_nontemporal:
3357 case OMPC_inclusive:
3358 case OMPC_exclusive:
3360 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3364 Diag(Tok, diag::err_omp_more_one_clause)
3365 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3369 Clause = ParseOpenMPSizesClause();
3371 case OMPC_uses_allocators:
3372 Clause = ParseOpenMPUsesAllocatorClause(DKind);
3375 if (DKind != OMPD_interop) {
3377 Diag(Tok, diag::err_omp_more_one_clause)
3378 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3381 Clause = ParseOpenMPClause(CKind, WrongDirective);
3387 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3389 case OMPC_device_type:
3391 skipUntilPragmaOpenMPEnd(DKind);
3393 case OMPC_threadprivate:
3396 if (!WrongDirective)
3397 Diag(Tok, diag::err_omp_unexpected_clause)
3398 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3404 return ErrorFound ? nullptr : Clause;
3412 bool IsAddressOfOperand) {
3414 if (T.
expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3419 ParseCastExpression(AnyCastExpr, IsAddressOfOperand,
NotTypeCast));
3492bool Parser::ParseOpenMPIndirectClause(Sema::DeclareTargetContextInfo &DTCI,
3497 if (Tok.
isNot(tok::l_paren)) {
3500 DTCI.Indirect =
nullptr;
3516 if (
Ret.isInvalid())
3521 if (
Ret.isInvalid())
3523 DTCI.Indirect = Val.
get();
3534 bool HasError =
false;
3535 bool IsTarget =
false;
3536 bool IsTargetSync =
false;
3538 while (Tok.
is(tok::identifier)) {
3540 bool PreferTypeAllowed =
Kind == OMPC_init &&
3548 Diag(Tok, diag::warn_omp_more_one_interop_type) <<
"target";
3553 Diag(Tok, diag::warn_omp_more_one_interop_type) <<
"targetsync";
3554 IsTargetSync =
true;
3557 PreferTypeAllowed) {
3560 tok::annot_pragma_openmp_end);
3561 if (PT.expectAndConsume(diag::err_expected_lparen_after,
"prefer_type"))
3564 while (Tok.
isNot(tok::r_paren)) {
3566 ExprResult LHS = ParseCastExpression(AnyCastExpr);
3575 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3579 if (Tok.
is(tok::comma))
3585 Diag(Tok, diag::err_omp_expected_interop_type);
3588 if (!Tok.
is(tok::comma))
3593 if (!HasError && !IsTarget && !IsTargetSync) {
3594 Diag(Tok, diag::err_omp_expected_interop_type);
3598 if (Kind == OMPC_init) {
3599 if (Tok.
isNot(tok::colon) && (IsTarget || IsTargetSync))
3600 Diag(Tok, diag::warn_pragma_expected_colon) <<
"interop types";
3601 if (Tok.
is(tok::colon))
3641 if (T.expectAndConsume(diag::err_expected_lparen_after,
3642 getOpenMPClauseName(Kind).data()))
3645 bool InteropError =
false;
3647 if (Kind == OMPC_init)
3648 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3655 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3661 if (!T.consumeClose())
3662 RLoc = T.getCloseLocation();
3664 if (ParseOnly || !InteropVarExpr.
isUsable() || InteropError)
3667 if (Kind == OMPC_init)
3669 T.getOpenLocation(), VarLoc, RLoc);
3670 if (Kind == OMPC_use)
3672 T.getOpenLocation(), VarLoc, RLoc);
3674 if (Kind == OMPC_destroy)
3676 T.getOpenLocation(), VarLoc, RLoc);
3678 llvm_unreachable(
"Unexpected interop variable clause.");
3699 if (!Val || ParseOnly)
3701 if (
getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3702 (
static_cast<DefaultKind
>(Val->Type) == OMP_DEFAULT_private ||
3703 static_cast<DefaultKind
>(Val->Type) ==
3704 OMP_DEFAULT_firstprivate)) {
3705 Diag(Val->LOpen, diag::err_omp_invalid_dsa)
3706 << getOpenMPClauseName(
static_cast<DefaultKind
>(Val->Type) ==
3709 : OMPC_firstprivate)
3710 << getOpenMPClauseName(OMPC_default) <<
"5.1";
3714 Val->TypeLoc, Val->LOpen,
3715 Val->Loc, Val->RLoc);
3776 if (T.expectAndConsume(diag::err_expected_lparen_after,
3777 getOpenMPClauseName(Kind).data()))
3783 if (Kind == OMPC_schedule) {
3784 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
3785 Arg.resize(NumberOfElements);
3786 KLoc.resize(NumberOfElements);
3794 Arg[Modifier1] = KindModifier;
3796 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3797 Tok.
isNot(tok::annot_pragma_openmp_end))
3799 if (Tok.
is(tok::comma)) {
3808 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3809 Tok.
isNot(tok::annot_pragma_openmp_end))
3813 if (Tok.
is(tok::colon))
3816 Diag(Tok, diag::warn_pragma_expected_colon) <<
"schedule modifier";
3820 Arg[ScheduleKind] = KindModifier;
3822 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3823 Tok.
isNot(tok::annot_pragma_openmp_end))
3825 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
3826 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
3827 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
3830 }
else if (Kind == OMPC_dist_schedule) {
3834 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3835 Tok.
isNot(tok::annot_pragma_openmp_end))
3837 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.
is(tok::comma))
3839 }
else if (Kind == OMPC_defaultmap) {
3847 Arg.push_back(Modifier);
3849 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3850 Tok.
isNot(tok::annot_pragma_openmp_end))
3854 if (Tok.
is(tok::colon))
3857 Diag(Tok, diag::warn_pragma_expected_colon) <<
"defaultmap modifier";
3862 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3863 Tok.
isNot(tok::annot_pragma_openmp_end))
3869 }
else if (Kind == OMPC_order) {
3870 enum { Modifier, OrderKind, NumberOfElements };
3871 Arg.resize(NumberOfElements);
3872 KLoc.resize(NumberOfElements);
3879 Arg[Modifier] = KindModifier;
3881 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3882 Tok.
isNot(tok::annot_pragma_openmp_end))
3885 if (Tok.
is(tok::colon))
3888 Diag(Tok, diag::warn_pragma_expected_colon) <<
"order modifier";
3892 Arg[OrderKind] = KindModifier;
3894 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3895 Tok.
isNot(tok::annot_pragma_openmp_end))
3897 }
else if (Kind == OMPC_device) {
3910 KLoc.emplace_back();
3912 }
else if (Kind == OMPC_grainsize) {
3920 Arg.push_back(Modifier);
3927 if (Modifier == OMPC_GRAINSIZE_strict) {
3928 Diag(Tok, diag::err_modifier_expected_colon) <<
"strict";
3933 KLoc.emplace_back();
3937 KLoc.emplace_back();
3939 }
else if (Kind == OMPC_num_tasks) {
3947 Arg.push_back(Modifier);
3954 if (Modifier == OMPC_NUMTASKS_strict) {
3955 Diag(Tok, diag::err_modifier_expected_colon) <<
"strict";
3960 KLoc.emplace_back();
3964 KLoc.emplace_back();
3967 assert(Kind == OMPC_if);
3969 TentativeParsingAction TPA(*
this);
3972 if (DK != OMPD_unknown) {
3979 Arg.back() =
unsigned(OMPD_unknown);
3986 bool NeedAnExpression = (
Kind == OMPC_schedule && DelimLoc.
isValid()) ||
3987 (Kind == OMPC_dist_schedule && DelimLoc.
isValid()) ||
3988 Kind == OMPC_if || Kind == OMPC_device ||
3989 Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
3990 if (NeedAnExpression) {
4000 if (!T.consumeClose())
4001 RLoc = T.getCloseLocation();
4003 if (NeedAnExpression && Val.
isInvalid())
4009 Kind, Arg, Val.
get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4014 if (ReductionIdScopeSpec.
isEmpty()) {
4016 switch (
P.getCurToken().getKind()) {
4051 return P.ParseUnqualifiedId(
4052 ReductionIdScopeSpec,
nullptr,
4056 false,
nullptr, ReductionId);
4062 Token Tok =
P.getCurToken();
4063 if (!Tok.
is(tok::identifier))
4070 return TypeModifier;
4078 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4084 ParseOptionalCXXScopeSpecifier(
Data.ReductionOrMapperIdScopeSpec,
4088 if (Tok.
isNot(tok::identifier) && Tok.
isNot(tok::kw_default)) {
4090 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4109 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4110 TypeModifier == OMPC_MAP_MODIFIER_close ||
4111 TypeModifier == OMPC_MAP_MODIFIER_present ||
4112 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4113 Data.MapTypeModifiers.push_back(TypeModifier);
4116 }
else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4117 Data.MapTypeModifiers.push_back(TypeModifier);
4126 if (Tok.
is(tok::comma)) {
4127 Diag(Tok, diag::err_omp_map_type_modifier_missing);
4134 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4149 Token Tok =
P.getCurToken();
4151 if (!Tok.
isOneOf(tok::identifier, tok::kw_delete))
4164 Token Tok =
P.getCurToken();
4165 if (Tok.
is(tok::colon)) {
4166 P.Diag(Tok, diag::err_omp_map_type_missing);
4171 P.Diag(Tok, diag::err_omp_unknown_map_type);
4177ExprResult Parser::ParseOpenMPIteratorsExpr() {
4178 assert(Tok.
is(tok::identifier) && PP.
getSpelling(Tok) ==
"iterator" &&
4179 "Expected 'iterator' token.");
4183 if (T.expectAndConsume(diag::err_expected_lparen_after,
"iterator"))
4188 while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end)) {
4191 if (Tok.
isNot(tok::identifier) ||
NextToken().isNot(tok::equal)) {
4198 IteratorType = TR.
get();
4204 if (Tok.
is(tok::identifier)) {
4208 Diag(Tok, diag::err_expected_unqualified_id) << 0;
4213 if (Tok.
is(tok::equal))
4216 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4222 ExprResult LHS = ParseCastExpression(AnyCastExpr);
4229 if (Tok.
is(tok::colon))
4234 LHS = ParseCastExpression(AnyCastExpr);
4243 if (Tok.
is(tok::colon)) {
4248 LHS = ParseCastExpression(AnyCastExpr);
4256 if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren))
4257 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4258 if (Tok.
is(tok::comma))
4264 D.
Type = IteratorType;
4275 if (!T.consumeClose())
4276 RLoc = T.getCloseLocation();
4287 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4290 if (Tok.
is(tok::identifier) &&
4293 if (
Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4294 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4295 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4296 else if (
Data.ExtraModifier != OMPC_DEPEND_out &&
4297 Data.ExtraModifier != OMPC_DEPEND_inout)
4298 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4300 Data.ExtraModifier =
Data.ExtraModifier == OMPC_DEPEND_out
4301 ? OMPC_DEPEND_outallmemory
4302 : OMPC_DEPEND_inoutallmemory;
4315 bool InvalidReductionId =
false;
4316 bool IsInvalidMapperModifier =
false;
4321 getOpenMPClauseName(Kind).data()))
4324 bool HasIterator =
false;
4325 bool InvalidIterator =
false;
4326 bool NeedRParenForLinear =
false;
4328 tok::annot_pragma_openmp_end);
4330 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4331 Kind == OMPC_in_reduction) {
4333 if (Kind == OMPC_reduction &&
getLangOpts().OpenMP >= 50 &&
4334 (Tok.
is(tok::identifier) || Tok.
is(tok::kw_default)) &&
4337 Data.ExtraModifier =
4341 assert(Tok.
is(tok::comma) &&
"Expected comma.");
4346 ParseOptionalCXXScopeSpecifier(
Data.ReductionOrMapperIdScopeSpec,
4351 *
this,
Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4352 if (InvalidReductionId) {
4353 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4356 if (Tok.
is(tok::colon))
4359 Diag(Tok, diag::warn_pragma_expected_colon) <<
"reduction identifier";
4360 if (!InvalidReductionId)
4361 Data.ReductionOrMapperId =
4363 }
else if (Kind == OMPC_depend) {
4365 if (Tok.
is(tok::identifier) && PP.
getSpelling(Tok) ==
"iterator") {
4374 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4375 Data.DepModOrTailExpr = IteratorRes.
get();
4377 ExpectAndConsume(tok::comma);
4387 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4392 if (DKind == OMPD_ordered &&
Data.ExtraModifier == OMPC_DEPEND_source) {
4398 if (Tok.
is(tok::colon)) {
4401 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
4402 : diag::warn_pragma_expected_colon)
4403 <<
"dependency type";
4405 }
else if (Kind == OMPC_linear) {
4407 Data.ExtraModifier = OMPC_LINEAR_val;
4408 if (Tok.
is(tok::identifier) && PP.
LookAhead(0).
is(tok::l_paren)) {
4409 Data.ExtraModifier =
4413 NeedRParenForLinear =
true;
4415 }
else if (Kind == OMPC_lastprivate) {
4422 Tok.
is(tok::identifier) && PP.
LookAhead(0).
is(tok::colon)) {
4423 Data.ExtraModifier =
4427 assert(Tok.
is(tok::colon) &&
"Expected colon.");
4430 }
else if (Kind == OMPC_map) {
4432 if (Tok.
is(tok::identifier) && PP.
getSpelling(Tok) ==
"iterator") {
4435 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
4437 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4438 Data.IteratorExpr = IteratorRes.
get();
4440 ExpectAndConsume(tok::comma);
4442 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4445 InvalidIterator =
true;
4458 TentativeParsingAction TPA(*
this);
4459 bool ColonPresent =
false;
4460 if (
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4462 if (Tok.
is(tok::colon))
4463 ColonPresent =
true;
4470 if (!IsInvalidMapperModifier)
4476 Data.ExtraModifier = OMPC_MAP_tofrom;
4478 if (DKind == OMPD_target_enter_data)
4479 Data.ExtraModifier = OMPC_MAP_to;
4480 else if (DKind == OMPD_target_exit_data)
4481 Data.ExtraModifier = OMPC_MAP_from;
4483 Data.IsMapTypeImplicit =
true;
4486 if (Tok.
is(tok::colon))
4488 }
else if (Kind == OMPC_to || Kind == OMPC_from) {
4489 while (Tok.
is(tok::identifier)) {
4494 Data.MotionModifiers.push_back(Modifier);
4497 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
4499 if (IsInvalidMapperModifier)
4507 if (Tok.
is(tok::comma))
4510 if (!
Data.MotionModifiers.empty() && Tok.
isNot(tok::colon)) {
4511 if (!IsInvalidMapperModifier) {
4513 Diag(Tok, diag::warn_pragma_expected_colon) <<
")";
4515 Diag(Tok, diag::warn_pragma_expected_colon) <<
"motion modifier";
4517 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4525 }
else if (Kind == OMPC_allocate ||
4526 (Kind == OMPC_affinity && Tok.
is(tok::identifier) &&
4530 TentativeParsingAction TPA(*
this);
4535 if (Kind == OMPC_allocate) {
4540 Tail = ParseOpenMPIteratorsExpr();
4546 if (Tok.
is(tok::colon)) {
4547 Data.DepModOrTailExpr = Tail.
get();
4558 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4561 }
else if (Kind == OMPC_adjust_args) {
4569 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4573 if (Tok.
is(tok::colon))
4575 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
4581 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
4582 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
4583 (Kind == OMPC_reduction && !InvalidReductionId) ||
4586 (Kind == OMPC_adjust_args &&
4588 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
4589 while (IsComma || (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::colon) &&
4590 Tok.
isNot(tok::annot_pragma_openmp_end))) {
4598 Vars.push_back(VarExpr.
get());
4600 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4605 IsComma = Tok.
is(tok::comma);
4608 else if (Tok.
isNot(tok::r_paren) &&
4609 Tok.
isNot(tok::annot_pragma_openmp_end) &&
4610 (!MayHaveTail || Tok.
isNot(tok::colon)))
4611 Diag(Tok, diag::err_omp_expected_punc)
4612 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
4613 : getOpenMPClauseName(Kind))
4614 << (Kind == OMPC_flush);
4618 if (NeedRParenForLinear)
4622 const bool MustHaveTail = MayHaveTail && Tok.
is(tok::colon);
4630 Data.DepModOrTailExpr = Tail.
get();
4632 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4643 return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
4644 (MustHaveTail && !
Data.DepModOrTailExpr) || InvalidReductionId ||
4645 IsInvalidMapperModifier || InvalidIterator;
Defines the clang::ASTContext interface.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
static void parseMapType(Parser &P, Sema::OpenMPVarListDataTy &Data)
Parse map-type in map clause.
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 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 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 { ....
bool expectAndConsume(unsigned DiagID=diag::err_expected, const char *Msg="", tok::TokenKind SkipToTok=tok::unknown)
SourceLocation getOpenLocation() const
SourceLocation getCloseLocation() const
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,...
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.
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)
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
void EnterScope(unsigned ScopeFlags)
EnterScope - Start a new scope.
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.
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, Sema::OpenMPVarListDataTy &Data)
Parses clauses with list.
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.
bool ParseOpenMPReservedLocator(OpenMPClauseKind Kind, Sema::OpenMPVarListDataTy &Data, const LangOptions &LangOpts)
Parses a reserved locator like 'omp_all_memory'.
bool parseMapperModifier(Sema::OpenMPVarListDataTy &Data)
Parses the mapper modifier in map, to, and from clauses.
bool parseMapTypeModifiers(Sema::OpenMPVarListDataTy &Data)
Parses map-type-modifiers in map clause.
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
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.
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.
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.
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
Scope * getCurScope() const
Retrieve the parser's current scope.
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'.
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 * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
void CodeCompleteInitializer(Scope *S, Decl *D)
QualType ProduceConstructorSignatureHelp(QualType Type, SourceLocation Loc, ArrayRef< Expr * > Args, SourceLocation OpenParLoc, bool Braced)
ExprResult CheckBooleanCondition(SourceLocation Loc, Expr *E, bool IsConstexpr=false)
CheckBooleanCondition - Diagnose problems involving the use of the given expression as a boolean cond...
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
void ActOnReenterFunctionContext(Scope *S, Decl *D)
Push the parameters of D, which must be a function, into scope.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
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.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
ASTContext & getASTContext() const
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
ExprResult ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val)
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
DeclContext * getCurLexicalContext() const
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef< Decl * > Group)
BuildDeclaratorGroup - convert a list of declarations into a declaration group, performing any necess...
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
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.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name)
Retrieves the declaration name from a parsed unqualified-id.
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
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 ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, 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'.
void ActOnInitializerError(Decl *Dcl)
ActOnInitializerError - Given that there was an error parsing an initializer for the given declaratio...
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
@ 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 StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
void EndOpenMPClause()
End analysis of clauses.
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...
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
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...
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
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.
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.
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.
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 correspnd...
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.
Data structure for iterator expression.
OMPIteratorExpr::IteratorRange Range
SourceLocation DeclIdentLoc
IdentifierInfo * DeclIdent
SourceLocation SecColonLoc
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Expr * Allocator
Allocator.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * AllocatorTraits
Allocator traits.
Clang specific specialization of the OMPContext to lookup target features.