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;
588 if (Tok.is(tok::eof) &&
getLangOpts().IncrementalExtensions &&
593 ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
596 if (CurTok && !
R.isInvalid())
603 assert(Tok.is(tok::kw___try) &&
"Expected '__try'");
606 if (Tok.isNot(tok::l_brace))
607 return StmtError(
Diag(Tok, diag::err_expected) << tok::l_brace);
612 if (TryBlock.isInvalid())
616 if (isTokenSEHExcept()) {
618 Handler = ParseSEHExceptBlock(Loc);
619 }
else if (Tok.is(tok::kw___finally)) {
621 Handler = ParseSEHFinallyBlock(Loc);
626 if(Handler.isInvalid())
629 return Actions.ActOnSEHTryBlock(
false ,
636 PoisonIdentifierRAIIObject raii(Ident__exception_code,
false),
637 raii2(Ident___exception_code,
false),
638 raii3(Ident_GetExceptionCode,
false);
640 if (ExpectAndConsume(tok::l_paren))
647 Ident__exception_info->setIsPoisoned(
false);
648 Ident___exception_info->setIsPoisoned(
false);
649 Ident_GetExceptionInfo->setIsPoisoned(
false);
654 ParseScopeFlags FilterScope(
this,
getCurScope()->getFlags() |
660 Ident__exception_info->setIsPoisoned(
true);
661 Ident___exception_info->setIsPoisoned(
true);
662 Ident_GetExceptionInfo->setIsPoisoned(
true);
668 if (ExpectAndConsume(tok::r_paren))
671 if (Tok.isNot(tok::l_brace))
672 return StmtError(
Diag(Tok, diag::err_expected) << tok::l_brace);
676 if(
Block.isInvalid())
679 return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.
get(),
Block.get());
683 PoisonIdentifierRAIIObject raii(Ident__abnormal_termination,
false),
684 raii2(Ident___abnormal_termination,
false),
685 raii3(Ident_AbnormalTermination,
false);
687 if (Tok.isNot(tok::l_brace))
688 return StmtError(
Diag(Tok, diag::err_expected) << tok::l_brace);
691 Actions.ActOnStartSEHFinallyBlock();
694 if(
Block.isInvalid()) {
695 Actions.ActOnAbortSEHFinallyBlock();
699 return Actions.ActOnFinishSEHFinallyBlock(FinallyLoc,
Block.get());
709 return Actions.ActOnSEHLeaveStmt(LeaveLoc,
getCurScope());
718 diag_compat::label_followed_by_declaration);
723 ParsedStmtContext StmtCtx) {
724 assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
725 "Not an identifier!");
730 StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
732 Token IdentTok = Tok;
735 assert(Tok.is(tok::colon) &&
"Not a label!");
740 LabelDecl *LD = Actions.LookupOrCreateLabel(
746 if (Tok.is(tok::kw___attribute)) {
747 ParsedAttributes TempAttrs(AttrFactory);
748 ParseGNUAttributes(TempAttrs);
761 ParsedAttributes EmptyCXX11Attrs(AttrFactory);
762 SubStmt = ParseStatementOrDeclarationAfterAttributes(
763 Stmts, StmtCtx,
nullptr, EmptyCXX11Attrs,
765 if (!TempAttrs.empty() && !SubStmt.isInvalid())
766 SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get());
771 if (SubStmt.isUnset() && Tok.is(tok::r_brace)) {
772 DiagnoseLabelAtEndOfCompoundStatement();
773 SubStmt = Actions.ActOnNullStmt(ColonLoc);
777 if (SubStmt.isUnset())
778 SubStmt = ParseStatement(
nullptr, StmtCtx, LD);
781 if (SubStmt.isInvalid())
782 SubStmt = Actions.ActOnNullStmt(ColonLoc);
790 return SubStmt.get();
793 Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
796 return Actions.ActOnLabelStmt(IdentTok.
getLocation(), LD, ColonLoc,
800StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
802 assert((MissingCase || Tok.is(tok::kw_case)) &&
"Not a case stmt!");
807 StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
830 Stmt *DeepestParsedCaseStmt =
nullptr;
833 SourceLocation ColonLoc;
835 SourceLocation CaseLoc = MissingCase ? Expr.
get()->
getExprLoc() :
837 ColonLoc = SourceLocation();
839 if (Tok.is(tok::code_completion)) {
841 Actions.CodeCompletion().CodeCompleteCase(
getCurScope());
860 LHS = Actions.ActOnCaseExpr(CaseLoc, Expr);
865 SourceLocation DotDotDotLoc;
871 DiagId = diag::ext_gnu_case_range;
873 DiagId = diag::warn_c23_compat_case_range;
875 DiagId = diag::ext_c2y_case_range;
876 Diag(DotDotDotLoc, DiagId);
884 ColonProtection.restore();
890 Diag(ColonLoc, diag::err_expected_after)
891 <<
"'case'" << tok::colon
896 Diag(ExpectedLoc, diag::err_expected_after)
897 <<
"'case'" << tok::colon
900 ColonLoc = ExpectedLoc;
904 Actions.ActOnCaseStmt(CaseLoc, LHS, DotDotDotLoc, RHS, ColonLoc);
908 if (Case.isInvalid()) {
909 if (TopLevelCase.isInvalid())
910 return ParseStatement(
nullptr, StmtCtx);
915 Stmt *NextDeepest = Case.get();
916 if (TopLevelCase.isInvalid())
919 Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, Case.get());
920 DeepestParsedCaseStmt = NextDeepest;
924 }
while (Tok.is(tok::kw_case));
929 if (Tok.is(tok::r_brace)) {
932 DiagnoseLabelAtEndOfCompoundStatement();
933 SubStmt = Actions.ActOnNullStmt(ColonLoc);
935 SubStmt = ParseStatement(
nullptr, StmtCtx);
939 if (DeepestParsedCaseStmt) {
941 if (SubStmt.isInvalid())
942 SubStmt = Actions.ActOnNullStmt(SourceLocation());
944 Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
951StmtResult Parser::ParseDefaultStatement(ParsedStmtContext StmtCtx) {
952 assert(Tok.is(tok::kw_default) &&
"Not a default stmt!");
957 StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
961 SourceLocation ColonLoc;
965 Diag(ColonLoc, diag::err_expected_after)
966 <<
"'default'" << tok::colon
969 SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
970 Diag(ExpectedLoc, diag::err_expected_after)
971 <<
"'default'" << tok::colon
973 ColonLoc = ExpectedLoc;
978 if (Tok.is(tok::r_brace)) {
981 DiagnoseLabelAtEndOfCompoundStatement();
982 SubStmt = Actions.ActOnNullStmt(ColonLoc);
984 SubStmt = ParseStatement(
nullptr, StmtCtx);
988 if (SubStmt.isInvalid())
989 SubStmt = Actions.ActOnNullStmt(ColonLoc);
992 return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
996StmtResult Parser::ParseCompoundStatement(
bool isStmtExpr) {
997 return ParseCompoundStatement(isStmtExpr,
1001StmtResult Parser::ParseCompoundStatement(
bool isStmtExpr,
1002 unsigned ScopeFlags) {
1003 assert(Tok.is(tok::l_brace) &&
"Not a compound stmt!");
1011 StackHandler.runWithSufficientStackSpace(Tok.getLocation(), [&,
this]() {
1012 R = ParseCompoundStatementBody(isStmtExpr);
1017void Parser::ParseCompoundStatementLeadingPragmas() {
1018 bool checkForPragmas =
true;
1019 while (checkForPragmas) {
1020 switch (Tok.getKind()) {
1021 case tok::annot_pragma_vis:
1022 HandlePragmaVisibility();
1024 case tok::annot_pragma_pack:
1027 case tok::annot_pragma_msstruct:
1028 HandlePragmaMSStruct();
1030 case tok::annot_pragma_align:
1031 HandlePragmaAlign();
1033 case tok::annot_pragma_weak:
1036 case tok::annot_pragma_weakalias:
1037 HandlePragmaWeakAlias();
1039 case tok::annot_pragma_redefine_extname:
1040 HandlePragmaRedefineExtname();
1042 case tok::annot_pragma_opencl_extension:
1043 HandlePragmaOpenCLExtension();
1045 case tok::annot_pragma_fp_contract:
1046 HandlePragmaFPContract();
1048 case tok::annot_pragma_fp:
1051 case tok::annot_pragma_fenv_access:
1052 case tok::annot_pragma_fenv_access_ms:
1053 HandlePragmaFEnvAccess();
1055 case tok::annot_pragma_fenv_round:
1056 HandlePragmaFEnvRound();
1058 case tok::annot_pragma_cx_limited_range:
1059 HandlePragmaCXLimitedRange();
1061 case tok::annot_pragma_float_control:
1062 HandlePragmaFloatControl();
1064 case tok::annot_pragma_ms_pointers_to_members:
1065 HandlePragmaMSPointersToMembers();
1067 case tok::annot_pragma_ms_pragma:
1068 HandlePragmaMSPragma();
1070 case tok::annot_pragma_ms_vtordisp:
1071 HandlePragmaMSVtorDisp();
1073 case tok::annot_pragma_dump:
1076 case tok::annot_pragma_export:
1077 HandlePragmaExport();
1080 checkForPragmas =
false;
1087void Parser::DiagnoseLabelAtEndOfCompoundStatement() {
1089 ? diag_compat::cxx_label_at_end_of_compound_statement
1090 : diag_compat::c_label_at_end_of_compound_statement);
1093bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
1094 if (!Tok.is(tok::semi))
1097 SourceLocation StartLoc = Tok.getLocation();
1098 SourceLocation EndLoc;
1100 while (Tok.is(tok::semi) && !Tok.hasLeadingEmptyMacro() &&
1101 Tok.getLocation().isValid() && !Tok.getLocation().isMacroID()) {
1102 EndLoc = Tok.getLocation();
1106 ParseStatementOrDeclaration(Stmts, ParsedStmtContext::SubStmt);
1108 Stmts.push_back(
R.get());
1115 Diag(StartLoc, diag::warn_null_statement)
1121 bool IsStmtExprResult =
false;
1122 if ((StmtCtx & ParsedStmtContext::InStmtExpr) != ParsedStmtContext()) {
1126 IsStmtExprResult = Tok.is(tok::r_brace) &&
NextToken().
is(tok::r_paren);
1129 if (IsStmtExprResult)
1130 E = Actions.ActOnStmtExprResult(E);
1131 return Actions.ActOnExprStmt(E, !IsStmtExprResult);
1134StmtResult Parser::ParseCompoundStatementBody(
bool isStmtExpr) {
1135 PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
1137 "in compound statement ('{}')");
1141 Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
1145 if (
T.consumeOpen())
1148 Sema::CompoundScopeRAII CompoundScope(Actions, isStmtExpr);
1151 ParseCompoundStatementLeadingPragmas();
1152 Actions.ActOnAfterCompoundStatementLeadingPragmas();
1158 while (Tok.is(tok::kw___label__)) {
1161 SmallVector<Decl *, 4> DeclsInGroup;
1163 if (Tok.isNot(tok::identifier)) {
1164 Diag(Tok, diag::err_expected) << tok::identifier;
1168 IdentifierInfo *II = Tok.getIdentifierInfo();
1170 DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc));
1176 DeclSpec DS(AttrFactory);
1178 Actions.FinalizeDeclaratorGroup(
getCurScope(), DS, DeclsInGroup);
1179 StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation());
1181 ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
1183 Stmts.push_back(
R.get());
1186 ParsedStmtContext SubStmtCtx =
1187 ParsedStmtContext::Compound |
1188 (isStmtExpr ? ParsedStmtContext::InStmtExpr : ParsedStmtContext());
1190 bool LastIsError =
false;
1191 while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
1192 Tok.isNot(tok::eof)) {
1193 if (Tok.is(tok::annot_pragma_unused)) {
1194 HandlePragmaUnused();
1198 if (ConsumeNullStmt(Stmts))
1202 if (Tok.isNot(tok::kw___extension__)) {
1203 R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
1210 while (Tok.is(tok::kw___extension__))
1213 ParsedAttributes attrs(AttrFactory);
1214 MaybeParseCXX11Attributes(attrs,
true);
1217 if (isDeclarationStatement()) {
1220 ExtensionRAIIObject O(Diags);
1222 SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
1223 ParsedAttributes DeclSpecAttrs(AttrFactory);
1225 attrs, DeclSpecAttrs);
1226 R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
1229 ExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
1231 if (Res.isInvalid()) {
1238 ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
1239 R = handleExprStmt(Res, SubStmtCtx);
1241 R = Actions.ActOnAttributedStmt(attrs,
R.get());
1246 Stmts.push_back(
R.get());
1247 LastIsError =
R.isInvalid();
1253 if (isStmtExpr && LastIsError && !Stmts.empty())
1260 if (!PP.getTargetInfo().supportSourceEvalMethod() &&
1261 (PP.getLastFPEvalPragmaLocation().isValid() ||
1262 PP.getCurrentFPEvalMethod() ==
1264 Diag(Tok.getLocation(),
1265 diag::warn_no_support_for_eval_method_source_on_m32);
1267 SourceLocation CloseLoc = Tok.getLocation();
1270 if (!
T.consumeClose()) {
1273 if (isStmtExpr && Tok.is(tok::r_paren))
1274 checkCompoundToken(CloseLoc, tok::r_brace, CompoundToken::StmtExprEnd);
1280 if (
T.getCloseLocation().isValid())
1281 CloseLoc =
T.getCloseLocation();
1283 return Actions.ActOnCompoundStmt(
T.getOpenLocation(), CloseLoc,
1287bool Parser::ParseParenExprOrCondition(
StmtResult *InitStmt,
1295 SourceLocation Start = Tok.getLocation();
1297 Cond = ParseCondition(InitStmt, Loc, CK,
false);
1302 if (Cond.
isInvalid() && Tok.isNot(tok::r_paren)) {
1306 if (Tok.isNot(tok::r_paren))
1311 ExprResult CondExpr = Actions.CreateRecoveryExpr(
1312 Start, Tok.getLocation() == Start ? Start : PrevTokLocation, {},
1313 Actions.PreferredConditionType(CK));
1315 Cond = Actions.ActOnCondition(
getCurScope(), Loc, CondExpr.
get(), CK,
1320 bool HasInitStmt = InitStmt !=
nullptr && InitStmt->isUsable();
1327 Diag(InitStmt->get()->getBeginLoc(),
1328 diag::err_c2y_first_condition_clause_is_not_declaration)
1329 << InitStmt->get()->getSourceRange();
1331 if (Decl *CondDecl = Cond.
get().first; CondDecl && InitStmt !=
nullptr) {
1337 Diag(CondDecl->getBeginLoc(), diag::err_expected_expression)
1338 << CondDecl->getSourceRange();
1341 DiagCompat(CondDecl->getBeginLoc(), diag_compat::decl_statement)
1346 if (Tok.is(tok::comma)) {
1347 Diag(Tok, diag::err_c2y_multiple_declarations);
1349 while (Tok.isNot(tok::r_paren) && !Tok.is(tok::eof))
1354 LParenLoc =
T.getOpenLocation();
1355 RParenLoc =
T.getCloseLocation();
1360 while (Tok.is(tok::r_paren)) {
1361 Diag(Tok, diag::err_extraneous_rparen_in_condition)
1371enum MisleadingStatementKind { MSK_if, MSK_else, MSK_for, MSK_while };
1373struct MisleadingIndentationChecker {
1375 SourceLocation StmtLoc;
1376 SourceLocation PrevLoc;
1377 unsigned NumDirectives;
1378 MisleadingStatementKind
Kind;
1380 MisleadingIndentationChecker(Parser &P, MisleadingStatementKind K,
1382 : P(P), StmtLoc(SL), PrevLoc(P.getCurToken().getLocation()),
1383 NumDirectives(P.getPreprocessor().getNumDirectives()),
Kind(K),
1384 ShouldSkip(P.getCurToken().
is(tok::l_brace)) {
1386 StmtLoc = P.MisleadingIndentationElseLoc;
1387 P.MisleadingIndentationElseLoc = SourceLocation();
1389 if (Kind == MSK_else && !ShouldSkip)
1395 static unsigned getVisualIndentation(SourceManager &SM, SourceLocation Loc) {
1399 if (ColNo == 0 || TabStop == 1)
1409 const char *EndPos = BufData.data() + FIDAndOffset.second;
1411 assert(FIDAndOffset.second + 1 >= ColNo &&
1412 "Column number smaller than file offset?");
1414 unsigned VisualColumn = 0;
1417 for (
const char *CurPos = EndPos - (ColNo - 1); CurPos != EndPos;
1419 if (*CurPos ==
'\t')
1421 VisualColumn += (TabStop - VisualColumn % TabStop);
1425 return VisualColumn + 1;
1440 if (Kind == MSK_else)
1444 unsigned PrevColNum = getVisualIndentation(SM, PrevLoc);
1445 unsigned CurColNum = getVisualIndentation(SM,
Tok.
getLocation());
1446 unsigned StmtColNum = getVisualIndentation(SM, StmtLoc);
1448 if (PrevColNum != 0 && CurColNum != 0 && StmtColNum != 0 &&
1449 ((PrevColNum > StmtColNum && PrevColNum == CurColNum) ||
1456 P.
Diag(StmtLoc, diag::note_previous_statement);
1464 assert(Tok.is(tok::kw_if) &&
"Not an if stmt!");
1467 bool IsConstexpr =
false;
1468 bool IsConsteval =
false;
1469 SourceLocation NotLocation;
1470 SourceLocation ConstevalLoc;
1472 if (Tok.is(tok::kw_constexpr)) {
1480 if (Tok.is(tok::exclaim)) {
1484 if (Tok.is(tok::kw_consteval)) {
1488 }
else if (Tok.is(tok::code_completion)) {
1490 Actions.CodeCompletion().CodeCompleteKeywordAfterIf(
1495 if (!IsConsteval && (NotLocation.
isValid() || Tok.isNot(tok::l_paren))) {
1496 Diag(Tok, diag::err_expected_lparen_after) <<
"if";
1519 Sema::ConditionResult Cond;
1520 SourceLocation LParen;
1521 SourceLocation RParen;
1522 std::optional<bool> ConstexprCondition;
1525 if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc,
1535 bool IsBracedThen = Tok.is(tok::l_brace);
1557 MisleadingIndentationChecker MIChecker(*
this, MSK_if, IfLoc);
1560 SourceLocation ThenStmtLoc = Tok.getLocation();
1562 SourceLocation InnerStatementTrailingElseLoc;
1565 bool ShouldEnter = ConstexprCondition && !*ConstexprCondition;
1568 if (NotLocation.
isInvalid() && IsConsteval) {
1573 EnterExpressionEvaluationContext PotentiallyDiscarded(
1574 Actions, Context,
nullptr,
1576 ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
1579 if (Tok.isNot(tok::kw_else))
1586 SourceLocation ElseLoc;
1587 SourceLocation ElseStmtLoc;
1590 if (Tok.is(tok::kw_else)) {
1591 if (TrailingElseLoc)
1592 *TrailingElseLoc = Tok.getLocation();
1595 ElseStmtLoc = Tok.getLocation();
1607 Tok.is(tok::l_brace));
1609 MisleadingIndentationChecker MIChecker(*
this, MSK_else, ElseLoc);
1610 bool ShouldEnter = ConstexprCondition && *ConstexprCondition;
1613 if (NotLocation.
isValid() && IsConsteval) {
1618 EnterExpressionEvaluationContext PotentiallyDiscarded(
1619 Actions, Context,
nullptr,
1621 ElseStmt = ParseStatement();
1623 if (ElseStmt.isUsable())
1628 }
else if (Tok.is(tok::code_completion)) {
1630 Actions.CodeCompletion().CodeCompleteAfterIf(
getCurScope(), IsBracedThen);
1632 }
else if (InnerStatementTrailingElseLoc.
isValid()) {
1633 Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else);
1641 if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
1642 (ThenStmt.isInvalid() && ElseStmt.get() ==
nullptr) ||
1643 (ThenStmt.get() ==
nullptr && ElseStmt.isInvalid())) {
1649 auto IsCompoundStatement = [](
const Stmt *S) {
1650 if (
const auto *Outer = dyn_cast_if_present<AttributedStmt>(S))
1651 S = Outer->getSubStmt();
1652 return isa_and_nonnull<clang::CompoundStmt>(S);
1655 if (!IsCompoundStatement(ThenStmt.get())) {
1656 Diag(ConstevalLoc, diag::err_expected_after) <<
"consteval"
1660 if (!ElseStmt.isUnset() && !IsCompoundStatement(ElseStmt.get())) {
1661 Diag(ElseLoc, diag::err_expected_after) <<
"else"
1668 if (ThenStmt.isInvalid())
1669 ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
1670 if (ElseStmt.isInvalid())
1671 ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
1676 else if (IsConsteval)
1680 return Actions.ActOnIfStmt(IfLoc, Kind, LParen, InitStmt.get(), Cond, RParen,
1681 ThenStmt.get(), ElseLoc, ElseStmt.get());
1686 assert(Tok.is(tok::kw_switch) &&
"Not a switch stmt!");
1689 if (Tok.isNot(tok::l_paren)) {
1690 Diag(Tok, diag::err_expected_lparen_after) <<
"switch";
1716 Sema::ConditionResult Cond;
1717 SourceLocation LParen;
1718 SourceLocation RParen;
1719 if (ParseParenExprOrCondition(&InitStmt, Cond, SwitchLoc,
1724 SwitchLoc, LParen, InitStmt.get(), Cond, RParen);
1726 if (
Switch.isInvalid()) {
1731 if (Tok.is(tok::l_brace)) {
1759 StmtResult Body(ParseStatement(TrailingElseLoc));
1765 return Actions.ActOnFinishSwitchStmt(SwitchLoc,
Switch.get(), Body.get());
1770 assert(Tok.is(tok::kw_while) &&
"Not a while stmt!");
1771 SourceLocation WhileLoc = Tok.getLocation();
1774 if (Tok.isNot(tok::l_paren)) {
1775 Diag(Tok, diag::err_expected_lparen_after) <<
"while";
1794 unsigned ScopeFlags =
1799 Sema::ConditionResult Cond;
1800 SourceLocation LParen;
1801 SourceLocation RParen;
1802 if (ParseParenExprOrCondition(
nullptr, Cond, WhileLoc,
1825 MisleadingIndentationChecker MIChecker(*
this, MSK_while, WhileLoc);
1828 StmtResult Body(ParseStatement(TrailingElseLoc));
1830 if (Body.isUsable())
1836 if (Cond.
isInvalid() || Body.isInvalid())
1839 return Actions.ActOnWhileStmt(WhileLoc, LParen, Cond, RParen, Body.get());
1843 assert(Tok.is(tok::kw_do) &&
"Not a do stmt!");
1877 if (Tok.isNot(tok::kw_while)) {
1878 if (!Body.isInvalid()) {
1879 Diag(Tok, diag::err_expected_while);
1880 Diag(DoLoc, diag::note_matching) <<
"'do'";
1887 if (Tok.isNot(tok::l_paren)) {
1888 Diag(Tok, diag::err_expected_lparen_after) <<
"do/while";
1898 DiagnoseAndSkipCXX11Attributes();
1900 SourceLocation Start = Tok.getLocation();
1903 if (!Tok.isOneOf(tok::r_paren, tok::r_square, tok::r_brace))
1905 Cond = Actions.CreateRecoveryExpr(
1906 Start, Start == Tok.getLocation() ? Start : PrevTokLocation, {},
1907 Actions.getASTContext().BoolTy);
1912 if (Cond.
isInvalid() || Body.isInvalid())
1915 return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc,
T.getOpenLocation(),
1916 Cond.
get(),
T.getCloseLocation());
1919bool Parser::isForRangeIdentifier() {
1920 assert(Tok.is(tok::identifier));
1923 if (
Next.is(tok::colon))
1926 if (
Next.isOneOf(tok::l_square, tok::kw_alignas)) {
1927 TentativeParsingAction PA(*
this);
1929 SkipCXX11Attributes();
1930 bool Result = Tok.is(tok::colon);
1938void Parser::ParseForRangeInitializerAfterColon(ForRangeInit &FRI,
1946 EnterExpressionEvaluationContext InitContext(
1954 auto &LastRecord = Actions.currentEvaluationContext();
1955 LastRecord.InLifetimeExtendingContext =
true;
1956 LastRecord.RebuildDefaultArgOrDefaultInit =
true;
1959 if (FRI.ExpansionStmt) {
1962 assert(Actions.CurContext->isExpansionStmt());
1963 Sema::ContextRAII CtxGuard(Actions, Actions.CurContext->getParent(),
1967 FRI.RangeExpr = Actions.MaybeCreateExprWithCleanups(FRI.RangeExpr);
1968 }
else if (Tok.is(tok::l_brace)) {
1969 FRI.RangeExpr = ParseBraceInitializer();
1976 Actions.ExprEvalContexts.back().ForRangeLifetimeExtendTemps.empty());
1980 FRI.LifetimeExtendTemps =
1981 std::move(Actions.ExprEvalContexts.back().ForRangeLifetimeExtendTemps);
1987 assert(Tok.is(tok::kw_for) &&
"Not a for stmt!");
1990 SourceLocation CoawaitLoc;
1991 if (Tok.is(tok::kw_co_await))
1994 if (Tok.isNot(tok::l_paren)) {
1995 Diag(Tok, diag::err_expected_lparen_after) <<
"for";
2032 bool ForEach =
false;
2034 Sema::ConditionResult SecondPart;
2036 ForRangeInfo ForRangeInfo;
2038 ForRangeInfo.ExpansionStmt = ESD;
2045 struct [[nodiscard]] ExpansionStmtContextRAII : Sema::ContextRAII {
2046 ExpansionStmtContextRAII(Sema &S,
struct ForRangeInfo &Info,
2048 : ContextRAII(S, Info.ExpansionStmt ? Ctx : S.CurContext,
2052 assert(!ESD || Actions.CurContext->isExpansionStmt());
2053 if (Tok.is(tok::code_completion)) {
2055 Actions.CodeCompletion().CodeCompleteOrdinaryName(
2061 ParsedAttributes attrs(AttrFactory);
2062 MaybeParseCXX11Attributes(attrs);
2064 SourceLocation EmptyInitStmtSemiLoc;
2067 if (Tok.is(tok::semi)) {
2068 ProhibitAttributes(attrs);
2070 SourceLocation SemiLoc = Tok.getLocation();
2071 if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.
isMacroID())
2072 EmptyInitStmtSemiLoc = SemiLoc;
2075 isForRangeIdentifier()) {
2079 ProhibitAttributes(attrs);
2080 IdentifierInfo *Name = Tok.getIdentifierInfo();
2082 MaybeParseCXX11Attributes(attrs);
2085 ParseForRangeInitializerAfterColon(ForRangeInfo,
nullptr);
2087 Diag(Loc, diag::err_for_range_identifier)
2088 << (ForRangeInfo.ExpansionStmt !=
nullptr)
2093 if (!ForRangeInfo.ExpansionStmt)
2094 ForRangeInfo.LoopVar =
2095 Actions.ActOnCXXForRangeIdentifier(
getCurScope(), Loc, Name, attrs);
2096 }
else if (isForInitDeclaration()) {
2098 ExpansionStmtContextRAII EnterParentContext{
2099 Actions, ForRangeInfo, Actions.CurContext->getParent()};
2102 if (!C99orCXXorObjC) {
2103 Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
2104 Diag(Tok, diag::warn_gcc_variable_decl_in_for_loop);
2107 SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
2109 Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
2110 ProhibitAttributes(attrs);
2111 Decl *D = ParseStaticAssertDeclaration(DeclEnd);
2112 DG = Actions.ConvertDeclToDeclGroup(D);
2113 FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
2114 }
else if (Tok.is(tok::kw_using)) {
2117 FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
2122 ParsedAttributes DeclSpecAttrs(AttrFactory);
2123 DG = ParseSimpleDeclaration(
2125 MightBeForRangeStmt ? &ForRangeInfo :
nullptr);
2126 FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
2127 if (ForRangeInfo.ParsedForRangeDecl()) {
2128 DiagCompat(ForRangeInfo.ColonLoc, diag_compat::for_range);
2129 ForRangeInfo.LoopVar = FirstPart;
2131 }
else if (Tok.is(tok::semi)) {
2133 }
else if ((ForEach = isTokIdentifier_in())) {
2134 Actions.ActOnForEachDeclStmt(DG);
2138 if (Tok.is(tok::code_completion)) {
2140 Actions.CodeCompletion().CodeCompleteObjCForCollection(
getCurScope(),
2146 Diag(Tok, diag::err_expected_semi_for);
2151 ExpansionStmtContextRAII EnterParentContext{
2152 Actions, ForRangeInfo, Actions.CurContext->getParent()};
2153 ProhibitAttributes(attrs);
2156 ForEach = isTokIdentifier_in();
2159 if (!
Value.isInvalid()) {
2161 FirstPart = Actions.ActOnForEachLValueExpr(
Value.get());
2168 bool IsRangeBasedFor =
2169 getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon);
2170 FirstPart = Actions.ActOnExprStmt(
Value, !IsRangeBasedFor);
2174 if (Tok.is(tok::semi)) {
2176 }
else if (ForEach) {
2179 if (Tok.is(tok::code_completion)) {
2181 Actions.CodeCompletion().CodeCompleteObjCForCollection(
getCurScope(),
2189 Diag(Tok, diag::err_for_range_expected_decl)
2190 << (ESD !=
nullptr) << FirstPart.get()->getSourceRange();
2194 if (!
Value.isInvalid()) {
2195 Diag(Tok, diag::err_expected_semi_for);
2199 if (Tok.is(tok::semi))
2206 if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() &&
2209 if (Tok.is(tok::semi)) {
2211 }
else if (Tok.is(tok::r_paren)) {
2217 bool MightBeForRangeStmt = !ForRangeInfo.ParsedForRangeDecl();
2219 SourceLocation SecondPartStart = Tok.getLocation();
2221 SecondPart = ParseCondition(
2222 nullptr, ForLoc, CK,
2224 true, MightBeForRangeStmt ? &ForRangeInfo :
nullptr);
2226 if (ForRangeInfo.ParsedForRangeDecl()) {
2227 DiagCompat(FirstPart.get() ? FirstPart.get()->getBeginLoc()
2228 : ForRangeInfo.ColonLoc,
2229 diag_compat::for_range_init_stmt)
2230 << (FirstPart.get() ? FirstPart.get()->getSourceRange()
2232 if (EmptyInitStmtSemiLoc.
isValid()) {
2233 Diag(EmptyInitStmtSemiLoc, diag::warn_empty_init_statement)
2240 ExprResult CondExpr = Actions.CreateRecoveryExpr(
2242 Tok.getLocation() == SecondPartStart ? SecondPartStart
2244 {}, Actions.PreferredConditionType(CK));
2246 SecondPart = Actions.ActOnCondition(
getCurScope(), ForLoc,
2256 SecondPart = Actions.ActOnCondition(
2264 if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) {
2265 if (Tok.isNot(tok::semi)) {
2267 Diag(Tok, diag::err_expected_semi_for);
2271 if (Tok.is(tok::semi)) {
2275 if (Tok.isNot(tok::r_paren)) {
2279 ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.
get());
2287 if (CoawaitLoc.
isValid() && !ForRangeInfo.ParsedForRangeDecl()) {
2288 Diag(CoawaitLoc, diag::err_for_co_await_not_range_for);
2289 CoawaitLoc = SourceLocation();
2293 Diag(CoawaitLoc, diag::warn_deprecated_for_co_await);
2302 ForRangeStmt = Actions.ActOnCXXExpansionStmtPattern(
2303 ESD, FirstPart.get(), ForRangeInfo.LoopVar.get(),
2304 ForRangeInfo.RangeExpr.get(),
T.getOpenLocation(),
2305 ForRangeInfo.ColonLoc,
T.getCloseLocation(),
2306 ForRangeInfo.LifetimeExtendTemps);
2307 }
else if (ForRangeInfo.ParsedForRangeDecl()) {
2308 ForRangeStmt = Actions.ActOnCXXForRangeStmt(
2309 getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
2310 ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc,
2312 ForRangeInfo.LifetimeExtendTemps);
2313 }
else if (ForEach) {
2316 ForEachStmt = Actions.ObjC().ActOnObjCForCollectionStmt(
2317 ForLoc, FirstPart.get(), Collection.
get(),
T.getCloseLocation());
2321 if (
getLangOpts().OpenMP && FirstPart.isUsable()) {
2322 Actions.OpenMP().ActOnOpenMPLoopInitialization(ForLoc, FirstPart.get());
2331 else if (ForRangeInfo.ParsedForRangeDecl())
2335 ForLoc, FirstPart.get(), SecondPart.
get().second, ThirdPart.get());
2341 bool BodyStartsWithAttr = Tok.isOneOf(tok::l_square, tok::kw___attribute);
2342 SourceLocation BodyBeginLoc = Tok.getLocation();
2356 Tok.is(tok::l_brace));
2365 MisleadingIndentationChecker MIChecker(*
this, MSK_for, ForLoc);
2368 StmtResult Body(ParseStatement(TrailingElseLoc));
2370 if (Body.isUsable())
2381 if (Body.isInvalid())
2385 return Actions.ObjC().FinishObjCForCollectionStmt(ForEachStmt.get(),
2389 if (!ForRangeInfo.ParsedForRangeDecl()) {
2390 Diag(ForLoc, diag::err_expansion_stmt_requires_range);
2399 ? diag::ext_expansion_stmt_body_attr
2400 : diag::ext_expansion_stmt_body_not_compound_stmt);
2402 return Actions.FinishCXXExpansionStmt(ForRangeStmt.get(), Body.get());
2405 if (ForRangeInfo.ParsedForRangeDecl())
2406 return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
2408 return Actions.ActOnForStmt(ForLoc,
T.getOpenLocation(), FirstPart.get(),
2409 SecondPart, ThirdPart,
T.getCloseLocation(),
2414 assert(Tok.is(tok::kw_goto) &&
"Not a goto stmt!");
2418 if (Tok.is(tok::identifier)) {
2419 LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
2421 Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD);
2423 }
else if (Tok.is(tok::star)) {
2425 Diag(Tok, diag::ext_gnu_indirect_goto);
2428 if (
R.isInvalid()) {
2432 Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc,
R.get());
2434 Diag(Tok, diag::err_expected) << tok::identifier;
2441StmtResult Parser::ParseBreakOrContinueStatement(
bool IsContinue) {
2443 SourceLocation LabelLoc;
2444 LabelDecl *
Target =
nullptr;
2445 if (Tok.is(tok::identifier)) {
2447 Actions.LookupExistingLabel(Tok.getIdentifierInfo(), Tok.getLocation());
2452 Diag(LabelLoc, diag::err_c2y_labeled_break_continue) << IsContinue;
2454 Diag(LabelLoc, diag::err_break_continue_label_not_found) << IsContinue;
2465 return ParseBreakOrContinueStatement(
true);
2469 return ParseBreakOrContinueStatement(
false);
2473 assert((Tok.is(tok::kw_return) || Tok.is(tok::kw_co_return)) &&
2474 "Not a return stmt!");
2475 bool IsCoreturn = Tok.is(tok::kw_co_return);
2479 if (Tok.isNot(tok::semi)) {
2481 PreferredType.enterReturn(Actions, Tok.getLocation());
2483 if (Tok.is(tok::code_completion) && !IsCoreturn) {
2485 Actions.CodeCompletion().CodeCompleteExpression(
2486 getCurScope(), PreferredType.get(Tok.getLocation()));
2491 R = ParseInitializer();
2494 diag_compat::generalized_initializer_lists);
2497 if (
R.isInvalid()) {
2503 return Actions.ActOnCoreturnStmt(
getCurScope(), ReturnLoc,
R.get());
2504 return Actions.ActOnReturnStmt(ReturnLoc,
R.get(),
getCurScope());
2508 assert(Tok.is(tok::kw__Defer));
2511 Actions.ActOnStartOfDeferStmt(DeferLoc,
getCurScope());
2513 llvm::scope_exit OnError([&] { Actions.ActOnDeferStmtError(
getCurScope()); });
2515 StmtResult Res = ParseStatement(TrailingElseLoc);
2516 if (!Res.isUsable())
2520 if (
auto *L = dyn_cast<LabelStmt>(Res.get())) {
2521 Diag(L->getIdentLoc(), diag::err_defer_ts_labeled_stmt);
2526 return Actions.ActOnEndOfDeferStmt(Res.get(),
getCurScope());
2529StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
2530 ParsedStmtContext StmtCtx,
2535 ParsedAttributes TempAttrs(AttrFactory);
2537 SourceLocation StartLoc = Tok.getLocation();
2540 while (Tok.is(tok::annot_pragma_loop_hint)) {
2542 if (!HandlePragmaLoopHint(Hint))
2548 AttributeScopeInfo(), ArgHints, 4,
2549 ParsedAttr::Form::Pragma());
2553 MaybeParseCXX11Attributes(Attrs);
2555 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2556 StmtResult S = ParseStatementOrDeclarationAfterAttributes(
2557 Stmts, StmtCtx, TrailingElseLoc, Attrs, EmptyDeclSpecAttrs,
2570Decl *Parser::ParseFunctionStatementBody(
Decl *
Decl, ParseScope &BodyScope) {
2571 assert(Tok.is(tok::l_brace));
2572 SourceLocation LBraceLoc = Tok.getLocation();
2574 PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, LBraceLoc,
2575 "parsing function body");
2580 Sema::PragmaStackSentinelRAII
2581 PragmaStackSentinel(Actions,
"InternalPragmaState", IsCXXMethod);
2586 StmtResult FnBody(ParseCompoundStatementBody());
2589 if (FnBody.isInvalid()) {
2590 Sema::CompoundScopeRAII CompoundScope(Actions);
2591 FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, {},
false);
2595 return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
2598Decl *Parser::ParseFunctionTryBlock(
Decl *
Decl, ParseScope &BodyScope) {
2599 assert(Tok.is(tok::kw_try) &&
"Expected 'try'");
2602 PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, TryLoc,
2603 "parsing function try block");
2606 if (Tok.is(tok::colon))
2607 ParseConstructorInitializer(Decl);
2609 Actions.ActOnDefaultCtorInitializers(Decl);
2614 Sema::PragmaStackSentinelRAII
2615 PragmaStackSentinel(Actions,
"InternalPragmaState", IsCXXMethod);
2617 SourceLocation LBraceLoc = Tok.getLocation();
2618 StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc,
true));
2621 if (FnBody.isInvalid()) {
2622 Sema::CompoundScopeRAII CompoundScope(Actions);
2623 FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, {},
false);
2627 return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
2630bool Parser::trySkippingFunctionBody() {
2631 assert(SkipFunctionBodies &&
2632 "Should only be called when SkipFunctionBodies is enabled");
2633 if (!PP.isCodeCompletionEnabled()) {
2640 TentativeParsingAction PA(*
this);
2641 bool IsTryCatch = Tok.is(tok::kw_try);
2643 bool ErrorInPrologue = ConsumeAndStoreFunctionPrologue(Toks);
2644 if (llvm::any_of(Toks, [](
const Token &Tok) {
2645 return Tok.is(tok::code_completion);
2650 if (ErrorInPrologue) {
2659 while (IsTryCatch && Tok.is(tok::kw_catch)) {
2671 assert(Tok.is(tok::kw_try) &&
"Expected 'try'");
2674 return ParseCXXTryBlockCommon(TryLoc);
2678 if (Tok.isNot(tok::l_brace))
2679 return StmtError(
Diag(Tok, diag::err_expected) << tok::l_brace);
2685 if (TryBlock.isInvalid())
2690 if (isTokenSEHExcept() || Tok.is(tok::kw___finally)) {
2693 if (isTokenSEHExcept()) {
2695 Handler = ParseSEHExceptBlock(Loc);
2698 Handler = ParseSEHFinallyBlock(Loc);
2700 if(Handler.isInvalid())
2703 return Actions.ActOnSEHTryBlock(
true ,
2712 DiagnoseAndSkipCXX11Attributes();
2714 if (Tok.isNot(tok::kw_catch))
2716 while (Tok.is(tok::kw_catch)) {
2717 StmtResult Handler(ParseCXXCatchBlock(FnTry));
2718 if (!Handler.isInvalid())
2719 Handlers.push_back(Handler.get());
2723 if (Handlers.empty())
2726 return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.get(), Handlers);
2730StmtResult Parser::ParseCXXCatchBlock(
bool FnCatch) {
2731 assert(Tok.is(tok::kw_catch) &&
"Expected 'catch'");
2736 if (
T.expectAndConsume())
2748 Decl *ExceptionDecl =
nullptr;
2749 if (Tok.isNot(tok::ellipsis)) {
2750 ParsedAttributes Attributes(AttrFactory);
2751 MaybeParseCXX11Attributes(Attributes);
2753 DeclSpec DS(AttrFactory);
2755 if (ParseCXXTypeSpecifierSeq(DS))
2759 ParseDeclarator(ExDecl);
2760 ExceptionDecl = Actions.ActOnExceptionDeclarator(
getCurScope(), ExDecl);
2765 if (
T.getCloseLocation().isInvalid())
2768 if (Tok.isNot(tok::l_brace))
2769 return StmtError(
Diag(Tok, diag::err_expected) << tok::l_brace);
2773 if (
Block.isInvalid())
2776 return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl,
Block.get());
2782 assert(Tok.is(tok::kw_for));
2784 CXXExpansionStmtDecl *ExpansionDecl =
2785 Actions.ActOnCXXExpansionStmtDecl(TemplateParameterDepth, TemplateLoc);
2787 CXXExpansionStmtPattern *Expansion;
2789 Sema::ContextRAII CtxGuard(Actions, ExpansionDecl,
false);
2790 TemplateParameterDepthRAII TParamDepthGuard(TemplateParameterDepth);
2794 ParseForStatement(TrailingElseLoc, PrecedingLabel, ExpansionDecl);
2802 DeclSpec DS(AttrFactory);
2804 Actions.FinalizeDeclaratorGroup(
getCurScope(), DS, {ExpansionDecl});
2806 return Actions.ActOnDeclStmt(DeclGroupPtr, Expansion->
getBeginLoc(),
2810void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
2811 IfExistsCondition
Result;
2812 if (ParseMicrosoftIfExistsCondition(
Result))
2820 if (!Tok.is(tok::l_brace)) {
2821 Diag(Tok, diag::err_expected) << tok::l_brace;
2825 StmtResult Compound = ParseCompoundStatement();
2826 if (Compound.isInvalid())
2829 StmtResult DepResult = Actions.ActOnMSDependentExistsStmt(
Result.KeywordLoc,
2834 if (DepResult.isUsable())
2835 Stmts.push_back(DepResult.get());
2840 if (
Braces.consumeOpen()) {
2841 Diag(Tok, diag::err_expected) << tok::l_brace;
2845 switch (
Result.Behavior) {
2851 llvm_unreachable(
"Dependent case handled above");
2859 while (Tok.isNot(tok::r_brace)) {
2861 ParseStatementOrDeclaration(Stmts, ParsedStmtContext::Compound);
2863 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
void setEofData(const void *D)
bool isNot(tok::TokenKind K) const
bool isAnnotation() const
Return true if this is any of tok::annot_* kind tokens.
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