20 #include "llvm/ADT/PointerIntPair.h" 21 #include "llvm/ADT/UniqueVector.h" 23 using namespace clang;
32 OMPD_cancellation = unsigned(OMPD_unknown) + 1,
44 OMPD_distribute_parallel,
45 OMPD_teams_distribute_parallel,
46 OMPD_target_teams_distribute_parallel,
54 struct OpenMPDirectiveKindExWrapper {
55 OpenMPDirectiveKindExWrapper(
unsigned Value) :
Value(Value) {}
60 operator unsigned()
const {
return Value; }
65 class DeclDirectiveListParserHelper final {
77 Identifiers.push_back(Res.
get());
86 OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
87 if (DKind != OMPD_unknown)
90 return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
91 .Case(
"cancellation", OMPD_cancellation)
92 .Case(
"data", OMPD_data)
93 .Case(
"declare", OMPD_declare)
94 .Case(
"end", OMPD_end)
95 .Case(
"enter", OMPD_enter)
96 .Case(
"exit", OMPD_exit)
97 .Case(
"point", OMPD_point)
98 .Case(
"reduction", OMPD_reduction)
99 .Case(
"update", OMPD_update)
100 .Case(
"mapper", OMPD_mapper)
101 .Case(
"variant", OMPD_variant)
102 .Default(OMPD_unknown);
109 static const OpenMPDirectiveKindExWrapper F[][3] = {
110 {OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
111 {OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
112 {OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
113 {OMPD_declare, OMPD_simd, OMPD_declare_simd},
114 {OMPD_declare, OMPD_target, OMPD_declare_target},
115 {OMPD_declare, OMPD_variant, OMPD_declare_variant},
116 {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
117 {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
118 {OMPD_distribute_parallel_for, OMPD_simd,
119 OMPD_distribute_parallel_for_simd},
120 {OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
121 {OMPD_end, OMPD_declare, OMPD_end_declare},
122 {OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
123 {OMPD_target, OMPD_data, OMPD_target_data},
124 {OMPD_target, OMPD_enter, OMPD_target_enter},
125 {OMPD_target, OMPD_exit, OMPD_target_exit},
126 {OMPD_target, OMPD_update, OMPD_target_update},
127 {OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
128 {OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
129 {OMPD_for, OMPD_simd, OMPD_for_simd},
130 {OMPD_parallel, OMPD_for, OMPD_parallel_for},
131 {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
132 {OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
133 {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
134 {OMPD_target, OMPD_parallel, OMPD_target_parallel},
135 {OMPD_target, OMPD_simd, OMPD_target_simd},
136 {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
137 {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
138 {OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
139 {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
140 {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
141 {OMPD_teams_distribute_parallel, OMPD_for,
142 OMPD_teams_distribute_parallel_for},
143 {OMPD_teams_distribute_parallel_for, OMPD_simd,
144 OMPD_teams_distribute_parallel_for_simd},
145 {OMPD_target, OMPD_teams, OMPD_target_teams},
146 {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
147 {OMPD_target_teams_distribute, OMPD_parallel,
148 OMPD_target_teams_distribute_parallel},
149 {OMPD_target_teams_distribute, OMPD_simd,
150 OMPD_target_teams_distribute_simd},
151 {OMPD_target_teams_distribute_parallel, OMPD_for,
152 OMPD_target_teams_distribute_parallel_for},
153 {OMPD_target_teams_distribute_parallel_for, OMPD_simd,
154 OMPD_target_teams_distribute_parallel_for_simd},
155 {OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
156 {OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
157 {OMPD_parallel, OMPD_master, OMPD_parallel_master},
158 {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
159 {OMPD_parallel_master_taskloop, OMPD_simd,
160 OMPD_parallel_master_taskloop_simd}};
161 enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
163 OpenMPDirectiveKindExWrapper DKind =
165 ?
static_cast<unsigned>(OMPD_unknown)
167 if (DKind == OMPD_unknown)
170 for (
unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
171 if (DKind != F[I][0])
175 OpenMPDirectiveKindExWrapper SDKind =
177 ?
static_cast<unsigned>(OMPD_unknown)
179 if (SDKind == OMPD_unknown)
182 if (SDKind == F[I][1]) {
187 return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
196 bool WithOperator =
false;
197 if (Tok.
is(tok::kw_operator)) {
227 case tok::identifier:
232 P.
Diag(Tok.
getLocation(), diag::err_omp_expected_reduction_identifier);
233 P.
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
240 : DeclNames.getCXXOperatorName(OOK);
258 diag::err_expected_lparen_after,
259 getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
260 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
261 return DeclGroupPtrTy();
265 if (Name.
isEmpty() &&
Tok.
is(tok::annot_pragma_openmp_end))
266 return DeclGroupPtrTy();
269 bool IsCorrect = !ExpectAndConsume(tok::colon);
271 if (!IsCorrect &&
Tok.
is(tok::annot_pragma_openmp_end))
272 return DeclGroupPtrTy();
274 IsCorrect = IsCorrect && !Name.
isEmpty();
276 if (
Tok.
is(tok::colon) ||
Tok.
is(tok::annot_pragma_openmp_end)) {
277 Diag(
Tok.getLocation(), diag::err_expected_type);
281 if (!IsCorrect &&
Tok.
is(tok::annot_pragma_openmp_end))
282 return DeclGroupPtrTy();
293 Actions.ActOnOpenMPDeclareReductionType(Range.
getBegin(), TR);
294 if (!ReductionType.
isNull()) {
295 ReductionTypes.push_back(
296 std::make_pair(ReductionType, Range.
getBegin()));
299 SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
303 if (
Tok.
is(tok::colon) ||
Tok.
is(tok::annot_pragma_openmp_end))
307 if (ExpectAndConsume(tok::comma)) {
309 if (
Tok.
is(tok::annot_pragma_openmp_end)) {
310 Diag(
Tok.getLocation(), diag::err_expected_type);
311 return DeclGroupPtrTy();
314 }
while (
Tok.
isNot(tok::annot_pragma_openmp_end));
316 if (ReductionTypes.empty()) {
317 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
318 return DeclGroupPtrTy();
321 if (!IsCorrect &&
Tok.
is(tok::annot_pragma_openmp_end))
322 return DeclGroupPtrTy();
325 if (ExpectAndConsume(tok::colon))
328 if (
Tok.
is(tok::annot_pragma_openmp_end)) {
329 Diag(
Tok.getLocation(), diag::err_expected_expression);
330 return DeclGroupPtrTy();
333 DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
334 getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
338 unsigned I = 0, E = ReductionTypes.size();
339 for (
Decl *D : DRD.get()) {
340 TentativeParsingAction TPA(*
this);
345 Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
346 ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
347 ParseExpression().
get(), D->getLocation(),
false);
348 Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.
get());
351 Tok.
isNot(tok::annot_pragma_openmp_end)) {
358 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
360 if (
Tok.
is(tok::identifier) &&
361 Tok.getIdentifierInfo()->isStr(
"initializer")) {
364 Diag(
Tok.getLocation(), diag::err_expected) <<
"'initializer'";
371 tok::annot_pragma_openmp_end);
375 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
381 Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
384 if (
Tok.
is(tok::identifier) &&
385 Tok.getIdentifierInfo()->isStr(
"omp_priv")) {
387 ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
389 InitializerResult = Actions.ActOnFinishFullExpr(
390 ParseAssignmentExpression().
get(), D->getLocation(),
393 Actions.ActOnOpenMPDeclareReductionInitializerEnd(
394 D, InitializerResult.
get(), OmpPrivParm);
396 Tok.
isNot(tok::annot_pragma_openmp_end)) {
414 return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
418 void Parser::ParseOpenMPReductionInitializerForDecl(
VarDecl *OmpPrivParm) {
421 if (isTokenEqualOrEqualTypo()) {
424 if (
Tok.
is(tok::code_completion)) {
425 Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
426 Actions.FinalizeDeclaration(OmpPrivParm);
431 PreferredType.enterVariableInit(
Tok.getLocation(), OmpPrivParm);
435 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
436 Actions.ActOnInitializerError(OmpPrivParm);
438 Actions.AddInitializerToDecl(OmpPrivParm, Init.
get(),
441 }
else if (
Tok.
is(tok::l_paren)) {
447 CommaLocsTy CommaLocs;
450 auto RunSignatureHelp = [
this, OmpPrivParm, LParLoc, &Exprs]() {
451 QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
454 CalledSignatureHelp =
true;
455 return PreferredType;
457 if (ParseExpressionList(Exprs, CommaLocs, [&] {
458 PreferredType.enterFunctionArgument(
Tok.getLocation(),
461 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
463 Actions.ActOnInitializerError(OmpPrivParm);
464 SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
471 assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
472 "Unexpected number of commas!");
476 Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
479 }
else if (getLangOpts().CPlusPlus11 &&
Tok.
is(tok::l_brace)) {
481 Diag(
Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
486 Actions.ActOnInitializerError(OmpPrivParm);
488 Actions.AddInitializerToDecl(OmpPrivParm, Init.
get(),
492 Actions.ActOnUninitializedDecl(OmpPrivParm);
506 bool IsCorrect =
true;
510 getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
511 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
512 return DeclGroupPtrTy();
516 auto &DeclNames = Actions.getASTContext().DeclarationNames;
518 if (PP.LookAhead(0).is(tok::colon)) {
520 Diag(
Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
523 MapperId = DeclNames.getIdentifier(
Tok.getIdentifierInfo());
527 ExpectAndConsume(tok::colon);
531 DeclNames.getIdentifier(&Actions.getASTContext().Idents.get(
"default"));
534 if (!IsCorrect &&
Tok.
is(tok::annot_pragma_openmp_end))
535 return DeclGroupPtrTy();
549 return DeclGroupPtrTy();
556 return DeclGroupPtrTy();
561 getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
567 ParseScope OMPDirectiveScope(
this, ScopeFlags);
568 Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
571 Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
572 DMD, getCurScope(), MapperType, Range.
getBegin(), VName);
576 while (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
580 Actions.StartOpenMPClause(CKind);
582 ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0);
584 Clauses.push_back(Clause);
588 if (
Tok.
is(tok::comma))
590 Actions.EndOpenMPClause();
592 if (Clauses.empty()) {
593 Diag(
Tok, diag::err_omp_expected_clause)
594 << getOpenMPDirectiveName(OMPD_declare_mapper);
599 Actions.EndOpenMPDSABlock(
nullptr);
600 OMPDirectiveScope.Exit();
603 Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses);
605 return DeclGroupPtrTy();
613 Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
615 ParseSpecifierQualifierList(DS, AS, DSC);
620 ParseDeclarator(DeclaratorInfo);
623 Diag(
Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
626 Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
628 return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
637 class FNContextRAII final {
642 bool HasTemplateScope =
false;
643 bool HasFunScope =
false;
644 FNContextRAII() =
delete;
645 FNContextRAII(
const FNContextRAII &) =
delete;
646 FNContextRAII &operator=(
const FNContextRAII &) =
delete;
663 if (HasTemplateScope)
664 Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
672 Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
679 if (HasTemplateScope)
702 bool IsError =
false;
703 while (Tok.
isNot(tok::annot_pragma_openmp_end)) {
704 if (Tok.
isNot(tok::identifier))
706 OMPDeclareSimdDeclAttr::BranchStateTy Out;
708 StringRef ClauseName = II->
getName();
710 if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
711 if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
712 P.
Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
714 << OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
720 }
else if (ClauseName.equals(
"simdlen")) {
722 P.
Diag(Tok, diag::err_omp_more_one_clause)
723 << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
734 CKind == OMPC_linear) {
737 if (CKind == OMPC_aligned) {
739 }
else if (CKind == OMPC_linear) {
748 if (CKind == OMPC_aligned) {
749 Alignments.append(Aligneds.size() - Alignments.size(), Data.
TailExpr);
750 }
else if (CKind == OMPC_linear) {
753 "Unexpected linear modifier.");
758 LinModifiers.append(Linears.size() - LinModifiers.size(),
760 Steps.append(Linears.size() - Steps.size(), Data.
TailExpr);
767 if (Tok.
is(tok::comma))
777 PP.EnterToken(
Tok,
true);
778 PP.EnterTokenStream(Toks,
true,
781 ConsumeAnyToken(
true);
782 ConsumeAnyToken(
true);
784 FNContextRAII FnContext(*
this, Ptr);
785 OMPDeclareSimdDeclAttr::BranchStateTy BS =
786 OMPDeclareSimdDeclAttr::BS_Undefined;
796 Alignments, Linears, LinModifiers, Steps);
798 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
799 Diag(
Tok, diag::warn_omp_extra_tokens_at_eol)
800 << getOpenMPDirectiveName(OMPD_declare_simd);
801 while (
Tok.
isNot(tok::annot_pragma_openmp_end))
808 return Actions.ActOnOpenMPDeclareSimdDirective(
809 Ptr, BS, Simdlen.
get(), Uniforms, Aligneds, Alignments, Linears,
817 StringRef SelectorName =
819 if (!SelectorName.equals(
"score"))
829 <<
"context selector score clause";
838 llvm::StringMap<SourceLocation> &UsedCtx,
842 if (!Tok.
is(tok::identifier)) {
843 P.
Diag(Tok.
getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
846 while (!P.
SkipUntil(tok::r_brace, tok::r_paren,
853 auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.
getLocation());
857 P.
Diag(Tok.
getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use)
858 << CtxSelectorName <<
"implementation";
859 P.
Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
865 case OMP_CTX_vendor: {
869 CtxSelectorName.data());
871 llvm::UniqueVector<Sema::OMPCtxStringType> Vendors;
874 StringRef VendorName;
875 if (Tok.
is(tok::identifier)) {
879 if (!VendorName.empty())
880 Vendors.insert(VendorName);
883 <<
"vendor identifier" 888 P.
Diag(Tok, diag::err_expected_punc)
889 << (VendorName.empty() ?
"vendor name" : VendorName);
891 }
while (Tok.
is(tok::identifier));
894 if (!Vendors.empty())
895 Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors);
900 P.
Diag(Tok.
getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
903 while (!P.
SkipUntil(tok::r_brace, tok::r_paren,
914 llvm::StringMap<SourceLocation> &UsedCtx,
918 if (!Tok.
is(tok::identifier)) {
919 P.
Diag(Tok.
getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
922 while (!P.
SkipUntil(tok::r_brace, tok::r_paren,
929 auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.
getLocation());
933 P.
Diag(Tok.
getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use)
934 << CtxSelectorName <<
"device";
935 P.
Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
945 CtxSelectorName.data());
946 llvm::UniqueVector<Sema::OMPCtxStringType> Kinds;
950 if (Tok.
is(tok::identifier)) {
955 if (llvm::StringSwitch<bool>(KindName)
957 .Case(
"nohost",
false)
962 P.
Diag(SLoc, diag::err_omp_wrong_device_kind_trait) << KindName;
964 Kinds.insert(KindName);
968 <<
"'host', 'nohost', 'cpu', 'gpu', or 'fpga'" 973 P.
Diag(Tok, diag::err_expected_punc)
974 << (KindName.empty() ?
"kind of device" : KindName);
976 }
while (Tok.
is(tok::identifier));
980 Data.emplace_back(OMP_CTX_SET_device, CSKind,
ExprResult(), Kinds);
985 P.
Diag(Tok.
getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
988 while (!P.
SkipUntil(tok::r_brace, tok::r_paren,
999 bool Parser::parseOpenMPContextSelectors(
1001 llvm::StringMap<SourceLocation> UsedCtxSets;
1004 if (!
Tok.
is(tok::identifier)) {
1005 Diag(
Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector)
1010 StringRef CtxSelectorSetName = PP.getSpelling(
Tok, Buffer);
1011 auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName,
Tok.getLocation());
1015 Diag(
Tok.getLocation(), diag::err_omp_declare_variant_ctx_set_mutiple_use)
1016 << CtxSelectorSetName;
1017 Diag(Res.first->getValue(),
1018 diag::note_omp_declare_variant_ctx_set_used_here)
1019 << CtxSelectorSetName;
1022 (void)ConsumeToken();
1024 Diag(
Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
1025 << CtxSelectorSetName;
1028 (void)ConsumeToken();
1034 tok::annot_pragma_openmp_end);
1039 llvm::StringMap<SourceLocation> UsedCtx;
1042 case OMP_CTX_SET_implementation:
1045 case OMP_CTX_SET_device:
1050 while (!SkipUntil(tok::r_brace, tok::r_paren,
1051 tok::annot_pragma_openmp_end, StopBeforeMatch))
1056 if (!TryConsumeToken(tok::comma) &&
Tok.
isNot(tok::r_brace))
1057 Diag(
Tok, diag::err_omp_expected_comma_brace)
1059 : PP.getSpelling(PrevTok));
1060 }
while (
Tok.
is(tok::identifier));
1066 (
void)ExpectAndConsume(tok::comma);
1067 }
while (
Tok.isAnyIdentifier());
1075 PP.EnterToken(
Tok,
true);
1076 PP.EnterTokenStream(Toks,
true,
1079 ConsumeAnyToken(
true);
1080 ConsumeAnyToken(
true);
1082 FNContextRAII FnContext(*
this, Ptr);
1093 AssociatedFunction = ParseOpenMPParensExpr(
1094 getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
1097 if (!AssociatedFunction.
isUsable()) {
1098 if (!
Tok.
is(tok::annot_pragma_openmp_end))
1099 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1102 (void)ConsumeAnnotationToken();
1106 Actions.checkOpenMPDeclareVariantFunction(
1114 Diag(
Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
1119 (void)ConsumeAnnotationToken();
1122 (void)ConsumeToken();
1127 while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
1130 (void)ConsumeAnnotationToken();
1136 if (!parseOpenMPContextSelectors(Loc, Data)) {
1140 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1141 Diag(
Tok, diag::warn_omp_extra_tokens_at_eol)
1142 << getOpenMPDirectiveName(OMPD_declare_variant);
1147 while (
Tok.
isNot(tok::annot_pragma_openmp_end))
1149 if (DeclVarData.hasValue())
1150 Actions.ActOnOpenMPDeclareVariantDirective(
1151 DeclVarData.getValue().first, DeclVarData.getValue().second,
1154 (void)ConsumeAnnotationToken();
1168 struct SimpleClauseData {
1176 : Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
1194 if (Tok.
isNot(tok::r_paren) && Tok.
isNot(tok::comma) &&
1195 Tok.
isNot(tok::annot_pragma_openmp_end))
1203 return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
1213 OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
1214 SourceLocation DeviceTypeLoc;
1215 while (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1216 OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
1217 if (
Tok.
is(tok::identifier)) {
1219 StringRef ClauseName = II->
getName();
1220 bool IsDeviceTypeClause =
1221 getLangOpts().OpenMP >= 50 &&
1224 if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) &&
1225 !IsDeviceTypeClause) {
1226 Diag(
Tok, diag::err_omp_declare_target_unexpected_clause)
1227 << ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);
1231 if (IsDeviceTypeClause) {
1234 if (DevTypeData.hasValue()) {
1235 if (DeviceTypeLoc.
isValid()) {
1237 Diag(DevTypeData.getValue().Loc,
1238 diag::warn_omp_more_one_device_type_clause);
1240 switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
1241 case OMPC_DEVICE_TYPE_any:
1242 DT = OMPDeclareTargetDeclAttr::DT_Any;
1244 case OMPC_DEVICE_TYPE_host:
1245 DT = OMPDeclareTargetDeclAttr::DT_Host;
1247 case OMPC_DEVICE_TYPE_nohost:
1248 DT = OMPDeclareTargetDeclAttr::DT_NoHost;
1251 llvm_unreachable(
"Unexpected device_type");
1253 DeviceTypeLoc = DevTypeData.getValue().Loc;
1259 auto &&Callback = [
this, MT, &DeclareTargetDecls, &SameDirectiveDecls](
1261 NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName(
1262 getCurScope(), SS, NameInfo, SameDirectiveDecls);
1264 DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND);
1266 if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
1271 if (
Tok.
is(tok::comma))
1274 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1276 for (
auto &MTLocDecl : DeclareTargetDecls) {
1277 OMPDeclareTargetDeclAttr::MapTypeTy MT;
1280 std::tie(MT, Loc, ND) = MTLocDecl;
1282 Actions.ActOnOpenMPDeclareTargetName(
1283 ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT);
1286 SameDirectiveDecls.end());
1288 return DeclGroupPtrTy();
1289 return Actions.BuildDeclaratorGroup(Decls);
1294 if (DKind != OMPD_end_declare_target) {
1295 Diag(
Tok, diag::err_expected_end_declare_target);
1296 Diag(DTLoc, diag::note_matching) <<
"'#pragma omp declare target'";
1300 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1301 Diag(
Tok, diag::warn_omp_extra_tokens_at_eol)
1302 << getOpenMPDirectiveName(OMPD_end_declare_target);
1303 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1340 assert(
Tok.
is(tok::annot_pragma_openmp) &&
"Not an OpenMP directive!");
1347 TentativeParsingAction TPA(*
this);
1348 Loc = ConsumeAnnotationToken();
1350 if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
1355 Toks.push_back(
Tok);
1357 (void)ConsumeAnyToken();
1358 if (
Tok.
is(tok::annot_pragma_openmp))
1360 else if (
Tok.
is(tok::annot_pragma_openmp_end))
1362 Toks.push_back(
Tok);
1366 (void)ConsumeAnyToken();
1367 auto *LP =
new LateParsedPragma(
this, AS);
1369 getCurrentClass().LateParsedDeclarations.push_back(LP);
1374 Loc = ConsumeAnnotationToken();
1379 case OMPD_threadprivate: {
1381 DeclDirectiveListParserHelper Helper(
this, DKind);
1382 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1386 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1387 Diag(
Tok, diag::warn_omp_extra_tokens_at_eol)
1388 << getOpenMPDirectiveName(DKind);
1389 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1392 ConsumeAnnotationToken();
1393 return Actions.ActOnOpenMPThreadprivateDirective(Loc,
1394 Helper.getIdentifiers());
1398 case OMPD_allocate: {
1400 DeclDirectiveListParserHelper Helper(
this, DKind);
1401 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1404 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1408 while (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1412 Actions.StartOpenMPClause(CKind);
1413 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
1414 !FirstClauses[CKind].getInt());
1415 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1417 FirstClauses[CKind].setInt(
true);
1418 if (Clause !=
nullptr)
1419 Clauses.push_back(Clause);
1420 if (
Tok.
is(tok::annot_pragma_openmp_end)) {
1421 Actions.EndOpenMPClause();
1425 if (
Tok.
is(tok::comma))
1427 Actions.EndOpenMPClause();
1431 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1432 Diag(
Tok, diag::warn_omp_extra_tokens_at_eol)
1433 << getOpenMPDirectiveName(DKind);
1434 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1438 ConsumeAnnotationToken();
1439 return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
1444 case OMPD_requires: {
1449 if (
Tok.
is(tok::annot_pragma_openmp_end)) {
1450 Diag(
Tok, diag::err_omp_expected_clause)
1451 << getOpenMPDirectiveName(OMPD_requires);
1454 while (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1458 Actions.StartOpenMPClause(CKind);
1459 OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
1460 !FirstClauses[CKind].getInt());
1461 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1463 FirstClauses[CKind].setInt(
true);
1464 if (Clause !=
nullptr)
1465 Clauses.push_back(Clause);
1466 if (
Tok.
is(tok::annot_pragma_openmp_end)) {
1467 Actions.EndOpenMPClause();
1471 if (
Tok.
is(tok::comma))
1473 Actions.EndOpenMPClause();
1476 if (Clauses.size() == 0) {
1477 Diag(
Tok, diag::err_omp_expected_clause)
1478 << getOpenMPDirectiveName(OMPD_requires);
1479 ConsumeAnnotationToken();
1482 ConsumeAnnotationToken();
1483 return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
1485 case OMPD_declare_reduction:
1487 if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
1490 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1491 Diag(
Tok, diag::warn_omp_extra_tokens_at_eol)
1492 << getOpenMPDirectiveName(OMPD_declare_reduction);
1493 while (
Tok.
isNot(tok::annot_pragma_openmp_end))
1497 ConsumeAnnotationToken();
1501 case OMPD_declare_mapper: {
1503 if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
1505 ConsumeAnnotationToken();
1510 case OMPD_declare_variant:
1511 case OMPD_declare_simd: {
1517 Toks.push_back(
Tok);
1519 while(
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1520 Toks.push_back(
Tok);
1523 Toks.push_back(
Tok);
1527 if (
Tok.
is(tok::annot_pragma_openmp)) {
1528 Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
1530 }
else if (
Tok.
isNot(tok::r_brace) && !isEofOrEom()) {
1534 MaybeParseCXX11Attributes(Attrs);
1536 Ptr = ParseExternalDeclaration(Attrs, &PDS);
1539 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs,
TagType, Tag);
1543 Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
1544 << (DKind == OMPD_declare_simd ? 0 : 1);
1545 return DeclGroupPtrTy();
1547 if (DKind == OMPD_declare_simd)
1548 return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
1549 assert(DKind == OMPD_declare_variant &&
1550 "Expected declare variant directive only");
1551 ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
1554 case OMPD_declare_target: {
1556 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1557 return ParseOMPDeclareTargetClauses();
1563 if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
1564 return DeclGroupPtrTy();
1574 MaybeParseCXX11Attributes(Attrs);
1576 Ptr = ParseExternalDeclaration(Attrs, &PDS);
1579 ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs,
TagType, Tag);
1583 Decls.append(Ref.
begin(), Ref.
end());
1585 if (
Tok.isAnnotation() &&
Tok.
is(tok::annot_pragma_openmp)) {
1586 TentativeParsingAction TPA(*
this);
1587 ConsumeAnnotationToken();
1589 if (DKind != OMPD_end_declare_target)
1596 ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
1597 Actions.ActOnFinishOpenMPDeclareTargetDirective();
1598 return Actions.BuildDeclaratorGroup(Decls);
1601 Diag(
Tok, diag::err_omp_unknown_directive);
1606 case OMPD_taskyield:
1609 case OMPD_taskgroup:
1619 case OMPD_parallel_for:
1620 case OMPD_parallel_for_simd:
1621 case OMPD_parallel_sections:
1622 case OMPD_parallel_master:
1626 case OMPD_cancellation_point:
1628 case OMPD_target_data:
1629 case OMPD_target_enter_data:
1630 case OMPD_target_exit_data:
1631 case OMPD_target_parallel:
1632 case OMPD_target_parallel_for:
1634 case OMPD_taskloop_simd:
1635 case OMPD_master_taskloop:
1636 case OMPD_master_taskloop_simd:
1637 case OMPD_parallel_master_taskloop:
1638 case OMPD_parallel_master_taskloop_simd:
1639 case OMPD_distribute:
1640 case OMPD_end_declare_target:
1641 case OMPD_target_update:
1642 case OMPD_distribute_parallel_for:
1643 case OMPD_distribute_parallel_for_simd:
1644 case OMPD_distribute_simd:
1645 case OMPD_target_parallel_for_simd:
1646 case OMPD_target_simd:
1647 case OMPD_teams_distribute:
1648 case OMPD_teams_distribute_simd:
1649 case OMPD_teams_distribute_parallel_for_simd:
1650 case OMPD_teams_distribute_parallel_for:
1651 case OMPD_target_teams:
1652 case OMPD_target_teams_distribute:
1653 case OMPD_target_teams_distribute_parallel_for:
1654 case OMPD_target_teams_distribute_parallel_for_simd:
1655 case OMPD_target_teams_distribute_simd:
1656 Diag(
Tok, diag::err_omp_unexpected_directive)
1657 << 1 << getOpenMPDirectiveName(DKind);
1660 while (
Tok.
isNot(tok::annot_pragma_openmp_end))
1707 Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
1708 assert(
Tok.
is(tok::annot_pragma_openmp) &&
"Not an OpenMP directive!");
1722 bool HasAssociatedStatement =
true;
1723 bool FlushHasClause =
false;
1726 case OMPD_threadprivate: {
1728 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1729 ParsedStmtContext()) {
1730 Diag(
Tok, diag::err_omp_immediate_directive)
1731 << getOpenMPDirectiveName(DKind) << 0;
1734 DeclDirectiveListParserHelper Helper(
this, DKind);
1735 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1739 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1740 Diag(
Tok, diag::warn_omp_extra_tokens_at_eol)
1741 << getOpenMPDirectiveName(DKind);
1742 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1744 DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
1745 Loc, Helper.getIdentifiers());
1746 Directive = Actions.ActOnDeclStmt(Res, Loc,
Tok.getLocation());
1748 SkipUntil(tok::annot_pragma_openmp_end);
1751 case OMPD_allocate: {
1753 if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
1754 ParsedStmtContext()) {
1755 Diag(
Tok, diag::err_omp_immediate_directive)
1756 << getOpenMPDirectiveName(DKind) << 0;
1759 DeclDirectiveListParserHelper Helper(
this, DKind);
1760 if (!ParseOpenMPSimpleVarList(DKind, Helper,
1763 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1767 while (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1771 Actions.StartOpenMPClause(CKind);
1772 OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
1773 !FirstClauses[CKind].getInt());
1774 SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
1776 FirstClauses[CKind].setInt(
true);
1777 if (Clause !=
nullptr)
1778 Clauses.push_back(Clause);
1779 if (
Tok.
is(tok::annot_pragma_openmp_end)) {
1780 Actions.EndOpenMPClause();
1784 if (
Tok.
is(tok::comma))
1786 Actions.EndOpenMPClause();
1790 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1791 Diag(
Tok, diag::warn_omp_extra_tokens_at_eol)
1792 << getOpenMPDirectiveName(DKind);
1793 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
1796 DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
1797 Loc, Helper.getIdentifiers(), Clauses);
1798 Directive = Actions.ActOnDeclStmt(Res, Loc,
Tok.getLocation());
1800 SkipUntil(tok::annot_pragma_openmp_end);
1803 case OMPD_declare_reduction:
1805 if (DeclGroupPtrTy Res =
1806 ParseOpenMPDeclareReductionDirective(
AS_none)) {
1809 if (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1810 Diag(
Tok, diag::warn_omp_extra_tokens_at_eol)
1811 << getOpenMPDirectiveName(OMPD_declare_reduction);
1812 while (
Tok.
isNot(tok::annot_pragma_openmp_end))
1816 Directive = Actions.ActOnDeclStmt(Res, Loc,
Tok.getLocation());
1818 SkipUntil(tok::annot_pragma_openmp_end);
1821 case OMPD_declare_mapper: {
1823 if (DeclGroupPtrTy Res =
1824 ParseOpenMPDeclareMapperDirective(
AS_none)) {
1826 ConsumeAnnotationToken();
1827 Directive = Actions.ActOnDeclStmt(Res, Loc,
Tok.getLocation());
1829 SkipUntil(tok::annot_pragma_openmp_end);
1834 if (PP.LookAhead(0).is(tok::l_paren)) {
1835 FlushHasClause =
true;
1838 PP.EnterToken(
Tok,
true);
1841 case OMPD_taskyield:
1844 case OMPD_cancellation_point:
1846 case OMPD_target_enter_data:
1847 case OMPD_target_exit_data:
1848 case OMPD_target_update:
1849 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1850 ParsedStmtContext()) {
1851 Diag(
Tok, diag::err_omp_immediate_directive)
1852 << getOpenMPDirectiveName(DKind) << 0;
1854 HasAssociatedStatement =
false;
1866 case OMPD_parallel_for:
1867 case OMPD_parallel_for_simd:
1868 case OMPD_parallel_sections:
1869 case OMPD_parallel_master:
1875 case OMPD_taskgroup:
1876 case OMPD_target_data:
1877 case OMPD_target_parallel:
1878 case OMPD_target_parallel_for:
1880 case OMPD_taskloop_simd:
1881 case OMPD_master_taskloop:
1882 case OMPD_master_taskloop_simd:
1883 case OMPD_parallel_master_taskloop:
1884 case OMPD_parallel_master_taskloop_simd:
1885 case OMPD_distribute:
1886 case OMPD_distribute_parallel_for:
1887 case OMPD_distribute_parallel_for_simd:
1888 case OMPD_distribute_simd:
1889 case OMPD_target_parallel_for_simd:
1890 case OMPD_target_simd:
1891 case OMPD_teams_distribute:
1892 case OMPD_teams_distribute_simd:
1893 case OMPD_teams_distribute_parallel_for_simd:
1894 case OMPD_teams_distribute_parallel_for:
1895 case OMPD_target_teams:
1896 case OMPD_target_teams_distribute:
1897 case OMPD_target_teams_distribute_parallel_for:
1898 case OMPD_target_teams_distribute_parallel_for_simd:
1899 case OMPD_target_teams_distribute_simd: {
1902 if (DKind == OMPD_critical) {
1904 tok::annot_pragma_openmp_end);
1906 if (
Tok.isAnyIdentifier()) {
1911 Diag(
Tok, diag::err_omp_expected_identifier_for_critical);
1915 }
else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
1917 if (
Tok.
isNot(tok::annot_pragma_openmp_end))
1925 ParseScope OMPDirectiveScope(
this, ScopeFlags);
1926 Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
1928 while (
Tok.
isNot(tok::annot_pragma_openmp_end)) {
1932 : FlushHasClause ? OMPC_flush
1934 Actions.StartOpenMPClause(CKind);
1935 FlushHasClause =
false;
1937 ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
1938 FirstClauses[CKind].setInt(
true);
1940 FirstClauses[CKind].setPointer(Clause);
1941 Clauses.push_back(Clause);
1945 if (
Tok.
is(tok::comma))
1947 Actions.EndOpenMPClause();
1950 EndLoc =
Tok.getLocation();
1952 ConsumeAnnotationToken();
1957 if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
1958 if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
1959 ParsedStmtContext()) {
1960 Diag(Loc, diag::err_omp_immediate_directive)
1961 << getOpenMPDirectiveName(DKind) << 1
1964 HasAssociatedStatement =
false;
1968 if (HasAssociatedStatement) {
1970 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1975 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1976 }
else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
1977 DKind == OMPD_target_exit_data) {
1978 Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
1980 Actions.ActOnCompoundStmt(Loc, Loc,
llvm::None,
1982 AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
1984 Directive = Actions.ActOnOpenMPExecutableDirective(
1985 DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
1989 Actions.EndOpenMPDSABlock(Directive.get());
1990 OMPDirectiveScope.Exit();
1993 case OMPD_declare_simd:
1994 case OMPD_declare_target:
1995 case OMPD_end_declare_target:
1997 case OMPD_declare_variant:
1998 Diag(
Tok, diag::err_omp_unexpected_directive)
1999 << 1 << getOpenMPDirectiveName(DKind);
2000 SkipUntil(tok::annot_pragma_openmp_end);
2003 Diag(
Tok, diag::err_omp_unknown_directive);
2004 SkipUntil(tok::annot_pragma_openmp_end);
2014 bool Parser::ParseOpenMPSimpleVarList(
2018 bool AllowScopeSpecifier) {
2022 getOpenMPDirectiveName(
Kind).data()))
2024 bool IsCorrect =
true;
2025 bool NoIdentIsFound =
true;
2028 while (
Tok.
isNot(tok::r_paren) &&
Tok.
isNot(tok::annot_pragma_openmp_end)) {
2033 NoIdentIsFound =
false;
2035 if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
2036 ParseOptionalCXXScopeSpecifier(SS,
nullptr,
false)) {
2038 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2040 }
else if (ParseUnqualifiedId(SS,
false,
false,
false,
false,
nullptr,
2043 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2046 Tok.
isNot(tok::annot_pragma_openmp_end)) {
2048 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2054 Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
2057 if (
Tok.
is(tok::comma)) {
2062 if (NoIdentIsFound) {
2063 Diag(
Tok, diag::err_expected) << tok::identifier;
2092 bool ErrorFound =
false;
2093 bool WrongDirective =
false;
2098 << getOpenMPDirectiveName(DKind);
2100 WrongDirective =
true;
2105 case OMPC_num_threads:
2111 case OMPC_num_teams:
2112 case OMPC_thread_limit:
2114 case OMPC_grainsize:
2115 case OMPC_num_tasks:
2117 case OMPC_allocator:
2141 Diag(
Tok, diag::err_omp_more_one_clause)
2146 if (CKind == OMPC_ordered && PP.LookAhead(0).isNot(tok::l_paren))
2147 Clause = ParseOpenMPClause(CKind, WrongDirective);
2149 Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
2152 case OMPC_proc_bind:
2153 case OMPC_atomic_default_mem_order:
2163 Diag(
Tok, diag::err_omp_more_one_clause)
2168 Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
2171 case OMPC_dist_schedule:
2172 case OMPC_defaultmap:
2177 if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
2179 Diag(
Tok, diag::err_omp_more_one_clause)
2185 Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
2189 case OMPC_mergeable:
2198 case OMPC_unified_address:
2199 case OMPC_unified_shared_memory:
2200 case OMPC_reverse_offload:
2201 case OMPC_dynamic_allocators:
2209 Diag(
Tok, diag::err_omp_more_one_clause)
2214 Clause = ParseOpenMPClause(CKind, WrongDirective);
2217 case OMPC_firstprivate:
2218 case OMPC_lastprivate:
2220 case OMPC_reduction:
2221 case OMPC_task_reduction:
2222 case OMPC_in_reduction:
2226 case OMPC_copyprivate:
2232 case OMPC_use_device_ptr:
2233 case OMPC_is_device_ptr:
2235 case OMPC_nontemporal:
2236 Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
2240 Diag(
Tok, diag::warn_omp_extra_tokens_at_eol)
2241 << getOpenMPDirectiveName(DKind);
2242 SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
2247 if (!WrongDirective)
2248 Diag(
Tok, diag::err_omp_unexpected_clause)
2250 SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
2253 return ErrorFound ? nullptr : Clause;
2261 bool IsAddressOfOperand) {
2263 if (T.
expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
2267 ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand,
2270 Val = Actions.ActOnFinishFullExpr(Val.
get(), ELoc,
false);
2273 RLoc =
Tok.getLocation();
2327 return Actions.ActOnOpenMPSingleExprClause(
Kind, Val.
get(), Loc, LLoc, RLoc);
2341 if (!Val || ParseOnly)
2343 return Actions.ActOnOpenMPSimpleClause(
2344 Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
2345 Val.getValue().Loc, Val.getValue().RLoc);
2380 return Actions.ActOnOpenMPClause(
Kind, Loc,
Tok.getLocation());
2410 if (
Kind == OMPC_schedule) {
2411 enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
2412 Arg.resize(NumberOfElements);
2413 KLoc.resize(NumberOfElements);
2418 Kind,
Tok.isAnnotation() ?
"" : PP.getSpelling(
Tok));
2421 Arg[Modifier1] = KindModifier;
2422 KLoc[Modifier1] =
Tok.getLocation();
2424 Tok.
isNot(tok::annot_pragma_openmp_end))
2426 if (
Tok.
is(tok::comma)) {
2430 Kind,
Tok.isAnnotation() ?
"" : PP.getSpelling(
Tok));
2434 KLoc[Modifier2] =
Tok.getLocation();
2436 Tok.
isNot(tok::annot_pragma_openmp_end))
2440 if (
Tok.
is(tok::colon))
2443 Diag(
Tok, diag::warn_pragma_expected_colon) <<
"schedule modifier";
2445 Kind,
Tok.isAnnotation() ?
"" : PP.getSpelling(
Tok));
2447 Arg[ScheduleKind] = KindModifier;
2448 KLoc[ScheduleKind] =
Tok.getLocation();
2450 Tok.
isNot(tok::annot_pragma_openmp_end))
2452 if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
2453 Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
2454 Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
2456 DelimLoc = ConsumeAnyToken();
2457 }
else if (
Kind == OMPC_dist_schedule) {
2459 Kind,
Tok.isAnnotation() ?
"" : PP.getSpelling(
Tok)));
2460 KLoc.push_back(
Tok.getLocation());
2462 Tok.
isNot(tok::annot_pragma_openmp_end))
2464 if (Arg.back() == OMPC_DIST_SCHEDULE_static &&
Tok.
is(tok::comma))
2465 DelimLoc = ConsumeAnyToken();
2466 }
else if (
Kind == OMPC_defaultmap) {
2469 Kind,
Tok.isAnnotation() ?
"" : PP.getSpelling(
Tok));
2474 Arg.push_back(Modifier);
2475 KLoc.push_back(
Tok.getLocation());
2477 Tok.
isNot(tok::annot_pragma_openmp_end))
2480 if (
Tok.
is(tok::colon))
2483 Diag(
Tok, diag::warn_pragma_expected_colon) <<
"defaultmap modifier";
2486 Kind,
Tok.isAnnotation() ?
"" : PP.getSpelling(
Tok)));
2487 KLoc.push_back(
Tok.getLocation());
2489 Tok.
isNot(tok::annot_pragma_openmp_end))
2492 assert(
Kind == OMPC_if);
2493 KLoc.push_back(
Tok.getLocation());
2494 TentativeParsingAction TPA(*
this);
2497 if (DK != OMPD_unknown) {
2499 if (
Tok.
is(tok::colon) && getLangOpts().OpenMP > 40) {
2501 DelimLoc = ConsumeToken();
2504 Arg.back() = unsigned(OMPD_unknown);
2511 bool NeedAnExpression = (
Kind == OMPC_schedule && DelimLoc.
isValid()) ||
2512 (
Kind == OMPC_dist_schedule && DelimLoc.
isValid()) ||
2514 if (NeedAnExpression) {
2516 ExprResult LHS(ParseCastExpression(AnyCastExpr,
false, NotTypeCast));
2519 Actions.ActOnFinishFullExpr(Val.
get(), ELoc,
false);
2527 if (NeedAnExpression && Val.
isInvalid())
2532 return Actions.ActOnOpenMPSingleExprWithArgClause(
2538 if (ReductionIdScopeSpec.
isEmpty()) {
2579 nullptr,
nullptr, ReductionId);
2585 if (!Tok.
is(tok::identifier))
2591 return TypeModifier;
2599 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2609 Diag(
Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
2610 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2614 auto &DeclNames = Actions.getASTContext().DeclarationNames;
2616 DeclNames.getIdentifier(
Tok.getIdentifierInfo()),
Tok.getLocation());
2626 while (getCurToken().isNot(tok::colon)) {
2628 if (TypeModifier == OMPC_MAP_MODIFIER_always ||
2629 TypeModifier == OMPC_MAP_MODIFIER_close) {
2633 }
else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
2637 if (parseMapperModifier(Data))
2643 if (
Tok.
is(tok::comma)) {
2644 Diag(
Tok, diag::err_omp_map_type_modifier_missing);
2649 if (PP.LookAhead(0).is(tok::colon))
2651 Diag(
Tok, diag::err_omp_unknown_map_type_modifier);
2654 if (getCurToken().is(tok::comma))
2664 if (!Tok.
isOneOf(tok::identifier, tok::kw_delete))
2677 if (Tok.
is(tok::colon)) {
2678 P.
Diag(Tok, diag::err_omp_map_type_missing);
2683 P.
Diag(Tok, diag::err_omp_unknown_map_type);
2693 bool InvalidReductionId =
false;
2694 bool IsInvalidMapperModifier =
false;
2702 bool NeedRParenForLinear =
false;
2704 tok::annot_pragma_openmp_end);
2706 if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
2707 Kind == OMPC_in_reduction) {
2715 if (InvalidReductionId) {
2716 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2719 if (
Tok.
is(tok::colon))
2722 Diag(
Tok, diag::warn_pragma_expected_colon) <<
"reduction identifier";
2723 if (!InvalidReductionId)
2725 Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
2726 }
else if (Kind == OMPC_depend) {
2730 Kind,
Tok.
is(tok::identifier) ? PP.getSpelling(
Tok) :
"");
2733 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2738 if (DKind == OMPD_ordered && Data.
ExtraModifier == OMPC_DEPEND_source) {
2744 if (
Tok.
is(tok::colon)) {
2747 Diag(
Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
2748 : diag::warn_pragma_expected_colon)
2749 <<
"dependency type";
2751 }
else if (Kind == OMPC_linear) {
2754 if (
Tok.
is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
2758 NeedRParenForLinear =
true;
2760 }
else if (Kind == OMPC_lastprivate) {
2767 Tok.
is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
2771 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2776 assert(
Tok.
is(tok::colon) &&
"Expected colon.");
2779 }
else if (Kind == OMPC_map) {
2790 TentativeParsingAction TPA(*
this);
2791 bool ColonPresent =
false;
2792 if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2794 if (
Tok.
is(tok::colon))
2795 ColonPresent =
true;
2801 IsInvalidMapperModifier = parseMapTypeModifiers(Data);
2802 if (!IsInvalidMapperModifier)
2805 SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
2812 if (
Tok.
is(tok::colon))
2814 }
else if (Kind == OMPC_to || Kind == OMPC_from) {
2815 if (
Tok.
is(tok::identifier)) {
2816 bool IsMapperModifier =
false;
2817 if (Kind == OMPC_to) {
2820 if (
Modifier == OMPC_TO_MODIFIER_mapper)
2821 IsMapperModifier =
true;
2825 if (
Modifier == OMPC_FROM_MODIFIER_mapper)
2826 IsMapperModifier =
true;
2828 if (IsMapperModifier) {
2831 IsInvalidMapperModifier = parseMapperModifier(Data);
2833 if (!IsInvalidMapperModifier)
2834 Diag(
Tok, diag::warn_pragma_expected_colon) <<
")";
2835 SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
2839 if (
Tok.
is(tok::colon))
2843 }
else if (Kind == OMPC_allocate) {
2846 TentativeParsingAction TPA(*
this);
2848 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2852 if (
Tok.
is(tok::colon)) {
2865 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2871 (Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
2872 Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
2873 (Kind == OMPC_reduction && !InvalidReductionId) ||
2876 const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
2878 Tok.
isNot(tok::annot_pragma_openmp_end))) {
2882 Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
2884 Vars.push_back(VarExpr.
get());
2886 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2890 IsComma =
Tok.
is(tok::comma);
2893 else if (
Tok.
isNot(tok::r_paren) &&
2894 Tok.
isNot(tok::annot_pragma_openmp_end) &&
2895 (!MayHaveTail ||
Tok.
isNot(tok::colon)))
2896 Diag(
Tok, diag::err_omp_expected_punc)
2897 << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
2899 << (Kind == OMPC_flush);
2903 if (NeedRParenForLinear)
2907 const bool MustHaveTail = MayHaveTail &&
Tok.
is(tok::colon);
2911 ExprResult Tail = ParseAssignmentExpression();
2913 Actions.ActOnFinishFullExpr(Tail.
get(), ELoc,
false);
2917 SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
2922 Data.
RLoc =
Tok.getLocation();
2927 (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
2928 (MustHaveTail && !Data.
TailExpr) || InvalidReductionId ||
2929 IsInvalidMapperModifier;
2987 if (ParseOpenMPVarList(DKind,
Kind, Vars, Data))
2993 return Actions.ActOnOpenMPVarListClause(
OpenMPFromModifierKind
OpenMP modifier kind for 'from' clause.
Defines the clang::ASTContext interface.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
ParseScope - Introduces a new scope for parsing.
A (possibly-)qualified type.
bool operator==(CanQual< T > x, CanQual< U > y)
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
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)) {...
DeclarationNameInfo ReductionOrMapperId
bool isEmpty() const
No scope specifier.
Decl - This represents one declaration (or definition), e.g.
SmallVector< OpenMPMapModifierKind, OMPMapClause::NumberOfModifiers > MapTypeModifiers
The base class of the type hierarchy.
SourceLocation getCloseLocation() const
This indicates that the scope corresponds to a function, which means that labels are set here...
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId)
AccessSpecifier
A C++ access specifier (public, private, protected), plus the special value "none" which means differ...
void ActOnExitFunctionContext()
Wrapper for void* pointer.
Parser - This implements a parser for the C family of languages.
bool isEmpty() const
Evaluates true when this declaration name is empty.
bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc)
Checks correctness of linear modifiers.
ExprResult ParseOpenMPParensExpr(StringRef ClauseName, SourceLocation &RLoc, bool IsAddressOfOperand=false)
Parses simple expression in parens for single-expression clauses of OpenMP constructs.
RAII object that enters a new expression evaluation context.
Represents a variable declaration or definition.
ActionResult< Stmt * > StmtResult
Information about one declarator, including the parsed type information and the identifier.
TypeSpecifierType
Specifies the kind of type.
RAII object used to temporarily allow the C++ 'this' expression to be used, with the given qualifiers...
RAII object that makes sure paren/bracket/brace count is correct after declaration/statement parsing...
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
static Optional< SimpleClauseData > parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind)
ColonProtectionRAIIObject - This sets the Parser::ColonIsSacred bool and restores it when destroyed...
tok::TokenKind getKind() 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 ...
The collection of all-type qualifiers we support.
OpenMPMapModifierKind
OpenMP modifier kind for 'map' clause.
Base wrapper for a particular "section" of type source info.
Represents a struct/union/class.
bool TryConsumeToken(tok::TokenKind Expected)
const char * getOpenMPClauseName(OpenMPClauseKind Kind)
One of these records is kept for each identifier that is lexed.
OpenMPContextSelectorKind
OpenMP context selectors.
static void parseDeviceSelector(Parser &P, SourceLocation Loc, llvm::StringMap< SourceLocation > &UsedCtx, SmallVectorImpl< Sema::OMPCtxSelectorData > &Data)
Parse context selector for 'device' selector set: 'kind' '(' <kind> { ',' <kind> } ')'...
Token - This structure provides full information about a lexed token.
RAII class that helps handle the parsing of an open/close delimiter pair, such as braces { ...
Defines some OpenMP-specific enums and functions.
OpaquePtr< QualType > ParsedType
An opaque type for threading parsed type information through the parser.
Represents a C++ unqualified-id that has been parsed.
OpenMPContextSelectorSetKind
OpenMP context selector sets.
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 isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, unsigned OpenMPVersion)
OpenMPClauseKind getOpenMPClauseKind(llvm::StringRef Str)
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.
OpenMPContextSelectorSetKind getOpenMPContextSelectorSet(llvm::StringRef Str)
ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id, OpenMPDirectiveKind Kind)
Called on correct id-expression from the '#pragma omp threadprivate'.
Represents a C++ nested-name-specifier or a global scope specifier.
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type...
llvm::omp::Directive OpenMPDirectiveKind
OpenMP directives.
SourceLocation DepLinMapLastLoc
IdentifierInfo * getIdentifier() const
static void parseImplementationSelector(Parser &P, SourceLocation Loc, llvm::StringMap< SourceLocation > &UsedCtx, SmallVectorImpl< Sema::OMPCtxSelectorData > &Data)
Parse context selector for 'implementation' selector set: 'vendor' '(' [ 'score' '(' <score _expr>=""...
Sema - This implements semantic analysis and AST building for C.
A RAII object to enter scope of a compound statement.
DeclarationNameTable DeclarationNames
This is the scope of OpenMP executable directive.
Sema & getActions() const
bool ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, bool AllowDeductionGuide, ParsedType ObjectType, SourceLocation *TemplateKWLoc, UnqualifiedId &Result)
Parse a C++ unqualified-id (or a C identifier), which describes the name of an entity.
const Token & getCurToken() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
OpenMPClauseKind
OpenMP clauses.
DeclContext * getDeclContext()
This is a compound statement scope.
static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data)
Parse map-type in map clause.
The current expression and its subexpressions occur within an unevaluated operand (C++11 [expr]p7)...
Preprocessor & getPreprocessor() const
SmallVector< SourceLocation, OMPMapClause::NumberOfModifiers > MapTypeModifiersLoc
bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a taskloop directive.
SourceLocation getOpenLocation() const
bool isNull() const
Return true if this QualType doesn't point to a type yet.
static OpenMPMapModifierKind isMapModifier(Parser &P)
Checks if the token is a valid map-type-modifier.
A class for parsing a DeclSpec.
bool isTemplateDecl() const
returns true if this declaration is a template
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
ASTContext & getASTContext() const
Encodes a location in the source.
bool ParseOpenMPVarList(OpenMPDirectiveKind DKind, OpenMPClauseKind Kind, SmallVectorImpl< Expr *> &Vars, OpenMPVarListDataTy &Data)
Parses clauses with list.
static unsigned getOpenMPDirectiveKindEx(StringRef S)
IdentifierInfo * getIdentifierInfo() const
OpenMPLinearClauseKind Modifier
Modifier of 'linear' clause.
This is a basic class for representing single OpenMP clause.
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
Scope * getCurScope() const
StringRef getName() const
Return the actual identifier string.
SourceRange getSourceRange() const LLVM_READONLY
Get the source range that spans this declarator.
bool isNot(tok::TokenKind K) const
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
bool expectAndConsume(unsigned DiagID=diag::err_expected, const char *Msg="", tok::TokenKind SkipToTok=tok::unknown)
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
This is the scope of some OpenMP simd directive.
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
static OpenMPMapClauseKind isMapType(Parser &P)
Checks if the token is a valid map-type.
This is a scope that corresponds to the template parameters of a C++ template.
The name of a declaration.
bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a simd directive.
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const
Data used for parsing list of variables in OpenMP clauses.
static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P)
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
static const TST TST_unspecified
OpenMPToModifierKind
OpenMP modifier kind for 'to' clause.
CXXScopeSpec ReductionOrMapperIdScopeSpec
Not an overloaded operator.
unsigned getOpenMPSimpleClauseType(OpenMPClauseKind Kind, llvm::StringRef Str)
bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a distribute directive.
QualType getCanonicalTypeInternal() const
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
This file defines OpenMP AST classes for executable directives and clauses.
void setOperatorFunctionId(SourceLocation OperatorLoc, OverloadedOperatorKind Op, SourceLocation SymbolLocations[3])
Specify that this unqualified-id was parsed as an operator-function-id.
int ExtraModifier
Additional modifier for linear, map, depend or lastprivate clause.
This is a scope that can contain a declaration.
Captures information about "declaration specifiers".
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
OpenMPMapClauseKind
OpenMP mapping kind for 'map' clause.
bool operator!=(CanQual< T > x, CanQual< U > y)
static DeclarationName parseOpenMPReductionId(Parser &P)
This represents '#pragma omp declare mapper ...' directive.
Activates OpenMP parsing mode to preseve OpenMP specific annotation tokens.
This is the scope of some OpenMP loop directive.
bool parseMapTypeModifiers(OpenMPVarListDataTy &Data)
Parses map-type-modifiers in map clause.
OpenMPContextSelectorKind getOpenMPContextSelector(llvm::StringRef Str)
bool parseMapperModifier(OpenMPVarListDataTy &Data)
Parses the mapper modifier in map, to, and from clauses.
This structure contains most locations needed for by an OMPVarListClause.
static ExprResult parseContextScore(Parser &P)
Parse optional 'score' '(' <expr> ')' ':'.
bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind)
Checks if the specified directive is a directive with an associated loop construct.
A trivial tuple used to represent a source range.
This represents a decl that may have a name.
Directive - Abstract class representing a parsed verify directive.
SourceLocation getBegin() const
VerifyDiagnosticConsumer::Directive Directive
SourceLocation getLocation() const
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
bool isCXXInstanceMember() const
Determine whether the given declaration is an instance member of a C++ class.
Stop skipping at specified token, but don't skip the token itself.
SourceLocation getEndLoc() const