17330f729Sjoerg //===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file implements the Statement and Block portions of the Parser
107330f729Sjoerg // interface.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg
147330f729Sjoerg #include "clang/AST/PrettyDeclStackTrace.h"
157330f729Sjoerg #include "clang/Basic/Attributes.h"
167330f729Sjoerg #include "clang/Basic/PrettyStackTrace.h"
177330f729Sjoerg #include "clang/Parse/LoopHint.h"
187330f729Sjoerg #include "clang/Parse/Parser.h"
197330f729Sjoerg #include "clang/Parse/RAIIObjectsForParser.h"
207330f729Sjoerg #include "clang/Sema/DeclSpec.h"
217330f729Sjoerg #include "clang/Sema/Scope.h"
227330f729Sjoerg #include "clang/Sema/TypoCorrection.h"
23*e038c9c4Sjoerg #include "llvm/ADT/STLExtras.h"
24*e038c9c4Sjoerg
257330f729Sjoerg using namespace clang;
267330f729Sjoerg
277330f729Sjoerg //===----------------------------------------------------------------------===//
287330f729Sjoerg // C99 6.8: Statements and Blocks.
297330f729Sjoerg //===----------------------------------------------------------------------===//
307330f729Sjoerg
317330f729Sjoerg /// Parse a standalone statement (for instance, as the body of an 'if',
327330f729Sjoerg /// 'while', or 'for').
ParseStatement(SourceLocation * TrailingElseLoc,ParsedStmtContext StmtCtx)337330f729Sjoerg StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc,
347330f729Sjoerg ParsedStmtContext StmtCtx) {
357330f729Sjoerg StmtResult Res;
367330f729Sjoerg
377330f729Sjoerg // We may get back a null statement if we found a #pragma. Keep going until
387330f729Sjoerg // we get an actual statement.
397330f729Sjoerg do {
407330f729Sjoerg StmtVector Stmts;
417330f729Sjoerg Res = ParseStatementOrDeclaration(Stmts, StmtCtx, TrailingElseLoc);
427330f729Sjoerg } while (!Res.isInvalid() && !Res.get());
437330f729Sjoerg
447330f729Sjoerg return Res;
457330f729Sjoerg }
467330f729Sjoerg
477330f729Sjoerg /// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
487330f729Sjoerg /// StatementOrDeclaration:
497330f729Sjoerg /// statement
507330f729Sjoerg /// declaration
517330f729Sjoerg ///
527330f729Sjoerg /// statement:
537330f729Sjoerg /// labeled-statement
547330f729Sjoerg /// compound-statement
557330f729Sjoerg /// expression-statement
567330f729Sjoerg /// selection-statement
577330f729Sjoerg /// iteration-statement
587330f729Sjoerg /// jump-statement
597330f729Sjoerg /// [C++] declaration-statement
607330f729Sjoerg /// [C++] try-block
617330f729Sjoerg /// [MS] seh-try-block
627330f729Sjoerg /// [OBC] objc-throw-statement
637330f729Sjoerg /// [OBC] objc-try-catch-statement
647330f729Sjoerg /// [OBC] objc-synchronized-statement
657330f729Sjoerg /// [GNU] asm-statement
667330f729Sjoerg /// [OMP] openmp-construct [TODO]
677330f729Sjoerg ///
687330f729Sjoerg /// labeled-statement:
697330f729Sjoerg /// identifier ':' statement
707330f729Sjoerg /// 'case' constant-expression ':' statement
717330f729Sjoerg /// 'default' ':' statement
727330f729Sjoerg ///
737330f729Sjoerg /// selection-statement:
747330f729Sjoerg /// if-statement
757330f729Sjoerg /// switch-statement
767330f729Sjoerg ///
777330f729Sjoerg /// iteration-statement:
787330f729Sjoerg /// while-statement
797330f729Sjoerg /// do-statement
807330f729Sjoerg /// for-statement
817330f729Sjoerg ///
827330f729Sjoerg /// expression-statement:
837330f729Sjoerg /// expression[opt] ';'
847330f729Sjoerg ///
857330f729Sjoerg /// jump-statement:
867330f729Sjoerg /// 'goto' identifier ';'
877330f729Sjoerg /// 'continue' ';'
887330f729Sjoerg /// 'break' ';'
897330f729Sjoerg /// 'return' expression[opt] ';'
907330f729Sjoerg /// [GNU] 'goto' '*' expression ';'
917330f729Sjoerg ///
927330f729Sjoerg /// [OBC] objc-throw-statement:
937330f729Sjoerg /// [OBC] '@' 'throw' expression ';'
947330f729Sjoerg /// [OBC] '@' 'throw' ';'
957330f729Sjoerg ///
967330f729Sjoerg StmtResult
ParseStatementOrDeclaration(StmtVector & Stmts,ParsedStmtContext StmtCtx,SourceLocation * TrailingElseLoc)977330f729Sjoerg Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
987330f729Sjoerg ParsedStmtContext StmtCtx,
997330f729Sjoerg SourceLocation *TrailingElseLoc) {
1007330f729Sjoerg
1017330f729Sjoerg ParenBraceBracketBalancer BalancerRAIIObj(*this);
1027330f729Sjoerg
103*e038c9c4Sjoerg // Because we're parsing either a statement or a declaration, the order of
104*e038c9c4Sjoerg // attribute parsing is important. [[]] attributes at the start of a
105*e038c9c4Sjoerg // statement are different from [[]] attributes that follow an __attribute__
106*e038c9c4Sjoerg // at the start of the statement. Thus, we're not using MaybeParseAttributes
107*e038c9c4Sjoerg // here because we don't want to allow arbitrary orderings.
1087330f729Sjoerg ParsedAttributesWithRange Attrs(AttrFactory);
1097330f729Sjoerg MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true);
110*e038c9c4Sjoerg if (getLangOpts().OpenCL)
111*e038c9c4Sjoerg MaybeParseGNUAttributes(Attrs);
1127330f729Sjoerg
1137330f729Sjoerg StmtResult Res = ParseStatementOrDeclarationAfterAttributes(
1147330f729Sjoerg Stmts, StmtCtx, TrailingElseLoc, Attrs);
115*e038c9c4Sjoerg MaybeDestroyTemplateIds();
1167330f729Sjoerg
1177330f729Sjoerg assert((Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
1187330f729Sjoerg "attributes on empty statement");
1197330f729Sjoerg
1207330f729Sjoerg if (Attrs.empty() || Res.isInvalid())
1217330f729Sjoerg return Res;
1227330f729Sjoerg
123*e038c9c4Sjoerg return Actions.ActOnAttributedStmt(Attrs, Res.get());
1247330f729Sjoerg }
1257330f729Sjoerg
1267330f729Sjoerg namespace {
1277330f729Sjoerg class StatementFilterCCC final : public CorrectionCandidateCallback {
1287330f729Sjoerg public:
StatementFilterCCC(Token nextTok)1297330f729Sjoerg StatementFilterCCC(Token nextTok) : NextToken(nextTok) {
1307330f729Sjoerg WantTypeSpecifiers = nextTok.isOneOf(tok::l_paren, tok::less, tok::l_square,
1317330f729Sjoerg tok::identifier, tok::star, tok::amp);
1327330f729Sjoerg WantExpressionKeywords =
1337330f729Sjoerg nextTok.isOneOf(tok::l_paren, tok::identifier, tok::arrow, tok::period);
1347330f729Sjoerg WantRemainingKeywords =
1357330f729Sjoerg nextTok.isOneOf(tok::l_paren, tok::semi, tok::identifier, tok::l_brace);
1367330f729Sjoerg WantCXXNamedCasts = false;
1377330f729Sjoerg }
1387330f729Sjoerg
ValidateCandidate(const TypoCorrection & candidate)1397330f729Sjoerg bool ValidateCandidate(const TypoCorrection &candidate) override {
1407330f729Sjoerg if (FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>())
1417330f729Sjoerg return !candidate.getCorrectionSpecifier() || isa<ObjCIvarDecl>(FD);
1427330f729Sjoerg if (NextToken.is(tok::equal))
1437330f729Sjoerg return candidate.getCorrectionDeclAs<VarDecl>();
1447330f729Sjoerg if (NextToken.is(tok::period) &&
1457330f729Sjoerg candidate.getCorrectionDeclAs<NamespaceDecl>())
1467330f729Sjoerg return false;
1477330f729Sjoerg return CorrectionCandidateCallback::ValidateCandidate(candidate);
1487330f729Sjoerg }
1497330f729Sjoerg
clone()1507330f729Sjoerg std::unique_ptr<CorrectionCandidateCallback> clone() override {
1517330f729Sjoerg return std::make_unique<StatementFilterCCC>(*this);
1527330f729Sjoerg }
1537330f729Sjoerg
1547330f729Sjoerg private:
1557330f729Sjoerg Token NextToken;
1567330f729Sjoerg };
1577330f729Sjoerg }
1587330f729Sjoerg
ParseStatementOrDeclarationAfterAttributes(StmtVector & Stmts,ParsedStmtContext StmtCtx,SourceLocation * TrailingElseLoc,ParsedAttributesWithRange & Attrs)1597330f729Sjoerg StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
1607330f729Sjoerg StmtVector &Stmts, ParsedStmtContext StmtCtx,
1617330f729Sjoerg SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs) {
1627330f729Sjoerg const char *SemiError = nullptr;
1637330f729Sjoerg StmtResult Res;
1647330f729Sjoerg SourceLocation GNUAttributeLoc;
1657330f729Sjoerg
1667330f729Sjoerg // Cases in this switch statement should fall through if the parser expects
1677330f729Sjoerg // the token to end in a semicolon (in which case SemiError should be set),
1687330f729Sjoerg // or they directly 'return;' if not.
1697330f729Sjoerg Retry:
1707330f729Sjoerg tok::TokenKind Kind = Tok.getKind();
1717330f729Sjoerg SourceLocation AtLoc;
1727330f729Sjoerg switch (Kind) {
1737330f729Sjoerg case tok::at: // May be a @try or @throw statement
1747330f729Sjoerg {
1757330f729Sjoerg AtLoc = ConsumeToken(); // consume @
1767330f729Sjoerg return ParseObjCAtStatement(AtLoc, StmtCtx);
1777330f729Sjoerg }
1787330f729Sjoerg
1797330f729Sjoerg case tok::code_completion:
1807330f729Sjoerg cutOffParsing();
181*e038c9c4Sjoerg Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement);
1827330f729Sjoerg return StmtError();
1837330f729Sjoerg
1847330f729Sjoerg case tok::identifier: {
1857330f729Sjoerg Token Next = NextToken();
1867330f729Sjoerg if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement
1877330f729Sjoerg // identifier ':' statement
1887330f729Sjoerg return ParseLabeledStatement(Attrs, StmtCtx);
1897330f729Sjoerg }
1907330f729Sjoerg
1917330f729Sjoerg // Look up the identifier, and typo-correct it to a keyword if it's not
1927330f729Sjoerg // found.
1937330f729Sjoerg if (Next.isNot(tok::coloncolon)) {
1947330f729Sjoerg // Try to limit which sets of keywords should be included in typo
1957330f729Sjoerg // correction based on what the next token is.
1967330f729Sjoerg StatementFilterCCC CCC(Next);
1977330f729Sjoerg if (TryAnnotateName(&CCC) == ANK_Error) {
1987330f729Sjoerg // Handle errors here by skipping up to the next semicolon or '}', and
1997330f729Sjoerg // eat the semicolon if that's what stopped us.
2007330f729Sjoerg SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
2017330f729Sjoerg if (Tok.is(tok::semi))
2027330f729Sjoerg ConsumeToken();
2037330f729Sjoerg return StmtError();
2047330f729Sjoerg }
2057330f729Sjoerg
2067330f729Sjoerg // If the identifier was typo-corrected, try again.
2077330f729Sjoerg if (Tok.isNot(tok::identifier))
2087330f729Sjoerg goto Retry;
2097330f729Sjoerg }
2107330f729Sjoerg
2117330f729Sjoerg // Fall through
2127330f729Sjoerg LLVM_FALLTHROUGH;
2137330f729Sjoerg }
2147330f729Sjoerg
2157330f729Sjoerg default: {
2167330f729Sjoerg if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt ||
2177330f729Sjoerg (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
2187330f729Sjoerg ParsedStmtContext()) &&
219*e038c9c4Sjoerg ((GNUAttributeLoc.isValid() &&
220*e038c9c4Sjoerg !(!Attrs.empty() &&
221*e038c9c4Sjoerg llvm::all_of(
222*e038c9c4Sjoerg Attrs, [](ParsedAttr &Attr) { return Attr.isStmtAttr(); }))) ||
223*e038c9c4Sjoerg isDeclarationStatement())) {
2247330f729Sjoerg SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
2257330f729Sjoerg DeclGroupPtrTy Decl;
2267330f729Sjoerg if (GNUAttributeLoc.isValid()) {
2277330f729Sjoerg DeclStart = GNUAttributeLoc;
228*e038c9c4Sjoerg Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, Attrs,
2297330f729Sjoerg &GNUAttributeLoc);
2307330f729Sjoerg } else {
231*e038c9c4Sjoerg Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, Attrs);
2327330f729Sjoerg }
2337330f729Sjoerg if (Attrs.Range.getBegin().isValid())
2347330f729Sjoerg DeclStart = Attrs.Range.getBegin();
2357330f729Sjoerg return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
2367330f729Sjoerg }
2377330f729Sjoerg
2387330f729Sjoerg if (Tok.is(tok::r_brace)) {
2397330f729Sjoerg Diag(Tok, diag::err_expected_statement);
2407330f729Sjoerg return StmtError();
2417330f729Sjoerg }
2427330f729Sjoerg
2437330f729Sjoerg return ParseExprStatement(StmtCtx);
2447330f729Sjoerg }
2457330f729Sjoerg
2467330f729Sjoerg case tok::kw___attribute: {
2477330f729Sjoerg GNUAttributeLoc = Tok.getLocation();
2487330f729Sjoerg ParseGNUAttributes(Attrs);
2497330f729Sjoerg goto Retry;
2507330f729Sjoerg }
2517330f729Sjoerg
2527330f729Sjoerg case tok::kw_case: // C99 6.8.1: labeled-statement
2537330f729Sjoerg return ParseCaseStatement(StmtCtx);
2547330f729Sjoerg case tok::kw_default: // C99 6.8.1: labeled-statement
2557330f729Sjoerg return ParseDefaultStatement(StmtCtx);
2567330f729Sjoerg
2577330f729Sjoerg case tok::l_brace: // C99 6.8.2: compound-statement
2587330f729Sjoerg return ParseCompoundStatement();
2597330f729Sjoerg case tok::semi: { // C99 6.8.3p3: expression[opt] ';'
2607330f729Sjoerg bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro();
2617330f729Sjoerg return Actions.ActOnNullStmt(ConsumeToken(), HasLeadingEmptyMacro);
2627330f729Sjoerg }
2637330f729Sjoerg
2647330f729Sjoerg case tok::kw_if: // C99 6.8.4.1: if-statement
2657330f729Sjoerg return ParseIfStatement(TrailingElseLoc);
2667330f729Sjoerg case tok::kw_switch: // C99 6.8.4.2: switch-statement
2677330f729Sjoerg return ParseSwitchStatement(TrailingElseLoc);
2687330f729Sjoerg
2697330f729Sjoerg case tok::kw_while: // C99 6.8.5.1: while-statement
2707330f729Sjoerg return ParseWhileStatement(TrailingElseLoc);
2717330f729Sjoerg case tok::kw_do: // C99 6.8.5.2: do-statement
2727330f729Sjoerg Res = ParseDoStatement();
2737330f729Sjoerg SemiError = "do/while";
2747330f729Sjoerg break;
2757330f729Sjoerg case tok::kw_for: // C99 6.8.5.3: for-statement
2767330f729Sjoerg return ParseForStatement(TrailingElseLoc);
2777330f729Sjoerg
2787330f729Sjoerg case tok::kw_goto: // C99 6.8.6.1: goto-statement
2797330f729Sjoerg Res = ParseGotoStatement();
2807330f729Sjoerg SemiError = "goto";
2817330f729Sjoerg break;
2827330f729Sjoerg case tok::kw_continue: // C99 6.8.6.2: continue-statement
2837330f729Sjoerg Res = ParseContinueStatement();
2847330f729Sjoerg SemiError = "continue";
2857330f729Sjoerg break;
2867330f729Sjoerg case tok::kw_break: // C99 6.8.6.3: break-statement
2877330f729Sjoerg Res = ParseBreakStatement();
2887330f729Sjoerg SemiError = "break";
2897330f729Sjoerg break;
2907330f729Sjoerg case tok::kw_return: // C99 6.8.6.4: return-statement
2917330f729Sjoerg Res = ParseReturnStatement();
2927330f729Sjoerg SemiError = "return";
2937330f729Sjoerg break;
2947330f729Sjoerg case tok::kw_co_return: // C++ Coroutines: co_return statement
2957330f729Sjoerg Res = ParseReturnStatement();
2967330f729Sjoerg SemiError = "co_return";
2977330f729Sjoerg break;
2987330f729Sjoerg
2997330f729Sjoerg case tok::kw_asm: {
3007330f729Sjoerg ProhibitAttributes(Attrs);
3017330f729Sjoerg bool msAsm = false;
3027330f729Sjoerg Res = ParseAsmStatement(msAsm);
3037330f729Sjoerg Res = Actions.ActOnFinishFullStmt(Res.get());
3047330f729Sjoerg if (msAsm) return Res;
3057330f729Sjoerg SemiError = "asm";
3067330f729Sjoerg break;
3077330f729Sjoerg }
3087330f729Sjoerg
3097330f729Sjoerg case tok::kw___if_exists:
3107330f729Sjoerg case tok::kw___if_not_exists:
3117330f729Sjoerg ProhibitAttributes(Attrs);
3127330f729Sjoerg ParseMicrosoftIfExistsStatement(Stmts);
3137330f729Sjoerg // An __if_exists block is like a compound statement, but it doesn't create
3147330f729Sjoerg // a new scope.
3157330f729Sjoerg return StmtEmpty();
3167330f729Sjoerg
3177330f729Sjoerg case tok::kw_try: // C++ 15: try-block
3187330f729Sjoerg return ParseCXXTryBlock();
3197330f729Sjoerg
3207330f729Sjoerg case tok::kw___try:
3217330f729Sjoerg ProhibitAttributes(Attrs); // TODO: is it correct?
3227330f729Sjoerg return ParseSEHTryBlock();
3237330f729Sjoerg
3247330f729Sjoerg case tok::kw___leave:
3257330f729Sjoerg Res = ParseSEHLeaveStatement();
3267330f729Sjoerg SemiError = "__leave";
3277330f729Sjoerg break;
3287330f729Sjoerg
3297330f729Sjoerg case tok::annot_pragma_vis:
3307330f729Sjoerg ProhibitAttributes(Attrs);
3317330f729Sjoerg HandlePragmaVisibility();
3327330f729Sjoerg return StmtEmpty();
3337330f729Sjoerg
3347330f729Sjoerg case tok::annot_pragma_pack:
3357330f729Sjoerg ProhibitAttributes(Attrs);
3367330f729Sjoerg HandlePragmaPack();
3377330f729Sjoerg return StmtEmpty();
3387330f729Sjoerg
3397330f729Sjoerg case tok::annot_pragma_msstruct:
3407330f729Sjoerg ProhibitAttributes(Attrs);
3417330f729Sjoerg HandlePragmaMSStruct();
3427330f729Sjoerg return StmtEmpty();
3437330f729Sjoerg
3447330f729Sjoerg case tok::annot_pragma_align:
3457330f729Sjoerg ProhibitAttributes(Attrs);
3467330f729Sjoerg HandlePragmaAlign();
3477330f729Sjoerg return StmtEmpty();
3487330f729Sjoerg
3497330f729Sjoerg case tok::annot_pragma_weak:
3507330f729Sjoerg ProhibitAttributes(Attrs);
3517330f729Sjoerg HandlePragmaWeak();
3527330f729Sjoerg return StmtEmpty();
3537330f729Sjoerg
3547330f729Sjoerg case tok::annot_pragma_weakalias:
3557330f729Sjoerg ProhibitAttributes(Attrs);
3567330f729Sjoerg HandlePragmaWeakAlias();
3577330f729Sjoerg return StmtEmpty();
3587330f729Sjoerg
3597330f729Sjoerg case tok::annot_pragma_redefine_extname:
3607330f729Sjoerg ProhibitAttributes(Attrs);
3617330f729Sjoerg HandlePragmaRedefineExtname();
3627330f729Sjoerg return StmtEmpty();
3637330f729Sjoerg
3647330f729Sjoerg case tok::annot_pragma_fp_contract:
3657330f729Sjoerg ProhibitAttributes(Attrs);
366*e038c9c4Sjoerg Diag(Tok, diag::err_pragma_file_or_compound_scope) << "fp_contract";
3677330f729Sjoerg ConsumeAnnotationToken();
3687330f729Sjoerg return StmtError();
3697330f729Sjoerg
3707330f729Sjoerg case tok::annot_pragma_fp:
3717330f729Sjoerg ProhibitAttributes(Attrs);
372*e038c9c4Sjoerg Diag(Tok, diag::err_pragma_file_or_compound_scope) << "clang fp";
3737330f729Sjoerg ConsumeAnnotationToken();
3747330f729Sjoerg return StmtError();
3757330f729Sjoerg
3767330f729Sjoerg case tok::annot_pragma_fenv_access:
3777330f729Sjoerg ProhibitAttributes(Attrs);
378*e038c9c4Sjoerg Diag(Tok, diag::err_pragma_stdc_fenv_access_scope);
379*e038c9c4Sjoerg ConsumeAnnotationToken();
3807330f729Sjoerg return StmtEmpty();
3817330f729Sjoerg
382*e038c9c4Sjoerg case tok::annot_pragma_fenv_round:
383*e038c9c4Sjoerg ProhibitAttributes(Attrs);
384*e038c9c4Sjoerg Diag(Tok, diag::err_pragma_file_or_compound_scope) << "STDC FENV_ROUND";
385*e038c9c4Sjoerg ConsumeAnnotationToken();
386*e038c9c4Sjoerg return StmtError();
387*e038c9c4Sjoerg
388*e038c9c4Sjoerg case tok::annot_pragma_float_control:
389*e038c9c4Sjoerg ProhibitAttributes(Attrs);
390*e038c9c4Sjoerg Diag(Tok, diag::err_pragma_file_or_compound_scope) << "float_control";
391*e038c9c4Sjoerg ConsumeAnnotationToken();
392*e038c9c4Sjoerg return StmtError();
393*e038c9c4Sjoerg
3947330f729Sjoerg case tok::annot_pragma_opencl_extension:
3957330f729Sjoerg ProhibitAttributes(Attrs);
3967330f729Sjoerg HandlePragmaOpenCLExtension();
3977330f729Sjoerg return StmtEmpty();
3987330f729Sjoerg
3997330f729Sjoerg case tok::annot_pragma_captured:
4007330f729Sjoerg ProhibitAttributes(Attrs);
4017330f729Sjoerg return HandlePragmaCaptured();
4027330f729Sjoerg
4037330f729Sjoerg case tok::annot_pragma_openmp:
4047330f729Sjoerg ProhibitAttributes(Attrs);
4057330f729Sjoerg return ParseOpenMPDeclarativeOrExecutableDirective(StmtCtx);
4067330f729Sjoerg
4077330f729Sjoerg case tok::annot_pragma_ms_pointers_to_members:
4087330f729Sjoerg ProhibitAttributes(Attrs);
4097330f729Sjoerg HandlePragmaMSPointersToMembers();
4107330f729Sjoerg return StmtEmpty();
4117330f729Sjoerg
4127330f729Sjoerg case tok::annot_pragma_ms_pragma:
4137330f729Sjoerg ProhibitAttributes(Attrs);
4147330f729Sjoerg HandlePragmaMSPragma();
4157330f729Sjoerg return StmtEmpty();
4167330f729Sjoerg
4177330f729Sjoerg case tok::annot_pragma_ms_vtordisp:
4187330f729Sjoerg ProhibitAttributes(Attrs);
4197330f729Sjoerg HandlePragmaMSVtorDisp();
4207330f729Sjoerg return StmtEmpty();
4217330f729Sjoerg
4227330f729Sjoerg case tok::annot_pragma_loop_hint:
4237330f729Sjoerg ProhibitAttributes(Attrs);
4247330f729Sjoerg return ParsePragmaLoopHint(Stmts, StmtCtx, TrailingElseLoc, Attrs);
4257330f729Sjoerg
4267330f729Sjoerg case tok::annot_pragma_dump:
4277330f729Sjoerg HandlePragmaDump();
4287330f729Sjoerg return StmtEmpty();
4297330f729Sjoerg
4307330f729Sjoerg case tok::annot_pragma_attribute:
4317330f729Sjoerg HandlePragmaAttribute();
4327330f729Sjoerg return StmtEmpty();
4337330f729Sjoerg }
4347330f729Sjoerg
4357330f729Sjoerg // If we reached this code, the statement must end in a semicolon.
4367330f729Sjoerg if (!TryConsumeToken(tok::semi) && !Res.isInvalid()) {
4377330f729Sjoerg // If the result was valid, then we do want to diagnose this. Use
4387330f729Sjoerg // ExpectAndConsume to emit the diagnostic, even though we know it won't
4397330f729Sjoerg // succeed.
4407330f729Sjoerg ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
4417330f729Sjoerg // Skip until we see a } or ;, but don't eat it.
4427330f729Sjoerg SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
4437330f729Sjoerg }
4447330f729Sjoerg
4457330f729Sjoerg return Res;
4467330f729Sjoerg }
4477330f729Sjoerg
4487330f729Sjoerg /// Parse an expression statement.
ParseExprStatement(ParsedStmtContext StmtCtx)4497330f729Sjoerg StmtResult Parser::ParseExprStatement(ParsedStmtContext StmtCtx) {
4507330f729Sjoerg // If a case keyword is missing, this is where it should be inserted.
4517330f729Sjoerg Token OldToken = Tok;
4527330f729Sjoerg
4537330f729Sjoerg ExprStatementTokLoc = Tok.getLocation();
4547330f729Sjoerg
4557330f729Sjoerg // expression[opt] ';'
4567330f729Sjoerg ExprResult Expr(ParseExpression());
4577330f729Sjoerg if (Expr.isInvalid()) {
4587330f729Sjoerg // If the expression is invalid, skip ahead to the next semicolon or '}'.
4597330f729Sjoerg // Not doing this opens us up to the possibility of infinite loops if
4607330f729Sjoerg // ParseExpression does not consume any tokens.
4617330f729Sjoerg SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
4627330f729Sjoerg if (Tok.is(tok::semi))
4637330f729Sjoerg ConsumeToken();
4647330f729Sjoerg return Actions.ActOnExprStmtError();
4657330f729Sjoerg }
4667330f729Sjoerg
4677330f729Sjoerg if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() &&
4687330f729Sjoerg Actions.CheckCaseExpression(Expr.get())) {
4697330f729Sjoerg // If a constant expression is followed by a colon inside a switch block,
4707330f729Sjoerg // suggest a missing case keyword.
4717330f729Sjoerg Diag(OldToken, diag::err_expected_case_before_expression)
4727330f729Sjoerg << FixItHint::CreateInsertion(OldToken.getLocation(), "case ");
4737330f729Sjoerg
4747330f729Sjoerg // Recover parsing as a case statement.
4757330f729Sjoerg return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
4767330f729Sjoerg }
4777330f729Sjoerg
4787330f729Sjoerg // Otherwise, eat the semicolon.
4797330f729Sjoerg ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
4807330f729Sjoerg return handleExprStmt(Expr, StmtCtx);
4817330f729Sjoerg }
4827330f729Sjoerg
4837330f729Sjoerg /// ParseSEHTryBlockCommon
4847330f729Sjoerg ///
4857330f729Sjoerg /// seh-try-block:
4867330f729Sjoerg /// '__try' compound-statement seh-handler
4877330f729Sjoerg ///
4887330f729Sjoerg /// seh-handler:
4897330f729Sjoerg /// seh-except-block
4907330f729Sjoerg /// seh-finally-block
4917330f729Sjoerg ///
ParseSEHTryBlock()4927330f729Sjoerg StmtResult Parser::ParseSEHTryBlock() {
4937330f729Sjoerg assert(Tok.is(tok::kw___try) && "Expected '__try'");
4947330f729Sjoerg SourceLocation TryLoc = ConsumeToken();
4957330f729Sjoerg
4967330f729Sjoerg if (Tok.isNot(tok::l_brace))
4977330f729Sjoerg return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
4987330f729Sjoerg
4997330f729Sjoerg StmtResult TryBlock(ParseCompoundStatement(
5007330f729Sjoerg /*isStmtExpr=*/false,
5017330f729Sjoerg Scope::DeclScope | Scope::CompoundStmtScope | Scope::SEHTryScope));
5027330f729Sjoerg if (TryBlock.isInvalid())
5037330f729Sjoerg return TryBlock;
5047330f729Sjoerg
5057330f729Sjoerg StmtResult Handler;
5067330f729Sjoerg if (Tok.is(tok::identifier) &&
5077330f729Sjoerg Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
5087330f729Sjoerg SourceLocation Loc = ConsumeToken();
5097330f729Sjoerg Handler = ParseSEHExceptBlock(Loc);
5107330f729Sjoerg } else if (Tok.is(tok::kw___finally)) {
5117330f729Sjoerg SourceLocation Loc = ConsumeToken();
5127330f729Sjoerg Handler = ParseSEHFinallyBlock(Loc);
5137330f729Sjoerg } else {
5147330f729Sjoerg return StmtError(Diag(Tok, diag::err_seh_expected_handler));
5157330f729Sjoerg }
5167330f729Sjoerg
5177330f729Sjoerg if(Handler.isInvalid())
5187330f729Sjoerg return Handler;
5197330f729Sjoerg
5207330f729Sjoerg return Actions.ActOnSEHTryBlock(false /* IsCXXTry */,
5217330f729Sjoerg TryLoc,
5227330f729Sjoerg TryBlock.get(),
5237330f729Sjoerg Handler.get());
5247330f729Sjoerg }
5257330f729Sjoerg
5267330f729Sjoerg /// ParseSEHExceptBlock - Handle __except
5277330f729Sjoerg ///
5287330f729Sjoerg /// seh-except-block:
5297330f729Sjoerg /// '__except' '(' seh-filter-expression ')' compound-statement
5307330f729Sjoerg ///
ParseSEHExceptBlock(SourceLocation ExceptLoc)5317330f729Sjoerg StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
5327330f729Sjoerg PoisonIdentifierRAIIObject raii(Ident__exception_code, false),
5337330f729Sjoerg raii2(Ident___exception_code, false),
5347330f729Sjoerg raii3(Ident_GetExceptionCode, false);
5357330f729Sjoerg
5367330f729Sjoerg if (ExpectAndConsume(tok::l_paren))
5377330f729Sjoerg return StmtError();
5387330f729Sjoerg
5397330f729Sjoerg ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope |
5407330f729Sjoerg Scope::SEHExceptScope);
5417330f729Sjoerg
5427330f729Sjoerg if (getLangOpts().Borland) {
5437330f729Sjoerg Ident__exception_info->setIsPoisoned(false);
5447330f729Sjoerg Ident___exception_info->setIsPoisoned(false);
5457330f729Sjoerg Ident_GetExceptionInfo->setIsPoisoned(false);
5467330f729Sjoerg }
5477330f729Sjoerg
5487330f729Sjoerg ExprResult FilterExpr;
5497330f729Sjoerg {
5507330f729Sjoerg ParseScopeFlags FilterScope(this, getCurScope()->getFlags() |
5517330f729Sjoerg Scope::SEHFilterScope);
5527330f729Sjoerg FilterExpr = Actions.CorrectDelayedTyposInExpr(ParseExpression());
5537330f729Sjoerg }
5547330f729Sjoerg
5557330f729Sjoerg if (getLangOpts().Borland) {
5567330f729Sjoerg Ident__exception_info->setIsPoisoned(true);
5577330f729Sjoerg Ident___exception_info->setIsPoisoned(true);
5587330f729Sjoerg Ident_GetExceptionInfo->setIsPoisoned(true);
5597330f729Sjoerg }
5607330f729Sjoerg
5617330f729Sjoerg if(FilterExpr.isInvalid())
5627330f729Sjoerg return StmtError();
5637330f729Sjoerg
5647330f729Sjoerg if (ExpectAndConsume(tok::r_paren))
5657330f729Sjoerg return StmtError();
5667330f729Sjoerg
5677330f729Sjoerg if (Tok.isNot(tok::l_brace))
5687330f729Sjoerg return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
5697330f729Sjoerg
5707330f729Sjoerg StmtResult Block(ParseCompoundStatement());
5717330f729Sjoerg
5727330f729Sjoerg if(Block.isInvalid())
5737330f729Sjoerg return Block;
5747330f729Sjoerg
5757330f729Sjoerg return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.get(), Block.get());
5767330f729Sjoerg }
5777330f729Sjoerg
5787330f729Sjoerg /// ParseSEHFinallyBlock - Handle __finally
5797330f729Sjoerg ///
5807330f729Sjoerg /// seh-finally-block:
5817330f729Sjoerg /// '__finally' compound-statement
5827330f729Sjoerg ///
ParseSEHFinallyBlock(SourceLocation FinallyLoc)5837330f729Sjoerg StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyLoc) {
5847330f729Sjoerg PoisonIdentifierRAIIObject raii(Ident__abnormal_termination, false),
5857330f729Sjoerg raii2(Ident___abnormal_termination, false),
5867330f729Sjoerg raii3(Ident_AbnormalTermination, false);
5877330f729Sjoerg
5887330f729Sjoerg if (Tok.isNot(tok::l_brace))
5897330f729Sjoerg return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
5907330f729Sjoerg
5917330f729Sjoerg ParseScope FinallyScope(this, 0);
5927330f729Sjoerg Actions.ActOnStartSEHFinallyBlock();
5937330f729Sjoerg
5947330f729Sjoerg StmtResult Block(ParseCompoundStatement());
5957330f729Sjoerg if(Block.isInvalid()) {
5967330f729Sjoerg Actions.ActOnAbortSEHFinallyBlock();
5977330f729Sjoerg return Block;
5987330f729Sjoerg }
5997330f729Sjoerg
6007330f729Sjoerg return Actions.ActOnFinishSEHFinallyBlock(FinallyLoc, Block.get());
6017330f729Sjoerg }
6027330f729Sjoerg
6037330f729Sjoerg /// Handle __leave
6047330f729Sjoerg ///
6057330f729Sjoerg /// seh-leave-statement:
6067330f729Sjoerg /// '__leave' ';'
6077330f729Sjoerg ///
ParseSEHLeaveStatement()6087330f729Sjoerg StmtResult Parser::ParseSEHLeaveStatement() {
6097330f729Sjoerg SourceLocation LeaveLoc = ConsumeToken(); // eat the '__leave'.
6107330f729Sjoerg return Actions.ActOnSEHLeaveStmt(LeaveLoc, getCurScope());
6117330f729Sjoerg }
6127330f729Sjoerg
6137330f729Sjoerg /// ParseLabeledStatement - We have an identifier and a ':' after it.
6147330f729Sjoerg ///
6157330f729Sjoerg /// labeled-statement:
6167330f729Sjoerg /// identifier ':' statement
6177330f729Sjoerg /// [GNU] identifier ':' attributes[opt] statement
6187330f729Sjoerg ///
ParseLabeledStatement(ParsedAttributesWithRange & attrs,ParsedStmtContext StmtCtx)6197330f729Sjoerg StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs,
6207330f729Sjoerg ParsedStmtContext StmtCtx) {
6217330f729Sjoerg assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
6227330f729Sjoerg "Not an identifier!");
6237330f729Sjoerg
6247330f729Sjoerg // The substatement is always a 'statement', not a 'declaration', but is
6257330f729Sjoerg // otherwise in the same context as the labeled-statement.
6267330f729Sjoerg StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
6277330f729Sjoerg
6287330f729Sjoerg Token IdentTok = Tok; // Save the whole token.
6297330f729Sjoerg ConsumeToken(); // eat the identifier.
6307330f729Sjoerg
6317330f729Sjoerg assert(Tok.is(tok::colon) && "Not a label!");
6327330f729Sjoerg
6337330f729Sjoerg // identifier ':' statement
6347330f729Sjoerg SourceLocation ColonLoc = ConsumeToken();
6357330f729Sjoerg
6367330f729Sjoerg // Read label attributes, if present.
6377330f729Sjoerg StmtResult SubStmt;
6387330f729Sjoerg if (Tok.is(tok::kw___attribute)) {
6397330f729Sjoerg ParsedAttributesWithRange TempAttrs(AttrFactory);
6407330f729Sjoerg ParseGNUAttributes(TempAttrs);
6417330f729Sjoerg
6427330f729Sjoerg // In C++, GNU attributes only apply to the label if they are followed by a
6437330f729Sjoerg // semicolon, to disambiguate label attributes from attributes on a labeled
6447330f729Sjoerg // declaration.
6457330f729Sjoerg //
6467330f729Sjoerg // This doesn't quite match what GCC does; if the attribute list is empty
6477330f729Sjoerg // and followed by a semicolon, GCC will reject (it appears to parse the
6487330f729Sjoerg // attributes as part of a statement in that case). That looks like a bug.
6497330f729Sjoerg if (!getLangOpts().CPlusPlus || Tok.is(tok::semi))
6507330f729Sjoerg attrs.takeAllFrom(TempAttrs);
651*e038c9c4Sjoerg else {
6527330f729Sjoerg StmtVector Stmts;
6537330f729Sjoerg SubStmt = ParseStatementOrDeclarationAfterAttributes(Stmts, StmtCtx,
6547330f729Sjoerg nullptr, TempAttrs);
6557330f729Sjoerg if (!TempAttrs.empty() && !SubStmt.isInvalid())
656*e038c9c4Sjoerg SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get());
6577330f729Sjoerg }
6587330f729Sjoerg }
6597330f729Sjoerg
6607330f729Sjoerg // If we've not parsed a statement yet, parse one now.
6617330f729Sjoerg if (!SubStmt.isInvalid() && !SubStmt.isUsable())
6627330f729Sjoerg SubStmt = ParseStatement(nullptr, StmtCtx);
6637330f729Sjoerg
6647330f729Sjoerg // Broken substmt shouldn't prevent the label from being added to the AST.
6657330f729Sjoerg if (SubStmt.isInvalid())
6667330f729Sjoerg SubStmt = Actions.ActOnNullStmt(ColonLoc);
6677330f729Sjoerg
6687330f729Sjoerg LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
6697330f729Sjoerg IdentTok.getLocation());
6707330f729Sjoerg Actions.ProcessDeclAttributeList(Actions.CurScope, LD, attrs);
6717330f729Sjoerg attrs.clear();
6727330f729Sjoerg
6737330f729Sjoerg return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc,
6747330f729Sjoerg SubStmt.get());
6757330f729Sjoerg }
6767330f729Sjoerg
6777330f729Sjoerg /// ParseCaseStatement
6787330f729Sjoerg /// labeled-statement:
6797330f729Sjoerg /// 'case' constant-expression ':' statement
6807330f729Sjoerg /// [GNU] 'case' constant-expression '...' constant-expression ':' statement
6817330f729Sjoerg ///
ParseCaseStatement(ParsedStmtContext StmtCtx,bool MissingCase,ExprResult Expr)6827330f729Sjoerg StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
6837330f729Sjoerg bool MissingCase, ExprResult Expr) {
6847330f729Sjoerg assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!");
6857330f729Sjoerg
6867330f729Sjoerg // The substatement is always a 'statement', not a 'declaration', but is
6877330f729Sjoerg // otherwise in the same context as the labeled-statement.
6887330f729Sjoerg StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
6897330f729Sjoerg
6907330f729Sjoerg // It is very very common for code to contain many case statements recursively
6917330f729Sjoerg // nested, as in (but usually without indentation):
6927330f729Sjoerg // case 1:
6937330f729Sjoerg // case 2:
6947330f729Sjoerg // case 3:
6957330f729Sjoerg // case 4:
6967330f729Sjoerg // case 5: etc.
6977330f729Sjoerg //
6987330f729Sjoerg // Parsing this naively works, but is both inefficient and can cause us to run
6997330f729Sjoerg // out of stack space in our recursive descent parser. As a special case,
7007330f729Sjoerg // flatten this recursion into an iterative loop. This is complex and gross,
7017330f729Sjoerg // but all the grossness is constrained to ParseCaseStatement (and some
7027330f729Sjoerg // weirdness in the actions), so this is just local grossness :).
7037330f729Sjoerg
7047330f729Sjoerg // TopLevelCase - This is the highest level we have parsed. 'case 1' in the
7057330f729Sjoerg // example above.
7067330f729Sjoerg StmtResult TopLevelCase(true);
7077330f729Sjoerg
7087330f729Sjoerg // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
7097330f729Sjoerg // gets updated each time a new case is parsed, and whose body is unset so
7107330f729Sjoerg // far. When parsing 'case 4', this is the 'case 3' node.
7117330f729Sjoerg Stmt *DeepestParsedCaseStmt = nullptr;
7127330f729Sjoerg
7137330f729Sjoerg // While we have case statements, eat and stack them.
7147330f729Sjoerg SourceLocation ColonLoc;
7157330f729Sjoerg do {
7167330f729Sjoerg SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() :
7177330f729Sjoerg ConsumeToken(); // eat the 'case'.
7187330f729Sjoerg ColonLoc = SourceLocation();
7197330f729Sjoerg
7207330f729Sjoerg if (Tok.is(tok::code_completion)) {
7217330f729Sjoerg cutOffParsing();
722*e038c9c4Sjoerg Actions.CodeCompleteCase(getCurScope());
7237330f729Sjoerg return StmtError();
7247330f729Sjoerg }
7257330f729Sjoerg
7267330f729Sjoerg /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
7277330f729Sjoerg /// Disable this form of error recovery while we're parsing the case
7287330f729Sjoerg /// expression.
7297330f729Sjoerg ColonProtectionRAIIObject ColonProtection(*this);
7307330f729Sjoerg
7317330f729Sjoerg ExprResult LHS;
7327330f729Sjoerg if (!MissingCase) {
7337330f729Sjoerg LHS = ParseCaseExpression(CaseLoc);
7347330f729Sjoerg if (LHS.isInvalid()) {
7357330f729Sjoerg // If constant-expression is parsed unsuccessfully, recover by skipping
7367330f729Sjoerg // current case statement (moving to the colon that ends it).
7377330f729Sjoerg if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
7387330f729Sjoerg return StmtError();
7397330f729Sjoerg }
7407330f729Sjoerg } else {
7417330f729Sjoerg LHS = Expr;
7427330f729Sjoerg MissingCase = false;
7437330f729Sjoerg }
7447330f729Sjoerg
7457330f729Sjoerg // GNU case range extension.
7467330f729Sjoerg SourceLocation DotDotDotLoc;
7477330f729Sjoerg ExprResult RHS;
7487330f729Sjoerg if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) {
7497330f729Sjoerg Diag(DotDotDotLoc, diag::ext_gnu_case_range);
7507330f729Sjoerg RHS = ParseCaseExpression(CaseLoc);
7517330f729Sjoerg if (RHS.isInvalid()) {
7527330f729Sjoerg if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
7537330f729Sjoerg return StmtError();
7547330f729Sjoerg }
7557330f729Sjoerg }
7567330f729Sjoerg
7577330f729Sjoerg ColonProtection.restore();
7587330f729Sjoerg
7597330f729Sjoerg if (TryConsumeToken(tok::colon, ColonLoc)) {
7607330f729Sjoerg } else if (TryConsumeToken(tok::semi, ColonLoc) ||
7617330f729Sjoerg TryConsumeToken(tok::coloncolon, ColonLoc)) {
7627330f729Sjoerg // Treat "case blah;" or "case blah::" as a typo for "case blah:".
7637330f729Sjoerg Diag(ColonLoc, diag::err_expected_after)
7647330f729Sjoerg << "'case'" << tok::colon
7657330f729Sjoerg << FixItHint::CreateReplacement(ColonLoc, ":");
7667330f729Sjoerg } else {
7677330f729Sjoerg SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
7687330f729Sjoerg Diag(ExpectedLoc, diag::err_expected_after)
7697330f729Sjoerg << "'case'" << tok::colon
7707330f729Sjoerg << FixItHint::CreateInsertion(ExpectedLoc, ":");
7717330f729Sjoerg ColonLoc = ExpectedLoc;
7727330f729Sjoerg }
7737330f729Sjoerg
7747330f729Sjoerg StmtResult Case =
7757330f729Sjoerg Actions.ActOnCaseStmt(CaseLoc, LHS, DotDotDotLoc, RHS, ColonLoc);
7767330f729Sjoerg
7777330f729Sjoerg // If we had a sema error parsing this case, then just ignore it and
7787330f729Sjoerg // continue parsing the sub-stmt.
7797330f729Sjoerg if (Case.isInvalid()) {
7807330f729Sjoerg if (TopLevelCase.isInvalid()) // No parsed case stmts.
7817330f729Sjoerg return ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
7827330f729Sjoerg // Otherwise, just don't add it as a nested case.
7837330f729Sjoerg } else {
7847330f729Sjoerg // If this is the first case statement we parsed, it becomes TopLevelCase.
7857330f729Sjoerg // Otherwise we link it into the current chain.
7867330f729Sjoerg Stmt *NextDeepest = Case.get();
7877330f729Sjoerg if (TopLevelCase.isInvalid())
7887330f729Sjoerg TopLevelCase = Case;
7897330f729Sjoerg else
7907330f729Sjoerg Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, Case.get());
7917330f729Sjoerg DeepestParsedCaseStmt = NextDeepest;
7927330f729Sjoerg }
7937330f729Sjoerg
7947330f729Sjoerg // Handle all case statements.
7957330f729Sjoerg } while (Tok.is(tok::kw_case));
7967330f729Sjoerg
7977330f729Sjoerg // If we found a non-case statement, start by parsing it.
7987330f729Sjoerg StmtResult SubStmt;
7997330f729Sjoerg
8007330f729Sjoerg if (Tok.isNot(tok::r_brace)) {
8017330f729Sjoerg SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
8027330f729Sjoerg } else {
8037330f729Sjoerg // Nicely diagnose the common error "switch (X) { case 4: }", which is
8047330f729Sjoerg // not valid. If ColonLoc doesn't point to a valid text location, there was
8057330f729Sjoerg // another parsing error, so avoid producing extra diagnostics.
8067330f729Sjoerg if (ColonLoc.isValid()) {
8077330f729Sjoerg SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc);
8087330f729Sjoerg Diag(AfterColonLoc, diag::err_label_end_of_compound_statement)
8097330f729Sjoerg << FixItHint::CreateInsertion(AfterColonLoc, " ;");
8107330f729Sjoerg }
8117330f729Sjoerg SubStmt = StmtError();
8127330f729Sjoerg }
8137330f729Sjoerg
8147330f729Sjoerg // Install the body into the most deeply-nested case.
8157330f729Sjoerg if (DeepestParsedCaseStmt) {
8167330f729Sjoerg // Broken sub-stmt shouldn't prevent forming the case statement properly.
8177330f729Sjoerg if (SubStmt.isInvalid())
8187330f729Sjoerg SubStmt = Actions.ActOnNullStmt(SourceLocation());
8197330f729Sjoerg Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
8207330f729Sjoerg }
8217330f729Sjoerg
8227330f729Sjoerg // Return the top level parsed statement tree.
8237330f729Sjoerg return TopLevelCase;
8247330f729Sjoerg }
8257330f729Sjoerg
8267330f729Sjoerg /// ParseDefaultStatement
8277330f729Sjoerg /// labeled-statement:
8287330f729Sjoerg /// 'default' ':' statement
8297330f729Sjoerg /// Note that this does not parse the 'statement' at the end.
8307330f729Sjoerg ///
ParseDefaultStatement(ParsedStmtContext StmtCtx)8317330f729Sjoerg StmtResult Parser::ParseDefaultStatement(ParsedStmtContext StmtCtx) {
8327330f729Sjoerg assert(Tok.is(tok::kw_default) && "Not a default stmt!");
8337330f729Sjoerg
8347330f729Sjoerg // The substatement is always a 'statement', not a 'declaration', but is
8357330f729Sjoerg // otherwise in the same context as the labeled-statement.
8367330f729Sjoerg StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
8377330f729Sjoerg
8387330f729Sjoerg SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
8397330f729Sjoerg
8407330f729Sjoerg SourceLocation ColonLoc;
8417330f729Sjoerg if (TryConsumeToken(tok::colon, ColonLoc)) {
8427330f729Sjoerg } else if (TryConsumeToken(tok::semi, ColonLoc)) {
8437330f729Sjoerg // Treat "default;" as a typo for "default:".
8447330f729Sjoerg Diag(ColonLoc, diag::err_expected_after)
8457330f729Sjoerg << "'default'" << tok::colon
8467330f729Sjoerg << FixItHint::CreateReplacement(ColonLoc, ":");
8477330f729Sjoerg } else {
8487330f729Sjoerg SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
8497330f729Sjoerg Diag(ExpectedLoc, diag::err_expected_after)
8507330f729Sjoerg << "'default'" << tok::colon
8517330f729Sjoerg << FixItHint::CreateInsertion(ExpectedLoc, ":");
8527330f729Sjoerg ColonLoc = ExpectedLoc;
8537330f729Sjoerg }
8547330f729Sjoerg
8557330f729Sjoerg StmtResult SubStmt;
8567330f729Sjoerg
8577330f729Sjoerg if (Tok.isNot(tok::r_brace)) {
8587330f729Sjoerg SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
8597330f729Sjoerg } else {
8607330f729Sjoerg // Diagnose the common error "switch (X) {... default: }", which is
8617330f729Sjoerg // not valid.
8627330f729Sjoerg SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc);
8637330f729Sjoerg Diag(AfterColonLoc, diag::err_label_end_of_compound_statement)
8647330f729Sjoerg << FixItHint::CreateInsertion(AfterColonLoc, " ;");
8657330f729Sjoerg SubStmt = true;
8667330f729Sjoerg }
8677330f729Sjoerg
8687330f729Sjoerg // Broken sub-stmt shouldn't prevent forming the case statement properly.
8697330f729Sjoerg if (SubStmt.isInvalid())
8707330f729Sjoerg SubStmt = Actions.ActOnNullStmt(ColonLoc);
8717330f729Sjoerg
8727330f729Sjoerg return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
8737330f729Sjoerg SubStmt.get(), getCurScope());
8747330f729Sjoerg }
8757330f729Sjoerg
ParseCompoundStatement(bool isStmtExpr)8767330f729Sjoerg StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
8777330f729Sjoerg return ParseCompoundStatement(isStmtExpr,
8787330f729Sjoerg Scope::DeclScope | Scope::CompoundStmtScope);
8797330f729Sjoerg }
8807330f729Sjoerg
8817330f729Sjoerg /// ParseCompoundStatement - Parse a "{}" block.
8827330f729Sjoerg ///
8837330f729Sjoerg /// compound-statement: [C99 6.8.2]
8847330f729Sjoerg /// { block-item-list[opt] }
8857330f729Sjoerg /// [GNU] { label-declarations block-item-list } [TODO]
8867330f729Sjoerg ///
8877330f729Sjoerg /// block-item-list:
8887330f729Sjoerg /// block-item
8897330f729Sjoerg /// block-item-list block-item
8907330f729Sjoerg ///
8917330f729Sjoerg /// block-item:
8927330f729Sjoerg /// declaration
8937330f729Sjoerg /// [GNU] '__extension__' declaration
8947330f729Sjoerg /// statement
8957330f729Sjoerg ///
8967330f729Sjoerg /// [GNU] label-declarations:
8977330f729Sjoerg /// [GNU] label-declaration
8987330f729Sjoerg /// [GNU] label-declarations label-declaration
8997330f729Sjoerg ///
9007330f729Sjoerg /// [GNU] label-declaration:
9017330f729Sjoerg /// [GNU] '__label__' identifier-list ';'
9027330f729Sjoerg ///
ParseCompoundStatement(bool isStmtExpr,unsigned ScopeFlags)9037330f729Sjoerg StmtResult Parser::ParseCompoundStatement(bool isStmtExpr,
9047330f729Sjoerg unsigned ScopeFlags) {
9057330f729Sjoerg assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
9067330f729Sjoerg
9077330f729Sjoerg // Enter a scope to hold everything within the compound stmt. Compound
9087330f729Sjoerg // statements can always hold declarations.
9097330f729Sjoerg ParseScope CompoundScope(this, ScopeFlags);
9107330f729Sjoerg
9117330f729Sjoerg // Parse the statements in the body.
9127330f729Sjoerg return ParseCompoundStatementBody(isStmtExpr);
9137330f729Sjoerg }
9147330f729Sjoerg
9157330f729Sjoerg /// Parse any pragmas at the start of the compound expression. We handle these
9167330f729Sjoerg /// separately since some pragmas (FP_CONTRACT) must appear before any C
9177330f729Sjoerg /// statement in the compound, but may be intermingled with other pragmas.
ParseCompoundStatementLeadingPragmas()9187330f729Sjoerg void Parser::ParseCompoundStatementLeadingPragmas() {
9197330f729Sjoerg bool checkForPragmas = true;
9207330f729Sjoerg while (checkForPragmas) {
9217330f729Sjoerg switch (Tok.getKind()) {
9227330f729Sjoerg case tok::annot_pragma_vis:
9237330f729Sjoerg HandlePragmaVisibility();
9247330f729Sjoerg break;
9257330f729Sjoerg case tok::annot_pragma_pack:
9267330f729Sjoerg HandlePragmaPack();
9277330f729Sjoerg break;
9287330f729Sjoerg case tok::annot_pragma_msstruct:
9297330f729Sjoerg HandlePragmaMSStruct();
9307330f729Sjoerg break;
9317330f729Sjoerg case tok::annot_pragma_align:
9327330f729Sjoerg HandlePragmaAlign();
9337330f729Sjoerg break;
9347330f729Sjoerg case tok::annot_pragma_weak:
9357330f729Sjoerg HandlePragmaWeak();
9367330f729Sjoerg break;
9377330f729Sjoerg case tok::annot_pragma_weakalias:
9387330f729Sjoerg HandlePragmaWeakAlias();
9397330f729Sjoerg break;
9407330f729Sjoerg case tok::annot_pragma_redefine_extname:
9417330f729Sjoerg HandlePragmaRedefineExtname();
9427330f729Sjoerg break;
9437330f729Sjoerg case tok::annot_pragma_opencl_extension:
9447330f729Sjoerg HandlePragmaOpenCLExtension();
9457330f729Sjoerg break;
9467330f729Sjoerg case tok::annot_pragma_fp_contract:
9477330f729Sjoerg HandlePragmaFPContract();
9487330f729Sjoerg break;
9497330f729Sjoerg case tok::annot_pragma_fp:
9507330f729Sjoerg HandlePragmaFP();
9517330f729Sjoerg break;
9527330f729Sjoerg case tok::annot_pragma_fenv_access:
9537330f729Sjoerg HandlePragmaFEnvAccess();
9547330f729Sjoerg break;
955*e038c9c4Sjoerg case tok::annot_pragma_fenv_round:
956*e038c9c4Sjoerg HandlePragmaFEnvRound();
957*e038c9c4Sjoerg break;
958*e038c9c4Sjoerg case tok::annot_pragma_float_control:
959*e038c9c4Sjoerg HandlePragmaFloatControl();
960*e038c9c4Sjoerg break;
9617330f729Sjoerg case tok::annot_pragma_ms_pointers_to_members:
9627330f729Sjoerg HandlePragmaMSPointersToMembers();
9637330f729Sjoerg break;
9647330f729Sjoerg case tok::annot_pragma_ms_pragma:
9657330f729Sjoerg HandlePragmaMSPragma();
9667330f729Sjoerg break;
9677330f729Sjoerg case tok::annot_pragma_ms_vtordisp:
9687330f729Sjoerg HandlePragmaMSVtorDisp();
9697330f729Sjoerg break;
9707330f729Sjoerg case tok::annot_pragma_dump:
9717330f729Sjoerg HandlePragmaDump();
9727330f729Sjoerg break;
9737330f729Sjoerg default:
9747330f729Sjoerg checkForPragmas = false;
9757330f729Sjoerg break;
9767330f729Sjoerg }
9777330f729Sjoerg }
9787330f729Sjoerg
9797330f729Sjoerg }
9807330f729Sjoerg
9817330f729Sjoerg /// Consume any extra semi-colons resulting in null statements,
9827330f729Sjoerg /// returning true if any tok::semi were consumed.
ConsumeNullStmt(StmtVector & Stmts)9837330f729Sjoerg bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
9847330f729Sjoerg if (!Tok.is(tok::semi))
9857330f729Sjoerg return false;
9867330f729Sjoerg
9877330f729Sjoerg SourceLocation StartLoc = Tok.getLocation();
9887330f729Sjoerg SourceLocation EndLoc;
9897330f729Sjoerg
9907330f729Sjoerg while (Tok.is(tok::semi) && !Tok.hasLeadingEmptyMacro() &&
9917330f729Sjoerg Tok.getLocation().isValid() && !Tok.getLocation().isMacroID()) {
9927330f729Sjoerg EndLoc = Tok.getLocation();
9937330f729Sjoerg
9947330f729Sjoerg // Don't just ConsumeToken() this tok::semi, do store it in AST.
9957330f729Sjoerg StmtResult R =
9967330f729Sjoerg ParseStatementOrDeclaration(Stmts, ParsedStmtContext::SubStmt);
9977330f729Sjoerg if (R.isUsable())
9987330f729Sjoerg Stmts.push_back(R.get());
9997330f729Sjoerg }
10007330f729Sjoerg
10017330f729Sjoerg // Did not consume any extra semi.
10027330f729Sjoerg if (EndLoc.isInvalid())
10037330f729Sjoerg return false;
10047330f729Sjoerg
10057330f729Sjoerg Diag(StartLoc, diag::warn_null_statement)
10067330f729Sjoerg << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc));
10077330f729Sjoerg return true;
10087330f729Sjoerg }
10097330f729Sjoerg
handleExprStmt(ExprResult E,ParsedStmtContext StmtCtx)10107330f729Sjoerg StmtResult Parser::handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx) {
10117330f729Sjoerg bool IsStmtExprResult = false;
10127330f729Sjoerg if ((StmtCtx & ParsedStmtContext::InStmtExpr) != ParsedStmtContext()) {
10137330f729Sjoerg // For GCC compatibility we skip past NullStmts.
10147330f729Sjoerg unsigned LookAhead = 0;
10157330f729Sjoerg while (GetLookAheadToken(LookAhead).is(tok::semi)) {
10167330f729Sjoerg ++LookAhead;
10177330f729Sjoerg }
10187330f729Sjoerg // Then look to see if the next two tokens close the statement expression;
10197330f729Sjoerg // if so, this expression statement is the last statement in a statment
10207330f729Sjoerg // expression.
10217330f729Sjoerg IsStmtExprResult = GetLookAheadToken(LookAhead).is(tok::r_brace) &&
10227330f729Sjoerg GetLookAheadToken(LookAhead + 1).is(tok::r_paren);
10237330f729Sjoerg }
10247330f729Sjoerg
10257330f729Sjoerg if (IsStmtExprResult)
10267330f729Sjoerg E = Actions.ActOnStmtExprResult(E);
10277330f729Sjoerg return Actions.ActOnExprStmt(E, /*DiscardedValue=*/!IsStmtExprResult);
10287330f729Sjoerg }
10297330f729Sjoerg
10307330f729Sjoerg /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
10317330f729Sjoerg /// ActOnCompoundStmt action. This expects the '{' to be the current token, and
10327330f729Sjoerg /// consume the '}' at the end of the block. It does not manipulate the scope
10337330f729Sjoerg /// stack.
ParseCompoundStatementBody(bool isStmtExpr)10347330f729Sjoerg StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
10357330f729Sjoerg PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
10367330f729Sjoerg Tok.getLocation(),
10377330f729Sjoerg "in compound statement ('{}')");
10387330f729Sjoerg
1039*e038c9c4Sjoerg // Record the current FPFeatures, restore on leaving the
10407330f729Sjoerg // compound statement.
1041*e038c9c4Sjoerg Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
10427330f729Sjoerg
10437330f729Sjoerg InMessageExpressionRAIIObject InMessage(*this, false);
10447330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_brace);
10457330f729Sjoerg if (T.consumeOpen())
10467330f729Sjoerg return StmtError();
10477330f729Sjoerg
10487330f729Sjoerg Sema::CompoundScopeRAII CompoundScope(Actions, isStmtExpr);
10497330f729Sjoerg
10507330f729Sjoerg // Parse any pragmas at the beginning of the compound statement.
10517330f729Sjoerg ParseCompoundStatementLeadingPragmas();
1052*e038c9c4Sjoerg Actions.ActOnAfterCompoundStatementLeadingPragmas();
10537330f729Sjoerg
10547330f729Sjoerg StmtVector Stmts;
10557330f729Sjoerg
10567330f729Sjoerg // "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
10577330f729Sjoerg // only allowed at the start of a compound stmt regardless of the language.
10587330f729Sjoerg while (Tok.is(tok::kw___label__)) {
10597330f729Sjoerg SourceLocation LabelLoc = ConsumeToken();
10607330f729Sjoerg
10617330f729Sjoerg SmallVector<Decl *, 8> DeclsInGroup;
10627330f729Sjoerg while (1) {
10637330f729Sjoerg if (Tok.isNot(tok::identifier)) {
10647330f729Sjoerg Diag(Tok, diag::err_expected) << tok::identifier;
10657330f729Sjoerg break;
10667330f729Sjoerg }
10677330f729Sjoerg
10687330f729Sjoerg IdentifierInfo *II = Tok.getIdentifierInfo();
10697330f729Sjoerg SourceLocation IdLoc = ConsumeToken();
10707330f729Sjoerg DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc));
10717330f729Sjoerg
10727330f729Sjoerg if (!TryConsumeToken(tok::comma))
10737330f729Sjoerg break;
10747330f729Sjoerg }
10757330f729Sjoerg
10767330f729Sjoerg DeclSpec DS(AttrFactory);
10777330f729Sjoerg DeclGroupPtrTy Res =
10787330f729Sjoerg Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
10797330f729Sjoerg StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation());
10807330f729Sjoerg
10817330f729Sjoerg ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
10827330f729Sjoerg if (R.isUsable())
10837330f729Sjoerg Stmts.push_back(R.get());
10847330f729Sjoerg }
10857330f729Sjoerg
10867330f729Sjoerg ParsedStmtContext SubStmtCtx =
10877330f729Sjoerg ParsedStmtContext::Compound |
10887330f729Sjoerg (isStmtExpr ? ParsedStmtContext::InStmtExpr : ParsedStmtContext());
10897330f729Sjoerg
10907330f729Sjoerg while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
10917330f729Sjoerg Tok.isNot(tok::eof)) {
10927330f729Sjoerg if (Tok.is(tok::annot_pragma_unused)) {
10937330f729Sjoerg HandlePragmaUnused();
10947330f729Sjoerg continue;
10957330f729Sjoerg }
10967330f729Sjoerg
10977330f729Sjoerg if (ConsumeNullStmt(Stmts))
10987330f729Sjoerg continue;
10997330f729Sjoerg
11007330f729Sjoerg StmtResult R;
11017330f729Sjoerg if (Tok.isNot(tok::kw___extension__)) {
11027330f729Sjoerg R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
11037330f729Sjoerg } else {
11047330f729Sjoerg // __extension__ can start declarations and it can also be a unary
11057330f729Sjoerg // operator for expressions. Consume multiple __extension__ markers here
11067330f729Sjoerg // until we can determine which is which.
11077330f729Sjoerg // FIXME: This loses extension expressions in the AST!
11087330f729Sjoerg SourceLocation ExtLoc = ConsumeToken();
11097330f729Sjoerg while (Tok.is(tok::kw___extension__))
11107330f729Sjoerg ConsumeToken();
11117330f729Sjoerg
11127330f729Sjoerg ParsedAttributesWithRange attrs(AttrFactory);
11137330f729Sjoerg MaybeParseCXX11Attributes(attrs, nullptr,
11147330f729Sjoerg /*MightBeObjCMessageSend*/ true);
11157330f729Sjoerg
11167330f729Sjoerg // If this is the start of a declaration, parse it as such.
11177330f729Sjoerg if (isDeclarationStatement()) {
11187330f729Sjoerg // __extension__ silences extension warnings in the subdeclaration.
11197330f729Sjoerg // FIXME: Save the __extension__ on the decl as a node somehow?
11207330f729Sjoerg ExtensionRAIIObject O(Diags);
11217330f729Sjoerg
11227330f729Sjoerg SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
11237330f729Sjoerg DeclGroupPtrTy Res =
1124*e038c9c4Sjoerg ParseDeclaration(DeclaratorContext::Block, DeclEnd, attrs);
11257330f729Sjoerg R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
11267330f729Sjoerg } else {
11277330f729Sjoerg // Otherwise this was a unary __extension__ marker.
11287330f729Sjoerg ExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
11297330f729Sjoerg
11307330f729Sjoerg if (Res.isInvalid()) {
11317330f729Sjoerg SkipUntil(tok::semi);
11327330f729Sjoerg continue;
11337330f729Sjoerg }
11347330f729Sjoerg
11357330f729Sjoerg // Eat the semicolon at the end of stmt and convert the expr into a
11367330f729Sjoerg // statement.
11377330f729Sjoerg ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
11387330f729Sjoerg R = handleExprStmt(Res, SubStmtCtx);
11397330f729Sjoerg if (R.isUsable())
1140*e038c9c4Sjoerg R = Actions.ActOnAttributedStmt(attrs, R.get());
11417330f729Sjoerg }
11427330f729Sjoerg }
11437330f729Sjoerg
11447330f729Sjoerg if (R.isUsable())
11457330f729Sjoerg Stmts.push_back(R.get());
11467330f729Sjoerg }
11477330f729Sjoerg
11487330f729Sjoerg SourceLocation CloseLoc = Tok.getLocation();
11497330f729Sjoerg
11507330f729Sjoerg // We broke out of the while loop because we found a '}' or EOF.
1151*e038c9c4Sjoerg if (!T.consumeClose()) {
1152*e038c9c4Sjoerg // If this is the '})' of a statement expression, check that it's written
1153*e038c9c4Sjoerg // in a sensible way.
1154*e038c9c4Sjoerg if (isStmtExpr && Tok.is(tok::r_paren))
1155*e038c9c4Sjoerg checkCompoundToken(CloseLoc, tok::r_brace, CompoundToken::StmtExprEnd);
1156*e038c9c4Sjoerg } else {
11577330f729Sjoerg // Recover by creating a compound statement with what we parsed so far,
1158*e038c9c4Sjoerg // instead of dropping everything and returning StmtError().
1159*e038c9c4Sjoerg }
1160*e038c9c4Sjoerg
1161*e038c9c4Sjoerg if (T.getCloseLocation().isValid())
11627330f729Sjoerg CloseLoc = T.getCloseLocation();
11637330f729Sjoerg
11647330f729Sjoerg return Actions.ActOnCompoundStmt(T.getOpenLocation(), CloseLoc,
11657330f729Sjoerg Stmts, isStmtExpr);
11667330f729Sjoerg }
11677330f729Sjoerg
11687330f729Sjoerg /// ParseParenExprOrCondition:
11697330f729Sjoerg /// [C ] '(' expression ')'
11707330f729Sjoerg /// [C++] '(' condition ')'
11717330f729Sjoerg /// [C++1z] '(' init-statement[opt] condition ')'
11727330f729Sjoerg ///
11737330f729Sjoerg /// This function parses and performs error recovery on the specified condition
11747330f729Sjoerg /// or expression (depending on whether we're in C++ or C mode). This function
11757330f729Sjoerg /// goes out of its way to recover well. It returns true if there was a parser
11767330f729Sjoerg /// error (the right paren couldn't be found), which indicates that the caller
11777330f729Sjoerg /// should try to recover harder. It returns false if the condition is
11787330f729Sjoerg /// successfully parsed. Note that a successful parse can still have semantic
11797330f729Sjoerg /// errors in the condition.
1180*e038c9c4Sjoerg /// Additionally, if LParenLoc and RParenLoc are non-null, it will assign
1181*e038c9c4Sjoerg /// the location of the outer-most '(' and ')', respectively, to them.
ParseParenExprOrCondition(StmtResult * InitStmt,Sema::ConditionResult & Cond,SourceLocation Loc,Sema::ConditionKind CK,SourceLocation * LParenLoc,SourceLocation * RParenLoc)11827330f729Sjoerg bool Parser::ParseParenExprOrCondition(StmtResult *InitStmt,
11837330f729Sjoerg Sema::ConditionResult &Cond,
11847330f729Sjoerg SourceLocation Loc,
1185*e038c9c4Sjoerg Sema::ConditionKind CK,
1186*e038c9c4Sjoerg SourceLocation *LParenLoc,
1187*e038c9c4Sjoerg SourceLocation *RParenLoc) {
11887330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
11897330f729Sjoerg T.consumeOpen();
11907330f729Sjoerg
11917330f729Sjoerg if (getLangOpts().CPlusPlus)
11927330f729Sjoerg Cond = ParseCXXCondition(InitStmt, Loc, CK);
11937330f729Sjoerg else {
11947330f729Sjoerg ExprResult CondExpr = ParseExpression();
11957330f729Sjoerg
11967330f729Sjoerg // If required, convert to a boolean value.
11977330f729Sjoerg if (CondExpr.isInvalid())
11987330f729Sjoerg Cond = Sema::ConditionError();
11997330f729Sjoerg else
12007330f729Sjoerg Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK);
12017330f729Sjoerg }
12027330f729Sjoerg
12037330f729Sjoerg // If the parser was confused by the condition and we don't have a ')', try to
12047330f729Sjoerg // recover by skipping ahead to a semi and bailing out. If condexp is
12057330f729Sjoerg // semantically invalid but we have well formed code, keep going.
12067330f729Sjoerg if (Cond.isInvalid() && Tok.isNot(tok::r_paren)) {
12077330f729Sjoerg SkipUntil(tok::semi);
12087330f729Sjoerg // Skipping may have stopped if it found the containing ')'. If so, we can
12097330f729Sjoerg // continue parsing the if statement.
12107330f729Sjoerg if (Tok.isNot(tok::r_paren))
12117330f729Sjoerg return true;
12127330f729Sjoerg }
12137330f729Sjoerg
12147330f729Sjoerg // Otherwise the condition is valid or the rparen is present.
12157330f729Sjoerg T.consumeClose();
12167330f729Sjoerg
1217*e038c9c4Sjoerg if (LParenLoc != nullptr) {
1218*e038c9c4Sjoerg *LParenLoc = T.getOpenLocation();
1219*e038c9c4Sjoerg }
1220*e038c9c4Sjoerg if (RParenLoc != nullptr) {
1221*e038c9c4Sjoerg *RParenLoc = T.getCloseLocation();
1222*e038c9c4Sjoerg }
1223*e038c9c4Sjoerg
12247330f729Sjoerg // Check for extraneous ')'s to catch things like "if (foo())) {". We know
12257330f729Sjoerg // that all callers are looking for a statement after the condition, so ")"
12267330f729Sjoerg // isn't valid.
12277330f729Sjoerg while (Tok.is(tok::r_paren)) {
12287330f729Sjoerg Diag(Tok, diag::err_extraneous_rparen_in_condition)
12297330f729Sjoerg << FixItHint::CreateRemoval(Tok.getLocation());
12307330f729Sjoerg ConsumeParen();
12317330f729Sjoerg }
12327330f729Sjoerg
12337330f729Sjoerg return false;
12347330f729Sjoerg }
12357330f729Sjoerg
1236*e038c9c4Sjoerg namespace {
1237*e038c9c4Sjoerg
1238*e038c9c4Sjoerg enum MisleadingStatementKind { MSK_if, MSK_else, MSK_for, MSK_while };
1239*e038c9c4Sjoerg
1240*e038c9c4Sjoerg struct MisleadingIndentationChecker {
1241*e038c9c4Sjoerg Parser &P;
1242*e038c9c4Sjoerg SourceLocation StmtLoc;
1243*e038c9c4Sjoerg SourceLocation PrevLoc;
1244*e038c9c4Sjoerg unsigned NumDirectives;
1245*e038c9c4Sjoerg MisleadingStatementKind Kind;
1246*e038c9c4Sjoerg bool ShouldSkip;
MisleadingIndentationChecker__anon81a834f20311::MisleadingIndentationChecker1247*e038c9c4Sjoerg MisleadingIndentationChecker(Parser &P, MisleadingStatementKind K,
1248*e038c9c4Sjoerg SourceLocation SL)
1249*e038c9c4Sjoerg : P(P), StmtLoc(SL), PrevLoc(P.getCurToken().getLocation()),
1250*e038c9c4Sjoerg NumDirectives(P.getPreprocessor().getNumDirectives()), Kind(K),
1251*e038c9c4Sjoerg ShouldSkip(P.getCurToken().is(tok::l_brace)) {
1252*e038c9c4Sjoerg if (!P.MisleadingIndentationElseLoc.isInvalid()) {
1253*e038c9c4Sjoerg StmtLoc = P.MisleadingIndentationElseLoc;
1254*e038c9c4Sjoerg P.MisleadingIndentationElseLoc = SourceLocation();
1255*e038c9c4Sjoerg }
1256*e038c9c4Sjoerg if (Kind == MSK_else && !ShouldSkip)
1257*e038c9c4Sjoerg P.MisleadingIndentationElseLoc = SL;
1258*e038c9c4Sjoerg }
1259*e038c9c4Sjoerg
1260*e038c9c4Sjoerg /// Compute the column number will aligning tabs on TabStop (-ftabstop), this
1261*e038c9c4Sjoerg /// gives the visual indentation of the SourceLocation.
getVisualIndentation__anon81a834f20311::MisleadingIndentationChecker1262*e038c9c4Sjoerg static unsigned getVisualIndentation(SourceManager &SM, SourceLocation Loc) {
1263*e038c9c4Sjoerg unsigned TabStop = SM.getDiagnostics().getDiagnosticOptions().TabStop;
1264*e038c9c4Sjoerg
1265*e038c9c4Sjoerg unsigned ColNo = SM.getSpellingColumnNumber(Loc);
1266*e038c9c4Sjoerg if (ColNo == 0 || TabStop == 1)
1267*e038c9c4Sjoerg return ColNo;
1268*e038c9c4Sjoerg
1269*e038c9c4Sjoerg std::pair<FileID, unsigned> FIDAndOffset = SM.getDecomposedLoc(Loc);
1270*e038c9c4Sjoerg
1271*e038c9c4Sjoerg bool Invalid;
1272*e038c9c4Sjoerg StringRef BufData = SM.getBufferData(FIDAndOffset.first, &Invalid);
1273*e038c9c4Sjoerg if (Invalid)
1274*e038c9c4Sjoerg return 0;
1275*e038c9c4Sjoerg
1276*e038c9c4Sjoerg const char *EndPos = BufData.data() + FIDAndOffset.second;
1277*e038c9c4Sjoerg // FileOffset are 0-based and Column numbers are 1-based
1278*e038c9c4Sjoerg assert(FIDAndOffset.second + 1 >= ColNo &&
1279*e038c9c4Sjoerg "Column number smaller than file offset?");
1280*e038c9c4Sjoerg
1281*e038c9c4Sjoerg unsigned VisualColumn = 0; // Stored as 0-based column, here.
1282*e038c9c4Sjoerg // Loop from beginning of line up to Loc's file position, counting columns,
1283*e038c9c4Sjoerg // expanding tabs.
1284*e038c9c4Sjoerg for (const char *CurPos = EndPos - (ColNo - 1); CurPos != EndPos;
1285*e038c9c4Sjoerg ++CurPos) {
1286*e038c9c4Sjoerg if (*CurPos == '\t')
1287*e038c9c4Sjoerg // Advance visual column to next tabstop.
1288*e038c9c4Sjoerg VisualColumn += (TabStop - VisualColumn % TabStop);
1289*e038c9c4Sjoerg else
1290*e038c9c4Sjoerg VisualColumn++;
1291*e038c9c4Sjoerg }
1292*e038c9c4Sjoerg return VisualColumn + 1;
1293*e038c9c4Sjoerg }
1294*e038c9c4Sjoerg
Check__anon81a834f20311::MisleadingIndentationChecker1295*e038c9c4Sjoerg void Check() {
1296*e038c9c4Sjoerg Token Tok = P.getCurToken();
1297*e038c9c4Sjoerg if (P.getActions().getDiagnostics().isIgnored(
1298*e038c9c4Sjoerg diag::warn_misleading_indentation, Tok.getLocation()) ||
1299*e038c9c4Sjoerg ShouldSkip || NumDirectives != P.getPreprocessor().getNumDirectives() ||
1300*e038c9c4Sjoerg Tok.isOneOf(tok::semi, tok::r_brace) || Tok.isAnnotation() ||
1301*e038c9c4Sjoerg Tok.getLocation().isMacroID() || PrevLoc.isMacroID() ||
1302*e038c9c4Sjoerg StmtLoc.isMacroID() ||
1303*e038c9c4Sjoerg (Kind == MSK_else && P.MisleadingIndentationElseLoc.isInvalid())) {
1304*e038c9c4Sjoerg P.MisleadingIndentationElseLoc = SourceLocation();
1305*e038c9c4Sjoerg return;
1306*e038c9c4Sjoerg }
1307*e038c9c4Sjoerg if (Kind == MSK_else)
1308*e038c9c4Sjoerg P.MisleadingIndentationElseLoc = SourceLocation();
1309*e038c9c4Sjoerg
1310*e038c9c4Sjoerg SourceManager &SM = P.getPreprocessor().getSourceManager();
1311*e038c9c4Sjoerg unsigned PrevColNum = getVisualIndentation(SM, PrevLoc);
1312*e038c9c4Sjoerg unsigned CurColNum = getVisualIndentation(SM, Tok.getLocation());
1313*e038c9c4Sjoerg unsigned StmtColNum = getVisualIndentation(SM, StmtLoc);
1314*e038c9c4Sjoerg
1315*e038c9c4Sjoerg if (PrevColNum != 0 && CurColNum != 0 && StmtColNum != 0 &&
1316*e038c9c4Sjoerg ((PrevColNum > StmtColNum && PrevColNum == CurColNum) ||
1317*e038c9c4Sjoerg !Tok.isAtStartOfLine()) &&
1318*e038c9c4Sjoerg SM.getPresumedLineNumber(StmtLoc) !=
1319*e038c9c4Sjoerg SM.getPresumedLineNumber(Tok.getLocation()) &&
1320*e038c9c4Sjoerg (Tok.isNot(tok::identifier) ||
1321*e038c9c4Sjoerg P.getPreprocessor().LookAhead(0).isNot(tok::colon))) {
1322*e038c9c4Sjoerg P.Diag(Tok.getLocation(), diag::warn_misleading_indentation) << Kind;
1323*e038c9c4Sjoerg P.Diag(StmtLoc, diag::note_previous_statement);
1324*e038c9c4Sjoerg }
1325*e038c9c4Sjoerg }
1326*e038c9c4Sjoerg };
1327*e038c9c4Sjoerg
1328*e038c9c4Sjoerg }
13297330f729Sjoerg
13307330f729Sjoerg /// ParseIfStatement
13317330f729Sjoerg /// if-statement: [C99 6.8.4.1]
13327330f729Sjoerg /// 'if' '(' expression ')' statement
13337330f729Sjoerg /// 'if' '(' expression ')' statement 'else' statement
13347330f729Sjoerg /// [C++] 'if' '(' condition ')' statement
13357330f729Sjoerg /// [C++] 'if' '(' condition ')' statement 'else' statement
13367330f729Sjoerg ///
ParseIfStatement(SourceLocation * TrailingElseLoc)13377330f729Sjoerg StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
13387330f729Sjoerg assert(Tok.is(tok::kw_if) && "Not an if stmt!");
13397330f729Sjoerg SourceLocation IfLoc = ConsumeToken(); // eat the 'if'.
13407330f729Sjoerg
13417330f729Sjoerg bool IsConstexpr = false;
13427330f729Sjoerg if (Tok.is(tok::kw_constexpr)) {
13437330f729Sjoerg Diag(Tok, getLangOpts().CPlusPlus17 ? diag::warn_cxx14_compat_constexpr_if
13447330f729Sjoerg : diag::ext_constexpr_if);
13457330f729Sjoerg IsConstexpr = true;
13467330f729Sjoerg ConsumeToken();
13477330f729Sjoerg }
13487330f729Sjoerg
13497330f729Sjoerg if (Tok.isNot(tok::l_paren)) {
13507330f729Sjoerg Diag(Tok, diag::err_expected_lparen_after) << "if";
13517330f729Sjoerg SkipUntil(tok::semi);
13527330f729Sjoerg return StmtError();
13537330f729Sjoerg }
13547330f729Sjoerg
13557330f729Sjoerg bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
13567330f729Sjoerg
13577330f729Sjoerg // C99 6.8.4p3 - In C99, the if statement is a block. This is not
13587330f729Sjoerg // the case for C90.
13597330f729Sjoerg //
13607330f729Sjoerg // C++ 6.4p3:
13617330f729Sjoerg // A name introduced by a declaration in a condition is in scope from its
13627330f729Sjoerg // point of declaration until the end of the substatements controlled by the
13637330f729Sjoerg // condition.
13647330f729Sjoerg // C++ 3.3.2p4:
13657330f729Sjoerg // Names declared in the for-init-statement, and in the condition of if,
13667330f729Sjoerg // while, for, and switch statements are local to the if, while, for, or
13677330f729Sjoerg // switch statement (including the controlled statement).
13687330f729Sjoerg //
13697330f729Sjoerg ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
13707330f729Sjoerg
13717330f729Sjoerg // Parse the condition.
13727330f729Sjoerg StmtResult InitStmt;
13737330f729Sjoerg Sema::ConditionResult Cond;
1374*e038c9c4Sjoerg SourceLocation LParen;
1375*e038c9c4Sjoerg SourceLocation RParen;
13767330f729Sjoerg if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc,
13777330f729Sjoerg IsConstexpr ? Sema::ConditionKind::ConstexprIf
1378*e038c9c4Sjoerg : Sema::ConditionKind::Boolean,
1379*e038c9c4Sjoerg &LParen, &RParen))
13807330f729Sjoerg return StmtError();
13817330f729Sjoerg
13827330f729Sjoerg llvm::Optional<bool> ConstexprCondition;
13837330f729Sjoerg if (IsConstexpr)
13847330f729Sjoerg ConstexprCondition = Cond.getKnownValue();
13857330f729Sjoerg
1386*e038c9c4Sjoerg bool IsBracedThen = Tok.is(tok::l_brace);
1387*e038c9c4Sjoerg
13887330f729Sjoerg // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
13897330f729Sjoerg // there is no compound stmt. C90 does not have this clause. We only do this
13907330f729Sjoerg // if the body isn't a compound statement to avoid push/pop in common cases.
13917330f729Sjoerg //
13927330f729Sjoerg // C++ 6.4p1:
13937330f729Sjoerg // The substatement in a selection-statement (each substatement, in the else
13947330f729Sjoerg // form of the if statement) implicitly defines a local scope.
13957330f729Sjoerg //
13967330f729Sjoerg // For C++ we create a scope for the condition and a new scope for
13977330f729Sjoerg // substatements because:
13987330f729Sjoerg // -When the 'then' scope exits, we want the condition declaration to still be
13997330f729Sjoerg // active for the 'else' scope too.
14007330f729Sjoerg // -Sema will detect name clashes by considering declarations of a
14017330f729Sjoerg // 'ControlScope' as part of its direct subscope.
14027330f729Sjoerg // -If we wanted the condition and substatement to be in the same scope, we
14037330f729Sjoerg // would have to notify ParseStatement not to create a new scope. It's
14047330f729Sjoerg // simpler to let it create a new scope.
14057330f729Sjoerg //
1406*e038c9c4Sjoerg ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, IsBracedThen);
1407*e038c9c4Sjoerg
1408*e038c9c4Sjoerg MisleadingIndentationChecker MIChecker(*this, MSK_if, IfLoc);
14097330f729Sjoerg
14107330f729Sjoerg // Read the 'then' stmt.
14117330f729Sjoerg SourceLocation ThenStmtLoc = Tok.getLocation();
14127330f729Sjoerg
14137330f729Sjoerg SourceLocation InnerStatementTrailingElseLoc;
14147330f729Sjoerg StmtResult ThenStmt;
14157330f729Sjoerg {
14167330f729Sjoerg EnterExpressionEvaluationContext PotentiallyDiscarded(
14177330f729Sjoerg Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr,
14187330f729Sjoerg Sema::ExpressionEvaluationContextRecord::EK_Other,
14197330f729Sjoerg /*ShouldEnter=*/ConstexprCondition && !*ConstexprCondition);
14207330f729Sjoerg ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
14217330f729Sjoerg }
14227330f729Sjoerg
1423*e038c9c4Sjoerg if (Tok.isNot(tok::kw_else))
1424*e038c9c4Sjoerg MIChecker.Check();
1425*e038c9c4Sjoerg
14267330f729Sjoerg // Pop the 'if' scope if needed.
14277330f729Sjoerg InnerScope.Exit();
14287330f729Sjoerg
14297330f729Sjoerg // If it has an else, parse it.
14307330f729Sjoerg SourceLocation ElseLoc;
14317330f729Sjoerg SourceLocation ElseStmtLoc;
14327330f729Sjoerg StmtResult ElseStmt;
14337330f729Sjoerg
14347330f729Sjoerg if (Tok.is(tok::kw_else)) {
14357330f729Sjoerg if (TrailingElseLoc)
14367330f729Sjoerg *TrailingElseLoc = Tok.getLocation();
14377330f729Sjoerg
14387330f729Sjoerg ElseLoc = ConsumeToken();
14397330f729Sjoerg ElseStmtLoc = Tok.getLocation();
14407330f729Sjoerg
14417330f729Sjoerg // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
14427330f729Sjoerg // there is no compound stmt. C90 does not have this clause. We only do
14437330f729Sjoerg // this if the body isn't a compound statement to avoid push/pop in common
14447330f729Sjoerg // cases.
14457330f729Sjoerg //
14467330f729Sjoerg // C++ 6.4p1:
14477330f729Sjoerg // The substatement in a selection-statement (each substatement, in the else
14487330f729Sjoerg // form of the if statement) implicitly defines a local scope.
14497330f729Sjoerg //
14507330f729Sjoerg ParseScope InnerScope(this, Scope::DeclScope, C99orCXX,
14517330f729Sjoerg Tok.is(tok::l_brace));
14527330f729Sjoerg
1453*e038c9c4Sjoerg MisleadingIndentationChecker MIChecker(*this, MSK_else, ElseLoc);
1454*e038c9c4Sjoerg
14557330f729Sjoerg EnterExpressionEvaluationContext PotentiallyDiscarded(
14567330f729Sjoerg Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr,
14577330f729Sjoerg Sema::ExpressionEvaluationContextRecord::EK_Other,
14587330f729Sjoerg /*ShouldEnter=*/ConstexprCondition && *ConstexprCondition);
14597330f729Sjoerg ElseStmt = ParseStatement();
14607330f729Sjoerg
1461*e038c9c4Sjoerg if (ElseStmt.isUsable())
1462*e038c9c4Sjoerg MIChecker.Check();
1463*e038c9c4Sjoerg
14647330f729Sjoerg // Pop the 'else' scope if needed.
14657330f729Sjoerg InnerScope.Exit();
14667330f729Sjoerg } else if (Tok.is(tok::code_completion)) {
14677330f729Sjoerg cutOffParsing();
1468*e038c9c4Sjoerg Actions.CodeCompleteAfterIf(getCurScope(), IsBracedThen);
14697330f729Sjoerg return StmtError();
14707330f729Sjoerg } else if (InnerStatementTrailingElseLoc.isValid()) {
14717330f729Sjoerg Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else);
14727330f729Sjoerg }
14737330f729Sjoerg
14747330f729Sjoerg IfScope.Exit();
14757330f729Sjoerg
14767330f729Sjoerg // If the then or else stmt is invalid and the other is valid (and present),
14777330f729Sjoerg // make turn the invalid one into a null stmt to avoid dropping the other
14787330f729Sjoerg // part. If both are invalid, return error.
14797330f729Sjoerg if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
14807330f729Sjoerg (ThenStmt.isInvalid() && ElseStmt.get() == nullptr) ||
14817330f729Sjoerg (ThenStmt.get() == nullptr && ElseStmt.isInvalid())) {
14827330f729Sjoerg // Both invalid, or one is invalid and other is non-present: return error.
14837330f729Sjoerg return StmtError();
14847330f729Sjoerg }
14857330f729Sjoerg
14867330f729Sjoerg // Now if either are invalid, replace with a ';'.
14877330f729Sjoerg if (ThenStmt.isInvalid())
14887330f729Sjoerg ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
14897330f729Sjoerg if (ElseStmt.isInvalid())
14907330f729Sjoerg ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
14917330f729Sjoerg
1492*e038c9c4Sjoerg return Actions.ActOnIfStmt(IfLoc, IsConstexpr, LParen, InitStmt.get(), Cond,
1493*e038c9c4Sjoerg RParen, ThenStmt.get(), ElseLoc, ElseStmt.get());
14947330f729Sjoerg }
14957330f729Sjoerg
14967330f729Sjoerg /// ParseSwitchStatement
14977330f729Sjoerg /// switch-statement:
14987330f729Sjoerg /// 'switch' '(' expression ')' statement
14997330f729Sjoerg /// [C++] 'switch' '(' condition ')' statement
ParseSwitchStatement(SourceLocation * TrailingElseLoc)15007330f729Sjoerg StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
15017330f729Sjoerg assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
15027330f729Sjoerg SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'.
15037330f729Sjoerg
15047330f729Sjoerg if (Tok.isNot(tok::l_paren)) {
15057330f729Sjoerg Diag(Tok, diag::err_expected_lparen_after) << "switch";
15067330f729Sjoerg SkipUntil(tok::semi);
15077330f729Sjoerg return StmtError();
15087330f729Sjoerg }
15097330f729Sjoerg
15107330f729Sjoerg bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
15117330f729Sjoerg
15127330f729Sjoerg // C99 6.8.4p3 - In C99, the switch statement is a block. This is
15137330f729Sjoerg // not the case for C90. Start the switch scope.
15147330f729Sjoerg //
15157330f729Sjoerg // C++ 6.4p3:
15167330f729Sjoerg // A name introduced by a declaration in a condition is in scope from its
15177330f729Sjoerg // point of declaration until the end of the substatements controlled by the
15187330f729Sjoerg // condition.
15197330f729Sjoerg // C++ 3.3.2p4:
15207330f729Sjoerg // Names declared in the for-init-statement, and in the condition of if,
15217330f729Sjoerg // while, for, and switch statements are local to the if, while, for, or
15227330f729Sjoerg // switch statement (including the controlled statement).
15237330f729Sjoerg //
15247330f729Sjoerg unsigned ScopeFlags = Scope::SwitchScope;
15257330f729Sjoerg if (C99orCXX)
15267330f729Sjoerg ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
15277330f729Sjoerg ParseScope SwitchScope(this, ScopeFlags);
15287330f729Sjoerg
15297330f729Sjoerg // Parse the condition.
15307330f729Sjoerg StmtResult InitStmt;
15317330f729Sjoerg Sema::ConditionResult Cond;
1532*e038c9c4Sjoerg SourceLocation LParen;
1533*e038c9c4Sjoerg SourceLocation RParen;
15347330f729Sjoerg if (ParseParenExprOrCondition(&InitStmt, Cond, SwitchLoc,
1535*e038c9c4Sjoerg Sema::ConditionKind::Switch, &LParen, &RParen))
15367330f729Sjoerg return StmtError();
15377330f729Sjoerg
1538*e038c9c4Sjoerg StmtResult Switch = Actions.ActOnStartOfSwitchStmt(
1539*e038c9c4Sjoerg SwitchLoc, LParen, InitStmt.get(), Cond, RParen);
15407330f729Sjoerg
15417330f729Sjoerg if (Switch.isInvalid()) {
15427330f729Sjoerg // Skip the switch body.
15437330f729Sjoerg // FIXME: This is not optimal recovery, but parsing the body is more
15447330f729Sjoerg // dangerous due to the presence of case and default statements, which
15457330f729Sjoerg // will have no place to connect back with the switch.
15467330f729Sjoerg if (Tok.is(tok::l_brace)) {
15477330f729Sjoerg ConsumeBrace();
15487330f729Sjoerg SkipUntil(tok::r_brace);
15497330f729Sjoerg } else
15507330f729Sjoerg SkipUntil(tok::semi);
15517330f729Sjoerg return Switch;
15527330f729Sjoerg }
15537330f729Sjoerg
15547330f729Sjoerg // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
15557330f729Sjoerg // there is no compound stmt. C90 does not have this clause. We only do this
15567330f729Sjoerg // if the body isn't a compound statement to avoid push/pop in common cases.
15577330f729Sjoerg //
15587330f729Sjoerg // C++ 6.4p1:
15597330f729Sjoerg // The substatement in a selection-statement (each substatement, in the else
15607330f729Sjoerg // form of the if statement) implicitly defines a local scope.
15617330f729Sjoerg //
15627330f729Sjoerg // See comments in ParseIfStatement for why we create a scope for the
15637330f729Sjoerg // condition and a new scope for substatement in C++.
15647330f729Sjoerg //
15657330f729Sjoerg getCurScope()->AddFlags(Scope::BreakScope);
15667330f729Sjoerg ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
15677330f729Sjoerg
15687330f729Sjoerg // We have incremented the mangling number for the SwitchScope and the
15697330f729Sjoerg // InnerScope, which is one too many.
15707330f729Sjoerg if (C99orCXX)
15717330f729Sjoerg getCurScope()->decrementMSManglingNumber();
15727330f729Sjoerg
15737330f729Sjoerg // Read the body statement.
15747330f729Sjoerg StmtResult Body(ParseStatement(TrailingElseLoc));
15757330f729Sjoerg
15767330f729Sjoerg // Pop the scopes.
15777330f729Sjoerg InnerScope.Exit();
15787330f729Sjoerg SwitchScope.Exit();
15797330f729Sjoerg
15807330f729Sjoerg return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get());
15817330f729Sjoerg }
15827330f729Sjoerg
15837330f729Sjoerg /// ParseWhileStatement
15847330f729Sjoerg /// while-statement: [C99 6.8.5.1]
15857330f729Sjoerg /// 'while' '(' expression ')' statement
15867330f729Sjoerg /// [C++] 'while' '(' condition ')' statement
ParseWhileStatement(SourceLocation * TrailingElseLoc)15877330f729Sjoerg StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
15887330f729Sjoerg assert(Tok.is(tok::kw_while) && "Not a while stmt!");
15897330f729Sjoerg SourceLocation WhileLoc = Tok.getLocation();
15907330f729Sjoerg ConsumeToken(); // eat the 'while'.
15917330f729Sjoerg
15927330f729Sjoerg if (Tok.isNot(tok::l_paren)) {
15937330f729Sjoerg Diag(Tok, diag::err_expected_lparen_after) << "while";
15947330f729Sjoerg SkipUntil(tok::semi);
15957330f729Sjoerg return StmtError();
15967330f729Sjoerg }
15977330f729Sjoerg
15987330f729Sjoerg bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
15997330f729Sjoerg
16007330f729Sjoerg // C99 6.8.5p5 - In C99, the while statement is a block. This is not
16017330f729Sjoerg // the case for C90. Start the loop scope.
16027330f729Sjoerg //
16037330f729Sjoerg // C++ 6.4p3:
16047330f729Sjoerg // A name introduced by a declaration in a condition is in scope from its
16057330f729Sjoerg // point of declaration until the end of the substatements controlled by the
16067330f729Sjoerg // condition.
16077330f729Sjoerg // C++ 3.3.2p4:
16087330f729Sjoerg // Names declared in the for-init-statement, and in the condition of if,
16097330f729Sjoerg // while, for, and switch statements are local to the if, while, for, or
16107330f729Sjoerg // switch statement (including the controlled statement).
16117330f729Sjoerg //
16127330f729Sjoerg unsigned ScopeFlags;
16137330f729Sjoerg if (C99orCXX)
16147330f729Sjoerg ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
16157330f729Sjoerg Scope::DeclScope | Scope::ControlScope;
16167330f729Sjoerg else
16177330f729Sjoerg ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
16187330f729Sjoerg ParseScope WhileScope(this, ScopeFlags);
16197330f729Sjoerg
16207330f729Sjoerg // Parse the condition.
16217330f729Sjoerg Sema::ConditionResult Cond;
1622*e038c9c4Sjoerg SourceLocation LParen;
1623*e038c9c4Sjoerg SourceLocation RParen;
16247330f729Sjoerg if (ParseParenExprOrCondition(nullptr, Cond, WhileLoc,
1625*e038c9c4Sjoerg Sema::ConditionKind::Boolean, &LParen, &RParen))
16267330f729Sjoerg return StmtError();
16277330f729Sjoerg
16287330f729Sjoerg // C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if
16297330f729Sjoerg // there is no compound stmt. C90 does not have this clause. We only do this
16307330f729Sjoerg // if the body isn't a compound statement to avoid push/pop in common cases.
16317330f729Sjoerg //
16327330f729Sjoerg // C++ 6.5p2:
16337330f729Sjoerg // The substatement in an iteration-statement implicitly defines a local scope
16347330f729Sjoerg // which is entered and exited each time through the loop.
16357330f729Sjoerg //
16367330f729Sjoerg // See comments in ParseIfStatement for why we create a scope for the
16377330f729Sjoerg // condition and a new scope for substatement in C++.
16387330f729Sjoerg //
16397330f729Sjoerg ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
16407330f729Sjoerg
1641*e038c9c4Sjoerg MisleadingIndentationChecker MIChecker(*this, MSK_while, WhileLoc);
1642*e038c9c4Sjoerg
16437330f729Sjoerg // Read the body statement.
16447330f729Sjoerg StmtResult Body(ParseStatement(TrailingElseLoc));
16457330f729Sjoerg
1646*e038c9c4Sjoerg if (Body.isUsable())
1647*e038c9c4Sjoerg MIChecker.Check();
16487330f729Sjoerg // Pop the body scope if needed.
16497330f729Sjoerg InnerScope.Exit();
16507330f729Sjoerg WhileScope.Exit();
16517330f729Sjoerg
16527330f729Sjoerg if (Cond.isInvalid() || Body.isInvalid())
16537330f729Sjoerg return StmtError();
16547330f729Sjoerg
1655*e038c9c4Sjoerg return Actions.ActOnWhileStmt(WhileLoc, LParen, Cond, RParen, Body.get());
16567330f729Sjoerg }
16577330f729Sjoerg
16587330f729Sjoerg /// ParseDoStatement
16597330f729Sjoerg /// do-statement: [C99 6.8.5.2]
16607330f729Sjoerg /// 'do' statement 'while' '(' expression ')' ';'
16617330f729Sjoerg /// Note: this lets the caller parse the end ';'.
ParseDoStatement()16627330f729Sjoerg StmtResult Parser::ParseDoStatement() {
16637330f729Sjoerg assert(Tok.is(tok::kw_do) && "Not a do stmt!");
16647330f729Sjoerg SourceLocation DoLoc = ConsumeToken(); // eat the 'do'.
16657330f729Sjoerg
16667330f729Sjoerg // C99 6.8.5p5 - In C99, the do statement is a block. This is not
16677330f729Sjoerg // the case for C90. Start the loop scope.
16687330f729Sjoerg unsigned ScopeFlags;
16697330f729Sjoerg if (getLangOpts().C99)
16707330f729Sjoerg ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
16717330f729Sjoerg else
16727330f729Sjoerg ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
16737330f729Sjoerg
16747330f729Sjoerg ParseScope DoScope(this, ScopeFlags);
16757330f729Sjoerg
16767330f729Sjoerg // C99 6.8.5p5 - In C99, the body of the do statement is a scope, even if
16777330f729Sjoerg // there is no compound stmt. C90 does not have this clause. We only do this
16787330f729Sjoerg // if the body isn't a compound statement to avoid push/pop in common cases.
16797330f729Sjoerg //
16807330f729Sjoerg // C++ 6.5p2:
16817330f729Sjoerg // The substatement in an iteration-statement implicitly defines a local scope
16827330f729Sjoerg // which is entered and exited each time through the loop.
16837330f729Sjoerg //
16847330f729Sjoerg bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
16857330f729Sjoerg ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
16867330f729Sjoerg
16877330f729Sjoerg // Read the body statement.
16887330f729Sjoerg StmtResult Body(ParseStatement());
16897330f729Sjoerg
16907330f729Sjoerg // Pop the body scope if needed.
16917330f729Sjoerg InnerScope.Exit();
16927330f729Sjoerg
16937330f729Sjoerg if (Tok.isNot(tok::kw_while)) {
16947330f729Sjoerg if (!Body.isInvalid()) {
16957330f729Sjoerg Diag(Tok, diag::err_expected_while);
16967330f729Sjoerg Diag(DoLoc, diag::note_matching) << "'do'";
16977330f729Sjoerg SkipUntil(tok::semi, StopBeforeMatch);
16987330f729Sjoerg }
16997330f729Sjoerg return StmtError();
17007330f729Sjoerg }
17017330f729Sjoerg SourceLocation WhileLoc = ConsumeToken();
17027330f729Sjoerg
17037330f729Sjoerg if (Tok.isNot(tok::l_paren)) {
17047330f729Sjoerg Diag(Tok, diag::err_expected_lparen_after) << "do/while";
17057330f729Sjoerg SkipUntil(tok::semi, StopBeforeMatch);
17067330f729Sjoerg return StmtError();
17077330f729Sjoerg }
17087330f729Sjoerg
17097330f729Sjoerg // Parse the parenthesized expression.
17107330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
17117330f729Sjoerg T.consumeOpen();
17127330f729Sjoerg
17137330f729Sjoerg // A do-while expression is not a condition, so can't have attributes.
17147330f729Sjoerg DiagnoseAndSkipCXX11Attributes();
17157330f729Sjoerg
17167330f729Sjoerg ExprResult Cond = ParseExpression();
17177330f729Sjoerg // Correct the typos in condition before closing the scope.
17187330f729Sjoerg if (Cond.isUsable())
17197330f729Sjoerg Cond = Actions.CorrectDelayedTyposInExpr(Cond);
17207330f729Sjoerg T.consumeClose();
17217330f729Sjoerg DoScope.Exit();
17227330f729Sjoerg
17237330f729Sjoerg if (Cond.isInvalid() || Body.isInvalid())
17247330f729Sjoerg return StmtError();
17257330f729Sjoerg
17267330f729Sjoerg return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, T.getOpenLocation(),
17277330f729Sjoerg Cond.get(), T.getCloseLocation());
17287330f729Sjoerg }
17297330f729Sjoerg
isForRangeIdentifier()17307330f729Sjoerg bool Parser::isForRangeIdentifier() {
17317330f729Sjoerg assert(Tok.is(tok::identifier));
17327330f729Sjoerg
17337330f729Sjoerg const Token &Next = NextToken();
17347330f729Sjoerg if (Next.is(tok::colon))
17357330f729Sjoerg return true;
17367330f729Sjoerg
17377330f729Sjoerg if (Next.isOneOf(tok::l_square, tok::kw_alignas)) {
17387330f729Sjoerg TentativeParsingAction PA(*this);
17397330f729Sjoerg ConsumeToken();
17407330f729Sjoerg SkipCXX11Attributes();
17417330f729Sjoerg bool Result = Tok.is(tok::colon);
17427330f729Sjoerg PA.Revert();
17437330f729Sjoerg return Result;
17447330f729Sjoerg }
17457330f729Sjoerg
17467330f729Sjoerg return false;
17477330f729Sjoerg }
17487330f729Sjoerg
17497330f729Sjoerg /// ParseForStatement
17507330f729Sjoerg /// for-statement: [C99 6.8.5.3]
17517330f729Sjoerg /// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
17527330f729Sjoerg /// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
17537330f729Sjoerg /// [C++] 'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
17547330f729Sjoerg /// [C++] statement
17557330f729Sjoerg /// [C++0x] 'for'
17567330f729Sjoerg /// 'co_await'[opt] [Coroutines]
17577330f729Sjoerg /// '(' for-range-declaration ':' for-range-initializer ')'
17587330f729Sjoerg /// statement
17597330f729Sjoerg /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
17607330f729Sjoerg /// [OBJC2] 'for' '(' expr 'in' expr ')' statement
17617330f729Sjoerg ///
17627330f729Sjoerg /// [C++] for-init-statement:
17637330f729Sjoerg /// [C++] expression-statement
17647330f729Sjoerg /// [C++] simple-declaration
17657330f729Sjoerg ///
17667330f729Sjoerg /// [C++0x] for-range-declaration:
17677330f729Sjoerg /// [C++0x] attribute-specifier-seq[opt] type-specifier-seq declarator
17687330f729Sjoerg /// [C++0x] for-range-initializer:
17697330f729Sjoerg /// [C++0x] expression
17707330f729Sjoerg /// [C++0x] braced-init-list [TODO]
ParseForStatement(SourceLocation * TrailingElseLoc)17717330f729Sjoerg StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
17727330f729Sjoerg assert(Tok.is(tok::kw_for) && "Not a for stmt!");
17737330f729Sjoerg SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
17747330f729Sjoerg
17757330f729Sjoerg SourceLocation CoawaitLoc;
17767330f729Sjoerg if (Tok.is(tok::kw_co_await))
17777330f729Sjoerg CoawaitLoc = ConsumeToken();
17787330f729Sjoerg
17797330f729Sjoerg if (Tok.isNot(tok::l_paren)) {
17807330f729Sjoerg Diag(Tok, diag::err_expected_lparen_after) << "for";
17817330f729Sjoerg SkipUntil(tok::semi);
17827330f729Sjoerg return StmtError();
17837330f729Sjoerg }
17847330f729Sjoerg
17857330f729Sjoerg bool C99orCXXorObjC = getLangOpts().C99 || getLangOpts().CPlusPlus ||
17867330f729Sjoerg getLangOpts().ObjC;
17877330f729Sjoerg
17887330f729Sjoerg // C99 6.8.5p5 - In C99, the for statement is a block. This is not
17897330f729Sjoerg // the case for C90. Start the loop scope.
17907330f729Sjoerg //
17917330f729Sjoerg // C++ 6.4p3:
17927330f729Sjoerg // A name introduced by a declaration in a condition is in scope from its
17937330f729Sjoerg // point of declaration until the end of the substatements controlled by the
17947330f729Sjoerg // condition.
17957330f729Sjoerg // C++ 3.3.2p4:
17967330f729Sjoerg // Names declared in the for-init-statement, and in the condition of if,
17977330f729Sjoerg // while, for, and switch statements are local to the if, while, for, or
17987330f729Sjoerg // switch statement (including the controlled statement).
17997330f729Sjoerg // C++ 6.5.3p1:
18007330f729Sjoerg // Names declared in the for-init-statement are in the same declarative-region
18017330f729Sjoerg // as those declared in the condition.
18027330f729Sjoerg //
18037330f729Sjoerg unsigned ScopeFlags = 0;
18047330f729Sjoerg if (C99orCXXorObjC)
18057330f729Sjoerg ScopeFlags = Scope::DeclScope | Scope::ControlScope;
18067330f729Sjoerg
18077330f729Sjoerg ParseScope ForScope(this, ScopeFlags);
18087330f729Sjoerg
18097330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
18107330f729Sjoerg T.consumeOpen();
18117330f729Sjoerg
18127330f729Sjoerg ExprResult Value;
18137330f729Sjoerg
18147330f729Sjoerg bool ForEach = false;
18157330f729Sjoerg StmtResult FirstPart;
18167330f729Sjoerg Sema::ConditionResult SecondPart;
18177330f729Sjoerg ExprResult Collection;
18187330f729Sjoerg ForRangeInfo ForRangeInfo;
18197330f729Sjoerg FullExprArg ThirdPart(Actions);
18207330f729Sjoerg
18217330f729Sjoerg if (Tok.is(tok::code_completion)) {
1822*e038c9c4Sjoerg cutOffParsing();
18237330f729Sjoerg Actions.CodeCompleteOrdinaryName(getCurScope(),
18247330f729Sjoerg C99orCXXorObjC? Sema::PCC_ForInit
18257330f729Sjoerg : Sema::PCC_Expression);
18267330f729Sjoerg return StmtError();
18277330f729Sjoerg }
18287330f729Sjoerg
18297330f729Sjoerg ParsedAttributesWithRange attrs(AttrFactory);
18307330f729Sjoerg MaybeParseCXX11Attributes(attrs);
18317330f729Sjoerg
18327330f729Sjoerg SourceLocation EmptyInitStmtSemiLoc;
18337330f729Sjoerg
18347330f729Sjoerg // Parse the first part of the for specifier.
18357330f729Sjoerg if (Tok.is(tok::semi)) { // for (;
18367330f729Sjoerg ProhibitAttributes(attrs);
18377330f729Sjoerg // no first part, eat the ';'.
18387330f729Sjoerg SourceLocation SemiLoc = Tok.getLocation();
18397330f729Sjoerg if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.isMacroID())
18407330f729Sjoerg EmptyInitStmtSemiLoc = SemiLoc;
18417330f729Sjoerg ConsumeToken();
18427330f729Sjoerg } else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) &&
18437330f729Sjoerg isForRangeIdentifier()) {
18447330f729Sjoerg ProhibitAttributes(attrs);
18457330f729Sjoerg IdentifierInfo *Name = Tok.getIdentifierInfo();
18467330f729Sjoerg SourceLocation Loc = ConsumeToken();
18477330f729Sjoerg MaybeParseCXX11Attributes(attrs);
18487330f729Sjoerg
18497330f729Sjoerg ForRangeInfo.ColonLoc = ConsumeToken();
18507330f729Sjoerg if (Tok.is(tok::l_brace))
18517330f729Sjoerg ForRangeInfo.RangeExpr = ParseBraceInitializer();
18527330f729Sjoerg else
18537330f729Sjoerg ForRangeInfo.RangeExpr = ParseExpression();
18547330f729Sjoerg
18557330f729Sjoerg Diag(Loc, diag::err_for_range_identifier)
18567330f729Sjoerg << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17)
18577330f729Sjoerg ? FixItHint::CreateInsertion(Loc, "auto &&")
18587330f729Sjoerg : FixItHint());
18597330f729Sjoerg
18607330f729Sjoerg ForRangeInfo.LoopVar = Actions.ActOnCXXForRangeIdentifier(
18617330f729Sjoerg getCurScope(), Loc, Name, attrs, attrs.Range.getEnd());
18627330f729Sjoerg } else if (isForInitDeclaration()) { // for (int X = 4;
18637330f729Sjoerg ParenBraceBracketBalancer BalancerRAIIObj(*this);
18647330f729Sjoerg
18657330f729Sjoerg // Parse declaration, which eats the ';'.
18667330f729Sjoerg if (!C99orCXXorObjC) { // Use of C99-style for loops in C90 mode?
18677330f729Sjoerg Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
18687330f729Sjoerg Diag(Tok, diag::warn_gcc_variable_decl_in_for_loop);
18697330f729Sjoerg }
18707330f729Sjoerg
18717330f729Sjoerg // In C++0x, "for (T NS:a" might not be a typo for ::
18727330f729Sjoerg bool MightBeForRangeStmt = getLangOpts().CPlusPlus;
18737330f729Sjoerg ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
18747330f729Sjoerg
18757330f729Sjoerg SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
18767330f729Sjoerg DeclGroupPtrTy DG = ParseSimpleDeclaration(
1877*e038c9c4Sjoerg DeclaratorContext::ForInit, DeclEnd, attrs, false,
18787330f729Sjoerg MightBeForRangeStmt ? &ForRangeInfo : nullptr);
18797330f729Sjoerg FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
18807330f729Sjoerg if (ForRangeInfo.ParsedForRangeDecl()) {
18817330f729Sjoerg Diag(ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus11 ?
18827330f729Sjoerg diag::warn_cxx98_compat_for_range : diag::ext_for_range);
18837330f729Sjoerg ForRangeInfo.LoopVar = FirstPart;
18847330f729Sjoerg FirstPart = StmtResult();
18857330f729Sjoerg } else if (Tok.is(tok::semi)) { // for (int x = 4;
18867330f729Sjoerg ConsumeToken();
18877330f729Sjoerg } else if ((ForEach = isTokIdentifier_in())) {
18887330f729Sjoerg Actions.ActOnForEachDeclStmt(DG);
18897330f729Sjoerg // ObjC: for (id x in expr)
18907330f729Sjoerg ConsumeToken(); // consume 'in'
18917330f729Sjoerg
18927330f729Sjoerg if (Tok.is(tok::code_completion)) {
18937330f729Sjoerg cutOffParsing();
1894*e038c9c4Sjoerg Actions.CodeCompleteObjCForCollection(getCurScope(), DG);
18957330f729Sjoerg return StmtError();
18967330f729Sjoerg }
18977330f729Sjoerg Collection = ParseExpression();
18987330f729Sjoerg } else {
18997330f729Sjoerg Diag(Tok, diag::err_expected_semi_for);
19007330f729Sjoerg }
19017330f729Sjoerg } else {
19027330f729Sjoerg ProhibitAttributes(attrs);
19037330f729Sjoerg Value = Actions.CorrectDelayedTyposInExpr(ParseExpression());
19047330f729Sjoerg
19057330f729Sjoerg ForEach = isTokIdentifier_in();
19067330f729Sjoerg
19077330f729Sjoerg // Turn the expression into a stmt.
19087330f729Sjoerg if (!Value.isInvalid()) {
19097330f729Sjoerg if (ForEach)
19107330f729Sjoerg FirstPart = Actions.ActOnForEachLValueExpr(Value.get());
19117330f729Sjoerg else {
19127330f729Sjoerg // We already know this is not an init-statement within a for loop, so
19137330f729Sjoerg // if we are parsing a C++11 range-based for loop, we should treat this
19147330f729Sjoerg // expression statement as being a discarded value expression because
19157330f729Sjoerg // we will err below. This way we do not warn on an unused expression
19167330f729Sjoerg // that was an error in the first place, like with: for (expr : expr);
19177330f729Sjoerg bool IsRangeBasedFor =
19187330f729Sjoerg getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon);
19197330f729Sjoerg FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor);
19207330f729Sjoerg }
19217330f729Sjoerg }
19227330f729Sjoerg
19237330f729Sjoerg if (Tok.is(tok::semi)) {
19247330f729Sjoerg ConsumeToken();
19257330f729Sjoerg } else if (ForEach) {
19267330f729Sjoerg ConsumeToken(); // consume 'in'
19277330f729Sjoerg
19287330f729Sjoerg if (Tok.is(tok::code_completion)) {
19297330f729Sjoerg cutOffParsing();
1930*e038c9c4Sjoerg Actions.CodeCompleteObjCForCollection(getCurScope(), nullptr);
19317330f729Sjoerg return StmtError();
19327330f729Sjoerg }
19337330f729Sjoerg Collection = ParseExpression();
19347330f729Sjoerg } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::colon) && FirstPart.get()) {
19357330f729Sjoerg // User tried to write the reasonable, but ill-formed, for-range-statement
19367330f729Sjoerg // for (expr : expr) { ... }
19377330f729Sjoerg Diag(Tok, diag::err_for_range_expected_decl)
19387330f729Sjoerg << FirstPart.get()->getSourceRange();
19397330f729Sjoerg SkipUntil(tok::r_paren, StopBeforeMatch);
19407330f729Sjoerg SecondPart = Sema::ConditionError();
19417330f729Sjoerg } else {
19427330f729Sjoerg if (!Value.isInvalid()) {
19437330f729Sjoerg Diag(Tok, diag::err_expected_semi_for);
19447330f729Sjoerg } else {
19457330f729Sjoerg // Skip until semicolon or rparen, don't consume it.
19467330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
19477330f729Sjoerg if (Tok.is(tok::semi))
19487330f729Sjoerg ConsumeToken();
19497330f729Sjoerg }
19507330f729Sjoerg }
19517330f729Sjoerg }
19527330f729Sjoerg
19537330f729Sjoerg // Parse the second part of the for specifier.
19547330f729Sjoerg if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() &&
19557330f729Sjoerg !SecondPart.isInvalid()) {
19567330f729Sjoerg // Parse the second part of the for specifier.
19577330f729Sjoerg if (Tok.is(tok::semi)) { // for (...;;
19587330f729Sjoerg // no second part.
19597330f729Sjoerg } else if (Tok.is(tok::r_paren)) {
19607330f729Sjoerg // missing both semicolons.
19617330f729Sjoerg } else {
19627330f729Sjoerg if (getLangOpts().CPlusPlus) {
19637330f729Sjoerg // C++2a: We've parsed an init-statement; we might have a
19647330f729Sjoerg // for-range-declaration next.
19657330f729Sjoerg bool MightBeForRangeStmt = !ForRangeInfo.ParsedForRangeDecl();
19667330f729Sjoerg ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
19677330f729Sjoerg SecondPart =
19687330f729Sjoerg ParseCXXCondition(nullptr, ForLoc, Sema::ConditionKind::Boolean,
1969*e038c9c4Sjoerg MightBeForRangeStmt ? &ForRangeInfo : nullptr,
1970*e038c9c4Sjoerg /*EnterForConditionScope*/ true);
19717330f729Sjoerg
19727330f729Sjoerg if (ForRangeInfo.ParsedForRangeDecl()) {
19737330f729Sjoerg Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc()
19747330f729Sjoerg : ForRangeInfo.ColonLoc,
1975*e038c9c4Sjoerg getLangOpts().CPlusPlus20
19767330f729Sjoerg ? diag::warn_cxx17_compat_for_range_init_stmt
19777330f729Sjoerg : diag::ext_for_range_init_stmt)
19787330f729Sjoerg << (FirstPart.get() ? FirstPart.get()->getSourceRange()
19797330f729Sjoerg : SourceRange());
19807330f729Sjoerg if (EmptyInitStmtSemiLoc.isValid()) {
19817330f729Sjoerg Diag(EmptyInitStmtSemiLoc, diag::warn_empty_init_statement)
19827330f729Sjoerg << /*for-loop*/ 2
19837330f729Sjoerg << FixItHint::CreateRemoval(EmptyInitStmtSemiLoc);
19847330f729Sjoerg }
19857330f729Sjoerg }
19867330f729Sjoerg } else {
1987*e038c9c4Sjoerg // We permit 'continue' and 'break' in the condition of a for loop.
1988*e038c9c4Sjoerg getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
1989*e038c9c4Sjoerg
19907330f729Sjoerg ExprResult SecondExpr = ParseExpression();
19917330f729Sjoerg if (SecondExpr.isInvalid())
19927330f729Sjoerg SecondPart = Sema::ConditionError();
19937330f729Sjoerg else
19947330f729Sjoerg SecondPart =
19957330f729Sjoerg Actions.ActOnCondition(getCurScope(), ForLoc, SecondExpr.get(),
19967330f729Sjoerg Sema::ConditionKind::Boolean);
19977330f729Sjoerg }
19987330f729Sjoerg }
19997330f729Sjoerg }
20007330f729Sjoerg
2001*e038c9c4Sjoerg // Enter a break / continue scope, if we didn't already enter one while
2002*e038c9c4Sjoerg // parsing the second part.
2003*e038c9c4Sjoerg if (!(getCurScope()->getFlags() & Scope::ContinueScope))
2004*e038c9c4Sjoerg getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
2005*e038c9c4Sjoerg
20067330f729Sjoerg // Parse the third part of the for statement.
20077330f729Sjoerg if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) {
20087330f729Sjoerg if (Tok.isNot(tok::semi)) {
20097330f729Sjoerg if (!SecondPart.isInvalid())
20107330f729Sjoerg Diag(Tok, diag::err_expected_semi_for);
20117330f729Sjoerg else
20127330f729Sjoerg // Skip until semicolon or rparen, don't consume it.
20137330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
20147330f729Sjoerg }
20157330f729Sjoerg
20167330f729Sjoerg if (Tok.is(tok::semi)) {
20177330f729Sjoerg ConsumeToken();
20187330f729Sjoerg }
20197330f729Sjoerg
20207330f729Sjoerg if (Tok.isNot(tok::r_paren)) { // for (...;...;)
20217330f729Sjoerg ExprResult Third = ParseExpression();
20227330f729Sjoerg // FIXME: The C++11 standard doesn't actually say that this is a
20237330f729Sjoerg // discarded-value expression, but it clearly should be.
20247330f729Sjoerg ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.get());
20257330f729Sjoerg }
20267330f729Sjoerg }
20277330f729Sjoerg // Match the ')'.
20287330f729Sjoerg T.consumeClose();
20297330f729Sjoerg
20307330f729Sjoerg // C++ Coroutines [stmt.iter]:
20317330f729Sjoerg // 'co_await' can only be used for a range-based for statement.
20327330f729Sjoerg if (CoawaitLoc.isValid() && !ForRangeInfo.ParsedForRangeDecl()) {
20337330f729Sjoerg Diag(CoawaitLoc, diag::err_for_co_await_not_range_for);
20347330f729Sjoerg CoawaitLoc = SourceLocation();
20357330f729Sjoerg }
20367330f729Sjoerg
20377330f729Sjoerg // We need to perform most of the semantic analysis for a C++0x for-range
20387330f729Sjoerg // statememt before parsing the body, in order to be able to deduce the type
20397330f729Sjoerg // of an auto-typed loop variable.
20407330f729Sjoerg StmtResult ForRangeStmt;
20417330f729Sjoerg StmtResult ForEachStmt;
20427330f729Sjoerg
20437330f729Sjoerg if (ForRangeInfo.ParsedForRangeDecl()) {
20447330f729Sjoerg ExprResult CorrectedRange =
20457330f729Sjoerg Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get());
20467330f729Sjoerg ForRangeStmt = Actions.ActOnCXXForRangeStmt(
20477330f729Sjoerg getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
20487330f729Sjoerg ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(),
20497330f729Sjoerg T.getCloseLocation(), Sema::BFRK_Build);
20507330f729Sjoerg
20517330f729Sjoerg // Similarly, we need to do the semantic analysis for a for-range
20527330f729Sjoerg // statement immediately in order to close over temporaries correctly.
20537330f729Sjoerg } else if (ForEach) {
20547330f729Sjoerg ForEachStmt = Actions.ActOnObjCForCollectionStmt(ForLoc,
20557330f729Sjoerg FirstPart.get(),
20567330f729Sjoerg Collection.get(),
20577330f729Sjoerg T.getCloseLocation());
20587330f729Sjoerg } else {
20597330f729Sjoerg // In OpenMP loop region loop control variable must be captured and be
20607330f729Sjoerg // private. Perform analysis of first part (if any).
20617330f729Sjoerg if (getLangOpts().OpenMP && FirstPart.isUsable()) {
20627330f729Sjoerg Actions.ActOnOpenMPLoopInitialization(ForLoc, FirstPart.get());
20637330f729Sjoerg }
20647330f729Sjoerg }
20657330f729Sjoerg
20667330f729Sjoerg // C99 6.8.5p5 - In C99, the body of the for statement is a scope, even if
20677330f729Sjoerg // there is no compound stmt. C90 does not have this clause. We only do this
20687330f729Sjoerg // if the body isn't a compound statement to avoid push/pop in common cases.
20697330f729Sjoerg //
20707330f729Sjoerg // C++ 6.5p2:
20717330f729Sjoerg // The substatement in an iteration-statement implicitly defines a local scope
20727330f729Sjoerg // which is entered and exited each time through the loop.
20737330f729Sjoerg //
20747330f729Sjoerg // See comments in ParseIfStatement for why we create a scope for
20757330f729Sjoerg // for-init-statement/condition and a new scope for substatement in C++.
20767330f729Sjoerg //
20777330f729Sjoerg ParseScope InnerScope(this, Scope::DeclScope, C99orCXXorObjC,
20787330f729Sjoerg Tok.is(tok::l_brace));
20797330f729Sjoerg
20807330f729Sjoerg // The body of the for loop has the same local mangling number as the
20817330f729Sjoerg // for-init-statement.
20827330f729Sjoerg // It will only be incremented if the body contains other things that would
20837330f729Sjoerg // normally increment the mangling number (like a compound statement).
20847330f729Sjoerg if (C99orCXXorObjC)
20857330f729Sjoerg getCurScope()->decrementMSManglingNumber();
20867330f729Sjoerg
2087*e038c9c4Sjoerg MisleadingIndentationChecker MIChecker(*this, MSK_for, ForLoc);
2088*e038c9c4Sjoerg
20897330f729Sjoerg // Read the body statement.
20907330f729Sjoerg StmtResult Body(ParseStatement(TrailingElseLoc));
20917330f729Sjoerg
2092*e038c9c4Sjoerg if (Body.isUsable())
2093*e038c9c4Sjoerg MIChecker.Check();
2094*e038c9c4Sjoerg
20957330f729Sjoerg // Pop the body scope if needed.
20967330f729Sjoerg InnerScope.Exit();
20977330f729Sjoerg
20987330f729Sjoerg // Leave the for-scope.
20997330f729Sjoerg ForScope.Exit();
21007330f729Sjoerg
21017330f729Sjoerg if (Body.isInvalid())
21027330f729Sjoerg return StmtError();
21037330f729Sjoerg
21047330f729Sjoerg if (ForEach)
21057330f729Sjoerg return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(),
21067330f729Sjoerg Body.get());
21077330f729Sjoerg
21087330f729Sjoerg if (ForRangeInfo.ParsedForRangeDecl())
21097330f729Sjoerg return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
21107330f729Sjoerg
21117330f729Sjoerg return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(),
21127330f729Sjoerg SecondPart, ThirdPart, T.getCloseLocation(),
21137330f729Sjoerg Body.get());
21147330f729Sjoerg }
21157330f729Sjoerg
21167330f729Sjoerg /// ParseGotoStatement
21177330f729Sjoerg /// jump-statement:
21187330f729Sjoerg /// 'goto' identifier ';'
21197330f729Sjoerg /// [GNU] 'goto' '*' expression ';'
21207330f729Sjoerg ///
21217330f729Sjoerg /// Note: this lets the caller parse the end ';'.
21227330f729Sjoerg ///
ParseGotoStatement()21237330f729Sjoerg StmtResult Parser::ParseGotoStatement() {
21247330f729Sjoerg assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
21257330f729Sjoerg SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
21267330f729Sjoerg
21277330f729Sjoerg StmtResult Res;
21287330f729Sjoerg if (Tok.is(tok::identifier)) {
21297330f729Sjoerg LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
21307330f729Sjoerg Tok.getLocation());
21317330f729Sjoerg Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD);
21327330f729Sjoerg ConsumeToken();
21337330f729Sjoerg } else if (Tok.is(tok::star)) {
21347330f729Sjoerg // GNU indirect goto extension.
21357330f729Sjoerg Diag(Tok, diag::ext_gnu_indirect_goto);
21367330f729Sjoerg SourceLocation StarLoc = ConsumeToken();
21377330f729Sjoerg ExprResult R(ParseExpression());
21387330f729Sjoerg if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
21397330f729Sjoerg SkipUntil(tok::semi, StopBeforeMatch);
21407330f729Sjoerg return StmtError();
21417330f729Sjoerg }
21427330f729Sjoerg Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.get());
21437330f729Sjoerg } else {
21447330f729Sjoerg Diag(Tok, diag::err_expected) << tok::identifier;
21457330f729Sjoerg return StmtError();
21467330f729Sjoerg }
21477330f729Sjoerg
21487330f729Sjoerg return Res;
21497330f729Sjoerg }
21507330f729Sjoerg
21517330f729Sjoerg /// ParseContinueStatement
21527330f729Sjoerg /// jump-statement:
21537330f729Sjoerg /// 'continue' ';'
21547330f729Sjoerg ///
21557330f729Sjoerg /// Note: this lets the caller parse the end ';'.
21567330f729Sjoerg ///
ParseContinueStatement()21577330f729Sjoerg StmtResult Parser::ParseContinueStatement() {
21587330f729Sjoerg SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
21597330f729Sjoerg return Actions.ActOnContinueStmt(ContinueLoc, getCurScope());
21607330f729Sjoerg }
21617330f729Sjoerg
21627330f729Sjoerg /// ParseBreakStatement
21637330f729Sjoerg /// jump-statement:
21647330f729Sjoerg /// 'break' ';'
21657330f729Sjoerg ///
21667330f729Sjoerg /// Note: this lets the caller parse the end ';'.
21677330f729Sjoerg ///
ParseBreakStatement()21687330f729Sjoerg StmtResult Parser::ParseBreakStatement() {
21697330f729Sjoerg SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
21707330f729Sjoerg return Actions.ActOnBreakStmt(BreakLoc, getCurScope());
21717330f729Sjoerg }
21727330f729Sjoerg
21737330f729Sjoerg /// ParseReturnStatement
21747330f729Sjoerg /// jump-statement:
21757330f729Sjoerg /// 'return' expression[opt] ';'
21767330f729Sjoerg /// 'return' braced-init-list ';'
21777330f729Sjoerg /// 'co_return' expression[opt] ';'
21787330f729Sjoerg /// 'co_return' braced-init-list ';'
ParseReturnStatement()21797330f729Sjoerg StmtResult Parser::ParseReturnStatement() {
21807330f729Sjoerg assert((Tok.is(tok::kw_return) || Tok.is(tok::kw_co_return)) &&
21817330f729Sjoerg "Not a return stmt!");
21827330f729Sjoerg bool IsCoreturn = Tok.is(tok::kw_co_return);
21837330f729Sjoerg SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
21847330f729Sjoerg
21857330f729Sjoerg ExprResult R;
21867330f729Sjoerg if (Tok.isNot(tok::semi)) {
21877330f729Sjoerg if (!IsCoreturn)
21887330f729Sjoerg PreferredType.enterReturn(Actions, Tok.getLocation());
21897330f729Sjoerg // FIXME: Code completion for co_return.
21907330f729Sjoerg if (Tok.is(tok::code_completion) && !IsCoreturn) {
2191*e038c9c4Sjoerg cutOffParsing();
21927330f729Sjoerg Actions.CodeCompleteExpression(getCurScope(),
21937330f729Sjoerg PreferredType.get(Tok.getLocation()));
21947330f729Sjoerg return StmtError();
21957330f729Sjoerg }
21967330f729Sjoerg
21977330f729Sjoerg if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus) {
21987330f729Sjoerg R = ParseInitializer();
21997330f729Sjoerg if (R.isUsable())
22007330f729Sjoerg Diag(R.get()->getBeginLoc(),
22017330f729Sjoerg getLangOpts().CPlusPlus11
22027330f729Sjoerg ? diag::warn_cxx98_compat_generalized_initializer_lists
22037330f729Sjoerg : diag::ext_generalized_initializer_lists)
22047330f729Sjoerg << R.get()->getSourceRange();
22057330f729Sjoerg } else
22067330f729Sjoerg R = ParseExpression();
22077330f729Sjoerg if (R.isInvalid()) {
22087330f729Sjoerg SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
22097330f729Sjoerg return StmtError();
22107330f729Sjoerg }
22117330f729Sjoerg }
22127330f729Sjoerg if (IsCoreturn)
22137330f729Sjoerg return Actions.ActOnCoreturnStmt(getCurScope(), ReturnLoc, R.get());
22147330f729Sjoerg return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope());
22157330f729Sjoerg }
22167330f729Sjoerg
ParsePragmaLoopHint(StmtVector & Stmts,ParsedStmtContext StmtCtx,SourceLocation * TrailingElseLoc,ParsedAttributesWithRange & Attrs)22177330f729Sjoerg StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
22187330f729Sjoerg ParsedStmtContext StmtCtx,
22197330f729Sjoerg SourceLocation *TrailingElseLoc,
22207330f729Sjoerg ParsedAttributesWithRange &Attrs) {
22217330f729Sjoerg // Create temporary attribute list.
22227330f729Sjoerg ParsedAttributesWithRange TempAttrs(AttrFactory);
22237330f729Sjoerg
2224*e038c9c4Sjoerg SourceLocation StartLoc = Tok.getLocation();
2225*e038c9c4Sjoerg
22267330f729Sjoerg // Get loop hints and consume annotated token.
22277330f729Sjoerg while (Tok.is(tok::annot_pragma_loop_hint)) {
22287330f729Sjoerg LoopHint Hint;
22297330f729Sjoerg if (!HandlePragmaLoopHint(Hint))
22307330f729Sjoerg continue;
22317330f729Sjoerg
22327330f729Sjoerg ArgsUnion ArgHints[] = {Hint.PragmaNameLoc, Hint.OptionLoc, Hint.StateLoc,
22337330f729Sjoerg ArgsUnion(Hint.ValueExpr)};
22347330f729Sjoerg TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr,
22357330f729Sjoerg Hint.PragmaNameLoc->Loc, ArgHints, 4,
22367330f729Sjoerg ParsedAttr::AS_Pragma);
22377330f729Sjoerg }
22387330f729Sjoerg
22397330f729Sjoerg // Get the next statement.
22407330f729Sjoerg MaybeParseCXX11Attributes(Attrs);
22417330f729Sjoerg
22427330f729Sjoerg StmtResult S = ParseStatementOrDeclarationAfterAttributes(
22437330f729Sjoerg Stmts, StmtCtx, TrailingElseLoc, Attrs);
22447330f729Sjoerg
22457330f729Sjoerg Attrs.takeAllFrom(TempAttrs);
2246*e038c9c4Sjoerg
2247*e038c9c4Sjoerg // Start of attribute range may already be set for some invalid input.
2248*e038c9c4Sjoerg // See PR46336.
2249*e038c9c4Sjoerg if (Attrs.Range.getBegin().isInvalid())
2250*e038c9c4Sjoerg Attrs.Range.setBegin(StartLoc);
2251*e038c9c4Sjoerg
22527330f729Sjoerg return S;
22537330f729Sjoerg }
22547330f729Sjoerg
ParseFunctionStatementBody(Decl * Decl,ParseScope & BodyScope)22557330f729Sjoerg Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
22567330f729Sjoerg assert(Tok.is(tok::l_brace));
22577330f729Sjoerg SourceLocation LBraceLoc = Tok.getLocation();
22587330f729Sjoerg
22597330f729Sjoerg PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, LBraceLoc,
22607330f729Sjoerg "parsing function body");
22617330f729Sjoerg
22627330f729Sjoerg // Save and reset current vtordisp stack if we have entered a C++ method body.
22637330f729Sjoerg bool IsCXXMethod =
22647330f729Sjoerg getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl);
22657330f729Sjoerg Sema::PragmaStackSentinelRAII
22667330f729Sjoerg PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
22677330f729Sjoerg
22687330f729Sjoerg // Do not enter a scope for the brace, as the arguments are in the same scope
22697330f729Sjoerg // (the function body) as the body itself. Instead, just read the statement
22707330f729Sjoerg // list and put it into a CompoundStmt for safe keeping.
22717330f729Sjoerg StmtResult FnBody(ParseCompoundStatementBody());
22727330f729Sjoerg
22737330f729Sjoerg // If the function body could not be parsed, make a bogus compoundstmt.
22747330f729Sjoerg if (FnBody.isInvalid()) {
22757330f729Sjoerg Sema::CompoundScopeRAII CompoundScope(Actions);
22767330f729Sjoerg FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, None, false);
22777330f729Sjoerg }
22787330f729Sjoerg
22797330f729Sjoerg BodyScope.Exit();
22807330f729Sjoerg return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
22817330f729Sjoerg }
22827330f729Sjoerg
22837330f729Sjoerg /// ParseFunctionTryBlock - Parse a C++ function-try-block.
22847330f729Sjoerg ///
22857330f729Sjoerg /// function-try-block:
22867330f729Sjoerg /// 'try' ctor-initializer[opt] compound-statement handler-seq
22877330f729Sjoerg ///
ParseFunctionTryBlock(Decl * Decl,ParseScope & BodyScope)22887330f729Sjoerg Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
22897330f729Sjoerg assert(Tok.is(tok::kw_try) && "Expected 'try'");
22907330f729Sjoerg SourceLocation TryLoc = ConsumeToken();
22917330f729Sjoerg
22927330f729Sjoerg PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, TryLoc,
22937330f729Sjoerg "parsing function try block");
22947330f729Sjoerg
22957330f729Sjoerg // Constructor initializer list?
22967330f729Sjoerg if (Tok.is(tok::colon))
22977330f729Sjoerg ParseConstructorInitializer(Decl);
22987330f729Sjoerg else
22997330f729Sjoerg Actions.ActOnDefaultCtorInitializers(Decl);
23007330f729Sjoerg
23017330f729Sjoerg // Save and reset current vtordisp stack if we have entered a C++ method body.
23027330f729Sjoerg bool IsCXXMethod =
23037330f729Sjoerg getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl);
23047330f729Sjoerg Sema::PragmaStackSentinelRAII
23057330f729Sjoerg PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
23067330f729Sjoerg
23077330f729Sjoerg SourceLocation LBraceLoc = Tok.getLocation();
23087330f729Sjoerg StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true));
23097330f729Sjoerg // If we failed to parse the try-catch, we just give the function an empty
23107330f729Sjoerg // compound statement as the body.
23117330f729Sjoerg if (FnBody.isInvalid()) {
23127330f729Sjoerg Sema::CompoundScopeRAII CompoundScope(Actions);
23137330f729Sjoerg FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, None, false);
23147330f729Sjoerg }
23157330f729Sjoerg
23167330f729Sjoerg BodyScope.Exit();
23177330f729Sjoerg return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
23187330f729Sjoerg }
23197330f729Sjoerg
trySkippingFunctionBody()23207330f729Sjoerg bool Parser::trySkippingFunctionBody() {
23217330f729Sjoerg assert(SkipFunctionBodies &&
23227330f729Sjoerg "Should only be called when SkipFunctionBodies is enabled");
23237330f729Sjoerg if (!PP.isCodeCompletionEnabled()) {
23247330f729Sjoerg SkipFunctionBody();
23257330f729Sjoerg return true;
23267330f729Sjoerg }
23277330f729Sjoerg
23287330f729Sjoerg // We're in code-completion mode. Skip parsing for all function bodies unless
23297330f729Sjoerg // the body contains the code-completion point.
23307330f729Sjoerg TentativeParsingAction PA(*this);
23317330f729Sjoerg bool IsTryCatch = Tok.is(tok::kw_try);
23327330f729Sjoerg CachedTokens Toks;
23337330f729Sjoerg bool ErrorInPrologue = ConsumeAndStoreFunctionPrologue(Toks);
23347330f729Sjoerg if (llvm::any_of(Toks, [](const Token &Tok) {
23357330f729Sjoerg return Tok.is(tok::code_completion);
23367330f729Sjoerg })) {
23377330f729Sjoerg PA.Revert();
23387330f729Sjoerg return false;
23397330f729Sjoerg }
23407330f729Sjoerg if (ErrorInPrologue) {
23417330f729Sjoerg PA.Commit();
23427330f729Sjoerg SkipMalformedDecl();
23437330f729Sjoerg return true;
23447330f729Sjoerg }
23457330f729Sjoerg if (!SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
23467330f729Sjoerg PA.Revert();
23477330f729Sjoerg return false;
23487330f729Sjoerg }
23497330f729Sjoerg while (IsTryCatch && Tok.is(tok::kw_catch)) {
23507330f729Sjoerg if (!SkipUntil(tok::l_brace, StopAtCodeCompletion) ||
23517330f729Sjoerg !SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
23527330f729Sjoerg PA.Revert();
23537330f729Sjoerg return false;
23547330f729Sjoerg }
23557330f729Sjoerg }
23567330f729Sjoerg PA.Commit();
23577330f729Sjoerg return true;
23587330f729Sjoerg }
23597330f729Sjoerg
23607330f729Sjoerg /// ParseCXXTryBlock - Parse a C++ try-block.
23617330f729Sjoerg ///
23627330f729Sjoerg /// try-block:
23637330f729Sjoerg /// 'try' compound-statement handler-seq
23647330f729Sjoerg ///
ParseCXXTryBlock()23657330f729Sjoerg StmtResult Parser::ParseCXXTryBlock() {
23667330f729Sjoerg assert(Tok.is(tok::kw_try) && "Expected 'try'");
23677330f729Sjoerg
23687330f729Sjoerg SourceLocation TryLoc = ConsumeToken();
23697330f729Sjoerg return ParseCXXTryBlockCommon(TryLoc);
23707330f729Sjoerg }
23717330f729Sjoerg
23727330f729Sjoerg /// ParseCXXTryBlockCommon - Parse the common part of try-block and
23737330f729Sjoerg /// function-try-block.
23747330f729Sjoerg ///
23757330f729Sjoerg /// try-block:
23767330f729Sjoerg /// 'try' compound-statement handler-seq
23777330f729Sjoerg ///
23787330f729Sjoerg /// function-try-block:
23797330f729Sjoerg /// 'try' ctor-initializer[opt] compound-statement handler-seq
23807330f729Sjoerg ///
23817330f729Sjoerg /// handler-seq:
23827330f729Sjoerg /// handler handler-seq[opt]
23837330f729Sjoerg ///
23847330f729Sjoerg /// [Borland] try-block:
23857330f729Sjoerg /// 'try' compound-statement seh-except-block
23867330f729Sjoerg /// 'try' compound-statement seh-finally-block
23877330f729Sjoerg ///
ParseCXXTryBlockCommon(SourceLocation TryLoc,bool FnTry)23887330f729Sjoerg StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
23897330f729Sjoerg if (Tok.isNot(tok::l_brace))
23907330f729Sjoerg return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
23917330f729Sjoerg
23927330f729Sjoerg StmtResult TryBlock(ParseCompoundStatement(
23937330f729Sjoerg /*isStmtExpr=*/false, Scope::DeclScope | Scope::TryScope |
23947330f729Sjoerg Scope::CompoundStmtScope |
23957330f729Sjoerg (FnTry ? Scope::FnTryCatchScope : 0)));
23967330f729Sjoerg if (TryBlock.isInvalid())
23977330f729Sjoerg return TryBlock;
23987330f729Sjoerg
23997330f729Sjoerg // Borland allows SEH-handlers with 'try'
24007330f729Sjoerg
24017330f729Sjoerg if ((Tok.is(tok::identifier) &&
24027330f729Sjoerg Tok.getIdentifierInfo() == getSEHExceptKeyword()) ||
24037330f729Sjoerg Tok.is(tok::kw___finally)) {
24047330f729Sjoerg // TODO: Factor into common return ParseSEHHandlerCommon(...)
24057330f729Sjoerg StmtResult Handler;
24067330f729Sjoerg if(Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
24077330f729Sjoerg SourceLocation Loc = ConsumeToken();
24087330f729Sjoerg Handler = ParseSEHExceptBlock(Loc);
24097330f729Sjoerg }
24107330f729Sjoerg else {
24117330f729Sjoerg SourceLocation Loc = ConsumeToken();
24127330f729Sjoerg Handler = ParseSEHFinallyBlock(Loc);
24137330f729Sjoerg }
24147330f729Sjoerg if(Handler.isInvalid())
24157330f729Sjoerg return Handler;
24167330f729Sjoerg
24177330f729Sjoerg return Actions.ActOnSEHTryBlock(true /* IsCXXTry */,
24187330f729Sjoerg TryLoc,
24197330f729Sjoerg TryBlock.get(),
24207330f729Sjoerg Handler.get());
24217330f729Sjoerg }
24227330f729Sjoerg else {
24237330f729Sjoerg StmtVector Handlers;
24247330f729Sjoerg
24257330f729Sjoerg // C++11 attributes can't appear here, despite this context seeming
24267330f729Sjoerg // statement-like.
24277330f729Sjoerg DiagnoseAndSkipCXX11Attributes();
24287330f729Sjoerg
24297330f729Sjoerg if (Tok.isNot(tok::kw_catch))
24307330f729Sjoerg return StmtError(Diag(Tok, diag::err_expected_catch));
24317330f729Sjoerg while (Tok.is(tok::kw_catch)) {
24327330f729Sjoerg StmtResult Handler(ParseCXXCatchBlock(FnTry));
24337330f729Sjoerg if (!Handler.isInvalid())
24347330f729Sjoerg Handlers.push_back(Handler.get());
24357330f729Sjoerg }
24367330f729Sjoerg // Don't bother creating the full statement if we don't have any usable
24377330f729Sjoerg // handlers.
24387330f729Sjoerg if (Handlers.empty())
24397330f729Sjoerg return StmtError();
24407330f729Sjoerg
24417330f729Sjoerg return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.get(), Handlers);
24427330f729Sjoerg }
24437330f729Sjoerg }
24447330f729Sjoerg
24457330f729Sjoerg /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
24467330f729Sjoerg ///
24477330f729Sjoerg /// handler:
24487330f729Sjoerg /// 'catch' '(' exception-declaration ')' compound-statement
24497330f729Sjoerg ///
24507330f729Sjoerg /// exception-declaration:
24517330f729Sjoerg /// attribute-specifier-seq[opt] type-specifier-seq declarator
24527330f729Sjoerg /// attribute-specifier-seq[opt] type-specifier-seq abstract-declarator[opt]
24537330f729Sjoerg /// '...'
24547330f729Sjoerg ///
ParseCXXCatchBlock(bool FnCatch)24557330f729Sjoerg StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
24567330f729Sjoerg assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
24577330f729Sjoerg
24587330f729Sjoerg SourceLocation CatchLoc = ConsumeToken();
24597330f729Sjoerg
24607330f729Sjoerg BalancedDelimiterTracker T(*this, tok::l_paren);
24617330f729Sjoerg if (T.expectAndConsume())
24627330f729Sjoerg return StmtError();
24637330f729Sjoerg
24647330f729Sjoerg // C++ 3.3.2p3:
24657330f729Sjoerg // The name in a catch exception-declaration is local to the handler and
24667330f729Sjoerg // shall not be redeclared in the outermost block of the handler.
24677330f729Sjoerg ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope |
24687330f729Sjoerg Scope::CatchScope |
24697330f729Sjoerg (FnCatch ? Scope::FnTryCatchScope : 0));
24707330f729Sjoerg
24717330f729Sjoerg // exception-declaration is equivalent to '...' or a parameter-declaration
24727330f729Sjoerg // without default arguments.
24737330f729Sjoerg Decl *ExceptionDecl = nullptr;
24747330f729Sjoerg if (Tok.isNot(tok::ellipsis)) {
24757330f729Sjoerg ParsedAttributesWithRange Attributes(AttrFactory);
24767330f729Sjoerg MaybeParseCXX11Attributes(Attributes);
24777330f729Sjoerg
24787330f729Sjoerg DeclSpec DS(AttrFactory);
24797330f729Sjoerg DS.takeAttributesFrom(Attributes);
24807330f729Sjoerg
24817330f729Sjoerg if (ParseCXXTypeSpecifierSeq(DS))
24827330f729Sjoerg return StmtError();
24837330f729Sjoerg
2484*e038c9c4Sjoerg Declarator ExDecl(DS, DeclaratorContext::CXXCatch);
24857330f729Sjoerg ParseDeclarator(ExDecl);
24867330f729Sjoerg ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl);
24877330f729Sjoerg } else
24887330f729Sjoerg ConsumeToken();
24897330f729Sjoerg
24907330f729Sjoerg T.consumeClose();
24917330f729Sjoerg if (T.getCloseLocation().isInvalid())
24927330f729Sjoerg return StmtError();
24937330f729Sjoerg
24947330f729Sjoerg if (Tok.isNot(tok::l_brace))
24957330f729Sjoerg return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
24967330f729Sjoerg
24977330f729Sjoerg // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
24987330f729Sjoerg StmtResult Block(ParseCompoundStatement());
24997330f729Sjoerg if (Block.isInvalid())
25007330f729Sjoerg return Block;
25017330f729Sjoerg
25027330f729Sjoerg return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.get());
25037330f729Sjoerg }
25047330f729Sjoerg
ParseMicrosoftIfExistsStatement(StmtVector & Stmts)25057330f729Sjoerg void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
25067330f729Sjoerg IfExistsCondition Result;
25077330f729Sjoerg if (ParseMicrosoftIfExistsCondition(Result))
25087330f729Sjoerg return;
25097330f729Sjoerg
25107330f729Sjoerg // Handle dependent statements by parsing the braces as a compound statement.
25117330f729Sjoerg // This is not the same behavior as Visual C++, which don't treat this as a
25127330f729Sjoerg // compound statement, but for Clang's type checking we can't have anything
25137330f729Sjoerg // inside these braces escaping to the surrounding code.
25147330f729Sjoerg if (Result.Behavior == IEB_Dependent) {
25157330f729Sjoerg if (!Tok.is(tok::l_brace)) {
25167330f729Sjoerg Diag(Tok, diag::err_expected) << tok::l_brace;
25177330f729Sjoerg return;
25187330f729Sjoerg }
25197330f729Sjoerg
25207330f729Sjoerg StmtResult Compound = ParseCompoundStatement();
25217330f729Sjoerg if (Compound.isInvalid())
25227330f729Sjoerg return;
25237330f729Sjoerg
25247330f729Sjoerg StmtResult DepResult = Actions.ActOnMSDependentExistsStmt(Result.KeywordLoc,
25257330f729Sjoerg Result.IsIfExists,
25267330f729Sjoerg Result.SS,
25277330f729Sjoerg Result.Name,
25287330f729Sjoerg Compound.get());
25297330f729Sjoerg if (DepResult.isUsable())
25307330f729Sjoerg Stmts.push_back(DepResult.get());
25317330f729Sjoerg return;
25327330f729Sjoerg }
25337330f729Sjoerg
25347330f729Sjoerg BalancedDelimiterTracker Braces(*this, tok::l_brace);
25357330f729Sjoerg if (Braces.consumeOpen()) {
25367330f729Sjoerg Diag(Tok, diag::err_expected) << tok::l_brace;
25377330f729Sjoerg return;
25387330f729Sjoerg }
25397330f729Sjoerg
25407330f729Sjoerg switch (Result.Behavior) {
25417330f729Sjoerg case IEB_Parse:
25427330f729Sjoerg // Parse the statements below.
25437330f729Sjoerg break;
25447330f729Sjoerg
25457330f729Sjoerg case IEB_Dependent:
25467330f729Sjoerg llvm_unreachable("Dependent case handled above");
25477330f729Sjoerg
25487330f729Sjoerg case IEB_Skip:
25497330f729Sjoerg Braces.skipToEnd();
25507330f729Sjoerg return;
25517330f729Sjoerg }
25527330f729Sjoerg
25537330f729Sjoerg // Condition is true, parse the statements.
25547330f729Sjoerg while (Tok.isNot(tok::r_brace)) {
25557330f729Sjoerg StmtResult R =
25567330f729Sjoerg ParseStatementOrDeclaration(Stmts, ParsedStmtContext::Compound);
25577330f729Sjoerg if (R.isUsable())
25587330f729Sjoerg Stmts.push_back(R.get());
25597330f729Sjoerg }
25607330f729Sjoerg Braces.consumeClose();
25617330f729Sjoerg }
2562