30#include "llvm/ADT/STLExtras.h"
31#include "llvm/ADT/ScopeExit.h"
41 ParsedStmtContext StmtCtx,
49 Res = ParseStatementOrDeclaration(Stmts, StmtCtx, TrailingElseLoc,
51 }
while (!Res.isInvalid() && !Res.get());
56StmtResult Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
57 ParsedStmtContext StmtCtx,
68 ParsedAttributes CXX11Attrs(AttrFactory);
70 MaybeParseCXX11Attributes(CXX11Attrs,
true);
71 ParsedAttributes GNUOrMSAttrs(AttrFactory);
73 MaybeParseGNUAttributes(GNUOrMSAttrs);
76 MaybeParseMicrosoftAttributes(GNUOrMSAttrs);
78 StmtResult Res = ParseStatementOrDeclarationAfterAttributes(
79 Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs, GNUOrMSAttrs,
81 MaybeDestroyTemplateIds();
85 assert((CXX11Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
86 "attributes on empty statement");
89 (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
90 ParsedStmtContext{} &&
91 isa_and_present<NullStmt>(Res.get()))
92 Diag(CXX11Attrs.Range.getBegin(), diag::warn_attr_in_secondary_block)
95 if (CXX11Attrs.empty() || Res.isInvalid())
98 return Actions.ActOnAttributedStmt(CXX11Attrs, Res.get());
104 StatementFilterCCC(Token nextTok) : NextToken(nextTok) {
105 WantTypeSpecifiers = nextTok.
isOneOf(tok::l_paren, tok::less, tok::l_square,
106 tok::identifier, tok::star, tok::amp);
107 WantExpressionKeywords =
108 nextTok.
isOneOf(tok::l_paren, tok::identifier, tok::arrow, tok::period);
109 WantRemainingKeywords =
110 nextTok.
isOneOf(tok::l_paren, tok::semi, tok::identifier, tok::l_brace);
111 WantCXXNamedCasts =
false;
114 bool ValidateCandidate(
const TypoCorrection &candidate)
override {
117 if (NextToken.is(tok::equal))
119 if (NextToken.is(tok::period) &&
125 std::unique_ptr<CorrectionCandidateCallback> clone()
override {
126 return std::make_unique<StatementFilterCCC>(*
this);
134StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
135 StmtVector &Stmts, ParsedStmtContext StmtCtx,
138 const char *SemiError =
nullptr;
140 SourceLocation GNUAttributeLoc;
147 SourceLocation AtLoc;
152 return ParseObjCAtStatement(AtLoc, StmtCtx);
155 case tok::code_completion:
157 Actions.CodeCompletion().CodeCompleteOrdinaryName(
161 case tok::identifier:
164 if (
Next.is(tok::colon)) {
171 return ParseLabeledStatement(CXX11Attrs, StmtCtx);
176 if (
Next.isNot(tok::coloncolon)) {
179 StatementFilterCCC CCC(
Next);
184 if (Tok.is(tok::semi))
190 if (Tok.isNot(tok::identifier))
202 bool HaveAttrs = !CXX11Attrs.
empty() || !GNUAttrs.
empty();
203 auto IsStmtAttr = [](ParsedAttr &Attr) {
return Attr.isStmtAttr(); };
204 bool AllAttrsAreStmtAttrs = llvm::all_of(CXX11Attrs, IsStmtAttr) &&
205 llvm::all_of(GNUAttrs, IsStmtAttr);
212 (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
213 ParsedStmtContext()) &&
214 ((GNUAttributeLoc.
isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) ||
215 isDeclarationStatement())) {
216 SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
218 if (GNUAttributeLoc.
isValid()) {
219 DeclStart = GNUAttributeLoc;
221 GNUAttrs, &GNUAttributeLoc);
234 return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
237 if (Tok.is(tok::r_brace)) {
238 Diag(Tok, diag::err_expected_statement);
242 switch (Tok.getKind()) {
243#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
244#include "clang/Basic/BuiltinTraits.inc"
246 Tok.setKind(tok::identifier);
247 Diag(Tok, diag::ext_keyword_as_ident)
248 << Tok.getIdentifierInfo()->getName() << 0;
249 goto ParseIdentifier;
253 return ParseExprStatement(StmtCtx);
257 case tok::kw___attribute: {
258 GNUAttributeLoc = Tok.getLocation();
259 ParseGNUAttributes(GNUAttrs);
263 case tok::kw_template: {
267 Diag(Tok.getLocation(), diag::err_expansion_stmt_requires_cxx2c);
272 return ParseForStatement(TrailingElseLoc, PrecedingLabel);
276 return ParseExpansionStatement(TrailingElseLoc, PrecedingLabel,
280 SourceLocation DeclEnd;
282 getAccessSpecifierIfPresent());
287 return ParseCaseStatement(StmtCtx);
288 case tok::kw_default:
289 return ParseDefaultStatement(StmtCtx);
292 return ParseCompoundStatement();
294 bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro();
295 return Actions.ActOnNullStmt(
ConsumeToken(), HasLeadingEmptyMacro);
299 return ParseIfStatement(TrailingElseLoc);
301 return ParseSwitchStatement(TrailingElseLoc, PrecedingLabel);
304 return ParseWhileStatement(TrailingElseLoc, PrecedingLabel);
306 Res = ParseDoStatement(PrecedingLabel);
307 SemiError =
"do/while";
312 Diag(Tok.getLocation(), diag::err_for_template)
314 SourceRange(Tok.getLocation(),
NextToken().getEndLoc()),
316 Tok.setKind(tok::kw_template);
318 Tok.setKind(tok::kw_for);
319 return ParseExpansionStatement(TrailingElseLoc, PrecedingLabel,
323 return ParseForStatement(TrailingElseLoc, PrecedingLabel);
326 Res = ParseGotoStatement();
329 case tok::kw_continue:
330 Res = ParseContinueStatement();
331 SemiError =
"continue";
334 Res = ParseBreakStatement();
338 Res = ParseReturnStatement();
339 SemiError =
"return";
341 case tok::kw_co_return:
342 Res = ParseReturnStatement();
343 SemiError =
"co_return";
346 return ParseDeferStatement(TrailingElseLoc);
349 for (
const ParsedAttr &AL : CXX11Attrs)
352 (AL.isRegularKeywordAttribute()
353 ?
Diag(AL.getRange().getBegin(), diag::err_keyword_not_allowed)
354 :
Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored))
358 ProhibitAttributes(GNUAttrs);
360 Res = ParseAsmStatement(msAsm);
361 if (msAsm)
return Res;
366 case tok::kw___if_exists:
367 case tok::kw___if_not_exists:
368 ProhibitAttributes(CXX11Attrs);
369 ProhibitAttributes(GNUAttrs);
370 ParseMicrosoftIfExistsStatement(Stmts);
376 return ParseCXXTryBlock();
379 ProhibitAttributes(CXX11Attrs);
380 ProhibitAttributes(GNUAttrs);
381 return ParseSEHTryBlock();
383 case tok::kw___leave:
384 Res = ParseSEHLeaveStatement();
385 SemiError =
"__leave";
388 case tok::annot_pragma_vis:
389 ProhibitAttributes(CXX11Attrs);
390 ProhibitAttributes(GNUAttrs);
391 HandlePragmaVisibility();
394 case tok::annot_pragma_pack:
395 ProhibitAttributes(CXX11Attrs);
396 ProhibitAttributes(GNUAttrs);
400 case tok::annot_pragma_msstruct:
401 ProhibitAttributes(CXX11Attrs);
402 ProhibitAttributes(GNUAttrs);
403 HandlePragmaMSStruct();
406 case tok::annot_pragma_align:
407 ProhibitAttributes(CXX11Attrs);
408 ProhibitAttributes(GNUAttrs);
412 case tok::annot_pragma_weak:
413 ProhibitAttributes(CXX11Attrs);
414 ProhibitAttributes(GNUAttrs);
418 case tok::annot_pragma_weakalias:
419 ProhibitAttributes(CXX11Attrs);
420 ProhibitAttributes(GNUAttrs);
421 HandlePragmaWeakAlias();
424 case tok::annot_pragma_redefine_extname:
425 ProhibitAttributes(CXX11Attrs);
426 ProhibitAttributes(GNUAttrs);
427 HandlePragmaRedefineExtname();
430 case tok::annot_pragma_fp_contract:
431 ProhibitAttributes(CXX11Attrs);
432 ProhibitAttributes(GNUAttrs);
433 Diag(Tok, diag::err_pragma_file_or_compound_scope) <<
"fp_contract";
434 ConsumeAnnotationToken();
437 case tok::annot_pragma_fp:
438 ProhibitAttributes(CXX11Attrs);
439 ProhibitAttributes(GNUAttrs);
440 Diag(Tok, diag::err_pragma_file_or_compound_scope) <<
"clang fp";
441 ConsumeAnnotationToken();
444 case tok::annot_pragma_fenv_access:
445 case tok::annot_pragma_fenv_access_ms:
446 ProhibitAttributes(CXX11Attrs);
447 ProhibitAttributes(GNUAttrs);
448 Diag(Tok, diag::err_pragma_file_or_compound_scope)
449 << (
Kind == tok::annot_pragma_fenv_access ?
"STDC FENV_ACCESS"
451 ConsumeAnnotationToken();
454 case tok::annot_pragma_fenv_round:
455 ProhibitAttributes(CXX11Attrs);
456 ProhibitAttributes(GNUAttrs);
457 Diag(Tok, diag::err_pragma_file_or_compound_scope) <<
"STDC FENV_ROUND";
458 ConsumeAnnotationToken();
461 case tok::annot_pragma_cx_limited_range:
462 ProhibitAttributes(CXX11Attrs);
463 ProhibitAttributes(GNUAttrs);
464 Diag(Tok, diag::err_pragma_file_or_compound_scope)
465 <<
"STDC CX_LIMITED_RANGE";
466 ConsumeAnnotationToken();
469 case tok::annot_pragma_float_control:
470 ProhibitAttributes(CXX11Attrs);
471 ProhibitAttributes(GNUAttrs);
472 Diag(Tok, diag::err_pragma_file_or_compound_scope) <<
"float_control";
473 ConsumeAnnotationToken();
476 case tok::annot_pragma_opencl_extension:
477 ProhibitAttributes(CXX11Attrs);
478 ProhibitAttributes(GNUAttrs);
479 HandlePragmaOpenCLExtension();
482 case tok::annot_pragma_captured:
483 ProhibitAttributes(CXX11Attrs);
484 ProhibitAttributes(GNUAttrs);
485 return HandlePragmaCaptured();
487 case tok::annot_pragma_openmp:
490 ProhibitAttributes(CXX11Attrs);
491 ProhibitAttributes(GNUAttrs);
493 case tok::annot_attr_openmp:
495 return ParseOpenMPDeclarativeOrExecutableDirective(StmtCtx);
497 case tok::annot_pragma_openacc:
500 case tok::annot_pragma_ms_pointers_to_members:
501 ProhibitAttributes(CXX11Attrs);
502 ProhibitAttributes(GNUAttrs);
503 HandlePragmaMSPointersToMembers();
506 case tok::annot_pragma_ms_pragma:
507 ProhibitAttributes(CXX11Attrs);
508 ProhibitAttributes(GNUAttrs);
509 HandlePragmaMSPragma();
512 case tok::annot_pragma_ms_vtordisp:
513 ProhibitAttributes(CXX11Attrs);
514 ProhibitAttributes(GNUAttrs);
515 HandlePragmaMSVtorDisp();
518 case tok::annot_pragma_loop_hint:
519 ProhibitAttributes(CXX11Attrs);
520 ProhibitAttributes(GNUAttrs);
521 return ParsePragmaLoopHint(Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs,
524 case tok::annot_pragma_dump:
525 ProhibitAttributes(CXX11Attrs);
526 ProhibitAttributes(GNUAttrs);
530 case tok::annot_pragma_attribute:
531 ProhibitAttributes(CXX11Attrs);
532 ProhibitAttributes(GNUAttrs);
533 HandlePragmaAttribute();
535 case tok::annot_pragma_export:
536 ProhibitAttributes(CXX11Attrs);
537 ProhibitAttributes(GNUAttrs);
538 HandlePragmaExport();
547 ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
555StmtResult Parser::ParseExprStatement(ParsedStmtContext StmtCtx) {
557 Token OldToken = Tok;
559 ExprStatementTokLoc = Tok.getLocation();
563 if (Expr.isInvalid()) {
568 if (Tok.is(tok::semi))
570 return Actions.ActOnExprStmtError();
573 if (Tok.is(tok::colon) &&
getCurScope()->isSwitchScope() &&
574 Actions.CheckCaseExpression(Expr.get())) {
577 Diag(OldToken, diag::err_expected_case_before_expression)
581 return ParseCaseStatement(StmtCtx,
true, Expr);
584 Token *CurTok =
nullptr;
587 if (Tok.is(tok::annot_repl_input_end))
591 ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
594 if (CurTok && !
R.isInvalid())
601 assert(Tok.is(tok::kw___try) &&
"Expected '__try'");
604 if (Tok.isNot(tok::l_brace))
605 return StmtError(
Diag(Tok, diag::err_expected) << tok::l_brace);
610 if (TryBlock.isInvalid())
614 if (Tok.is(tok::identifier) &&
615 Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
617 Handler = ParseSEHExceptBlock(Loc);
618 }
else if (Tok.is(tok::kw___finally)) {
620 Handler = ParseSEHFinallyBlock(Loc);
625 if(Handler.isInvalid())
628 return Actions.ActOnSEHTryBlock(
false ,
635 PoisonIdentifierRAIIObject raii(Ident__exception_code,
false),
636 raii2(Ident___exception_code,
false),
637 raii3(Ident_GetExceptionCode,
false);
639 if (ExpectAndConsume(tok::l_paren))
646 Ident__exception_info->setIsPoisoned(
false);
647 Ident___exception_info->setIsPoisoned(
false);
648 Ident_GetExceptionInfo->setIsPoisoned(
false);
653 ParseScopeFlags FilterScope(
this,
getCurScope()->getFlags() |
659 Ident__exception_info->setIsPoisoned(
true);
660 Ident___exception_info->setIsPoisoned(
true);
661 Ident_GetExceptionInfo->setIsPoisoned(
true);
667 if (ExpectAndConsume(tok::r_paren))
670 if (Tok.isNot(tok::l_brace))
671 return StmtError(
Diag(Tok, diag::err_expected) << tok::l_brace);
675 if(
Block.isInvalid())
678 return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.
get(),
Block.get());
682 PoisonIdentifierRAIIObject raii(Ident__abnormal_termination,
false),
683 raii2(Ident___abnormal_termination,
false),
684 raii3(Ident_AbnormalTermination,
false);
686 if (Tok.isNot(tok::l_brace))
687 return StmtError(
Diag(Tok, diag::err_expected) << tok::l_brace);
690 Actions.ActOnStartSEHFinallyBlock();
693 if(
Block.isInvalid()) {
694 Actions.ActOnAbortSEHFinallyBlock();
698 return Actions.ActOnFinishSEHFinallyBlock(FinallyLoc,
Block.get());
708 return Actions.ActOnSEHLeaveStmt(LeaveLoc,
getCurScope());
717 diag_compat::label_followed_by_declaration);
722 ParsedStmtContext StmtCtx) {
723 assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
724 "Not an identifier!");
729 StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
731 Token IdentTok = Tok;
734 assert(Tok.is(tok::colon) &&
"Not a label!");
739 LabelDecl *LD = Actions.LookupOrCreateLabel(
745 if (Tok.is(tok::kw___attribute)) {
746 ParsedAttributes TempAttrs(AttrFactory);
747 ParseGNUAttributes(TempAttrs);
760 ParsedAttributes EmptyCXX11Attrs(AttrFactory);
761 SubStmt = ParseStatementOrDeclarationAfterAttributes(
762 Stmts, StmtCtx,
nullptr, EmptyCXX11Attrs,
764 if (!TempAttrs.empty() && !SubStmt.isInvalid())
765 SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get());
770 if (SubStmt.isUnset() && Tok.is(tok::r_brace)) {
771 DiagnoseLabelAtEndOfCompoundStatement();
772 SubStmt = Actions.ActOnNullStmt(ColonLoc);
776 if (SubStmt.isUnset())
777 SubStmt = ParseStatement(
nullptr, StmtCtx, LD);
780 if (SubStmt.isInvalid())
781 SubStmt = Actions.ActOnNullStmt(ColonLoc);
789 return SubStmt.get();
792 Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
795 return Actions.ActOnLabelStmt(IdentTok.
getLocation(), LD, ColonLoc,
799StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
801 assert((MissingCase || Tok.is(tok::kw_case)) &&
"Not a case stmt!");
806 StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
829 Stmt *DeepestParsedCaseStmt =
nullptr;
832 SourceLocation ColonLoc;
834 SourceLocation CaseLoc = MissingCase ? Expr.
get()->
getExprLoc() :
836 ColonLoc = SourceLocation();
838 if (Tok.is(tok::code_completion)) {
840 Actions.CodeCompletion().CodeCompleteCase(
getCurScope());
859 LHS = Actions.ActOnCaseExpr(CaseLoc, Expr);
864 SourceLocation DotDotDotLoc;
870 DiagId = diag::ext_gnu_case_range;
872 DiagId = diag::warn_c23_compat_case_range;
874 DiagId = diag::ext_c2y_case_range;
875 Diag(DotDotDotLoc, DiagId);
883 ColonProtection.restore();
889 Diag(ColonLoc, diag::err_expected_after)
890 <<
"'case'" << tok::colon
895 Diag(ExpectedLoc, diag::err_expected_after)
896 <<
"'case'" << tok::colon
899 ColonLoc = ExpectedLoc;
903 Actions.ActOnCaseStmt(CaseLoc, LHS, DotDotDotLoc, RHS, ColonLoc);
907 if (Case.isInvalid()) {
908 if (TopLevelCase.isInvalid())
909 return ParseStatement(
nullptr, StmtCtx);
914 Stmt *NextDeepest = Case.get();
915 if (TopLevelCase.isInvalid())
918 Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, Case.get());
919 DeepestParsedCaseStmt = NextDeepest;
923 }
while (Tok.is(tok::kw_case));
928 if (Tok.is(tok::r_brace)) {
931 DiagnoseLabelAtEndOfCompoundStatement();
932 SubStmt = Actions.ActOnNullStmt(ColonLoc);
934 SubStmt = ParseStatement(
nullptr, StmtCtx);
938 if (DeepestParsedCaseStmt) {
940 if (SubStmt.isInvalid())
941 SubStmt = Actions.ActOnNullStmt(SourceLocation());
943 Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
950StmtResult Parser::ParseDefaultStatement(ParsedStmtContext StmtCtx) {
951 assert(Tok.is(tok::kw_default) &&
"Not a default stmt!");
956 StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
960 SourceLocation ColonLoc;
964 Diag(ColonLoc, diag::err_expected_after)
965 <<
"'default'" << tok::colon
968 SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
969 Diag(ExpectedLoc, diag::err_expected_after)
970 <<
"'default'" << tok::colon
972 ColonLoc = ExpectedLoc;
977 if (Tok.is(tok::r_brace)) {
980 DiagnoseLabelAtEndOfCompoundStatement();
981 SubStmt = Actions.ActOnNullStmt(ColonLoc);
983 SubStmt = ParseStatement(
nullptr, StmtCtx);
987 if (SubStmt.isInvalid())
988 SubStmt = Actions.ActOnNullStmt(ColonLoc);
991 return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
995StmtResult Parser::ParseCompoundStatement(
bool isStmtExpr) {
996 return ParseCompoundStatement(isStmtExpr,
1000StmtResult Parser::ParseCompoundStatement(
bool isStmtExpr,
1001 unsigned ScopeFlags) {
1002 assert(Tok.is(tok::l_brace) &&
"Not a compound stmt!");
1010 StackHandler.runWithSufficientStackSpace(Tok.getLocation(), [&,
this]() {
1011 R = ParseCompoundStatementBody(isStmtExpr);
1016void Parser::ParseCompoundStatementLeadingPragmas() {
1017 bool checkForPragmas =
true;
1018 while (checkForPragmas) {
1019 switch (Tok.getKind()) {
1020 case tok::annot_pragma_vis:
1021 HandlePragmaVisibility();
1023 case tok::annot_pragma_pack:
1026 case tok::annot_pragma_msstruct:
1027 HandlePragmaMSStruct();
1029 case tok::annot_pragma_align:
1030 HandlePragmaAlign();
1032 case tok::annot_pragma_weak:
1035 case tok::annot_pragma_weakalias:
1036 HandlePragmaWeakAlias();
1038 case tok::annot_pragma_redefine_extname:
1039 HandlePragmaRedefineExtname();
1041 case tok::annot_pragma_opencl_extension:
1042 HandlePragmaOpenCLExtension();
1044 case tok::annot_pragma_fp_contract:
1045 HandlePragmaFPContract();
1047 case tok::annot_pragma_fp:
1050 case tok::annot_pragma_fenv_access:
1051 case tok::annot_pragma_fenv_access_ms:
1052 HandlePragmaFEnvAccess();
1054 case tok::annot_pragma_fenv_round:
1055 HandlePragmaFEnvRound();
1057 case tok::annot_pragma_cx_limited_range:
1058 HandlePragmaCXLimitedRange();
1060 case tok::annot_pragma_float_control:
1061 HandlePragmaFloatControl();
1063 case tok::annot_pragma_ms_pointers_to_members:
1064 HandlePragmaMSPointersToMembers();
1066 case tok::annot_pragma_ms_pragma:
1067 HandlePragmaMSPragma();
1069 case tok::annot_pragma_ms_vtordisp:
1070 HandlePragmaMSVtorDisp();
1072 case tok::annot_pragma_dump:
1075 case tok::annot_pragma_export:
1076 HandlePragmaExport();
1079 checkForPragmas =
false;
1086void Parser::DiagnoseLabelAtEndOfCompoundStatement() {
1088 ? diag_compat::cxx_label_at_end_of_compound_statement
1089 : diag_compat::c_label_at_end_of_compound_statement);
1092bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
1093 if (!Tok.is(tok::semi))
1096 SourceLocation StartLoc = Tok.getLocation();
1097 SourceLocation EndLoc;
1099 while (Tok.is(tok::semi) && !Tok.hasLeadingEmptyMacro() &&
1100 Tok.getLocation().isValid() && !Tok.getLocation().isMacroID()) {
1101 EndLoc = Tok.getLocation();
1105 ParseStatementOrDeclaration(Stmts, ParsedStmtContext::SubStmt);
1107 Stmts.push_back(
R.get());
1114 Diag(StartLoc, diag::warn_null_statement)
1120 bool IsStmtExprResult =
false;
1121 if ((StmtCtx & ParsedStmtContext::InStmtExpr) != ParsedStmtContext()) {
1125 IsStmtExprResult = Tok.is(tok::r_brace) &&
NextToken().
is(tok::r_paren);
1128 if (IsStmtExprResult)
1129 E = Actions.ActOnStmtExprResult(E);
1130 return Actions.ActOnExprStmt(E, !IsStmtExprResult);
1133StmtResult Parser::ParseCompoundStatementBody(
bool isStmtExpr) {
1134 PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
1136 "in compound statement ('{}')");
1140 Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
1144 if (
T.consumeOpen())
1147 Sema::CompoundScopeRAII CompoundScope(Actions, isStmtExpr);
1150 ParseCompoundStatementLeadingPragmas();
1151 Actions.ActOnAfterCompoundStatementLeadingPragmas();
1157 while (Tok.is(tok::kw___label__)) {
1160 SmallVector<Decl *, 4> DeclsInGroup;
1162 if (Tok.isNot(tok::identifier)) {
1163 Diag(Tok, diag::err_expected) << tok::identifier;
1167 IdentifierInfo *II = Tok.getIdentifierInfo();
1169 DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc));
1175 DeclSpec DS(AttrFactory);
1177 Actions.FinalizeDeclaratorGroup(
getCurScope(), DS, DeclsInGroup);
1178 StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation());
1180 ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
1182 Stmts.push_back(
R.get());
1185 ParsedStmtContext SubStmtCtx =
1186 ParsedStmtContext::Compound |
1187 (isStmtExpr ? ParsedStmtContext::InStmtExpr : ParsedStmtContext());
1189 bool LastIsError =
false;
1190 while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
1191 Tok.isNot(tok::eof)) {
1192 if (Tok.is(tok::annot_pragma_unused)) {
1193 HandlePragmaUnused();
1197 if (ConsumeNullStmt(Stmts))
1201 if (Tok.isNot(tok::kw___extension__)) {
1202 R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
1209 while (Tok.is(tok::kw___extension__))
1212 ParsedAttributes attrs(AttrFactory);
1213 MaybeParseCXX11Attributes(attrs,
true);
1216 if (isDeclarationStatement()) {
1219 ExtensionRAIIObject O(Diags);
1221 SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
1222 ParsedAttributes DeclSpecAttrs(AttrFactory);
1224 attrs, DeclSpecAttrs);
1225 R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
1228 ExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
1230 if (Res.isInvalid()) {
1237 ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
1238 R = handleExprStmt(Res, SubStmtCtx);
1240 R = Actions.ActOnAttributedStmt(attrs,
R.get());
1245 Stmts.push_back(
R.get());
1246 LastIsError =
R.isInvalid();
1252 if (isStmtExpr && LastIsError && !Stmts.empty())
1259 if (!PP.getTargetInfo().supportSourceEvalMethod() &&
1260 (PP.getLastFPEvalPragmaLocation().isValid() ||
1261 PP.getCurrentFPEvalMethod() ==
1263 Diag(Tok.getLocation(),
1264 diag::warn_no_support_for_eval_method_source_on_m32);
1266 SourceLocation CloseLoc = Tok.getLocation();
1269 if (!
T.consumeClose()) {
1272 if (isStmtExpr && Tok.is(tok::r_paren))
1273 checkCompoundToken(CloseLoc, tok::r_brace, CompoundToken::StmtExprEnd);
1279 if (
T.getCloseLocation().isValid())
1280 CloseLoc =
T.getCloseLocation();
1282 return Actions.ActOnCompoundStmt(
T.getOpenLocation(), CloseLoc,
1286bool Parser::ParseParenExprOrCondition(
StmtResult *InitStmt,
1294 SourceLocation Start = Tok.getLocation();
1296 Cond = ParseCondition(InitStmt, Loc, CK,
false);
1301 if (Cond.
isInvalid() && Tok.isNot(tok::r_paren)) {
1305 if (Tok.isNot(tok::r_paren))
1310 ExprResult CondExpr = Actions.CreateRecoveryExpr(
1311 Start, Tok.getLocation() == Start ? Start : PrevTokLocation, {},
1312 Actions.PreferredConditionType(CK));
1314 Cond = Actions.ActOnCondition(
getCurScope(), Loc, CondExpr.
get(), CK,
1319 if (InitStmt !=
nullptr && InitStmt->isUsable()) {
1325 Diag(InitStmt->get()->getBeginLoc(),
1326 diag::err_c2y_first_condition_clause_is_not_declaration)
1327 << InitStmt->get()->getSourceRange();
1329 if (Cond.
get().first !=
nullptr)
1331 Diag(Cond.
get().first->getBeginLoc(), diag::err_expected_expression)
1332 << Cond.
get().first->getSourceRange();
1333 }
else if (Cond.
get().first !=
nullptr)
1335 DiagCompat(Cond.
get().first->getBeginLoc(), diag_compat::decl_statement)
1339 if (Tok.is(tok::comma)) {
1340 Diag(Tok, diag::err_c2y_multiple_declarations);
1342 while (Tok.isNot(tok::r_paren) && !Tok.is(tok::eof))
1347 LParenLoc =
T.getOpenLocation();
1348 RParenLoc =
T.getCloseLocation();
1353 while (Tok.is(tok::r_paren)) {
1354 Diag(Tok, diag::err_extraneous_rparen_in_condition)
1364enum MisleadingStatementKind { MSK_if, MSK_else, MSK_for, MSK_while };
1366struct MisleadingIndentationChecker {
1368 SourceLocation StmtLoc;
1369 SourceLocation PrevLoc;
1370 unsigned NumDirectives;
1371 MisleadingStatementKind
Kind;
1373 MisleadingIndentationChecker(Parser &P, MisleadingStatementKind K,
1375 : P(P), StmtLoc(SL), PrevLoc(P.getCurToken().getLocation()),
1376 NumDirectives(P.getPreprocessor().getNumDirectives()),
Kind(K),
1377 ShouldSkip(P.getCurToken().
is(tok::l_brace)) {
1379 StmtLoc = P.MisleadingIndentationElseLoc;
1380 P.MisleadingIndentationElseLoc = SourceLocation();
1382 if (Kind == MSK_else && !ShouldSkip)
1388 static unsigned getVisualIndentation(SourceManager &SM, SourceLocation Loc) {
1392 if (ColNo == 0 || TabStop == 1)
1402 const char *EndPos = BufData.data() + FIDAndOffset.second;
1404 assert(FIDAndOffset.second + 1 >= ColNo &&
1405 "Column number smaller than file offset?");
1407 unsigned VisualColumn = 0;
1410 for (
const char *CurPos = EndPos - (ColNo - 1); CurPos != EndPos;
1412 if (*CurPos ==
'\t')
1414 VisualColumn += (TabStop - VisualColumn % TabStop);
1418 return VisualColumn + 1;
1433 if (Kind == MSK_else)
1437 unsigned PrevColNum = getVisualIndentation(SM, PrevLoc);
1438 unsigned CurColNum = getVisualIndentation(SM,
Tok.
getLocation());
1439 unsigned StmtColNum = getVisualIndentation(SM, StmtLoc);
1441 if (PrevColNum != 0 && CurColNum != 0 && StmtColNum != 0 &&
1442 ((PrevColNum > StmtColNum && PrevColNum == CurColNum) ||
1449 P.
Diag(StmtLoc, diag::note_previous_statement);
1457 assert(Tok.is(tok::kw_if) &&
"Not an if stmt!");
1460 bool IsConstexpr =
false;
1461 bool IsConsteval =
false;
1462 SourceLocation NotLocation;
1463 SourceLocation ConstevalLoc;
1465 if (Tok.is(tok::kw_constexpr)) {
1473 if (Tok.is(tok::exclaim)) {
1477 if (Tok.is(tok::kw_consteval)) {
1481 }
else if (Tok.is(tok::code_completion)) {
1483 Actions.CodeCompletion().CodeCompleteKeywordAfterIf(
1488 if (!IsConsteval && (NotLocation.
isValid() || Tok.isNot(tok::l_paren))) {
1489 Diag(Tok, diag::err_expected_lparen_after) <<
"if";
1512 Sema::ConditionResult Cond;
1513 SourceLocation LParen;
1514 SourceLocation RParen;
1515 std::optional<bool> ConstexprCondition;
1518 if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc,
1528 bool IsBracedThen = Tok.is(tok::l_brace);
1550 MisleadingIndentationChecker MIChecker(*
this, MSK_if, IfLoc);
1553 SourceLocation ThenStmtLoc = Tok.getLocation();
1555 SourceLocation InnerStatementTrailingElseLoc;
1558 bool ShouldEnter = ConstexprCondition && !*ConstexprCondition;
1561 if (NotLocation.
isInvalid() && IsConsteval) {
1566 EnterExpressionEvaluationContext PotentiallyDiscarded(
1567 Actions, Context,
nullptr,
1569 ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
1572 if (Tok.isNot(tok::kw_else))
1579 SourceLocation ElseLoc;
1580 SourceLocation ElseStmtLoc;
1583 if (Tok.is(tok::kw_else)) {
1584 if (TrailingElseLoc)
1585 *TrailingElseLoc = Tok.getLocation();
1588 ElseStmtLoc = Tok.getLocation();
1600 Tok.is(tok::l_brace));
1602 MisleadingIndentationChecker MIChecker(*
this, MSK_else, ElseLoc);
1603 bool ShouldEnter = ConstexprCondition && *ConstexprCondition;
1606 if (NotLocation.
isValid() && IsConsteval) {
1611 EnterExpressionEvaluationContext PotentiallyDiscarded(
1612 Actions, Context,
nullptr,
1614 ElseStmt = ParseStatement();
1616 if (ElseStmt.isUsable())
1621 }
else if (Tok.is(tok::code_completion)) {
1623 Actions.CodeCompletion().CodeCompleteAfterIf(
getCurScope(), IsBracedThen);
1625 }
else if (InnerStatementTrailingElseLoc.
isValid()) {
1626 Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else);
1634 if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
1635 (ThenStmt.isInvalid() && ElseStmt.get() ==
nullptr) ||
1636 (ThenStmt.get() ==
nullptr && ElseStmt.isInvalid())) {
1642 auto IsCompoundStatement = [](
const Stmt *S) {
1643 if (
const auto *Outer = dyn_cast_if_present<AttributedStmt>(S))
1644 S = Outer->getSubStmt();
1645 return isa_and_nonnull<clang::CompoundStmt>(S);
1648 if (!IsCompoundStatement(ThenStmt.get())) {
1649 Diag(ConstevalLoc, diag::err_expected_after) <<
"consteval"
1653 if (!ElseStmt.isUnset() && !IsCompoundStatement(ElseStmt.get())) {
1654 Diag(ElseLoc, diag::err_expected_after) <<
"else"
1661 if (ThenStmt.isInvalid())
1662 ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
1663 if (ElseStmt.isInvalid())
1664 ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
1669 else if (IsConsteval)
1673 return Actions.ActOnIfStmt(IfLoc, Kind, LParen, InitStmt.get(), Cond, RParen,
1674 ThenStmt.get(), ElseLoc, ElseStmt.get());
1679 assert(Tok.is(tok::kw_switch) &&
"Not a switch stmt!");
1682 if (Tok.isNot(tok::l_paren)) {
1683 Diag(Tok, diag::err_expected_lparen_after) <<
"switch";
1709 Sema::ConditionResult Cond;
1710 SourceLocation LParen;
1711 SourceLocation RParen;
1712 if (ParseParenExprOrCondition(&InitStmt, Cond, SwitchLoc,
1717 SwitchLoc, LParen, InitStmt.get(), Cond, RParen);
1719 if (
Switch.isInvalid()) {
1724 if (Tok.is(tok::l_brace)) {
1752 StmtResult Body(ParseStatement(TrailingElseLoc));
1758 return Actions.ActOnFinishSwitchStmt(SwitchLoc,
Switch.get(), Body.get());
1763 assert(Tok.is(tok::kw_while) &&
"Not a while stmt!");
1764 SourceLocation WhileLoc = Tok.getLocation();
1767 if (Tok.isNot(tok::l_paren)) {
1768 Diag(Tok, diag::err_expected_lparen_after) <<
"while";
1787 unsigned ScopeFlags =
1792 Sema::ConditionResult Cond;
1793 SourceLocation LParen;
1794 SourceLocation RParen;
1795 if (ParseParenExprOrCondition(
nullptr, Cond, WhileLoc,
1818 MisleadingIndentationChecker MIChecker(*
this, MSK_while, WhileLoc);
1821 StmtResult Body(ParseStatement(TrailingElseLoc));
1823 if (Body.isUsable())
1829 if (Cond.
isInvalid() || Body.isInvalid())
1832 return Actions.ActOnWhileStmt(WhileLoc, LParen, Cond, RParen, Body.get());
1836 assert(Tok.is(tok::kw_do) &&
"Not a do stmt!");
1870 if (Tok.isNot(tok::kw_while)) {
1871 if (!Body.isInvalid()) {
1872 Diag(Tok, diag::err_expected_while);
1873 Diag(DoLoc, diag::note_matching) <<
"'do'";
1880 if (Tok.isNot(tok::l_paren)) {
1881 Diag(Tok, diag::err_expected_lparen_after) <<
"do/while";
1891 DiagnoseAndSkipCXX11Attributes();
1893 SourceLocation Start = Tok.getLocation();
1896 if (!Tok.isOneOf(tok::r_paren, tok::r_square, tok::r_brace))
1898 Cond = Actions.CreateRecoveryExpr(
1899 Start, Start == Tok.getLocation() ? Start : PrevTokLocation, {},
1900 Actions.getASTContext().BoolTy);
1905 if (Cond.
isInvalid() || Body.isInvalid())
1908 return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc,
T.getOpenLocation(),
1909 Cond.
get(),
T.getCloseLocation());
1912bool Parser::isForRangeIdentifier() {
1913 assert(Tok.is(tok::identifier));
1916 if (
Next.is(tok::colon))
1919 if (
Next.isOneOf(tok::l_square, tok::kw_alignas)) {
1920 TentativeParsingAction PA(*
this);
1922 SkipCXX11Attributes();
1923 bool Result = Tok.is(tok::colon);
1931void Parser::ParseForRangeInitializerAfterColon(ForRangeInit &FRI,
1939 EnterExpressionEvaluationContext InitContext(
1947 auto &LastRecord = Actions.currentEvaluationContext();
1948 LastRecord.InLifetimeExtendingContext =
true;
1949 LastRecord.RebuildDefaultArgOrDefaultInit =
true;
1952 if (FRI.ExpansionStmt) {
1955 assert(Actions.CurContext->isExpansionStmt());
1956 Sema::ContextRAII CtxGuard(Actions, Actions.CurContext->getParent(),
1960 FRI.RangeExpr = Actions.MaybeCreateExprWithCleanups(FRI.RangeExpr);
1961 }
else if (Tok.is(tok::l_brace)) {
1962 FRI.RangeExpr = ParseBraceInitializer();
1969 Actions.ExprEvalContexts.back().ForRangeLifetimeExtendTemps.empty());
1973 FRI.LifetimeExtendTemps =
1974 std::move(Actions.ExprEvalContexts.back().ForRangeLifetimeExtendTemps);
1980 assert(Tok.is(tok::kw_for) &&
"Not a for stmt!");
1983 SourceLocation CoawaitLoc;
1984 if (Tok.is(tok::kw_co_await))
1987 if (Tok.isNot(tok::l_paren)) {
1988 Diag(Tok, diag::err_expected_lparen_after) <<
"for";
2025 bool ForEach =
false;
2027 Sema::ConditionResult SecondPart;
2029 ForRangeInfo ForRangeInfo;
2031 ForRangeInfo.ExpansionStmt = ESD;
2038 struct [[nodiscard]] ExpansionStmtContextRAII : Sema::ContextRAII {
2039 ExpansionStmtContextRAII(Sema &S,
struct ForRangeInfo &Info,
2041 : ContextRAII(S, Info.ExpansionStmt ? Ctx : S.CurContext,
2045 assert(!ESD || Actions.CurContext->isExpansionStmt());
2046 if (Tok.is(tok::code_completion)) {
2048 Actions.CodeCompletion().CodeCompleteOrdinaryName(
2054 ParsedAttributes attrs(AttrFactory);
2055 MaybeParseCXX11Attributes(attrs);
2057 SourceLocation EmptyInitStmtSemiLoc;
2060 if (Tok.is(tok::semi)) {
2061 ProhibitAttributes(attrs);
2063 SourceLocation SemiLoc = Tok.getLocation();
2064 if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.
isMacroID())
2065 EmptyInitStmtSemiLoc = SemiLoc;
2068 isForRangeIdentifier()) {
2072 ProhibitAttributes(attrs);
2073 IdentifierInfo *Name = Tok.getIdentifierInfo();
2075 MaybeParseCXX11Attributes(attrs);
2078 ParseForRangeInitializerAfterColon(ForRangeInfo,
nullptr);
2080 Diag(Loc, diag::err_for_range_identifier)
2081 << (ForRangeInfo.ExpansionStmt !=
nullptr)
2086 if (!ForRangeInfo.ExpansionStmt)
2087 ForRangeInfo.LoopVar =
2088 Actions.ActOnCXXForRangeIdentifier(
getCurScope(), Loc, Name, attrs);
2089 }
else if (isForInitDeclaration()) {
2091 ExpansionStmtContextRAII EnterParentContext{
2092 Actions, ForRangeInfo, Actions.CurContext->getParent()};
2095 if (!C99orCXXorObjC) {
2096 Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
2097 Diag(Tok, diag::warn_gcc_variable_decl_in_for_loop);
2100 SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
2102 Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
2103 ProhibitAttributes(attrs);
2104 Decl *D = ParseStaticAssertDeclaration(DeclEnd);
2105 DG = Actions.ConvertDeclToDeclGroup(D);
2106 FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
2107 }
else if (Tok.is(tok::kw_using)) {
2110 FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
2115 ParsedAttributes DeclSpecAttrs(AttrFactory);
2116 DG = ParseSimpleDeclaration(
2118 MightBeForRangeStmt ? &ForRangeInfo :
nullptr);
2119 FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
2120 if (ForRangeInfo.ParsedForRangeDecl()) {
2121 DiagCompat(ForRangeInfo.ColonLoc, diag_compat::for_range);
2122 ForRangeInfo.LoopVar = FirstPart;
2124 }
else if (Tok.is(tok::semi)) {
2126 }
else if ((ForEach = isTokIdentifier_in())) {
2127 Actions.ActOnForEachDeclStmt(DG);
2131 if (Tok.is(tok::code_completion)) {
2133 Actions.CodeCompletion().CodeCompleteObjCForCollection(
getCurScope(),
2139 Diag(Tok, diag::err_expected_semi_for);
2144 ExpansionStmtContextRAII EnterParentContext{
2145 Actions, ForRangeInfo, Actions.CurContext->getParent()};
2146 ProhibitAttributes(attrs);
2149 ForEach = isTokIdentifier_in();
2152 if (!
Value.isInvalid()) {
2154 FirstPart = Actions.ActOnForEachLValueExpr(
Value.get());
2161 bool IsRangeBasedFor =
2162 getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon);
2163 FirstPart = Actions.ActOnExprStmt(
Value, !IsRangeBasedFor);
2167 if (Tok.is(tok::semi)) {
2169 }
else if (ForEach) {
2172 if (Tok.is(tok::code_completion)) {
2174 Actions.CodeCompletion().CodeCompleteObjCForCollection(
getCurScope(),
2182 Diag(Tok, diag::err_for_range_expected_decl)
2183 << (ESD !=
nullptr) << FirstPart.get()->getSourceRange();
2187 if (!
Value.isInvalid()) {
2188 Diag(Tok, diag::err_expected_semi_for);
2192 if (Tok.is(tok::semi))
2199 if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() &&
2202 if (Tok.is(tok::semi)) {
2204 }
else if (Tok.is(tok::r_paren)) {
2210 bool MightBeForRangeStmt = !ForRangeInfo.ParsedForRangeDecl();
2212 SourceLocation SecondPartStart = Tok.getLocation();
2214 SecondPart = ParseCondition(
2215 nullptr, ForLoc, CK,
2217 true, MightBeForRangeStmt ? &ForRangeInfo :
nullptr);
2219 if (ForRangeInfo.ParsedForRangeDecl()) {
2220 DiagCompat(FirstPart.get() ? FirstPart.get()->getBeginLoc()
2221 : ForRangeInfo.ColonLoc,
2222 diag_compat::for_range_init_stmt)
2223 << (FirstPart.get() ? FirstPart.get()->getSourceRange()
2225 if (EmptyInitStmtSemiLoc.
isValid()) {
2226 Diag(EmptyInitStmtSemiLoc, diag::warn_empty_init_statement)
2233 ExprResult CondExpr = Actions.CreateRecoveryExpr(
2235 Tok.getLocation() == SecondPartStart ? SecondPartStart
2237 {}, Actions.PreferredConditionType(CK));
2239 SecondPart = Actions.ActOnCondition(
getCurScope(), ForLoc,
2249 SecondPart = Actions.ActOnCondition(
2257 if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) {
2258 if (Tok.isNot(tok::semi)) {
2260 Diag(Tok, diag::err_expected_semi_for);
2264 if (Tok.is(tok::semi)) {
2268 if (Tok.isNot(tok::r_paren)) {
2272 ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.
get());
2280 if (CoawaitLoc.
isValid() && !ForRangeInfo.ParsedForRangeDecl()) {
2281 Diag(CoawaitLoc, diag::err_for_co_await_not_range_for);
2282 CoawaitLoc = SourceLocation();
2286 Diag(CoawaitLoc, diag::warn_deprecated_for_co_await);
2295 ForRangeStmt = Actions.ActOnCXXExpansionStmtPattern(
2296 ESD, FirstPart.get(), ForRangeInfo.LoopVar.get(),
2297 ForRangeInfo.RangeExpr.get(),
T.getOpenLocation(),
2298 ForRangeInfo.ColonLoc,
T.getCloseLocation(),
2299 ForRangeInfo.LifetimeExtendTemps);
2300 }
else if (ForRangeInfo.ParsedForRangeDecl()) {
2301 ForRangeStmt = Actions.ActOnCXXForRangeStmt(
2302 getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
2303 ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc,
2305 ForRangeInfo.LifetimeExtendTemps);
2306 }
else if (ForEach) {
2309 ForEachStmt = Actions.ObjC().ActOnObjCForCollectionStmt(
2310 ForLoc, FirstPart.get(), Collection.
get(),
T.getCloseLocation());
2314 if (
getLangOpts().OpenMP && FirstPart.isUsable()) {
2315 Actions.OpenMP().ActOnOpenMPLoopInitialization(ForLoc, FirstPart.get());
2324 else if (ForRangeInfo.ParsedForRangeDecl())
2328 ForLoc, FirstPart.get(), SecondPart.
get().second, ThirdPart.get());
2334 bool BodyStartsWithAttr = Tok.isOneOf(tok::l_square, tok::kw___attribute);
2335 SourceLocation BodyBeginLoc = Tok.getLocation();
2349 Tok.is(tok::l_brace));
2358 MisleadingIndentationChecker MIChecker(*
this, MSK_for, ForLoc);
2361 StmtResult Body(ParseStatement(TrailingElseLoc));
2363 if (Body.isUsable())
2374 if (Body.isInvalid())
2378 return Actions.ObjC().FinishObjCForCollectionStmt(ForEachStmt.get(),
2382 if (!ForRangeInfo.ParsedForRangeDecl()) {
2383 Diag(ForLoc, diag::err_expansion_stmt_requires_range);
2392 ? diag::ext_expansion_stmt_body_attr
2393 : diag::ext_expansion_stmt_body_not_compound_stmt);
2395 return Actions.FinishCXXExpansionStmt(ForRangeStmt.get(), Body.get());
2398 if (ForRangeInfo.ParsedForRangeDecl())
2399 return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
2401 return Actions.ActOnForStmt(ForLoc,
T.getOpenLocation(), FirstPart.get(),
2402 SecondPart, ThirdPart,
T.getCloseLocation(),
2407 assert(Tok.is(tok::kw_goto) &&
"Not a goto stmt!");
2411 if (Tok.is(tok::identifier)) {
2412 LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
2414 Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD);
2416 }
else if (Tok.is(tok::star)) {
2418 Diag(Tok, diag::ext_gnu_indirect_goto);
2421 if (
R.isInvalid()) {
2425 Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc,
R.get());
2427 Diag(Tok, diag::err_expected) << tok::identifier;
2434StmtResult Parser::ParseBreakOrContinueStatement(
bool IsContinue) {
2436 SourceLocation LabelLoc;
2437 LabelDecl *
Target =
nullptr;
2438 if (Tok.is(tok::identifier)) {
2440 Actions.LookupExistingLabel(Tok.getIdentifierInfo(), Tok.getLocation());
2445 Diag(LabelLoc, diag::err_c2y_labeled_break_continue) << IsContinue;
2447 Diag(LabelLoc, diag::err_break_continue_label_not_found) << IsContinue;
2458 return ParseBreakOrContinueStatement(
true);
2462 return ParseBreakOrContinueStatement(
false);
2466 assert((Tok.is(tok::kw_return) || Tok.is(tok::kw_co_return)) &&
2467 "Not a return stmt!");
2468 bool IsCoreturn = Tok.is(tok::kw_co_return);
2472 if (Tok.isNot(tok::semi)) {
2474 PreferredType.enterReturn(Actions, Tok.getLocation());
2476 if (Tok.is(tok::code_completion) && !IsCoreturn) {
2478 Actions.CodeCompletion().CodeCompleteExpression(
2479 getCurScope(), PreferredType.get(Tok.getLocation()));
2484 R = ParseInitializer();
2487 diag_compat::generalized_initializer_lists);
2490 if (
R.isInvalid()) {
2496 return Actions.ActOnCoreturnStmt(
getCurScope(), ReturnLoc,
R.get());
2497 return Actions.ActOnReturnStmt(ReturnLoc,
R.get(),
getCurScope());
2501 assert(Tok.is(tok::kw__Defer));
2504 Actions.ActOnStartOfDeferStmt(DeferLoc,
getCurScope());
2506 llvm::scope_exit OnError([&] { Actions.ActOnDeferStmtError(
getCurScope()); });
2508 StmtResult Res = ParseStatement(TrailingElseLoc);
2509 if (!Res.isUsable())
2513 if (
auto *L = dyn_cast<LabelStmt>(Res.get())) {
2514 Diag(L->getIdentLoc(), diag::err_defer_ts_labeled_stmt);
2519 return Actions.ActOnEndOfDeferStmt(Res.get(),
getCurScope());
2522StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
2523 ParsedStmtContext StmtCtx,
2528 ParsedAttributes TempAttrs(AttrFactory);
2530 SourceLocation StartLoc = Tok.getLocation();
2533 while (Tok.is(tok::annot_pragma_loop_hint)) {
2535 if (!HandlePragmaLoopHint(Hint))
2541 AttributeScopeInfo(), ArgHints, 4,
2542 ParsedAttr::Form::Pragma());
2546 MaybeParseCXX11Attributes(Attrs);
2548 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2549 StmtResult S = ParseStatementOrDeclarationAfterAttributes(
2550 Stmts, StmtCtx, TrailingElseLoc, Attrs, EmptyDeclSpecAttrs,
2563Decl *Parser::ParseFunctionStatementBody(
Decl *
Decl, ParseScope &BodyScope) {
2564 assert(Tok.is(tok::l_brace));
2565 SourceLocation LBraceLoc = Tok.getLocation();
2567 PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, LBraceLoc,
2568 "parsing function body");
2573 Sema::PragmaStackSentinelRAII
2574 PragmaStackSentinel(Actions,
"InternalPragmaState", IsCXXMethod);
2579 StmtResult FnBody(ParseCompoundStatementBody());
2582 if (FnBody.isInvalid()) {
2583 Sema::CompoundScopeRAII CompoundScope(Actions);
2584 FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, {},
false);
2588 return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
2591Decl *Parser::ParseFunctionTryBlock(
Decl *
Decl, ParseScope &BodyScope) {
2592 assert(Tok.is(tok::kw_try) &&
"Expected 'try'");
2595 PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, TryLoc,
2596 "parsing function try block");
2599 if (Tok.is(tok::colon))
2600 ParseConstructorInitializer(Decl);
2602 Actions.ActOnDefaultCtorInitializers(Decl);
2607 Sema::PragmaStackSentinelRAII
2608 PragmaStackSentinel(Actions,
"InternalPragmaState", IsCXXMethod);
2610 SourceLocation LBraceLoc = Tok.getLocation();
2611 StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc,
true));
2614 if (FnBody.isInvalid()) {
2615 Sema::CompoundScopeRAII CompoundScope(Actions);
2616 FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, {},
false);
2620 return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
2623bool Parser::trySkippingFunctionBody() {
2624 assert(SkipFunctionBodies &&
2625 "Should only be called when SkipFunctionBodies is enabled");
2626 if (!PP.isCodeCompletionEnabled()) {
2633 TentativeParsingAction PA(*
this);
2634 bool IsTryCatch = Tok.is(tok::kw_try);
2636 bool ErrorInPrologue = ConsumeAndStoreFunctionPrologue(Toks);
2637 if (llvm::any_of(Toks, [](
const Token &Tok) {
2638 return Tok.is(tok::code_completion);
2643 if (ErrorInPrologue) {
2652 while (IsTryCatch && Tok.is(tok::kw_catch)) {
2664 assert(Tok.is(tok::kw_try) &&
"Expected 'try'");
2667 return ParseCXXTryBlockCommon(TryLoc);
2671 if (Tok.isNot(tok::l_brace))
2672 return StmtError(
Diag(Tok, diag::err_expected) << tok::l_brace);
2678 if (TryBlock.isInvalid())
2683 if ((Tok.is(tok::identifier) &&
2684 Tok.getIdentifierInfo() == getSEHExceptKeyword()) ||
2685 Tok.is(tok::kw___finally)) {
2688 if(Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
2690 Handler = ParseSEHExceptBlock(Loc);
2694 Handler = ParseSEHFinallyBlock(Loc);
2696 if(Handler.isInvalid())
2699 return Actions.ActOnSEHTryBlock(
true ,
2709 DiagnoseAndSkipCXX11Attributes();
2711 if (Tok.isNot(tok::kw_catch))
2713 while (Tok.is(tok::kw_catch)) {
2714 StmtResult Handler(ParseCXXCatchBlock(FnTry));
2715 if (!Handler.isInvalid())
2716 Handlers.push_back(Handler.get());
2720 if (Handlers.empty())
2723 return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.get(), Handlers);
2727StmtResult Parser::ParseCXXCatchBlock(
bool FnCatch) {
2728 assert(Tok.is(tok::kw_catch) &&
"Expected 'catch'");
2733 if (
T.expectAndConsume())
2745 Decl *ExceptionDecl =
nullptr;
2746 if (Tok.isNot(tok::ellipsis)) {
2747 ParsedAttributes Attributes(AttrFactory);
2748 MaybeParseCXX11Attributes(Attributes);
2750 DeclSpec DS(AttrFactory);
2752 if (ParseCXXTypeSpecifierSeq(DS))
2756 ParseDeclarator(ExDecl);
2757 ExceptionDecl = Actions.ActOnExceptionDeclarator(
getCurScope(), ExDecl);
2762 if (
T.getCloseLocation().isInvalid())
2765 if (Tok.isNot(tok::l_brace))
2766 return StmtError(
Diag(Tok, diag::err_expected) << tok::l_brace);
2770 if (
Block.isInvalid())
2773 return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl,
Block.get());
2779 assert(Tok.is(tok::kw_for));
2781 CXXExpansionStmtDecl *ExpansionDecl =
2782 Actions.ActOnCXXExpansionStmtDecl(TemplateParameterDepth, TemplateLoc);
2784 CXXExpansionStmtPattern *Expansion;
2786 Sema::ContextRAII CtxGuard(Actions, ExpansionDecl,
false);
2787 TemplateParameterDepthRAII TParamDepthGuard(TemplateParameterDepth);
2791 ParseForStatement(TrailingElseLoc, PrecedingLabel, ExpansionDecl);
2799 DeclSpec DS(AttrFactory);
2801 Actions.FinalizeDeclaratorGroup(
getCurScope(), DS, {ExpansionDecl});
2803 return Actions.ActOnDeclStmt(DeclGroupPtr, Expansion->
getBeginLoc(),
2807void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
2808 IfExistsCondition
Result;
2809 if (ParseMicrosoftIfExistsCondition(
Result))
2817 if (!Tok.is(tok::l_brace)) {
2818 Diag(Tok, diag::err_expected) << tok::l_brace;
2822 StmtResult Compound = ParseCompoundStatement();
2823 if (Compound.isInvalid())
2826 StmtResult DepResult = Actions.ActOnMSDependentExistsStmt(
Result.KeywordLoc,
2831 if (DepResult.isUsable())
2832 Stmts.push_back(DepResult.get());
2837 if (
Braces.consumeOpen()) {
2838 Diag(Tok, diag::err_expected) << tok::l_brace;
2842 switch (
Result.Behavior) {
2848 llvm_unreachable(
"Dependent case handled above");
2856 while (Tok.isNot(tok::r_brace)) {
2858 ParseStatementOrDeclaration(Stmts, ParsedStmtContext::Compound);
2860 Stmts.push_back(
R.get());
This file defines the classes used to store parsed information about declaration-specifiers and decla...
static void DiagnoseLabelFollowedByDecl(Parser &P, const Stmt *SubStmt)
Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...
This file declares facilities that support code completion.
This file declares semantic analysis for Objective-C.
This file declares semantic analysis for OpenACC constructs and clauses.
This file declares semantic analysis for OpenMP constructs and clauses.
Defines the clang::TokenKind enum and support functions.
Represents a C++26 expansion statement declaration.
void setExpansionPattern(CXXExpansionStmtPattern *S)
SourceLocation getEndLoc() const
SourceLocation getBeginLoc() const
Base class for callback objects used by Sema::CorrectTypo to check the validity of a potential typo c...
virtual bool ValidateCandidate(const TypoCorrection &candidate)
Simple predicate used by the default RankCandidate to determine whether to return an edit distance of...
bool hasConstexprSpecifier() const
Decl - This represents one declaration (or definition), e.g.
DiagnosticOptions & getDiagnosticOptions() const
Retrieve the diagnostic options.
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
This represents one expression.
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
static FixItHint CreateRemoval(CharSourceRange RemoveRange)
Create a code modification hint that removes the given source range.
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
IdentifierInfo * getIdentifierInfo() const
Represents the declaration of a label.
@ FEM_Source
Use the declared type for fp arithmetic.
ParsedAttributes - A collection of parsed attributes.
void takeAllPrependingFrom(ParsedAttributes &Other)
void takeAllAppendingFrom(ParsedAttributes &Other)
ParseScope - Introduces a new scope for parsing.
Parser - This implements a parser for the C family of languages.
DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
SourceLocation getEndOfPreviousToken() const
DiagnosticBuilder DiagCompat(SourceLocation Loc, unsigned CompatDiagId)
Preprocessor & getPreprocessor() const
Sema::FullExprArg FullExprArg
SourceLocation ConsumeToken()
ConsumeToken - Consume the current 'peek token' and lex the next one.
Sema & getActions() const
ExprResult ParseCaseExpression(SourceLocation CaseLoc)
SmallVector< Stmt *, 24 > StmtVector
A SmallVector of statements.
friend class ColonProtectionRAIIObject
SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok=false)
ConsumeAnyToken - Dispatch to the right Consume* method based on the current token type.
StmtResult ParseOpenACCDirectiveStmt()
bool TryConsumeToken(tok::TokenKind Expected)
OpaquePtr< DeclGroupRef > DeclGroupPtrTy
Scope * getCurScope() const
friend class InMessageExpressionRAIIObject
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 ...
void SkipMalformedDecl()
SkipMalformedDecl - Read tokens until we get to some likely good stopping point for skipping past a s...
const Token & getCurToken() const
SourceLocation MisleadingIndentationElseLoc
The location of the first statement inside an else that might have a missleading indentation.
const LangOptions & getLangOpts() const
friend class ParenBraceBracketBalancer
ExprResult ParseExpression(TypoCorrectionTypeBehavior CorrectionBehavior=TypoCorrectionTypeBehavior::AllowNonTypes)
Simple precedence-based parser for binary/ternary operators.
@ StopBeforeMatch
Stop skipping at specified token, but don't skip the token itself.
@ StopAtCodeCompletion
Stop at code completion.
@ StopAtSemi
Stop skipping at semicolon.
const Token & NextToken()
NextToken - This peeks ahead one token and returns it without consuming it.
friend class BalancedDelimiterTracker
A class for parsing a DeclSpec.
unsigned getNumDirectives() const
Retrieve the number of Directives that have been processed by the Preprocessor.
const Token & LookAhead(unsigned N)
Peeks ahead N tokens and returns that token without consuming any tokens.
SourceManager & getSourceManager() const
void EnterSwitchBody(LabelDecl *PrecedingLabel)
Mark that we're entering the body of a switch statement.
void LeaveLoopBody()
Mark that we're leaving the body of a loop; this is only needed for do loops where the condition foll...
void decrementMSManglingNumber()
void EnterLoopBody(LabelDecl *PrecedingLabel)
Mark that we're entering the body of a loop (for, while, do).
@ SEHTryScope
This scope corresponds to an SEH try.
@ ControlScope
The controlling scope in a if/switch/while/for statement.
@ ExpansionStmtScope
This is the scope of a C++26 expansion statement.
@ TemplateParamScope
This is a scope that corresponds to the template parameters of a C++ template.
@ SEHFilterScope
We are currently in the filter expression of an SEH except block.
@ SwitchScope
This is a scope that corresponds to a switch statement.
@ CatchScope
This is the scope of a C++ catch statement.
@ CompoundStmtScope
This is a compound statement scope.
@ FnTryCatchScope
This is the scope for a function-level C++ try or catch scope.
@ SEHExceptScope
This scope corresponds to an SEH except.
@ TryScope
This is the scope of a C++ try statement.
@ DeclScope
This is a scope that can contain a declaration.
@ PCC_ForInit
Code completion occurs at the beginning of the initialization statement (or expression) in a for loop...
@ PCC_Expression
Code completion occurs within an expression.
@ PCC_Statement
Code completion occurs within a statement, which may also be an expression or a declaration.
void ActOnWhileStmt(SourceLocation WhileLoc)
void ActOnDoStmt(SourceLocation DoLoc)
void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor, const Stmt *RangeFor)
void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body)
void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First, const Stmt *Second, const Stmt *Third)
std::pair< VarDecl *, Expr * > get() const
std::optional< bool > getKnownValue() const
@ Boolean
A boolean condition, from 'if', 'while', 'for', or 'do'.
@ Switch
An integral condition for a 'switch' statement.
@ ConstexprIf
A constant boolean condition from 'if constexpr'.
DiagnosticsEngine & getDiagnostics() const
ExpressionEvaluationContext
Describes how the expressions currently being parsed are evaluated at run-time, if at all.
@ DiscardedStatement
The current expression occurs within a discarded statement.
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
@ ImmediateFunctionContext
In addition of being constant evaluated, the current expression occurs in an immediate function conte...
@ BFRK_Build
Initial building of a for-range statement.
static ConditionResult ConditionError()
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
FileIDAndOffset getDecomposedLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
DiagnosticsEngine & getDiagnostics() const
StringRef getBufferData(FileID FID, bool *Invalid=nullptr) const
Return a StringRef to the source buffer data for the specified FileID.
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
void setBegin(SourceLocation b)
SourceLocation getBegin() const
Stmt - This represents one statement.
SourceLocation getBeginLoc() const LLVM_READONLY
IdentifierInfo * getIdentifierInfo() 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)) {....
bool isAtStartOfLine() const
isAtStartOfLine - Return true if this token is at the start of a line.
bool isOneOf(Ts... Ks) const
bool isNot(tok::TokenKind K) const
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
void setAnnotationValue(void *val)
DeclClass * getCorrectionDeclAs() const
NestedNameSpecifier getCorrectionSpecifier() const
Gets the NestedNameSpecifier needed to use the typo correction.
Defines the clang::TargetInfo interface.
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
IfStatementKind
In an if statement, this denotes whether the statement is a constexpr or consteval if statement.
llvm::PointerUnion< Expr *, IdentifierLoc * > ArgsUnion
A union of the various pointer types that can be passed to an ParsedAttr as an argument.
@ Error
Annotation has failed and emitted an error.
std::pair< FileID, unsigned > FileIDAndOffset
@ Dependent
Parse the block as a dependent block, which may be used in some template instantiations but not other...
@ Skip
Skip the block entirely; this code is never used.
@ Parse
Parse the block; this code is always used.
@ Result
The result type of a method or function.
const FunctionProtoType * T
void takeAndConcatenateAttrs(ParsedAttributes &First, ParsedAttributes &&Second)
Consumes the attributes from Second and concatenates them at the end of First.
U cast(CodeGen::Address addr)
SmallVector< Token, 4 > CachedTokens
A set of tokens that has been cached for later parsing.
ActionResult< Expr * > ExprResult
@ Braces
New-expression has a C++11 list-initializer.
ActionResult< Stmt * > StmtResult
IdentifierLoc * OptionLoc
IdentifierLoc * PragmaNameLoc