25#include "llvm/ADT/PointerIntPair.h"
26#include "llvm/ADT/StringSwitch.h"
27#include "llvm/ADT/UniqueVector.h"
28#include "llvm/Frontend/OpenMP/OMPAssume.h"
29#include "llvm/Frontend/OpenMP/OMPContext.h"
33using namespace llvm::omp;
40enum OpenMPDirectiveKindEx {
41 OMPD_cancellation = llvm::omp::Directive_enumSize + 1,
53 OMPD_distribute_parallel,
54 OMPD_teams_distribute_parallel,
55 OMPD_target_teams_distribute_parallel,
65struct OpenMPDirectiveKindExWrapper {
68 bool operator==(OpenMPDirectiveKindExWrapper
V)
const {
71 bool operator!=(OpenMPDirectiveKindExWrapper
V)
const {
82class DeclDirectiveListParserHelper final {
91 ExprResult Res =
P->getActions().OpenMP().ActOnOpenMPIdExpression(
92 P->getCurScope(), SS, NameInfo, Kind);
94 Identifiers.push_back(Res.
get());
103 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
104 if (DKind != OMPD_unknown)
107 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
108 .Case(
"cancellation", OMPD_cancellation)
109 .Case(
"data", OMPD_data)
110 .Case(
"declare", OMPD_declare)
111 .Case(
"end", OMPD_end)
112 .Case(
"enter", OMPD_enter)
113 .Case(
"exit", OMPD_exit)
114 .Case(
"point", OMPD_point)
115 .Case(
"reduction", OMPD_reduction)
116 .Case(
"update", OMPD_update)
117 .Case(
"mapper", OMPD_mapper)
118 .Case(
"variant", OMPD_variant)
119 .Case(
"begin", OMPD_begin)
120 .Default(OMPD_unknown);
127 static const OpenMPDirectiveKindExWrapper F[][3] = {
128 {OMPD_begin, OMPD_declare, OMPD_begin_declare},
129 {OMPD_begin, OMPD_assumes, OMPD_begin_assumes},
130 {OMPD_end, OMPD_declare, OMPD_end_declare},
131 {OMPD_end, OMPD_assumes, OMPD_end_assumes},
132 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
133 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
134 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
135 {OMPD_declare, OMPD_simd, OMPD_declare_simd},
136 {OMPD_declare, OMPD_target, OMPD_declare_target},
137 {OMPD_declare, OMPD_variant, OMPD_declare_variant},
138 {OMPD_begin_declare, OMPD_target, OMPD_begin_declare_target},
139 {OMPD_begin_declare, OMPD_variant, OMPD_begin_declare_variant},
140 {OMPD_end_declare, OMPD_variant, OMPD_end_declare_variant},
141 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
142 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
143 {OMPD_distribute_parallel_for, OMPD_simd,
144 OMPD_distribute_parallel_for_simd},
145 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
146 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
147 {OMPD_target, OMPD_data, OMPD_target_data},
148 {OMPD_target, OMPD_enter, OMPD_target_enter},
149 {OMPD_target, OMPD_exit, OMPD_target_exit},
150 {OMPD_target, OMPD_update, OMPD_target_update},
151 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
152 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
153 {OMPD_for, OMPD_simd, OMPD_for_simd},
154 {OMPD_parallel, OMPD_for, OMPD_parallel_for},
155 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
156 {OMPD_parallel, OMPD_loop, OMPD_parallel_loop},
157 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
158 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
159 {OMPD_target, OMPD_parallel, OMPD_target_parallel},
160 {OMPD_target, OMPD_simd, OMPD_target_simd},
161 {OMPD_target_parallel, OMPD_loop, OMPD_target_parallel_loop},
162 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
163 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
164 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
165 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
166 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
167 {OMPD_teams_distribute_parallel, OMPD_for,
168 OMPD_teams_distribute_parallel_for},
169 {OMPD_teams_distribute_parallel_for, OMPD_simd,
170 OMPD_teams_distribute_parallel_for_simd},
171 {OMPD_teams, OMPD_loop, OMPD_teams_loop},
172 {OMPD_target, OMPD_teams, OMPD_target_teams},
173 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
174 {OMPD_target_teams, OMPD_loop, OMPD_target_teams_loop},
175 {OMPD_target_teams_distribute, OMPD_parallel,
176 OMPD_target_teams_distribute_parallel},
177 {OMPD_target_teams_distribute, OMPD_simd,
178 OMPD_target_teams_distribute_simd},
179 {OMPD_target_teams_distribute_parallel, OMPD_for,
180 OMPD_target_teams_distribute_parallel_for},
181 {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
182 OMPD_target_teams_distribute_parallel_for_simd},
183 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
184 {OMPD_masked, OMPD_taskloop, OMPD_masked_taskloop},
185 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
186 {OMPD_masked_taskloop, OMPD_simd, OMPD_masked_taskloop_simd},
187 {OMPD_parallel, OMPD_master, OMPD_parallel_master},
188 {OMPD_parallel, OMPD_masked, OMPD_parallel_masked},
189 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
190 {OMPD_parallel_masked, OMPD_taskloop, OMPD_parallel_masked_taskloop},
191 {OMPD_parallel_master_taskloop, OMPD_simd,
192 OMPD_parallel_master_taskloop_simd},
193 {OMPD_parallel_masked_taskloop, OMPD_simd,
194 OMPD_parallel_masked_taskloop_simd}};
195 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
196 Token Tok =
P.getCurToken();
197 OpenMPDirectiveKindExWrapper DKind =
199 ?
static_cast<unsigned>(OMPD_unknown)
201 if (DKind == OMPD_unknown)
204 for (
const auto &I : F) {
208 Tok =
P.getPreprocessor().LookAhead(0);
209 OpenMPDirectiveKindExWrapper SDKind =
211 ?
static_cast<unsigned>(OMPD_unknown)
213 if (SDKind == OMPD_unknown)
216 if (SDKind == I[1]) {
221 return unsigned(DKind) < llvm::omp::Directive_enumSize
227 Token Tok =
P.getCurToken();
228 Sema &Actions =
P.getActions();
231 bool WithOperator =
false;
232 if (Tok.
is(tok::kw_operator)) {
234 Tok =
P.getCurToken();
262 case tok::identifier:
267 P.Diag(Tok.
getLocation(), diag::err_omp_expected_reduction_identifier);
268 P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
275 : DeclNames.getCXXOperatorName(OOK);
292 if (
T.expectAndConsume(
293 diag::err_expected_lparen_after,
294 getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
300 if (Name.isEmpty() && Tok.
is(tok::annot_pragma_openmp_end))
304 bool IsCorrect = !ExpectAndConsume(tok::colon);
306 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
309 IsCorrect = IsCorrect && !Name.isEmpty();
311 if (Tok.
is(tok::colon) || Tok.
is(tok::annot_pragma_openmp_end)) {
316 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
327 Range.getBegin(), TR);
328 if (!ReductionType.
isNull()) {
329 ReductionTypes.push_back(
330 std::make_pair(ReductionType,
Range.getBegin()));
333 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
337 if (Tok.
is(tok::colon) || Tok.
is(tok::annot_pragma_openmp_end))
341 if (ExpectAndConsume(tok::comma)) {
343 if (Tok.
is(tok::annot_pragma_openmp_end)) {
348 }
while (Tok.
isNot(tok::annot_pragma_openmp_end));
350 if (ReductionTypes.empty()) {
355 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
359 if (ExpectAndConsume(tok::colon))
362 if (Tok.
is(tok::annot_pragma_openmp_end)) {
374 unsigned I = 0, E = ReductionTypes.size();
375 for (
Decl *D : DRD.get()) {
376 TentativeParsingAction TPA(*
this);
385 D, CombinerResult.
get());
388 Tok.
isNot(tok::annot_pragma_openmp_end)) {
393 IsCorrect = !
T.consumeClose() && IsCorrect && CombinerResult.
isUsable();
395 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
397 if (Tok.
is(tok::identifier) &&
408 tok::annot_pragma_openmp_end);
410 !
T.expectAndConsume(diag::err_expected_lparen_after,
"initializer") &&
412 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
421 if (Tok.
is(tok::identifier) &&
424 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
431 D, InitializerResult.
get(), OmpPrivParm);
433 Tok.
isNot(tok::annot_pragma_openmp_end)) {
439 !
T.consumeClose() && IsCorrect && !InitializerResult.
isInvalid();
455void Parser::ParseOpenMPReductionInitializerForDecl(
VarDecl *OmpPrivParm) {
458 if (isTokenEqualOrEqualTypo()) {
461 if (Tok.
is(tok::code_completion)) {
471 if (
Init.isInvalid()) {
478 }
else if (Tok.
is(tok::l_paren)) {
486 auto RunSignatureHelp = [
this, OmpPrivParm, LParLoc, &Exprs]() {
489 OmpPrivParm->
getLocation(), Exprs, LParLoc,
false);
490 CalledSignatureHelp =
true;
491 return PreferredType;
493 if (ParseExpressionList(Exprs, [&] {
494 PreferredType.enterFunctionArgument(Tok.
getLocation(),
504 if (!
T.consumeClose())
505 RLoc =
T.getCloseLocation();
514 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
518 if (
Init.isInvalid()) {
539 bool IsCorrect =
true;
542 if (
T.expectAndConsume(diag::err_expected_lparen_after,
543 getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
552 if (Tok.
isNot(tok::identifier) && Tok.
isNot(tok::kw_default)) {
560 ExpectAndConsume(tok::colon);
567 if (!IsCorrect && Tok.
is(tok::annot_pragma_openmp_end))
586 IsCorrect &= !
T.consumeClose();
597 ParseScope OMPDirectiveScope(
this, ScopeFlags);
608 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
614 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.empty());
616 Clauses.push_back(Clause);
620 if (Tok.
is(tok::comma))
624 if (Clauses.empty()) {
625 Diag(Tok, diag::err_omp_expected_clause)
626 << getOpenMPDirectiveName(OMPD_declare_mapper);
632 OMPDirectiveScope.Exit();
635 Range.getBegin(), VName, AS, MapperVarRef.
get(), Clauses);
646 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
648 ParseSpecifierQualifierList(DS, AS, DSC);
653 ParseDeclarator(DeclaratorInfo);
654 Range = DeclaratorInfo.getSourceRange();
655 if (DeclaratorInfo.getIdentifier() ==
nullptr) {
671class FNContextRAII final {
675 bool HasFunScope =
false;
676 FNContextRAII() =
delete;
677 FNContextRAII(
const FNContextRAII &) =
delete;
678 FNContextRAII &operator=(
const FNContextRAII &) =
delete;
685 Sema &Actions =
P.getActions();
693 P.ReenterTemplateScopes(Scopes, D);
705 P.getActions().ActOnExitFunctionContext();
724 const Token &Tok =
P.getCurToken();
725 bool IsError =
false;
726 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
727 if (Tok.
isNot(tok::identifier))
729 OMPDeclareSimdDeclAttr::BranchStateTy Out;
731 StringRef ClauseName = II->
getName();
733 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
734 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
735 P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
737 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
743 }
else if (ClauseName.equals(
"simdlen")) {
745 P.Diag(Tok, diag::err_omp_more_one_clause)
746 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
751 SimdLen =
P.ParseOpenMPParensExpr(ClauseName, RLoc);
756 if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
757 CKind == OMPC_linear) {
760 if (CKind == OMPC_aligned) {
762 }
else if (CKind == OMPC_linear) {
763 Data.ExtraModifier = OMPC_LINEAR_val;
768 if (
P.ParseOpenMPVarList(OMPD_declare_simd,
769 getOpenMPClauseKind(ClauseName), *Vars,
Data))
771 if (CKind == OMPC_aligned) {
772 Alignments.append(Aligneds.size() - Alignments.size(),
773 Data.DepModOrTailExpr);
774 }
else if (CKind == OMPC_linear) {
775 assert(0 <=
Data.ExtraModifier &&
777 "Unexpected linear modifier.");
778 if (
P.getActions().OpenMP().CheckOpenMPLinearModifier(
780 Data.ExtraModifierLoc))
781 Data.ExtraModifier = OMPC_LINEAR_val;
782 LinModifiers.append(Linears.size() - LinModifiers.size(),
784 Steps.append(Linears.size() - Steps.size(),
Data.DepModOrTailExpr);
791 if (Tok.
is(tok::comma))
802 PP.EnterTokenStream(Toks,
true,
808 FNContextRAII FnContext(*
this, Ptr);
809 OMPDeclareSimdDeclAttr::BranchStateTy BS =
810 OMPDeclareSimdDeclAttr::BS_Undefined;
820 Alignments, Linears, LinModifiers, Steps);
821 skipUntilPragmaOpenMPEnd(OMPD_declare_simd);
827 Ptr, BS, Simdlen.
get(), Uniforms, Aligneds, Alignments, Linears,
835 CONTEXT_SELECTOR_SET_LVL = 0,
836 CONTEXT_SELECTOR_LVL = 1,
837 CONTEXT_TRAIT_LVL = 2,
840static StringRef stringLiteralParser(
Parser &
P) {
841 ExprResult Res =
P.ParseStringLiteralExpression(
true);
845static StringRef getNameFromIdOrString(
Parser &
P,
Token &Tok,
847 if (Tok.
is(tok::identifier) || Tok.
is(tok::kw_for)) {
849 StringRef Name =
P.getPreprocessor().getSpelling(Tok, Buffer);
850 (void)
P.ConsumeToken();
855 return stringLiteralParser(
P);
858 diag::warn_omp_declare_variant_string_literal_or_identifier)
863static bool checkForDuplicates(
Parser &
P, StringRef Name,
865 llvm::StringMap<SourceLocation> &Seen,
867 auto Res = Seen.try_emplace(Name, NameLoc);
873 P.Diag(NameLoc, diag::warn_omp_declare_variant_ctx_mutiple_use)
875 P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
882 llvm::omp::TraitSet
Set,
884 llvm::StringMap<SourceLocation> &Seen) {
885 TIProperty.
Kind = TraitProperty::invalid;
888 StringRef Name = getNameFromIdOrString(*
this, Tok, CONTEXT_TRAIT_LVL);
891 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(
Set,
Selector);
896 TIProperty.
Kind = getOpenMPContextTraitPropertyKind(
Set,
Selector, Name);
897 if (TIProperty.
Kind != TraitProperty::invalid) {
898 if (checkForDuplicates(*
this, Name, NameLoc, Seen, CONTEXT_TRAIT_LVL))
899 TIProperty.
Kind = TraitProperty::invalid;
905 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_property)
906 << Name << getOpenMPContextTraitSelectorName(
Selector)
907 << getOpenMPContextTraitSetName(
Set);
909 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
910 if (SetForName != TraitSet::invalid) {
911 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
912 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_TRAIT_LVL;
913 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
914 << Name <<
"<selector-name>"
915 <<
"(<property-name>)";
918 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
919 if (SelectorForName != TraitSelector::invalid) {
920 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
921 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_TRAIT_LVL;
922 bool AllowsTraitScore =
false;
923 bool RequiresProperty =
false;
924 isValidTraitSelectorForTraitSet(
925 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
926 AllowsTraitScore, RequiresProperty);
927 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
928 << getOpenMPContextTraitSetName(
929 getOpenMPContextTraitSetForSelector(SelectorForName))
930 << Name << (RequiresProperty ?
"(<property-name>)" :
"");
933 for (
const auto &PotentialSet :
934 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
936 TraitProperty PropertyForName =
937 getOpenMPContextTraitPropertyKind(PotentialSet,
Selector, Name);
938 if (PropertyForName == TraitProperty::invalid)
940 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
941 << getOpenMPContextTraitSetName(
942 getOpenMPContextTraitSetForProperty(PropertyForName))
943 << getOpenMPContextTraitSelectorName(
944 getOpenMPContextTraitSelectorForProperty(PropertyForName))
945 << (
"(" + Name +
")").str();
948 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
949 << CONTEXT_TRAIT_LVL << listOpenMPContextTraitProperties(
Set,
Selector);
955 llvm::StringMap<SourceLocation> &Seen) {
956 assert(TISelector.
Kind ==
957 llvm::omp::TraitSelector::implementation_extension &&
958 "Only for extension properties, e.g., "
959 "`implementation={extension(PROPERTY)}`");
960 if (TIProperty.
Kind == TraitProperty::invalid)
963 if (TIProperty.
Kind ==
964 TraitProperty::implementation_extension_disable_implicit_base)
967 if (TIProperty.
Kind ==
968 TraitProperty::implementation_extension_allow_templates)
971 if (TIProperty.
Kind ==
972 TraitProperty::implementation_extension_bind_to_declaration)
977 llvm::omp::TraitProperty::implementation_extension_match_all ||
979 llvm::omp::TraitProperty::implementation_extension_match_any ||
981 llvm::omp::TraitProperty::implementation_extension_match_none);
984 if (IsMatchExtension(TIProperty)) {
986 if (IsMatchExtension(SeenProp)) {
987 P.Diag(Loc, diag::err_omp_variant_ctx_second_match_extension);
988 StringRef SeenName = llvm::omp::getOpenMPContextTraitPropertyName(
991 P.Diag(SeenLoc, diag::note_omp_declare_variant_ctx_used_here)
992 << CONTEXT_TRAIT_LVL << SeenName;
998 llvm_unreachable(
"Unknown extension property!");
1002 llvm::omp::TraitSet
Set,
1003 llvm::StringMap<SourceLocation> &Seen) {
1004 assert(TISelector.
Kind != TraitSelector::user_condition &&
1005 "User conditions are special properties not handled here!");
1009 parseOMPTraitPropertyKind(TIProperty,
Set, TISelector.
Kind, Seen);
1011 if (TISelector.
Kind == llvm::omp::TraitSelector::implementation_extension)
1014 TIProperty.
Kind = TraitProperty::invalid;
1017 if (TIProperty.
Kind == TraitProperty::invalid) {
1019 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1020 << CONTEXT_TRAIT_LVL;
1024 if (isValidTraitPropertyForTraitSetAndSelector(TIProperty.
Kind,
1033 Diag(PropertyLoc, diag::warn_omp_ctx_incompatible_property_for_selector)
1034 << getOpenMPContextTraitPropertyName(TIProperty.
Kind,
1036 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1037 << getOpenMPContextTraitSetName(
Set);
1038 Diag(PropertyLoc, diag::note_omp_ctx_compatible_set_and_selector_for_property)
1039 << getOpenMPContextTraitPropertyName(TIProperty.
Kind,
1041 << getOpenMPContextTraitSelectorName(
1042 getOpenMPContextTraitSelectorForProperty(TIProperty.
Kind))
1043 << getOpenMPContextTraitSetName(
1044 getOpenMPContextTraitSetForProperty(TIProperty.
Kind));
1045 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1046 << CONTEXT_TRAIT_LVL;
1050 llvm::omp::TraitSet
Set,
1051 llvm::StringMap<SourceLocation> &Seen) {
1052 TISelector.
Kind = TraitSelector::invalid;
1055 StringRef Name = getNameFromIdOrString(*
this, Tok, CONTEXT_SELECTOR_LVL);
1058 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(
Set);
1062 TISelector.
Kind = getOpenMPContextTraitSelectorKind(Name);
1063 if (TISelector.
Kind != TraitSelector::invalid) {
1064 if (checkForDuplicates(*
this, Name, NameLoc, Seen, CONTEXT_SELECTOR_LVL))
1065 TISelector.
Kind = TraitSelector::invalid;
1070 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_selector)
1071 << Name << getOpenMPContextTraitSetName(
Set);
1073 TraitSet SetForName = getOpenMPContextTraitSetKind(Name);
1074 if (SetForName != TraitSet::invalid) {
1075 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1076 << Name << CONTEXT_SELECTOR_SET_LVL << CONTEXT_SELECTOR_LVL;
1077 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1078 << Name <<
"<selector-name>"
1079 <<
"<property-name>";
1082 for (
const auto &PotentialSet :
1083 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1084 TraitSet::device}) {
1085 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1086 PotentialSet, TraitSelector::invalid, Name);
1087 if (PropertyForName == TraitProperty::invalid)
1089 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1090 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_LVL;
1091 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1092 << getOpenMPContextTraitSetName(
1093 getOpenMPContextTraitSetForProperty(PropertyForName))
1094 << getOpenMPContextTraitSelectorName(
1095 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1096 << (
"(" + Name +
")").str();
1099 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1100 << CONTEXT_SELECTOR_LVL << listOpenMPContextTraitSelectors(
Set);
1107 StringRef SelectorName =
1108 P.getPreprocessor().getSpelling(
P.getCurToken(), Buffer);
1109 if (!SelectorName.equals(
"score"))
1111 (void)
P.ConsumeToken();
1113 ScoreExpr =
P.ParseOpenMPParensExpr(SelectorName, RLoc);
1115 if (
P.getCurToken().is(tok::colon))
1116 (
void)
P.ConsumeAnyToken();
1118 P.Diag(
P.getCurToken(), diag::warn_omp_declare_variant_expected)
1120 <<
"score expression";
1127void Parser::parseOMPContextSelector(
1129 llvm::StringMap<SourceLocation> &SeenSelectors) {
1130 unsigned short OuterPC = ParenCount;
1135 auto FinishSelector = [OuterPC,
this]() ->
void {
1138 while (!
SkipUntil({tok::r_brace, tok::r_paren, tok::comma,
1139 tok::annot_pragma_openmp_end},
1142 if (Tok.
is(tok::r_paren) && OuterPC > ParenCount)
1143 (
void)ConsumeParen();
1144 if (OuterPC <= ParenCount) {
1148 if (!Tok.
is(tok::comma) && !Tok.
is(tok::r_paren)) {
1154 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1155 << CONTEXT_SELECTOR_LVL;
1159 parseOMPTraitSelectorKind(TISelector,
Set, SeenSelectors);
1160 if (TISelector.
Kind == TraitSelector::invalid)
1161 return FinishSelector();
1163 bool AllowsTraitScore =
false;
1164 bool RequiresProperty =
false;
1165 if (!isValidTraitSelectorForTraitSet(TISelector.
Kind,
Set, AllowsTraitScore,
1166 RequiresProperty)) {
1167 Diag(SelectorLoc, diag::warn_omp_ctx_incompatible_selector_for_set)
1168 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1169 << getOpenMPContextTraitSetName(
Set);
1170 Diag(SelectorLoc, diag::note_omp_ctx_compatible_set_for_selector)
1171 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1172 << getOpenMPContextTraitSetName(
1173 getOpenMPContextTraitSetForSelector(TISelector.
Kind))
1174 << RequiresProperty;
1175 return FinishSelector();
1178 if (!RequiresProperty) {
1180 {getOpenMPContextTraitPropertyForSelector(TISelector.
Kind),
1181 getOpenMPContextTraitSelectorName(TISelector.
Kind)});
1185 if (!Tok.
is(tok::l_paren)) {
1186 Diag(SelectorLoc, diag::warn_omp_ctx_selector_without_properties)
1187 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1188 << getOpenMPContextTraitSetName(
Set);
1189 return FinishSelector();
1192 if (TISelector.
Kind == TraitSelector::user_condition) {
1196 return FinishSelector();
1199 {TraitProperty::user_condition_unknown,
"<condition>"});
1204 tok::annot_pragma_openmp_end);
1206 (void)BDT.consumeOpen();
1211 if (!AllowsTraitScore && !Score.
isUnset()) {
1213 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1214 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1215 << getOpenMPContextTraitSetName(
Set) << Score.
get();
1217 Diag(ScoreLoc, diag::warn_omp_ctx_incompatible_score_for_property)
1218 << getOpenMPContextTraitSelectorName(TISelector.
Kind)
1219 << getOpenMPContextTraitSetName(
Set) <<
"<invalid>";
1227 llvm::StringMap<SourceLocation> SeenProperties;
1229 parseOMPContextProperty(TISelector,
Set, SeenProperties);
1236void Parser::parseOMPTraitSetKind(
OMPTraitSet &TISet,
1237 llvm::StringMap<SourceLocation> &Seen) {
1238 TISet.
Kind = TraitSet::invalid;
1241 StringRef Name = getNameFromIdOrString(*
this, Tok, CONTEXT_SELECTOR_SET_LVL);
1244 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1248 TISet.
Kind = getOpenMPContextTraitSetKind(Name);
1249 if (TISet.
Kind != TraitSet::invalid) {
1250 if (checkForDuplicates(*
this, Name, NameLoc, Seen,
1251 CONTEXT_SELECTOR_SET_LVL))
1252 TISet.
Kind = TraitSet::invalid;
1257 Diag(NameLoc, diag::warn_omp_declare_variant_ctx_not_a_set) << Name;
1259 TraitSelector SelectorForName = getOpenMPContextTraitSelectorKind(Name);
1260 if (SelectorForName != TraitSelector::invalid) {
1261 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1262 << Name << CONTEXT_SELECTOR_LVL << CONTEXT_SELECTOR_SET_LVL;
1263 bool AllowsTraitScore =
false;
1264 bool RequiresProperty =
false;
1265 isValidTraitSelectorForTraitSet(
1266 SelectorForName, getOpenMPContextTraitSetForSelector(SelectorForName),
1267 AllowsTraitScore, RequiresProperty);
1268 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1269 << getOpenMPContextTraitSetName(
1270 getOpenMPContextTraitSetForSelector(SelectorForName))
1271 << Name << (RequiresProperty ?
"(<property-name>)" :
"");
1274 for (
const auto &PotentialSet :
1275 {TraitSet::construct, TraitSet::user, TraitSet::implementation,
1276 TraitSet::device}) {
1277 TraitProperty PropertyForName = getOpenMPContextTraitPropertyKind(
1278 PotentialSet, TraitSelector::invalid, Name);
1279 if (PropertyForName == TraitProperty::invalid)
1281 Diag(NameLoc, diag::note_omp_declare_variant_ctx_is_a)
1282 << Name << CONTEXT_TRAIT_LVL << CONTEXT_SELECTOR_SET_LVL;
1283 Diag(NameLoc, diag::note_omp_declare_variant_ctx_try)
1284 << getOpenMPContextTraitSetName(
1285 getOpenMPContextTraitSetForProperty(PropertyForName))
1286 << getOpenMPContextTraitSelectorName(
1287 getOpenMPContextTraitSelectorForProperty(PropertyForName))
1288 << (
"(" + Name +
")").str();
1291 Diag(NameLoc, diag::note_omp_declare_variant_ctx_options)
1292 << CONTEXT_SELECTOR_SET_LVL << listOpenMPContextTraitSets();
1298void Parser::parseOMPContextSelectorSet(
1299 OMPTraitSet &TISet, llvm::StringMap<SourceLocation> &SeenSets) {
1300 auto OuterBC = BraceCount;
1305 auto FinishSelectorSet = [
this, OuterBC]() ->
void {
1308 while (!
SkipUntil({tok::comma, tok::r_brace, tok::r_paren,
1309 tok::annot_pragma_openmp_end},
1312 if (Tok.
is(tok::r_brace) && OuterBC > BraceCount)
1313 (
void)ConsumeBrace();
1314 if (OuterBC <= BraceCount) {
1318 if (!Tok.
is(tok::comma) && !Tok.
is(tok::r_brace)) {
1324 Diag(Tok.
getLocation(), diag::note_omp_declare_variant_ctx_continue_here)
1325 << CONTEXT_SELECTOR_SET_LVL;
1328 parseOMPTraitSetKind(TISet, SeenSets);
1329 if (TISet.
Kind == TraitSet::invalid)
1330 return FinishSelectorSet();
1336 << (
"context set name \"" + getOpenMPContextTraitSetName(TISet.
Kind) +
1341 if (Tok.
is(tok::l_brace)) {
1342 (void)ConsumeBrace();
1346 << (
"'=' that follows the context set name \"" +
1347 getOpenMPContextTraitSetName(TISet.
Kind) +
"\"")
1351 llvm::StringMap<SourceLocation> SeenSelectors;
1354 parseOMPContextSelector(TISelector, TISet.
Kind, SeenSelectors);
1355 if (TISelector.
Kind != TraitSelector::invalid &&
1361 if (Tok.
is(tok::r_brace)) {
1362 (void)ConsumeBrace();
1366 << (
"context selectors for the context set \"" +
1367 getOpenMPContextTraitSetName(TISet.
Kind) +
"\"")
1376 llvm::StringMap<SourceLocation> SeenSets;
1379 parseOMPContextSelectorSet(TISet, SeenSets);
1380 if (TISet.
Kind != TraitSet::invalid && !TISet.
Selectors.empty())
1381 TI.
Sets.push_back(TISet);
1392 PP.EnterTokenStream(Toks,
true,
1398 FNContextRAII FnContext(*
this, Ptr);
1410 getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1413 if (!AssociatedFunction.
isUsable()) {
1414 if (!Tok.
is(tok::annot_pragma_openmp_end))
1418 (void)ConsumeAnnotationToken();
1423 Actions.
OpenMP().getOMPTraitInfoForSurroundingScope();
1432 if (Tok.
is(tok::annot_pragma_openmp_end)) {
1437 bool IsError =
false;
1438 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1442 if (!isAllowedClauseForDirective(OMPD_declare_variant, CKind,
1451 IsError = parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI);
1453 case OMPC_adjust_args: {
1461 llvm::append_range(
Data.ExtraModifier == OMPC_ADJUST_ARGS_nothing
1463 : AdjustNeedDevicePtr,
1467 case OMPC_append_args:
1468 if (!AppendArgs.empty()) {
1469 Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
1470 << getOpenMPDirectiveName(OMPD_declare_variant)
1471 << getOpenMPClauseName(CKind) << 0;
1477 IsError = parseOpenMPAppendArgs(AppendArgs);
1481 llvm_unreachable(
"Unexpected clause for declare variant.");
1488 (void)ConsumeAnnotationToken();
1492 if (Tok.
is(tok::comma))
1496 std::optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
1498 Ptr, AssociatedFunction.
get(), TI, AppendArgs.size(),
1501 if (DeclVarData && !TI.
Sets.empty())
1503 DeclVarData->first, DeclVarData->second, TI, AdjustNothing,
1504 AdjustNeedDevicePtr, AppendArgs, AdjustArgsLoc, AppendArgsLoc,
1508 (void)ConsumeAnnotationToken();
1511bool Parser::parseOpenMPAppendArgs(
1513 bool HasError =
false;
1516 if (
T.expectAndConsume(diag::err_expected_lparen_after,
1517 getOpenMPClauseName(OMPC_append_args).data()))
1525 tok::annot_pragma_openmp_end);
1526 if (IT.expectAndConsume(diag::err_expected_lparen_after,
"interop"))
1530 if (ParseOMPInteropInfo(InteropInfo, OMPC_append_args))
1533 InteropInfos.push_back(InteropInfo);
1536 if (Tok.
is(tok::comma))
1539 if (!HasError && InteropInfos.empty()) {
1542 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
1545 HasError =
T.consumeClose() || HasError;
1549bool Parser::parseOMPDeclareVariantMatchClause(
SourceLocation Loc,
1556 if (CKind != OMPC_match) {
1564 if (
T.expectAndConsume(diag::err_expected_lparen_after,
1565 getOpenMPClauseName(OMPC_match).data()))
1569 parseOMPContextSelectors(Loc, TI);
1572 (void)
T.consumeClose();
1583 bool MergedSet =
false;
1585 if (
Set.Kind != ParentSet.
Kind)
1589 bool MergedSelector =
false;
1593 MergedSelector =
true;
1596 bool MergedProperty =
false;
1610 if (
Selector.Kind == llvm::omp::TraitSelector::user_condition) {
1611 Diag(Loc, diag::err_omp_declare_variant_nested_user_condition);
1612 }
else if (
Selector.ScoreOrCondition !=
1614 Diag(Loc, diag::err_omp_declare_variant_duplicate_nested_trait)
1615 << getOpenMPContextTraitPropertyName(
1617 << getOpenMPContextTraitSelectorName(ParentSelector.
Kind)
1618 << getOpenMPContextTraitSetName(ParentSet.
Kind);
1621 if (!MergedProperty)
1622 Selector.Properties.push_back(ParentProperty);
1625 if (!MergedSelector)
1626 Set.Selectors.push_back(ParentSelector);
1630 TI.
Sets.push_back(ParentSet);
1647 llvm::omp::Clause_enumSize + 1>
1648 FirstClauses(llvm::omp::Clause_enumSize + 1);
1649 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1655 DKind, CKind, !FirstClauses[
unsigned(CKind)].getInt());
1656 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1658 FirstClauses[
unsigned(CKind)].setInt(
true);
1659 if (Clause !=
nullptr)
1660 Clauses.push_back(Clause);
1661 if (Tok.
is(tok::annot_pragma_openmp_end)) {
1666 if (Tok.
is(tok::comma))
1687 bool SkippedClauses =
false;
1689 auto SkipBraces = [&](llvm::StringRef Spelling,
bool IssueNote) {
1691 tok::annot_pragma_openmp_end);
1692 if (
T.expectAndConsume(diag::err_expected_lparen_after, Spelling.data()))
1695 if (IssueNote &&
T.getCloseLocation().isValid())
1696 Diag(
T.getCloseLocation(),
1697 diag::note_omp_assumption_clause_continue_here);
1703 auto MatchACMClause = [&](StringRef RawString) {
1704 llvm::StringSwitch<int> SS(RawString);
1705 unsigned ACMIdx = 0;
1706 for (
const AssumptionClauseMappingInfo &ACMI : AssumptionClauseMappings) {
1707 if (ACMI.StartsWith)
1708 SS.StartsWith(ACMI.Identifier, ACMIdx++);
1710 SS.Case(ACMI.Identifier, ACMIdx++);
1712 return SS.Default(-1);
1715 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1721 Idx = MatchACMClause(II->
getName());
1725 bool NextIsLPar = Tok.
is(tok::l_paren);
1728 Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
1729 << llvm::omp::getOpenMPDirectiveName(DKind)
1730 << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
1732 SkipBraces(II ? II->
getName() :
"",
true);
1733 SkippedClauses =
true;
1736 const AssumptionClauseMappingInfo &ACMI = AssumptionClauseMappings[Idx];
1737 if (ACMI.HasDirectiveList || ACMI.HasExpression) {
1740 SkippedClauses =
true;
1741 SkipBraces(II->
getName(),
false);
1747 diag::warn_omp_unknown_assumption_clause_without_args)
1749 SkipBraces(II->
getName(),
true);
1752 assert(II &&
"Expected an identifier clause!");
1753 std::string Assumption = II->
getName().str();
1754 if (ACMI.StartsWith)
1755 Assumption =
"ompx_" + Assumption.substr(ACMI.Identifier.size());
1757 Assumption =
"omp_" + Assumption;
1758 Assumptions.push_back(Assumption);
1769 Diag(Loc, diag::err_expected_begin_assumes);
1783struct SimpleClauseData {
1795static std::optional<SimpleClauseData>
1797 const Token &Tok =
P.getCurToken();
1802 if (
T.expectAndConsume(diag::err_expected_lparen_after,
1803 getOpenMPClauseName(Kind).data()))
1804 return std::nullopt;
1807 Kind, Tok.
isAnnotation() ?
"" :
P.getPreprocessor().getSpelling(Tok),
1810 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1811 Tok.
isNot(tok::annot_pragma_openmp_end))
1812 P.ConsumeAnyToken();
1816 if (!
T.consumeClose())
1817 RLoc =
T.getCloseLocation();
1819 return SimpleClauseData(
Type, Loc, LOpen,
TypeLoc, RLoc);
1822void Parser::ParseOMPDeclareTargetClauses(
1825 bool RequiresToOrLinkOrIndirectClause =
false;
1826 bool HasToOrLinkOrIndirectClause =
false;
1827 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
1828 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1829 bool HasIdentifier = Tok.
is(tok::identifier);
1830 if (HasIdentifier) {
1832 RequiresToOrLinkOrIndirectClause =
true;
1834 StringRef ClauseName = II->
getName();
1835 bool IsDeviceTypeClause =
1837 getOpenMPClauseKind(ClauseName) == OMPC_device_type;
1839 bool IsIndirectClause =
getLangOpts().OpenMP >= 51 &&
1840 getOpenMPClauseKind(ClauseName) == OMPC_indirect;
1841 if (DTCI.
Indirect && IsIndirectClause) {
1842 Diag(Tok, diag::err_omp_more_one_clause)
1843 << getOpenMPDirectiveName(OMPD_declare_target)
1844 << getOpenMPClauseName(OMPC_indirect) << 0;
1847 bool IsToEnterOrLinkClause =
1848 OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
1849 assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
1854 if (
getLangOpts().OpenMP >= 52 && ClauseName ==
"to") {
1855 Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause);
1858 if (
getLangOpts().OpenMP <= 51 && ClauseName ==
"enter") {
1859 Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause);
1863 if (!IsDeviceTypeClause && !IsIndirectClause &&
1864 DTCI.
Kind == OMPD_begin_declare_target) {
1865 Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
1866 << ClauseName << (
getLangOpts().OpenMP >= 51 ? 3 : 0);
1869 if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
1871 ? diag::err_omp_declare_target_unexpected_clause_52
1872 : diag::err_omp_declare_target_unexpected_clause)
1880 if (IsToEnterOrLinkClause || IsIndirectClause)
1881 HasToOrLinkOrIndirectClause =
true;
1883 if (IsIndirectClause) {
1884 if (!ParseOpenMPIndirectClause(DTCI,
false))
1889 if (IsDeviceTypeClause) {
1890 std::optional<SimpleClauseData> DevTypeData =
1893 if (DeviceTypeLoc.
isValid()) {
1895 Diag(DevTypeData->Loc,
1896 diag::warn_omp_more_one_device_type_clause);
1900 case OMPC_DEVICE_TYPE_any:
1901 DTCI.
DT = OMPDeclareTargetDeclAttr::DT_Any;
1903 case OMPC_DEVICE_TYPE_host:
1904 DTCI.
DT = OMPDeclareTargetDeclAttr::DT_Host;
1906 case OMPC_DEVICE_TYPE_nohost:
1907 DTCI.
DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1910 llvm_unreachable(
"Unexpected device_type");
1912 DeviceTypeLoc = DevTypeData->Loc;
1919 if (DTCI.
Kind == OMPD_declare_target || HasIdentifier) {
1929 Diag(NameInfo.
getLoc(), diag::err_omp_declare_target_multiple)
1932 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1937 if (Tok.
is(tok::l_paren)) {
1939 diag::err_omp_begin_declare_target_unexpected_implicit_to_clause);
1942 if (!HasIdentifier && Tok.
isNot(tok::annot_pragma_openmp_end)) {
1945 ? diag::err_omp_declare_target_wrong_clause_after_implicit_enter
1946 : diag::err_omp_declare_target_wrong_clause_after_implicit_to);
1951 if (Tok.
is(tok::comma))
1955 if (DTCI.
Indirect && DTCI.
DT != OMPDeclareTargetDeclAttr::DT_Any)
1956 Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
1959 if (DTCI.
Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
1960 !HasToOrLinkOrIndirectClause)
1963 ? diag::err_omp_declare_target_missing_enter_or_link_clause
1964 : diag::err_omp_declare_target_missing_to_or_link_clause)
1973 if (Tok.
is(tok::annot_pragma_openmp_end))
1976 Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
1977 << getOpenMPDirectiveName(DKind);
1978 while (Tok.
isNot(tok::annot_pragma_openmp_end))
1987 bool SkipUntilOpenMPEnd) {
1988 int DiagSelection = ExpectedKind == OMPD_end_declare_target ? 0 : 1;
1990 if (FoundKind == ExpectedKind) {
1992 skipUntilPragmaOpenMPEnd(ExpectedKind);
1996 Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
1998 Diag(BeginLoc, diag::note_matching)
1999 << (
"'#pragma omp " + getOpenMPDirectiveName(BeginKind) +
"'").str();
2000 if (SkipUntilOpenMPEnd)
2007 parseOMPEndDirective(BeginDKind, OMPD_end_declare_target, EndDKind, DKLoc,
2011 if (Tok.
is(tok::annot_pragma_openmp_end))
2012 ConsumeAnnotationToken();
2054 assert(Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2055 "Not an OpenMP directive!");
2062 TentativeParsingAction TPA(*
this);
2063 Loc = ConsumeAnnotationToken();
2065 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
2070 Toks.push_back(Tok);
2071 while (Cnt && Tok.
isNot(tok::eof)) {
2073 if (Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp))
2075 else if (Tok.
is(tok::annot_pragma_openmp_end))
2077 Toks.push_back(Tok);
2082 auto *LP =
new LateParsedPragma(
this, AS);
2084 getCurrentClass().LateParsedDeclarations.push_back(LP);
2089 Loc = ConsumeAnnotationToken();
2094 case OMPD_threadprivate: {
2096 DeclDirectiveListParserHelper Helper(
this, DKind);
2097 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2099 skipUntilPragmaOpenMPEnd(DKind);
2101 ConsumeAnnotationToken();
2103 Loc, Helper.getIdentifiers());
2107 case OMPD_allocate: {
2109 DeclDirectiveListParserHelper Helper(
this, DKind);
2110 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2113 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2115 llvm::omp::Clause_enumSize + 1>
2116 FirstClauses(llvm::omp::Clause_enumSize + 1);
2117 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2123 OMPD_allocate, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2124 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2126 FirstClauses[
unsigned(CKind)].setInt(
true);
2127 if (Clause !=
nullptr)
2128 Clauses.push_back(Clause);
2129 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2134 if (Tok.
is(tok::comma))
2138 skipUntilPragmaOpenMPEnd(DKind);
2141 ConsumeAnnotationToken();
2143 Loc, Helper.getIdentifiers(), Clauses);
2147 case OMPD_requires: {
2151 llvm::omp::Clause_enumSize + 1>
2152 FirstClauses(llvm::omp::Clause_enumSize + 1);
2153 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2154 Diag(Tok, diag::err_omp_expected_clause)
2155 << getOpenMPDirectiveName(OMPD_requires);
2158 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2164 OMPD_requires, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2165 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2167 FirstClauses[
unsigned(CKind)].setInt(
true);
2168 if (Clause !=
nullptr)
2169 Clauses.push_back(Clause);
2170 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2175 if (Tok.
is(tok::comma))
2180 if (Clauses.empty()) {
2181 Diag(Tok, diag::err_omp_expected_clause)
2182 << getOpenMPDirectiveName(OMPD_requires);
2183 ConsumeAnnotationToken();
2186 ConsumeAnnotationToken();
2192 ParseOpenMPClauses(DKind, Clauses, StartLoc);
2199 case OMPD_begin_assumes:
2202 case OMPD_end_assumes:
2205 case OMPD_declare_reduction:
2207 if (
DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
2208 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2210 ConsumeAnnotationToken();
2214 case OMPD_declare_mapper: {
2216 if (
DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
2218 ConsumeAnnotationToken();
2223 case OMPD_begin_declare_variant: {
2231 Actions.
OpenMP().getOMPTraitInfoForSurroundingScope();
2234 if (parseOMPDeclareVariantMatchClause(Loc, TI, ParentTI)) {
2238 (void)ConsumeAnnotationToken();
2243 skipUntilPragmaOpenMPEnd(OMPD_begin_declare_variant);
2247 VariantMatchInfo VMI;
2250 std::function<void(StringRef)> DiagUnknownTrait =
2251 [
this, Loc](StringRef ISATrait) {
2254 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2257 ASTCtx, std::move(DiagUnknownTrait),
2261 if (isVariantApplicableInContext(VMI, OMPCtx,
true)) {
2267 unsigned Nesting = 1;
2273 if (DK == OMPD_end_declare_variant)
2275 else if (DK == OMPD_begin_declare_variant)
2277 if (!Nesting || isEofOrEom())
2282 parseOMPEndDirective(OMPD_begin_declare_variant, OMPD_end_declare_variant,
2283 DK, Loc, DKLoc,
true);
2288 case OMPD_end_declare_variant: {
2292 Diag(Loc, diag::err_expected_begin_declare_variant);
2296 case OMPD_declare_variant:
2297 case OMPD_declare_simd: {
2303 Toks.push_back(Tok);
2305 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2306 Toks.push_back(Tok);
2309 Toks.push_back(Tok);
2313 if (Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {
2314 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
2316 }
else if (Tok.
isNot(tok::r_brace) && !isEofOrEom()) {
2321 MaybeParseCXX11Attributes(Attrs);
2323 Ptr = ParseExternalDeclaration(Attrs, EmptyDeclSpecAttrs, &PDS);
2326 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs,
TagType, Tag);
2330 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
2331 << (DKind == OMPD_declare_simd ? 0 : 1);
2334 if (DKind == OMPD_declare_simd)
2335 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
2336 assert(DKind == OMPD_declare_variant &&
2337 "Expected declare variant directive only");
2338 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
2341 case OMPD_begin_declare_target:
2342 case OMPD_declare_target: {
2344 bool HasClauses = Tok.
isNot(tok::annot_pragma_openmp_end);
2347 ParseOMPDeclareTargetClauses(DTCI);
2348 bool HasImplicitMappings = DKind == OMPD_begin_declare_target ||
2355 if (HasImplicitMappings) {
2363 Decls.push_back(It.first);
2366 case OMPD_end_declare_target: {
2368 Diag(Tok, diag::err_omp_unexpected_directive)
2369 << 1 << getOpenMPDirectiveName(DKind);
2374 ParseOMPEndDeclareTargetDirective(DTCI.
Kind, DKind, DTCI.
Loc);
2378 Diag(Tok, diag::err_omp_unknown_directive);
2385 case OMPD_taskyield:
2388 case OMPD_taskgroup:
2400 case OMPD_parallel_for:
2401 case OMPD_parallel_for_simd:
2402 case OMPD_parallel_sections:
2403 case OMPD_parallel_master:
2404 case OMPD_parallel_masked:
2408 case OMPD_cancellation_point:
2410 case OMPD_target_data:
2411 case OMPD_target_enter_data:
2412 case OMPD_target_exit_data:
2413 case OMPD_target_parallel:
2414 case OMPD_target_parallel_for:
2416 case OMPD_taskloop_simd:
2417 case OMPD_master_taskloop:
2418 case OMPD_master_taskloop_simd:
2419 case OMPD_parallel_master_taskloop:
2420 case OMPD_parallel_master_taskloop_simd:
2421 case OMPD_masked_taskloop:
2422 case OMPD_masked_taskloop_simd:
2423 case OMPD_parallel_masked_taskloop:
2424 case OMPD_parallel_masked_taskloop_simd:
2425 case OMPD_distribute:
2426 case OMPD_target_update:
2427 case OMPD_distribute_parallel_for:
2428 case OMPD_distribute_parallel_for_simd:
2429 case OMPD_distribute_simd:
2430 case OMPD_target_parallel_for_simd:
2431 case OMPD_target_simd:
2433 case OMPD_teams_distribute:
2434 case OMPD_teams_distribute_simd:
2435 case OMPD_teams_distribute_parallel_for_simd:
2436 case OMPD_teams_distribute_parallel_for:
2437 case OMPD_target_teams:
2438 case OMPD_target_teams_distribute:
2439 case OMPD_target_teams_distribute_parallel_for:
2440 case OMPD_target_teams_distribute_parallel_for_simd:
2441 case OMPD_target_teams_distribute_simd:
2444 case OMPD_metadirective:
2446 case OMPD_teams_loop:
2447 case OMPD_target_teams_loop:
2448 case OMPD_parallel_loop:
2449 case OMPD_target_parallel_loop:
2450 Diag(Tok, diag::err_omp_unexpected_directive)
2451 << 1 << getOpenMPDirectiveName(DKind);
2456 while (Tok.
isNot(tok::annot_pragma_openmp_end))
2502StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
2503 ParsedStmtContext StmtCtx,
bool ReadDirectiveWithinMetadirective) {
2504 if (!ReadDirectiveWithinMetadirective)
2505 assert(Tok.
isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp) &&
2506 "Not an OpenMP directive!");
2511 llvm::omp::Clause_enumSize + 1>
2512 FirstClauses(llvm::omp::Clause_enumSize + 1);
2517 : ConsumeAnnotationToken(),
2520 if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
2521 Diag(Tok, diag::err_omp_unknown_directive);
2528 bool HasAssociatedStatement =
true;
2535 if (ReadDirectiveWithinMetadirective && Tok.
is(tok::r_paren))
2536 while (Tok.
isNot(tok::annot_pragma_openmp_end))
2539 skipUntilPragmaOpenMPEnd(DKind);
2540 if (Tok.
is(tok::annot_pragma_openmp_end))
2541 ConsumeAnnotationToken();
2544 case OMPD_metadirective: {
2551 TentativeParsingAction TPA(*
this);
2555 tok::annot_pragma_openmp_end);
2556 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2563 if (
T.expectAndConsume(diag::err_expected_lparen_after,
2564 getOpenMPClauseName(CKind).data()))
2568 if (CKind == OMPC_when) {
2570 parseOMPContextSelectors(Loc, TI);
2571 if (TI.
Sets.size() == 0) {
2572 Diag(Tok, diag::err_omp_expected_context_selector) <<
"when clause";
2578 if (Tok.
is(tok::colon))
2581 Diag(Tok, diag::err_omp_expected_colon) <<
"when clause";
2588 while (Tok.
isNot(tok::r_paren) || paren != 0) {
2589 if (Tok.
is(tok::l_paren))
2591 if (Tok.
is(tok::r_paren))
2593 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2594 Diag(Tok, diag::err_omp_expected_punc)
2595 << getOpenMPClauseName(CKind) << 0;
2602 if (Tok.
is(tok::r_paren))
2605 VariantMatchInfo VMI;
2608 VMIs.push_back(VMI);
2614 std::function<void(StringRef)> DiagUnknownTrait =
2615 [
this, Loc](StringRef ISATrait) {
2618 Diag(Loc, diag::warn_unknown_declare_variant_isa_trait) << ISATrait;
2625 int BestIdx = getBestVariantMatchForContext(VMIs, OMPCtx);
2632 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2634 if (Idx++ != BestIdx) {
2639 while (Tok.
isNot(tok::r_paren) || paren != 0) {
2640 if (Tok.
is(tok::l_paren))
2642 if (Tok.
is(tok::r_paren))
2647 if (Tok.
is(tok::r_paren))
2661 if (CKind == OMPC_when) {
2664 parseOMPContextSelectors(Loc, TI);
2672 if (Tok.
is(tok::r_paren)) {
2673 SkipUntil(tok::annot_pragma_openmp_end);
2678 Directive = ParseOpenMPDeclarativeOrExecutableDirective(
2685 case OMPD_threadprivate: {
2687 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2688 ParsedStmtContext()) {
2689 Diag(Tok, diag::err_omp_immediate_directive)
2690 << getOpenMPDirectiveName(DKind) << 0;
2693 DeclDirectiveListParserHelper Helper(
this, DKind);
2694 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2696 skipUntilPragmaOpenMPEnd(DKind);
2698 Loc, Helper.getIdentifiers());
2701 SkipUntil(tok::annot_pragma_openmp_end);
2704 case OMPD_allocate: {
2706 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2707 ParsedStmtContext()) {
2708 Diag(Tok, diag::err_omp_immediate_directive)
2709 << getOpenMPDirectiveName(DKind) << 0;
2712 DeclDirectiveListParserHelper Helper(
this, DKind);
2713 if (!ParseOpenMPSimpleVarList(DKind, Helper,
2716 if (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2718 llvm::omp::Clause_enumSize + 1>
2719 FirstClauses(llvm::omp::Clause_enumSize + 1);
2720 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2726 OMPD_allocate, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2727 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
2729 FirstClauses[
unsigned(CKind)].setInt(
true);
2730 if (Clause !=
nullptr)
2731 Clauses.push_back(Clause);
2732 if (Tok.
is(tok::annot_pragma_openmp_end)) {
2737 if (Tok.
is(tok::comma))
2741 skipUntilPragmaOpenMPEnd(DKind);
2744 Loc, Helper.getIdentifiers(), Clauses);
2747 SkipUntil(tok::annot_pragma_openmp_end);
2750 case OMPD_declare_reduction:
2753 ParseOpenMPDeclareReductionDirective(
AS_none)) {
2754 skipUntilPragmaOpenMPEnd(OMPD_declare_reduction);
2758 SkipUntil(tok::annot_pragma_openmp_end);
2761 case OMPD_declare_mapper: {
2764 ParseOpenMPDeclareMapperDirective(
AS_none)) {
2766 ConsumeAnnotationToken();
2769 SkipUntil(tok::annot_pragma_openmp_end);
2776 case OMPD_taskyield:
2780 case OMPD_cancellation_point:
2782 case OMPD_target_enter_data:
2783 case OMPD_target_exit_data:
2784 case OMPD_target_update:
2786 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2787 ParsedStmtContext()) {
2788 Diag(Tok, diag::err_omp_immediate_directive)
2789 << getOpenMPDirectiveName(DKind) << 0;
2790 if (DKind == OMPD_error) {
2791 SkipUntil(tok::annot_pragma_openmp_end);
2795 HasAssociatedStatement =
false;
2809 case OMPD_parallel_for:
2810 case OMPD_parallel_for_simd:
2811 case OMPD_parallel_sections:
2812 case OMPD_parallel_master:
2813 case OMPD_parallel_masked:
2819 case OMPD_taskgroup:
2820 case OMPD_target_data:
2821 case OMPD_target_parallel:
2822 case OMPD_target_parallel_for:
2824 case OMPD_teams_loop:
2825 case OMPD_target_teams_loop:
2826 case OMPD_parallel_loop:
2827 case OMPD_target_parallel_loop:
2830 case OMPD_taskloop_simd:
2831 case OMPD_master_taskloop:
2832 case OMPD_masked_taskloop:
2833 case OMPD_master_taskloop_simd:
2834 case OMPD_masked_taskloop_simd:
2835 case OMPD_parallel_master_taskloop:
2836 case OMPD_parallel_masked_taskloop:
2837 case OMPD_parallel_master_taskloop_simd:
2838 case OMPD_parallel_masked_taskloop_simd:
2839 case OMPD_distribute:
2840 case OMPD_distribute_parallel_for:
2841 case OMPD_distribute_parallel_for_simd:
2842 case OMPD_distribute_simd:
2843 case OMPD_target_parallel_for_simd:
2844 case OMPD_target_simd:
2845 case OMPD_teams_distribute:
2846 case OMPD_teams_distribute_simd:
2847 case OMPD_teams_distribute_parallel_for_simd:
2848 case OMPD_teams_distribute_parallel_for:
2849 case OMPD_target_teams:
2850 case OMPD_target_teams_distribute:
2851 case OMPD_target_teams_distribute_parallel_for:
2852 case OMPD_target_teams_distribute_parallel_for_simd:
2853 case OMPD_target_teams_distribute_simd:
2858 bool ImplicitClauseAllowed =
false;
2859 if (DKind == OMPD_flush || DKind == OMPD_depobj) {
2861 ImplicitClauseAllowed =
true;
2865 if (DKind == OMPD_critical) {
2867 tok::annot_pragma_openmp_end);
2868 if (!
T.consumeOpen()) {
2874 Diag(Tok, diag::err_omp_expected_identifier_for_critical);
2878 }
else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
2880 if (Tok.
isNot(tok::annot_pragma_openmp_end))
2888 ParseScope OMPDirectiveScope(
this, ScopeFlags);
2892 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
2895 if (ReadDirectiveWithinMetadirective && Tok.
is(tok::r_paren)) {
2896 while (Tok.
isNot(tok::annot_pragma_openmp_end))
2900 bool HasImplicitClause =
false;
2901 if (ImplicitClauseAllowed && Tok.
is(tok::l_paren)) {
2902 HasImplicitClause =
true;
2912 if (HasImplicitClause) {
2913 assert(CKind == OMPC_unknown &&
"Must be unknown implicit clause.");
2914 if (DKind == OMPD_flush) {
2917 assert(DKind == OMPD_depobj &&
2918 "Expected flush or depobj directives.");
2919 CKind = OMPC_depobj;
2923 ImplicitClauseAllowed =
false;
2925 HasImplicitClause =
false;
2927 DKind, CKind, !FirstClauses[
unsigned(CKind)].getInt());
2928 FirstClauses[
unsigned(CKind)].setInt(
true);
2930 FirstClauses[
unsigned(CKind)].setPointer(Clause);
2931 Clauses.push_back(Clause);
2935 if (Tok.
is(tok::comma))
2942 ConsumeAnnotationToken();
2944 if (DKind == OMPD_ordered) {
2947 for (
auto CK : {OMPC_depend, OMPC_doacross}) {
2948 if (FirstClauses[
unsigned(CK)].getInt()) {
2949 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
2950 ParsedStmtContext()) {
2951 Diag(Loc, diag::err_omp_immediate_directive)
2952 << getOpenMPDirectiveName(DKind) << 1
2953 << getOpenMPClauseName(CK);
2955 HasAssociatedStatement =
false;
2960 if (DKind == OMPD_tile && !FirstClauses[
unsigned(OMPC_sizes)].getInt()) {
2961 Diag(Loc, diag::err_omp_required_clause)
2962 << getOpenMPDirectiveName(OMPD_tile) <<
"sizes";
2966 if (HasAssociatedStatement) {
2975 AssociatedStmt = ParseStatement();
2984 }
else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
2985 DKind == OMPD_target_exit_data) {
2994 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.
get(), Loc,
2999 OMPDirectiveScope.Exit();
3002 case OMPD_declare_target: {
3004 bool HasClauses = Tok.
isNot(tok::annot_pragma_openmp_end);
3007 ParseOMPDeclareTargetClauses(DTCI);
3008 bool HasImplicitMappings =
3011 if (HasImplicitMappings) {
3012 Diag(Tok, diag::err_omp_unexpected_directive)
3013 << 1 << getOpenMPDirectiveName(DKind);
3014 SkipUntil(tok::annot_pragma_openmp_end);
3024 case OMPD_declare_simd:
3025 case OMPD_begin_declare_target:
3026 case OMPD_end_declare_target:
3028 case OMPD_begin_declare_variant:
3029 case OMPD_end_declare_variant:
3030 case OMPD_declare_variant:
3031 Diag(Tok, diag::err_omp_unexpected_directive)
3032 << 1 << getOpenMPDirectiveName(DKind);
3033 SkipUntil(tok::annot_pragma_openmp_end);
3037 Diag(Tok, diag::err_omp_unknown_directive);
3038 SkipUntil(tok::annot_pragma_openmp_end);
3048bool Parser::ParseOpenMPSimpleVarList(
3052 bool AllowScopeSpecifier) {
3055 if (
T.expectAndConsume(diag::err_expected_lparen_after,
3056 getOpenMPDirectiveName(Kind).data()))
3058 bool IsCorrect =
true;
3059 bool NoIdentIsFound =
true;
3062 while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end)) {
3066 Token PrevTok = Tok;
3067 NoIdentIsFound =
false;
3070 ParseOptionalCXXScopeSpecifier(SS,
nullptr,
3073 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3076 false,
false,
false,
3077 false,
false,
nullptr, Name)) {
3079 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3081 }
else if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren) &&
3082 Tok.
isNot(tok::annot_pragma_openmp_end)) {
3084 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3093 if (Tok.
is(tok::comma)) {
3098 if (NoIdentIsFound) {
3099 Diag(Tok, diag::err_expected) << tok::identifier;
3104 IsCorrect = !
T.consumeClose() && IsCorrect;
3109OMPClause *Parser::ParseOpenMPSizesClause() {
3114 if (
T.consumeOpen()) {
3115 Diag(Tok, diag::err_expected) << tok::l_paren;
3126 ValExprs.push_back(Val.
get());
3128 if (Tok.
is(tok::r_paren) || Tok.
is(tok::annot_pragma_openmp_end))
3131 ExpectAndConsume(tok::comma);
3137 ValExprs, ClauseNameLoc,
T.getOpenLocation(),
T.getCloseLocation());
3146 if (
T.expectAndConsume(diag::err_expected_lparen_after,
"uses_allocator"))
3154 ? ParseCXXIdExpression()
3155 : tryParseCXXIdExpression(SS,
false,
3157 if (Allocator.isInvalid()) {
3158 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3164 if (Tok.
is(tok::l_paren)) {
3166 tok::annot_pragma_openmp_end);
3172 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3180 if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren))
3181 Diag(Tok, diag::err_omp_expected_punc) <<
"uses_allocators" << 0;
3183 if (Tok.
is(tok::comma))
3185 }
while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end));
3188 Loc,
T.getOpenLocation(),
T.getCloseLocation(),
Data);
3213 OMPClauseKind = CKind;
3215 bool ErrorFound =
false;
3216 bool WrongDirective =
false;
3218 if (CKind != OMPC_unknown &&
3219 !isAllowedClauseForDirective(DKind, CKind,
getLangOpts().OpenMP)) {
3220 Diag(Tok, diag::err_omp_unexpected_clause)
3221 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3223 WrongDirective =
true;
3228 case OMPC_num_threads:
3233 case OMPC_num_teams:
3234 case OMPC_thread_limit:
3236 case OMPC_grainsize:
3237 case OMPC_num_tasks:
3239 case OMPC_allocator:
3242 case OMPC_novariants:
3243 case OMPC_nocontext:
3248 case OMPC_ompx_dyn_cgroup_mem:
3277 Diag(Tok, diag::err_omp_more_one_clause)
3278 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3282 if ((CKind == OMPC_ordered || CKind == OMPC_partial) &&
3284 Clause = ParseOpenMPClause(CKind, WrongDirective);
3285 else if (CKind == OMPC_grainsize || CKind == OMPC_num_tasks)
3286 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3288 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
3292 case OMPC_proc_bind:
3293 case OMPC_atomic_default_mem_order:
3311 Diag(Tok, diag::err_omp_more_one_clause)
3312 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3316 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
3320 case OMPC_dist_schedule:
3321 case OMPC_defaultmap:
3331 if ((
getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
3332 (CKind != OMPC_order ||
getLangOpts().OpenMP >= 51) && !FirstClause) {
3333 Diag(Tok, diag::err_omp_more_one_clause)
3334 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3339 Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
3343 case OMPC_mergeable:
3357 case OMPC_unified_address:
3358 case OMPC_unified_shared_memory:
3359 case OMPC_reverse_offload:
3360 case OMPC_dynamic_allocators:
3369 Diag(Tok, diag::err_omp_more_one_clause)
3370 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3374 Clause = ParseOpenMPClause(CKind, WrongDirective);
3378 Diag(Tok, diag::err_omp_more_one_clause)
3379 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3383 Clause = (DKind == OMPD_depobj)
3384 ? ParseOpenMPSimpleClause(CKind, WrongDirective)
3385 : ParseOpenMPClause(CKind, WrongDirective);
3388 case OMPC_firstprivate:
3389 case OMPC_lastprivate:
3391 case OMPC_reduction:
3392 case OMPC_task_reduction:
3393 case OMPC_in_reduction:
3397 case OMPC_copyprivate:
3403 case OMPC_use_device_ptr:
3404 case OMPC_use_device_addr:
3405 case OMPC_is_device_ptr:
3406 case OMPC_has_device_addr:
3408 case OMPC_nontemporal:
3409 case OMPC_inclusive:
3410 case OMPC_exclusive:
3414 if (
getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
3415 CKind == OMPC_depend)
3416 Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
3417 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
3421 Diag(Tok, diag::err_omp_more_one_clause)
3422 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3426 Clause = ParseOpenMPSizesClause();
3428 case OMPC_uses_allocators:
3429 Clause = ParseOpenMPUsesAllocatorClause(DKind);
3432 if (DKind != OMPD_interop) {
3434 Diag(Tok, diag::err_omp_more_one_clause)
3435 << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
3438 Clause = ParseOpenMPClause(CKind, WrongDirective);
3444 Clause = ParseOpenMPInteropClause(CKind, WrongDirective);
3446 case OMPC_device_type:
3448 skipUntilPragmaOpenMPEnd(DKind);
3450 case OMPC_threadprivate:
3453 if (!WrongDirective)
3454 Diag(Tok, diag::err_omp_unexpected_clause)
3455 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3458 case OMPC_ompx_attribute:
3459 Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
3461 case OMPC_ompx_bare:
3463 Diag(Tok, diag::note_ompx_bare_clause)
3464 << getOpenMPClauseName(CKind) <<
"target teams";
3465 if (!ErrorFound && !
getLangOpts().OpenMPExtensions) {
3466 Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
3467 << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
3470 Clause = ParseOpenMPClause(CKind, WrongDirective);
3475 return ErrorFound ? nullptr : Clause;
3483 bool IsAddressOfOperand) {
3485 if (
T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
3490 ParseCastExpression(AnyCastExpr, IsAddressOfOperand,
NotTypeCast));
3496 if (!
T.consumeClose())
3497 RLoc =
T.getCloseLocation();
3564bool Parser::ParseOpenMPIndirectClause(
3569 if (Tok.
isNot(tok::l_paren)) {
3588 if (
Ret.isInvalid())
3593 if (
Ret.isInvalid())
3606 bool HasError =
false;
3607 bool IsTarget =
false;
3608 bool IsTargetSync =
false;
3610 while (Tok.
is(tok::identifier)) {
3612 bool PreferTypeAllowed =
Kind == OMPC_init &&
3620 Diag(Tok, diag::warn_omp_more_one_interop_type) <<
"target";
3625 Diag(Tok, diag::warn_omp_more_one_interop_type) <<
"targetsync";
3626 IsTargetSync =
true;
3629 PreferTypeAllowed) {
3632 tok::annot_pragma_openmp_end);
3633 if (PT.expectAndConsume(diag::err_expected_lparen_after,
"prefer_type"))
3636 while (Tok.
isNot(tok::r_paren)) {
3638 ExprResult LHS = ParseCastExpression(AnyCastExpr);
3647 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3651 if (Tok.
is(tok::comma))
3657 Diag(Tok, diag::err_omp_expected_interop_type);
3660 if (!Tok.
is(tok::comma))
3665 if (!HasError && !IsTarget && !IsTargetSync) {
3666 Diag(Tok, diag::err_omp_expected_interop_type);
3670 if (Kind == OMPC_init) {
3671 if (Tok.
isNot(tok::colon) && (IsTarget || IsTargetSync))
3672 Diag(Tok, diag::warn_pragma_expected_colon) <<
"interop types";
3673 if (Tok.
is(tok::colon))
3713 if (
T.expectAndConsume(diag::err_expected_lparen_after,
3714 getOpenMPClauseName(Kind).data()))
3717 bool InteropError =
false;
3719 if (Kind == OMPC_init)
3720 InteropError = ParseOMPInteropInfo(InteropInfo, OMPC_init);
3727 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
3733 if (!
T.consumeClose())
3734 RLoc =
T.getCloseLocation();
3736 if (ParseOnly || !InteropVarExpr.
isUsable() || InteropError)
3739 if (Kind == OMPC_init)
3741 InteropVarExpr.
get(), InteropInfo, Loc,
T.getOpenLocation(), VarLoc,
3743 if (Kind == OMPC_use)
3745 InteropVarExpr.
get(), Loc,
T.getOpenLocation(), VarLoc, RLoc);
3747 if (Kind == OMPC_destroy)
3749 InteropVarExpr.
get(), Loc,
T.getOpenLocation(), VarLoc, RLoc);
3751 llvm_unreachable(
"Unexpected interop variable clause.");
3754OMPClause *Parser::ParseOpenMPOMPXAttributesClause(
bool ParseOnly) {
3758 if (
T.expectAndConsume(diag::err_expected_lparen_after,
3759 getOpenMPClauseName(OMPC_ompx_attribute).data()))
3763 ParseAttributes(PAKM_GNU | PAKM_CXX11, ParsedAttrs);
3766 if (
T.consumeClose())
3774 switch (PA.getKind()) {
3775 case ParsedAttr::AT_AMDGPUFlatWorkGroupSize:
3776 if (!PA.checkExactlyNumArgs(Actions, 2))
3779 PA, PA.getArgAsExpr(0), PA.getArgAsExpr(1)))
3782 case ParsedAttr::AT_AMDGPUWavesPerEU:
3783 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3784 !PA.checkAtMostNumArgs(Actions, 2))
3787 PA, PA.getArgAsExpr(0),
3788 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) :
nullptr))
3791 case ParsedAttr::AT_CUDALaunchBounds:
3792 if (!PA.checkAtLeastNumArgs(Actions, 1) ||
3793 !PA.checkAtMostNumArgs(Actions, 2))
3796 PA, PA.getArgAsExpr(0),
3797 PA.getNumArgs() > 1 ? PA.getArgAsExpr(1) :
nullptr,
3798 PA.getNumArgs() > 2 ? PA.getArgAsExpr(2) :
nullptr))
3802 Diag(Loc, diag::warn_omp_invalid_attribute_for_ompx_attributes) << PA;
3808 Attrs, Loc,
T.getOpenLocation(),
T.getCloseLocation());
3829 if (!Val || ParseOnly)
3831 if (
getLangOpts().OpenMP < 51 && Kind == OMPC_default &&
3832 (
static_cast<DefaultKind
>(Val->Type) == OMP_DEFAULT_private ||
3833 static_cast<DefaultKind
>(Val->Type) ==
3834 OMP_DEFAULT_firstprivate)) {
3835 Diag(Val->LOpen, diag::err_omp_invalid_dsa)
3836 << getOpenMPClauseName(
static_cast<DefaultKind
>(Val->Type) ==
3839 : OMPC_firstprivate)
3840 << getOpenMPClauseName(OMPC_default) <<
"5.1";
3844 Kind, Val->Type, Val->TypeLoc, Val->LOpen, Val->Loc, Val->RLoc);
3905 if (
T.expectAndConsume(diag::err_expected_lparen_after,
3906 getOpenMPClauseName(Kind).data()))
3912 if (Kind == OMPC_schedule) {
3913 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
3914 Arg.resize(NumberOfElements);
3915 KLoc.resize(NumberOfElements);
3923 Arg[Modifier1] = KindModifier;
3925 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3926 Tok.
isNot(tok::annot_pragma_openmp_end))
3928 if (Tok.
is(tok::comma)) {
3937 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3938 Tok.
isNot(tok::annot_pragma_openmp_end))
3942 if (Tok.
is(tok::colon))
3945 Diag(Tok, diag::warn_pragma_expected_colon) <<
"schedule modifier";
3949 Arg[ScheduleKind] = KindModifier;
3951 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3952 Tok.
isNot(tok::annot_pragma_openmp_end))
3954 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
3955 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
3956 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
3959 }
else if (Kind == OMPC_dist_schedule) {
3963 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3964 Tok.
isNot(tok::annot_pragma_openmp_end))
3966 if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.
is(tok::comma))
3968 }
else if (Kind == OMPC_defaultmap) {
3976 Arg.push_back(Modifier);
3978 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3979 Tok.
isNot(tok::annot_pragma_openmp_end))
3983 if (Tok.
is(tok::colon))
3986 Diag(Tok, diag::warn_pragma_expected_colon) <<
"defaultmap modifier";
3991 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
3992 Tok.
isNot(tok::annot_pragma_openmp_end))
3998 }
else if (Kind == OMPC_order) {
3999 enum { Modifier, OrderKind, NumberOfElements };
4000 Arg.resize(NumberOfElements);
4001 KLoc.resize(NumberOfElements);
4008 Arg[Modifier] = KindModifier;
4010 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
4011 Tok.
isNot(tok::annot_pragma_openmp_end))
4014 if (Tok.
is(tok::colon))
4017 Diag(Tok, diag::warn_pragma_expected_colon) <<
"order modifier";
4021 Arg[OrderKind] = KindModifier;
4023 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
4024 Tok.
isNot(tok::annot_pragma_openmp_end))
4026 }
else if (Kind == OMPC_device) {
4039 KLoc.emplace_back();
4041 }
else if (Kind == OMPC_grainsize) {
4049 Arg.push_back(Modifier);
4056 if (Modifier == OMPC_GRAINSIZE_strict) {
4057 Diag(Tok, diag::err_modifier_expected_colon) <<
"strict";
4062 KLoc.emplace_back();
4066 KLoc.emplace_back();
4068 }
else if (Kind == OMPC_num_tasks) {
4076 Arg.push_back(Modifier);
4083 if (Modifier == OMPC_NUMTASKS_strict) {
4084 Diag(Tok, diag::err_modifier_expected_colon) <<
"strict";
4089 KLoc.emplace_back();
4093 KLoc.emplace_back();
4096 assert(Kind == OMPC_if);
4098 TentativeParsingAction TPA(*
this);
4101 if (DK != OMPD_unknown) {
4108 Arg.back() =
unsigned(OMPD_unknown);
4115 bool NeedAnExpression = (
Kind == OMPC_schedule && DelimLoc.
isValid()) ||
4116 (Kind == OMPC_dist_schedule && DelimLoc.
isValid()) ||
4117 Kind == OMPC_if || Kind == OMPC_device ||
4118 Kind == OMPC_grainsize || Kind == OMPC_num_tasks;
4119 if (NeedAnExpression) {
4129 if (!
T.consumeClose())
4130 RLoc =
T.getCloseLocation();
4132 if (NeedAnExpression && Val.
isInvalid())
4138 Kind, Arg, Val.
get(), Loc,
T.getOpenLocation(), KLoc, DelimLoc, RLoc);
4143 if (ReductionIdScopeSpec.
isEmpty()) {
4145 switch (
P.getCurToken().getKind()) {
4180 return P.ParseUnqualifiedId(
4181 ReductionIdScopeSpec,
nullptr,
4185 false,
nullptr, ReductionId);
4191 Token Tok =
P.getCurToken();
4192 if (!Tok.
is(tok::identifier))
4199 return TypeModifier;
4206 if (
T.expectAndConsume(diag::err_expected_lparen_after,
"mapper")) {
4207 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4213 ParseOptionalCXXScopeSpecifier(
Data.ReductionOrMapperIdScopeSpec,
4217 if (Tok.
isNot(tok::identifier) && Tok.
isNot(tok::kw_default)) {
4219 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4228 return T.consumeClose();
4238 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
4239 TypeModifier == OMPC_MAP_MODIFIER_close ||
4240 TypeModifier == OMPC_MAP_MODIFIER_present ||
4241 TypeModifier == OMPC_MAP_MODIFIER_ompx_hold) {
4242 Data.MapTypeModifiers.push_back(TypeModifier);
4247 <<
"map type modifier";
4249 }
else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
4250 Data.MapTypeModifiers.push_back(TypeModifier);
4255 if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::colon) &&
4257 Diag(
Data.MapTypeModifiersLoc.back(), diag::err_omp_missing_comma)
4258 <<
"map type modifier";
4264 if (Tok.
is(tok::comma)) {
4265 Diag(Tok, diag::err_omp_map_type_modifier_missing);
4272 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4287 Token Tok =
P.getCurToken();
4289 if (!Tok.
isOneOf(tok::identifier, tok::kw_delete))
4302 Token Tok =
P.getCurToken();
4303 if (Tok.
is(tok::colon)) {
4304 P.Diag(Tok, diag::err_omp_map_type_missing);
4309 P.Diag(Tok, diag::err_omp_unknown_map_type);
4315ExprResult Parser::ParseOpenMPIteratorsExpr() {
4316 assert(Tok.
is(tok::identifier) && PP.
getSpelling(Tok) ==
"iterator" &&
4317 "Expected 'iterator' token.");
4321 if (
T.expectAndConsume(diag::err_expected_lparen_after,
"iterator"))
4326 while (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::annot_pragma_openmp_end)) {
4329 if (Tok.
isNot(tok::identifier) ||
NextToken().isNot(tok::equal)) {
4336 IteratorType = TR.
get();
4342 if (Tok.
is(tok::identifier)) {
4346 Diag(Tok, diag::err_expected_unqualified_id) << 0;
4351 if (Tok.
is(tok::equal))
4354 Diag(Tok, diag::err_omp_expected_equal_in_iterator);
4360 ExprResult LHS = ParseCastExpression(AnyCastExpr);
4367 if (Tok.
is(tok::colon))
4372 LHS = ParseCastExpression(AnyCastExpr);
4381 if (Tok.
is(tok::colon)) {
4386 LHS = ParseCastExpression(AnyCastExpr);
4394 if (Tok.
isNot(tok::comma) && Tok.
isNot(tok::r_paren))
4395 Diag(Tok, diag::err_omp_expected_punc_after_iterator);
4396 if (Tok.
is(tok::comma))
4402 D.
Type = IteratorType;
4413 if (!
T.consumeClose())
4414 RLoc =
T.getCloseLocation();
4425 if (Kind != OMPC_depend || LangOpts.OpenMP < 51)
4428 if (Tok.
is(tok::identifier) &&
4431 if (
Data.ExtraModifier == OMPC_DEPEND_outallmemory ||
4432 Data.ExtraModifier == OMPC_DEPEND_inoutallmemory)
4433 Diag(Tok, diag::warn_omp_more_one_omp_all_memory);
4434 else if (
Data.ExtraModifier != OMPC_DEPEND_out &&
4435 Data.ExtraModifier != OMPC_DEPEND_inout)
4436 Diag(Tok, diag::err_omp_requires_out_inout_depend_type);
4438 Data.ExtraModifier =
Data.ExtraModifier == OMPC_DEPEND_out
4439 ? OMPC_DEPEND_outallmemory
4440 : OMPC_DEPEND_inoutallmemory;
4452 Sema &Actions =
P.getActions();
4456 Data.DepModOrTailExpr = Tail.
get();
4457 Token CurTok =
P.getCurToken();
4458 if (CurTok.
isNot(tok::r_paren) && CurTok.
isNot(tok::comma)) {
4459 P.Diag(CurTok, diag::err_expected_punc) <<
"step expression";
4472 bool InvalidReductionId =
false;
4473 bool IsInvalidMapperModifier =
false;
4477 if (
T.expectAndConsume(diag::err_expected_lparen_after,
4478 getOpenMPClauseName(Kind).data()))
4481 bool HasIterator =
false;
4482 bool InvalidIterator =
false;
4483 bool NeedRParenForLinear =
false;
4485 tok::annot_pragma_openmp_end);
4487 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
4488 Kind == OMPC_in_reduction) {
4490 if (Kind == OMPC_reduction &&
getLangOpts().OpenMP >= 50 &&
4491 (Tok.
is(tok::identifier) || Tok.
is(tok::kw_default)) &&
4494 Data.ExtraModifier =
4498 assert(Tok.
is(tok::comma) &&
"Expected comma.");
4503 ParseOptionalCXXScopeSpecifier(
Data.ReductionOrMapperIdScopeSpec,
4508 *
this,
Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
4509 if (InvalidReductionId) {
4510 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4513 if (Tok.
is(tok::colon))
4516 Diag(Tok, diag::warn_pragma_expected_colon) <<
"reduction identifier";
4517 if (!InvalidReductionId)
4518 Data.ReductionOrMapperId =
4520 }
else if (Kind == OMPC_depend || Kind == OMPC_doacross) {
4522 if (Tok.
is(tok::identifier) && PP.
getSpelling(Tok) ==
"iterator") {
4531 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4532 Data.DepModOrTailExpr = IteratorRes.
get();
4534 ExpectAndConsume(tok::comma);
4544 (Kind == OMPC_doacross &&
4546 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4551 if (DKind == OMPD_ordered && Kind == OMPC_depend &&
4552 Data.ExtraModifier == OMPC_DEPEND_source) {
4558 if (Tok.
is(tok::colon)) {
4560 }
else if (Kind != OMPC_doacross || Tok.
isNot(tok::r_paren)) {
4561 Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
4562 : diag::warn_pragma_expected_colon)
4563 << (Kind == OMPC_depend ?
"dependency type" :
"dependence-type");
4565 if (Kind == OMPC_doacross) {
4566 if (Tok.
is(tok::identifier) &&
4568 Data.ExtraModifier =
Data.ExtraModifier == OMPC_DOACROSS_source
4569 ? OMPC_DOACROSS_source_omp_cur_iteration
4570 : OMPC_DOACROSS_sink_omp_cur_iteration;
4573 if (
Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration) {
4574 if (Tok.
isNot(tok::minus)) {
4575 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4576 << getOpenMPClauseName(Kind) << 0 << 0;
4583 if (Tok.
isNot(tok::numeric_constant) ||
4585 Diag(Loc, diag::err_omp_sink_and_source_iteration_not_allowd)
4586 << getOpenMPClauseName(Kind) << 0 << 0;
4592 if (
Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration) {
4593 if (Tok.
isNot(tok::r_paren)) {
4594 Diag(Tok, diag::err_omp_sink_and_source_iteration_not_allowd)
4595 << getOpenMPClauseName(Kind) << 1 << 1;
4601 if (Kind == OMPC_doacross &&
4602 (
Data.ExtraModifier == OMPC_DOACROSS_source ||
4603 Data.ExtraModifier == OMPC_DOACROSS_source_omp_cur_iteration ||
4604 Data.ExtraModifier == OMPC_DOACROSS_sink_omp_cur_iteration)) {
4610 }
else if (Kind == OMPC_linear) {
4612 Data.ExtraModifier = OMPC_LINEAR_val;
4613 if (Tok.
is(tok::identifier) && PP.
LookAhead(0).
is(tok::l_paren)) {
4614 Data.ExtraModifier =
4618 NeedRParenForLinear =
true;
4620 Diag(
Data.ExtraModifierLoc, diag::err_omp_deprecate_old_syntax)
4621 <<
"linear-modifier(list)" << getOpenMPClauseName(Kind)
4622 <<
"linear(list: [linear-modifier,] step(step-size))";
4624 }
else if (Kind == OMPC_lastprivate) {
4631 Tok.
is(tok::identifier) && PP.
LookAhead(0).
is(tok::colon)) {
4632 Data.ExtraModifier =
4636 assert(Tok.
is(tok::colon) &&
"Expected colon.");
4639 }
else if (Kind == OMPC_map) {
4641 if (Tok.
is(tok::identifier) && PP.
getSpelling(Tok) ==
"iterator") {
4644 Data.MapTypeModifiers.push_back(OMPC_MAP_MODIFIER_iterator);
4646 ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
4647 Data.IteratorExpr = IteratorRes.
get();
4649 ExpectAndConsume(tok::comma);
4651 Diag(Tok, diag::err_omp_unknown_map_type_modifier)
4654 InvalidIterator =
true;
4667 TentativeParsingAction TPA(*
this);
4668 bool ColonPresent =
false;
4669 if (
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4671 if (Tok.
is(tok::colon))
4672 ColonPresent =
true;
4679 if (!IsInvalidMapperModifier)
4685 Data.ExtraModifier = OMPC_MAP_tofrom;
4687 if (DKind == OMPD_target_enter_data)
4688 Data.ExtraModifier = OMPC_MAP_to;
4689 else if (DKind == OMPD_target_exit_data)
4690 Data.ExtraModifier = OMPC_MAP_from;
4692 Data.IsMapTypeImplicit =
true;
4695 if (Tok.
is(tok::colon))
4697 }
else if (Kind == OMPC_to || Kind == OMPC_from) {
4698 while (Tok.
is(tok::identifier)) {
4703 Data.MotionModifiers.push_back(Modifier);
4706 if (Modifier == OMPC_MOTION_MODIFIER_mapper) {
4708 if (IsInvalidMapperModifier)
4716 if (Tok.
is(tok::comma))
4719 if (!
Data.MotionModifiers.empty() && Tok.
isNot(tok::colon)) {
4720 if (!IsInvalidMapperModifier) {
4722 Diag(Tok, diag::warn_pragma_expected_colon) <<
")";
4724 Diag(Tok, diag::warn_pragma_expected_colon) <<
"motion modifier";
4726 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4734 }
else if (Kind == OMPC_allocate ||
4735 (Kind == OMPC_affinity && Tok.
is(tok::identifier) &&
4739 TentativeParsingAction TPA(*
this);
4744 if (Kind == OMPC_allocate) {
4749 Tail = ParseOpenMPIteratorsExpr();
4755 if (Tok.
is(tok::colon)) {
4756 Data.DepModOrTailExpr = Tail.
get();
4767 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4770 }
else if (Kind == OMPC_adjust_args) {
4778 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
4782 if (Tok.
is(tok::colon))
4784 ExpectAndConsume(tok::colon, diag::warn_pragma_expected_colon,
4790 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
4791 Kind != OMPC_in_reduction && Kind != OMPC_depend &&
4792 Kind != OMPC_doacross && Kind != OMPC_map) ||
4793 (Kind == OMPC_reduction && !InvalidReductionId) ||
4797 (Kind == OMPC_adjust_args &&
4799 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
4800 while (IsComma || (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::colon) &&
4801 Tok.
isNot(tok::annot_pragma_openmp_end))) {
4809 Vars.push_back(VarExpr.
get());
4811 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4816 IsComma = Tok.
is(tok::comma);
4819 else if (Tok.
isNot(tok::r_paren) &&
4820 Tok.
isNot(tok::annot_pragma_openmp_end) &&
4821 (!MayHaveTail || Tok.
isNot(tok::colon)))
4822 Diag(Tok, diag::err_omp_expected_punc)
4823 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
4824 : getOpenMPClauseName(Kind))
4825 << (Kind == OMPC_flush);
4829 if (NeedRParenForLinear)
4834 const bool MustHaveTail = MayHaveTail && Tok.
is(tok::colon);
4835 bool StepFound =
false;
4836 bool ModifierFound =
false;
4841 if (
getLangOpts().OpenMP >= 52 && Kind == OMPC_linear) {
4842 while (Tok.
isNot(tok::r_paren)) {
4843 if (Tok.
is(tok::identifier)) {
4851 if (LinKind == OMPC_LINEAR_step) {
4853 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 0;
4856 tok::annot_pragma_openmp_end);
4860 Diag(StepModifierLoc, diag::err_expected_lparen_after) <<
"step";
4865 Data.StepModifierLoc = StepModifierLoc;
4869 }
else if (LinKind >= 0 && LinKind < OMPC_LINEAR_step) {
4871 Diag(Tok, diag::err_omp_multiple_step_or_linear_modifier) << 1;
4873 Data.ExtraModifier = LinKind;
4875 ModifierFound =
true;
4884 if (Tok.
is(tok::comma))
4886 if (Tok.
is(tok::r_paren) || Tok.
is(tok::annot_pragma_openmp_end))
4889 if (!StepFound && !ModifierFound)
4890 Diag(ELoc, diag::err_expected_expression);
4897 Data.DepModOrTailExpr = Tail.
get();
4899 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
4906 if (!
T.consumeClose())
4907 Data.RLoc =
T.getCloseLocation();
4911 return (Kind != OMPC_depend && Kind != OMPC_doacross && Kind != OMPC_map &&
4913 (MustHaveTail && !
Data.DepModOrTailExpr && StepFound) ||
4914 InvalidReductionId || IsInvalidMapperModifier || InvalidIterator;
Defines the clang::ASTContext interface.
This file defines OpenMP AST classes for clauses.
Defines some OpenMP-specific enums and functions.
static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P)
static OpenMPMapModifierKind isMapModifier(Parser &P)
Checks if the token is a valid map-type-modifier.
static std::optional< SimpleClauseData > parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind)
static unsigned getOpenMPDirectiveKindEx(StringRef S)
static bool checkExtensionProperty(Parser &P, SourceLocation Loc, OMPTraitProperty &TIProperty, OMPTraitSelector &TISelector, llvm::StringMap< SourceLocation > &Seen)
static DeclarationName parseOpenMPReductionId(Parser &P)
static ExprResult parseContextScore(Parser &P)
Parse optional 'score' '(' <expr> ')' ':'.
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
static bool parseStepSize(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data, OpenMPClauseKind CKind, SourceLocation ELoc)
Parse step size expression.
static void parseMapType(Parser &P, SemaOpenMP::OpenMPVarListDataTy &Data)
Parse map-type in map clause.
static bool parseDeclareSimdClauses(Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen, SmallVectorImpl< Expr * > &Uniforms, SmallVectorImpl< Expr * > &Aligneds, SmallVectorImpl< Expr * > &Alignments, SmallVectorImpl< Expr * > &Linears, SmallVectorImpl< unsigned > &LinModifiers, SmallVectorImpl< Expr * > &Steps)
Parses clauses for 'declare simd' directive.
static OpenMPMapClauseKind isMapType(Parser &P)
Checks if the token is a valid map-type.
This file declares semantic analysis for OpenMP constructs and clauses.
This file defines OpenMP AST classes for executable directives and clauses.
Defines the clang::TokenKind enum and support functions.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
DeclarationNameTable DeclarationNames
OMPTraitInfo & getNewOMPTraitInfo()
Return a new OMPTraitInfo object owned by this context.
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ....
Represents a C++ nested-name-specifier or a global scope specifier.
bool isEmpty() const
No scope specifier.
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed.
Captures information about "declaration specifiers".
static const TST TST_unspecified
Decl - This represents one declaration (or definition), e.g.
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
SourceLocation getLocation() const
DeclContext * getDeclContext()
The name of a declaration.
Information about one declarator, including the parsed type information and the identifier.
RAII object that enters a new expression evaluation context.
bool isValueDependent() const
Determines whether the value of this expression depends on.
bool isTypeDependent() const
Determines whether the type of this expression depends on.
bool containsUnexpandedParameterPack() const
Whether this expression contains an unexpanded parameter pack (for C++11 variadic templates).
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
One of these records is kept for each identifier that is lexed.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
StringRef getName() const
Return the actual identifier string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
This represents a decl that may have a name.
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
This is a basic class for representing single OpenMP clause.
Helper data structure representing the traits in a match clause of an declare variant or metadirectiv...
void getAsVariantMatchInfo(ASTContext &ASTCtx, llvm::omp::VariantMatchInfo &VMI) const
Create a variant match info object from this trait info object.
llvm::SmallVector< OMPTraitSet, 2 > Sets
The outermost level of selector sets.
Wrapper for void* pointer.
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing,...
ParsedAttr - Represents a syntactic attribute.
static const ParsedAttributesView & none()
ParsedAttributes - A collection of parsed attributes.
Introduces zero or more scopes for parsing.
ParseScope - Introduces a new scope for parsing.
Parser - This implements a parser for the C family of languages.
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr * > &Vars, SemaOpenMP::OpenMPVarListDataTy &Data)
Parses clauses with list.
TypeResult ParseTypeName(SourceRange *Range=nullptr, DeclaratorContext Context=DeclaratorContext::TypeName, AccessSpecifier AS=AS_none, Decl **OwnedType=nullptr, ParsedAttributes *Attrs=nullptr)
ParseTypeName type-name: [C99 6.7.6] specifier-qualifier-list abstract-declarator[opt].
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
bool parseMapTypeModifiers(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses map-type-modifiers in map clause.
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
void EnterScope(unsigned ScopeFlags)
EnterScope - Start a new scope.
bool parseMapperModifier(SemaOpenMP::OpenMPVarListDataTy &Data)
Parses the mapper modifier in map, to, and from clauses.
bool ParseUnqualifiedId(CXXScopeSpec &SS, ParsedType ObjectType, bool ObjectHadErrors, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, SourceLocation *TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
ExprResult ParseConstantExpression()
bool TryConsumeToken(tok::TokenKind Expected)
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Scope * getCurScope() const
bool SkipUntil(tok::TokenKind T, SkipUntilFlags Flags=static_cast< SkipUntilFlags >(0))
SkipUntil - Read tokens until we get to the specified token, then consume it (unless StopBeforeMatch ...
const Token & getCurToken() const
void ExitScope()
ExitScope - Pop a scope off the scope stack.
ExprResult ParseAssignmentExpression(TypeCastState isTypeCast=NotTypeCast)
Parse an expr that doesn't include (top-level) commas.
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc, bool IsAddressOfOperand=false)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
const LangOptions & getLangOpts() const
ExprResult ParseExpression(TypeCastState isTypeCast=NotTypeCast)
Simple precedence-based parser for binary/ternary operators.
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
bool ParseOpenMPReservedLocator(OpenMPClauseKind Kind, SemaOpenMP::OpenMPVarListDataTy &Data, const LangOptions &LangOpts)
Parses a reserved locator like 'omp_all_memory'.
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
A class for parsing a DeclSpec.
Activates OpenMP parsing mode to preseve OpenMP specific annotation tokens.
void enterVariableInit(SourceLocation Tok, Decl *D)
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void EnterToken(const Token &Tok, bool IsReinject)
Enters a token in the token stream to be lexed next.
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value)
Parses a simple integer literal to get its numeric value.
StringRef getSpelling(SourceLocation loc, SmallVectorImpl< char > &buffer, bool *invalid=nullptr) const
Return the 'spelling' of the token at the given location; does not go up to the spelling location or ...
bool isCodeCompletionReached() const
Returns true if code-completion is enabled and we have hit the code-completion point.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
The collection of all-type qualifiers we support.
Represents a struct/union/class.
Scope - A scope is a transient data structure that is used while parsing the program.
@ OpenMPDirectiveScope
This is the scope of OpenMP executable directive.
@ CompoundStmtScope
This is a compound statement scope.
@ OpenMPSimdDirectiveScope
This is the scope of some OpenMP simd directive.
@ FnScope
This indicates that the scope corresponds to a function, which means that labels are set here.
@ OpenMPLoopDirectiveScope
This is the scope of some OpenMP loop directive.
@ DeclScope
This is a scope that can contain a declaration.
Smart pointer class that efficiently represents Objective-C method names.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd(Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid)
Called at the end of '#pragma omp declare reduction'.
void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner)
Finish current declare reduction construct initializer.
OMPClause * ActOnOpenMPUseClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'use' clause.
void ActOnFinishedOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called once a target context is completed, that can be when a '#pragma omp end declare target' was en...
void StartOpenMPClause(OpenMPClauseKind K)
Start analysis of clauses.
ExprResult ActOnOpenMPDeclareMapperDirectiveVarDecl(Scope *S, QualType MapperType, SourceLocation StartLoc, DeclarationName VN)
Build the mapper variable of '#pragma omp declare mapper'.
StmtResult ActOnOpenMPErrorDirective(ArrayRef< OMPClause * > Clauses, SourceLocation StartLoc, SourceLocation EndLoc, bool InExContext=true)
Called on well-formed '#pragma omp error'.
DeclGroupPtrTy ActOnOpenMPRequiresDirective(SourceLocation Loc, ArrayRef< OMPClause * > ClauseList)
Called on well-formed '#pragma omp requires'.
OMPClause * ActOnOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, ArrayRef< unsigned > Arguments, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef< SourceLocation > ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPDestroyClause(Expr *InteropVar, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'destroy' clause.
VarDecl * ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
void ActOnOpenMPEndAssumesDirective()
Called on well-formed '#pragma omp end assumes'.
QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare reduction' construct.
DeclGroupPtrTy ActOnOpenMPAllocateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList, ArrayRef< OMPClause * > Clauses, DeclContext *Owner=nullptr)
Called on well-formed '#pragma omp allocate'.
OMPClause * ActOnOpenMPSimpleClause(OpenMPClauseKind Kind, unsigned Argument, SourceLocation ArgumentLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
bool isInOpenMPDeclareVariantScope() const
Can we exit an OpenMP declare variant scope at the moment.
TypeResult ActOnOpenMPDeclareMapperVarDecl(Scope *S, Declarator &D)
Check variable declaration in 'omp declare mapper' construct.
ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc, ArrayRef< OMPIteratorData > Data)
OMPClause * ActOnOpenMPUsesAllocatorClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef< UsesAllocatorsData > Data)
Called on well-formed 'uses_allocators' clause.
StmtResult ActOnOpenMPRegionEnd(StmtResult S, ArrayRef< OMPClause * > Clauses)
End of OpenMP region.
DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart(Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef< std::pair< QualType, SourceLocation > > ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare reduction'.
void ActOnOpenMPEndDeclareVariant()
Handle a omp end declare variant.
void EndOpenMPDSABlock(Stmt *CurDirective)
Called on end of data sharing attribute block.
OMPClause * ActOnOpenMPSizesClause(ArrayRef< Expr * > SizeExprs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on well-form 'sizes' clause.
bool ActOnStartOpenMPDeclareTargetContext(DeclareTargetContextInfo &DTCI)
Called on the start of target region i.e. '#pragma omp declare target'.
StmtResult ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef< OMPClause * > Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind PrevMappedDirective=llvm::omp::OMPD_unknown)
void EndOpenMPClause()
End analysis of clauses.
bool isInOpenMPAssumeScope() const
Check if there is an active global omp begin assumes directive.
QualType ActOnOpenMPDeclareMapperType(SourceLocation TyLoc, TypeResult ParsedType)
Check if the specified type is allowed to be used in 'omp declare mapper' construct.
std::optional< std::pair< FunctionDecl *, Expr * > > checkOpenMPDeclareVariantFunction(DeclGroupPtrTy DG, Expr *VariantRef, OMPTraitInfo &TI, unsigned NumAppendArgs, SourceRange SR)
Checks '#pragma omp declare variant' variant function and original functions after parsing of the ass...
OMPClause * ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
OMPClause * ActOnOpenMPInitClause(Expr *InteropVar, OMPInteropInfo &InteropInfo, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation VarLoc, SourceLocation EndLoc)
Called on well-formed 'init' clause.
void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D)
Initialize declare reduction construct initializer.
bool isInOpenMPDeclareTargetContext() const
Return true inside OpenMP declare target region.
OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef< Expr * > Vars, const OMPVarListLocTy &Locs, OpenMPVarListDataTy &Data)
void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc)
Called on start of new data sharing attribute block.
void ActOnOpenMPDeclareVariantDirective(FunctionDecl *FD, Expr *VariantRef, OMPTraitInfo &TI, ArrayRef< Expr * > AdjustArgsNothing, ArrayRef< Expr * > AdjustArgsNeedDevicePtr, ArrayRef< OMPInteropInfo > AppendArgs, SourceLocation AdjustArgsLoc, SourceLocation AppendArgsLoc, SourceRange SR)
Called on well-formed '#pragma omp declare variant' after parsing of the associated method/function.
void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm)
Finish current declare reduction construct initializer.
DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective(DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, Expr *Simdlen, ArrayRef< Expr * > Uniforms, ArrayRef< Expr * > Aligneds, ArrayRef< Expr * > Alignments, ArrayRef< Expr * > Linears, ArrayRef< unsigned > LinModifiers, ArrayRef< Expr * > Steps, SourceRange SR)
Called on well-formed '#pragma omp declare simd' after parsing of the associated method/function.
OMPClause * ActOnOpenMPXAttributeClause(ArrayRef< const Attr * > Attrs, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
Called on a well-formed 'ompx_attribute' clause.
DeclGroupPtrTy ActOnOpenMPThreadprivateDirective(SourceLocation Loc, ArrayRef< Expr * > VarList)
Called on well-formed '#pragma omp threadprivate'.
void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope)
Initialization of captured region for OpenMP region.
NamedDecl * lookupOpenMPDeclareTargetName(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id)
Searches for the provided declaration name for OpenMP declare target directive.
void ActOnOpenMPAssumesDirective(SourceLocation Loc, OpenMPDirectiveKind DKind, ArrayRef< std::string > Assumptions, bool SkippedClauses)
Called on well-formed '#pragma omp [begin] assume[s]'.
void ActOnOpenMPBeginDeclareVariant(SourceLocation Loc, OMPTraitInfo &TI)
Handle a omp begin declare variant.
StmtResult ActOnOpenMPLoopnest(Stmt *AStmt)
Process a canonical OpenMP loop nest that can either be a canonical literal loop (ForStmt or CXXForRa...
const DeclareTargetContextInfo ActOnOpenMPEndDeclareTargetDirective()
Called at the end of target region i.e. '#pragma omp end declare target'.
OMPClause * ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc)
DeclGroupPtrTy ActOnOpenMPDeclareMapperDirective(Scope *S, DeclContext *DC, DeclarationName Name, QualType MapperType, SourceLocation StartLoc, DeclarationName VN, AccessSpecifier AS, Expr *MapperVarRef, ArrayRef< OMPClause * > Clauses, Decl *PrevDeclInScope=nullptr)
Called on start of '#pragma omp declare mapper'.
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
A RAII object to enter scope of a compound statement.
Sema - This implements semantic analysis and AST building for C.
Scope * getCurScope() const
Retrieve the parser's current scope.
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...
AMDGPUFlatWorkGroupSizeAttr * CreateAMDGPUFlatWorkGroupSizeAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
ExprResult VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result, VerifyICEDiagnoser &Diagnoser, AllowFoldKind CanFold=NoFold)
VerifyIntegerConstantExpression - Verifies that an expression is an ICE, and reports the appropriate ...
void ActOnReenterFunctionContext(Scope *S, Decl *D)
Push the parameters of D, which must be a function, into scope.
void FinalizeDeclaration(Decl *D)
FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform any semantic actions neces...
DeclarationNameInfo GetNameForDeclarator(Declarator &D)
GetNameForDeclarator - Determine the full declaration name for the given Declarator.
AMDGPUWavesPerEUAttr * CreateAMDGPUWavesPerEUAttr(const AttributeCommonInfo &CI, Expr *Min, Expr *Max)
Create an AMDGPUWavesPerEUAttr attribute.
ASTContext & getASTContext() const
ExprResult ActOnParenListExpr(SourceLocation L, SourceLocation R, MultiExprArg Val)
DeclContext * getCurLexicalContext() const
DeclGroupPtrTy BuildDeclaratorGroup(MutableArrayRef< Decl * > Group)
BuildDeclaratorGroup - convert a list of declarations into a declaration group, performing any necess...
DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name)
Retrieves the declaration name from a parsed unqualified-id.
void ActOnInitializerError(Decl *Dcl)
ActOnInitializerError - Given that there was an error parsing an initializer for the given declaratio...
@ Unevaluated
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7),...
StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)
void ActOnUninitializedDecl(Decl *dcl)
void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)
AddInitializerToDecl - Adds the initializer Init to the declaration dcl.
CUDALaunchBoundsAttr * CreateLaunchBoundsAttr(const AttributeCommonInfo &CI, Expr *MaxThreads, Expr *MinBlocks, Expr *MaxBlocks)
Create an CUDALaunchBoundsAttr attribute.
StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef< Stmt * > Elts, bool isStmtExpr)
ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})
Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...
ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
StringLiteral - This represents a string literal expression, e.g.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
bool isAnyIdentifier() const
Return true if this is a raw identifier (when lexing in raw mode) or a non-keyword identifier (when l...
SourceLocation getEndLoc() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
bool is(tok::TokenKind K) const
is/isNot - Predicates to check if this token is a specific kind, as in "if (Tok.is(tok::l_brace)) {....
tok::TokenKind getKind() const
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
bool isNot(tok::TokenKind K) const
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
Base wrapper for a particular "section" of type source info.
The base class of the type hierarchy.
QualType getCanonicalTypeInternal() const
Represents a C++ unqualified-id that has been parsed.
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
Represents a variable declaration or definition.
Directive - Abstract class representing a parsed verify directive.
Defines the clang::TargetInfo interface.
bool Ret(InterpState &S, CodePtr &PC, APValue &Result)
bool isStringLiteral(TokenKind K)
Return true if this is a C or C++ string-literal (or C++11 user-defined-string-literal) token.
The JSON file list parser is used to communicate input to InstallAPI.
TypeSpecifierType
Specifies the kind of type.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
@ OMPC_DEFAULTMAP_MODIFIER_unknown
@ OMPC_ORDER_MODIFIER_unknown
@ OMPC_ADJUST_ARGS_unknown
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
OpenMPDeviceType
OpenMP device type for 'device_type' clause.
@ OMPC_DEVICE_TYPE_unknown
@ OMPC_SCHEDULE_MODIFIER_unknown
llvm::omp::Clause OpenMPClauseKind
OpenMP clauses.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a target code offload directive.
@ Property
The type of a property.
@ Result
The result type of a method or function.
@ OMPC_LASTPRIVATE_unknown
OpenMPGrainsizeClauseModifier
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str, const LangOptions &LangOpts)
OpenMPNumTasksClauseModifier
ActionResult< Expr * > ExprResult
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
OpenMPMotionModifierKind
OpenMP modifier kind for 'to' or 'from' clause.
@ OMPC_MOTION_MODIFIER_unknown
bool operator!=(CanQual< T > x, CanQual< U > y)
@ OMPC_DEFAULTMAP_unknown
OpenMPLinearClauseKind
OpenMP attributes for 'linear' clause.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
const FunctionProtoType * T
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
@ OMPC_MAP_MODIFIER_unknown
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
SourceLocation getLoc() const
getLoc - Returns the main location of the declaration name.
DeclarationName getName() const
getName - Returns the embedded declaration name.
llvm::SmallVector< Expr *, 4 > PreferTypes
llvm::omp::TraitProperty Kind
StringRef RawString
The raw string as we parsed it.
llvm::omp::TraitSelector Kind
llvm::SmallVector< OMPTraitProperty, 1 > Properties
llvm::SmallVector< OMPTraitSelector, 2 > Selectors
This structure contains most locations needed for by an OMPVarListClause.
std::optional< Expr * > Indirect
The directive with indirect clause.
OpenMPDirectiveKind Kind
The directive kind, begin declare target or declare target.
OMPDeclareTargetDeclAttr::DevTypeTy DT
The 'device_type' as parsed from the clause.
SourceLocation Loc
The directive location.
llvm::DenseMap< NamedDecl *, MapInfo > ExplicitlyMapped
Explicitly listed variables and functions in a 'to' or 'link' clause.
Data structure for iterator expression.
SourceLocation DeclIdentLoc
SourceLocation SecColonLoc
IdentifierInfo * DeclIdent
OMPIteratorExpr::IteratorRange Range
Data used for processing a list of variables in OpenMP clauses.
Data for list of allocators.
Expr * AllocatorTraits
Allocator traits.
SourceLocation LParenLoc
Locations of '(' and ')' symbols.
Expr * Allocator
Allocator.
Clang specific specialization of the OMPContext to lookup target features.