text: //===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
  //
  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  // See https://llvm.org/LICENSE.txt for license information.
  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  //
  //===----------------------------------------------------------------------===//
  //
  // This file implements the Statement and Block portions of the Parser
  // interface.
  //
  //===----------------------------------------------------------------------===//
  
  #include "clang/AST/PrettyDeclStackTrace.h"
  #include "clang/Basic/Attributes.h"
  #include "clang/Basic/PrettyStackTrace.h"
  #include "clang/Parse/LoopHint.h"
  #include "clang/Parse/Parser.h"
  #include "clang/Parse/RAIIObjectsForParser.h"
  #include "clang/Sema/DeclSpec.h"
  #include "clang/Sema/Scope.h"
  #include "clang/Sema/TypoCorrection.h"
  #include "llvm/ADT/STLExtras.h"
  
  using namespace clang;
  
  //===----------------------------------------------------------------------===//
  // C99 6.8: Statements and Blocks.
  //===----------------------------------------------------------------------===//
  
  /// Parse a standalone statement (for instance, as the body of an 'if',
  /// 'while', or 'for').
  StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc,
                                    ParsedStmtContext StmtCtx) {
    StmtResult Res;
  
    // We may get back a null statement if we found a #pragma. Keep going until
    // we get an actual statement.
    do {
      StmtVector Stmts;
      Res = ParseStatementOrDeclaration(Stmts, StmtCtx, TrailingElseLoc);
    } while (!Res.isInvalid() && !Res.get());
  
    return Res;
  }
  
  /// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
  ///       StatementOrDeclaration:
  ///         statement
  ///         declaration
  ///
  ///       statement:
  ///         labeled-statement
  ///         compound-statement
  ///         expression-statement
  ///         selection-statement
  ///         iteration-statement
  ///         jump-statement
  /// [C++]   declaration-statement
  /// [C++]   try-block
  /// [MS]    seh-try-block
  /// [OBC]   objc-throw-statement
  /// [OBC]   objc-try-catch-statement
  /// [OBC]   objc-synchronized-statement
  /// [GNU]   asm-statement
  /// [OMP]   openmp-construct             [TODO]
  ///
  ///       labeled-statement:
  ///         identifier ':' statement
  ///         'case' constant-expression ':' statement
  ///         'default' ':' statement
  ///
  ///       selection-statement:
  ///         if-statement
  ///         switch-statement
  ///
  ///       iteration-statement:
  ///         while-statement
  ///         do-statement
  ///         for-statement
  ///
  ///       expression-statement:
  ///         expression[opt] ';'
  ///
  ///       jump-statement:
  ///         'goto' identifier ';'
  ///         'continue' ';'
  ///         'break' ';'
  ///         'return' expression[opt] ';'
  /// [GNU]   'goto' '*' expression ';'
  ///
  /// [OBC] objc-throw-statement:
  /// [OBC]   '@' 'throw' expression ';'
  /// [OBC]   '@' 'throw' ';'
  ///
  StmtResult
  Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
                                      ParsedStmtContext StmtCtx,
                                      SourceLocation *TrailingElseLoc) {
  
    ParenBraceBracketBalancer BalancerRAIIObj(*this);
  
    // Because we're parsing either a statement or a declaration, the order of
    // attribute parsing is important. [[]] attributes at the start of a
    // statement are different from [[]] attributes that follow an __attribute__
    // at the start of the statement. Thus, we're not using MaybeParseAttributes
    // here because we don't want to allow arbitrary orderings.
    ParsedAttributes Attrs(AttrFactory);
    MaybeParseCXX11Attributes(Attrs, /*MightBeObjCMessageSend*/ true);
    if (getLangOpts().OpenCL)
      MaybeParseGNUAttributes(Attrs);
  
    StmtResult Res = ParseStatementOrDeclarationAfterAttributes(
        Stmts, StmtCtx, TrailingElseLoc, Attrs);
    MaybeDestroyTemplateIds();
  
    assert((Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
           "attributes on empty statement");
  
    if (Attrs.empty() || Res.isInvalid())
      return Res;
  
    return Actions.ActOnAttributedStmt(Attrs, Res.get());
  }
  
  namespace {
  class StatementFilterCCC final : public CorrectionCandidateCallback {
  public:
    StatementFilterCCC(Token nextTok) : NextToken(nextTok) {
      WantTypeSpecifiers = nextTok.isOneOf(tok::l_paren, tok::less, tok::l_square,
                                           tok::identifier, tok::star, tok::amp);
      WantExpressionKeywords =
          nextTok.isOneOf(tok::l_paren, tok::identifier, tok::arrow, tok::period);
      WantRemainingKeywords =
          nextTok.isOneOf(tok::l_paren, tok::semi, tok::identifier, tok::l_brace);
      WantCXXNamedCasts = false;
    }
  
    bool ValidateCandidate(const TypoCorrection &candidate) override {
      if (FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>())
        return !candidate.getCorrectionSpecifier() || isa<ObjCIvarDecl>(FD);
      if (NextToken.is(tok::equal))
        return candidate.getCorrectionDeclAs<VarDecl>();
      if (NextToken.is(tok::period) &&
          candidate.getCorrectionDeclAs<NamespaceDecl>())
        return false;
      return CorrectionCandidateCallback::ValidateCandidate(candidate);
    }
  
    std::unique_ptr<CorrectionCandidateCallback> clone() override {
      return std::make_unique<StatementFilterCCC>(*this);
    }
  
  private:
    Token NextToken;
  };
  }
  
  StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
      StmtVector &Stmts, ParsedStmtContext StmtCtx,
      SourceLocation *TrailingElseLoc, ParsedAttributes &Attrs) {
    const char *SemiError = nullptr;
    StmtResult Res;
    SourceLocation GNUAttributeLoc;
  
    // Cases in this switch statement should fall through if the parser expects
    // the token to end in a semicolon (in which case SemiError should be set),
    // or they directly 'return;' if not.
  Retry:
    tok::TokenKind Kind  = Tok.getKind();
    SourceLocation AtLoc;
    switch (Kind) {
    case tok::at: // May be a @try or @throw statement
      {
        AtLoc = ConsumeToken();  // consume @
        return ParseObjCAtStatement(AtLoc, StmtCtx);
      }
  
    case tok::code_completion:
      cutOffParsing();
      Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement);
      return StmtError();
  
    case tok::identifier: {
      Token Next = NextToken();
      if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement
        // identifier ':' statement
        return ParseLabeledStatement(Attrs, StmtCtx);
      }
  
      // Look up the identifier, and typo-correct it to a keyword if it's not
      // found.
      if (Next.isNot(tok::coloncolon)) {
        // Try to limit which sets of keywords should be included in typo
        // correction based on what the next token is.
        StatementFilterCCC CCC(Next);
        if (TryAnnotateName(&CCC) == ANK_Error) {
          // Handle errors here by skipping up to the next semicolon or '}', and
          // eat the semicolon if that's what stopped us.
          SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
          if (Tok.is(tok::semi))
            ConsumeToken();
          return StmtError();
        }
  
        // If the identifier was typo-corrected, try again.
        if (Tok.isNot(tok::identifier))
          goto Retry;
      }
  
      // Fall through
      LLVM_FALLTHROUGH;
    }
  
    default: {
      if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt ||
           (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
               ParsedStmtContext()) &&
          ((GNUAttributeLoc.isValid() &&
            !(!Attrs.empty() &&
              llvm::all_of(
                  Attrs, [](ParsedAttr &Attr) { return Attr.isStmtAttr(); }))) ||
           isDeclarationStatement())) {
        SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
        DeclGroupPtrTy Decl;
        if (GNUAttributeLoc.isValid()) {
          DeclStart = GNUAttributeLoc;
          Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, Attrs,
                                  &GNUAttributeLoc);
        } else {
          Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, Attrs);
        }
        if (Attrs.Range.getBegin().isValid())
          DeclStart = Attrs.Range.getBegin();
        return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
      }
  
      if (Tok.is(tok::r_brace)) {
        Diag(Tok, diag::err_expected_statement);
        return StmtError();
      }
  
      return ParseExprStatement(StmtCtx);
    }
  
    case tok::kw___attribute: {
      GNUAttributeLoc = Tok.getLocation();
      ParseGNUAttributes(Attrs);
      goto Retry;
    }
  
    case tok::kw_case:                // C99 6.8.1: labeled-statement
      return ParseCaseStatement(StmtCtx);
    case tok::kw_default:             // C99 6.8.1: labeled-statement
      return ParseDefaultStatement(StmtCtx);
  
    case tok::l_brace:                // C99 6.8.2: compound-statement
      return ParseCompoundStatement();
    case tok::semi: {                 // C99 6.8.3p3: expression[opt] ';'
      bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro();
      return Actions.ActOnNullStmt(ConsumeToken(), HasLeadingEmptyMacro);
    }
  
    case tok::kw_if:                  // C99 6.8.4.1: if-statement
      return ParseIfStatement(TrailingElseLoc);
    case tok::kw_switch:              // C99 6.8.4.2: switch-statement
      return ParseSwitchStatement(TrailingElseLoc);
  
    case tok::kw_while:               // C99 6.8.5.1: while-statement
      return ParseWhileStatement(TrailingElseLoc);
    case tok::kw_do:                  // C99 6.8.5.2: do-statement
      Res = ParseDoStatement();
      SemiError = "do/while";
      break;
    case tok::kw_for:                 // C99 6.8.5.3: for-statement
      return ParseForStatement(TrailingElseLoc);
  
    case tok::kw_goto:                // C99 6.8.6.1: goto-statement
      Res = ParseGotoStatement();
      SemiError = "goto";
      break;
    case tok::kw_continue:            // C99 6.8.6.2: continue-statement
      Res = ParseContinueStatement();
      SemiError = "continue";
      break;
    case tok::kw_break:               // C99 6.8.6.3: break-statement
      Res = ParseBreakStatement();
      SemiError = "break";
      break;
    case tok::kw_return:              // C99 6.8.6.4: return-statement
      Res = ParseReturnStatement();
      SemiError = "return";
      break;
    case tok::kw_co_return:            // C++ Coroutines: co_return statement
      Res = ParseReturnStatement();
      SemiError = "co_return";
      break;
  
    case tok::kw_asm: {
      ProhibitAttributes(Attrs);
      bool msAsm = false;
      Res = ParseAsmStatement(msAsm);
      Res = Actions.ActOnFinishFullStmt(Res.get());
      if (msAsm) return Res;
      SemiError = "asm";
      break;
    }
  
    case tok::kw___if_exists:
    case tok::kw___if_not_exists:
      ProhibitAttributes(Attrs);
      ParseMicrosoftIfExistsStatement(Stmts);
      // An __if_exists block is like a compound statement, but it doesn't create
      // a new scope.
      return StmtEmpty();
  
    case tok::kw_try:                 // C++ 15: try-block
      return ParseCXXTryBlock();
  
    case tok::kw___try:
      ProhibitAttributes(Attrs); // TODO: is it correct?
      return ParseSEHTryBlock();
  
    case tok::kw___leave:
      Res = ParseSEHLeaveStatement();
      SemiError = "__leave";
      break;
  
    case tok::annot_pragma_vis:
      ProhibitAttributes(Attrs);
      HandlePragmaVisibility();
      return StmtEmpty();
  
    case tok::annot_pragma_pack:
      ProhibitAttributes(Attrs);
      HandlePragmaPack();
      return StmtEmpty();
  
    case tok::annot_pragma_msstruct:
      ProhibitAttributes(Attrs);
      HandlePragmaMSStruct();
      return StmtEmpty();
  
    case tok::annot_pragma_align:
      ProhibitAttributes(Attrs);
      HandlePragmaAlign();
      return StmtEmpty();
  
    case tok::annot_pragma_weak:
      ProhibitAttributes(Attrs);
      HandlePragmaWeak();
      return StmtEmpty();
  
    case tok::annot_pragma_weakalias:
      ProhibitAttributes(Attrs);
      HandlePragmaWeakAlias();
      return StmtEmpty();
  
    case tok::annot_pragma_redefine_extname:
      ProhibitAttributes(Attrs);
      HandlePragmaRedefineExtname();
      return StmtEmpty();
  
    case tok::annot_pragma_fp_contract:
      ProhibitAttributes(Attrs);
      Diag(Tok, diag::err_pragma_file_or_compound_scope) << "fp_contract";
      ConsumeAnnotationToken();
      return StmtError();
  
    case tok::annot_pragma_fp:
      ProhibitAttributes(Attrs);
      Diag(Tok, diag::err_pragma_file_or_compound_scope) << "clang fp";
      ConsumeAnnotationToken();
      return StmtError();
  
    case tok::annot_pragma_fenv_access:
    case tok::annot_pragma_fenv_access_ms:
      ProhibitAttributes(Attrs);
      Diag(Tok, diag::err_pragma_file_or_compound_scope)
          << (Kind == tok::annot_pragma_fenv_access ? "STDC FENV_ACCESS"
                                                      : "fenv_access");
      ConsumeAnnotationToken();
      return StmtEmpty();
  
    case tok::annot_pragma_fenv_round:
      ProhibitAttributes(Attrs);
      Diag(Tok, diag::err_pragma_file_or_compound_scope) << "STDC FENV_ROUND";
      ConsumeAnnotationToken();
      return StmtError();
  
    case tok::annot_pragma_float_control:
      ProhibitAttributes(Attrs);
      Diag(Tok, diag::err_pragma_file_or_compound_scope) << "float_control";
      ConsumeAnnotationToken();
      return StmtError();
  
    case tok::annot_pragma_opencl_extension:
      ProhibitAttributes(Attrs);
      HandlePragmaOpenCLExtension();
      return StmtEmpty();
  
    case tok::annot_pragma_captured:
      ProhibitAttributes(Attrs);
      return HandlePragmaCaptured();
  
    case tok::annot_pragma_openmp:
      // Prohibit attributes that are not OpenMP attributes, but only before
      // processing a #pragma omp clause.
      ProhibitAttributes(Attrs);
      LLVM_FALLTHROUGH;
    case tok::annot_attr_openmp:
      // Do not prohibit attributes if they were OpenMP attributes.
      return ParseOpenMPDeclarativeOrExecutableDirective(StmtCtx);
  
    case tok::annot_pragma_ms_pointers_to_members:
      ProhibitAttributes(Attrs);
      HandlePragmaMSPointersToMembers();
      return StmtEmpty();
  
    case tok::annot_pragma_ms_pragma:
      ProhibitAttributes(Attrs);
      HandlePragmaMSPragma();
      return StmtEmpty();
  
    case tok::annot_pragma_ms_vtordisp:
      ProhibitAttributes(Attrs);
      HandlePragmaMSVtorDisp();
      return StmtEmpty();
  
    case tok::annot_pragma_loop_hint:
      ProhibitAttributes(Attrs);
      return ParsePragmaLoopHint(Stmts, StmtCtx, TrailingElseLoc, Attrs);
  
    case tok::annot_pragma_dump:
      HandlePragmaDump();
      return StmtEmpty();
  
    case tok::annot_pragma_attribute:
      HandlePragmaAttribute();
      return StmtEmpty();
    }
  
    // If we reached this code, the statement must end in a semicolon.
    if (!TryConsumeToken(tok::semi) && !Res.isInvalid()) {
      // If the result was valid, then we do want to diagnose this.  Use
      // ExpectAndConsume to emit the diagnostic, even though we know it won't
      // succeed.
      ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
      // Skip until we see a } or ;, but don't eat it.
      SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
    }
  
    return Res;
  }
  
  /// Parse an expression statement.
  StmtResult Parser::ParseExprStatement(ParsedStmtContext StmtCtx) {
    // If a case keyword is missing, this is where it should be inserted.
    Token OldToken = Tok;
  
    ExprStatementTokLoc = Tok.getLocation();
  
    // expression[opt] ';'
    ExprResult Expr(ParseExpression());
    if (Expr.isInvalid()) {
      // If the expression is invalid, skip ahead to the next semicolon or '}'.
      // Not doing this opens us up to the possibility of infinite loops if
      // ParseExpression does not consume any tokens.
      SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
      if (Tok.is(tok::semi))
        ConsumeToken();
      return Actions.ActOnExprStmtError();
    }
  
    if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() &&
        Actions.CheckCaseExpression(Expr.get())) {
      // If a constant expression is followed by a colon inside a switch block,
      // suggest a missing case keyword.
      Diag(OldToken, diag::err_expected_case_before_expression)
        << FixItHint::CreateInsertion(OldToken.getLocation(), "case ");
  
      // Recover parsing as a case statement.
      return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
    }
  
    // Otherwise, eat the semicolon.
    ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
    return handleExprStmt(Expr, StmtCtx);
  }
  
  /// ParseSEHTryBlockCommon
  ///
  /// seh-try-block:
  ///   '__try' compound-statement seh-handler
  ///
  /// seh-handler:
  ///   seh-except-block
  ///   seh-finally-block
  ///
  StmtResult Parser::ParseSEHTryBlock() {
    assert(Tok.is(tok::kw___try) && "Expected '__try'");
    SourceLocation TryLoc = ConsumeToken();
  
    if (Tok.isNot(tok::l_brace))
      return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
  
    StmtResult TryBlock(ParseCompoundStatement(
        /*isStmtExpr=*/false,
        Scope::DeclScope | Scope::CompoundStmtScope | Scope::SEHTryScope));
    if (TryBlock.isInvalid())
      return TryBlock;
  
    StmtResult Handler;
    if (Tok.is(tok::identifier) &&
        Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
      SourceLocation Loc = ConsumeToken();
      Handler = ParseSEHExceptBlock(Loc);
    } else if (Tok.is(tok::kw___finally)) {
      SourceLocation Loc = ConsumeToken();
      Handler = ParseSEHFinallyBlock(Loc);
    } else {
      return StmtError(Diag(Tok, diag::err_seh_expected_handler));
    }
  
    if(Handler.isInvalid())
      return Handler;
  
    return Actions.ActOnSEHTryBlock(false /* IsCXXTry */,
                                    TryLoc,
                                    TryBlock.get(),
                                    Handler.get());
  }
  
  /// ParseSEHExceptBlock - Handle __except
  ///
  /// seh-except-block:
  ///   '__except' '(' seh-filter-expression ')' compound-statement
  ///
  StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
    PoisonIdentifierRAIIObject raii(Ident__exception_code, false),
      raii2(Ident___exception_code, false),
      raii3(Ident_GetExceptionCode, false);
  
    if (ExpectAndConsume(tok::l_paren))
      return StmtError();
  
    ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope |
                                     Scope::SEHExceptScope);
  
    if (getLangOpts().Borland) {
      Ident__exception_info->setIsPoisoned(false);
      Ident___exception_info->setIsPoisoned(false);
      Ident_GetExceptionInfo->setIsPoisoned(false);
    }
  
    ExprResult FilterExpr;
    {
      ParseScopeFlags FilterScope(this, getCurScope()->getFlags() |
                                            Scope::SEHFilterScope);
      FilterExpr = Actions.CorrectDelayedTyposInExpr(ParseExpression());
    }
  
    if (getLangOpts().Borland) {
      Ident__exception_info->setIsPoisoned(true);
      Ident___exception_info->setIsPoisoned(true);
      Ident_GetExceptionInfo->setIsPoisoned(true);
    }
  
    if(FilterExpr.isInvalid())
      return StmtError();
  
    if (ExpectAndConsume(tok::r_paren))
      return StmtError();
  
    if (Tok.isNot(tok::l_brace))
      return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
  
    StmtResult Block(ParseCompoundStatement());
  
    if(Block.isInvalid())
      return Block;
  
    return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.get(), Block.get());
  }
  
  /// ParseSEHFinallyBlock - Handle __finally
  ///
  /// seh-finally-block:
  ///   '__finally' compound-statement
  ///
  StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyLoc) {
    PoisonIdentifierRAIIObject raii(Ident__abnormal_termination, false),
      raii2(Ident___abnormal_termination, false),
      raii3(Ident_AbnormalTermination, false);
  
    if (Tok.isNot(tok::l_brace))
      return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
  
    ParseScope FinallyScope(this, 0);
    Actions.ActOnStartSEHFinallyBlock();
  
    StmtResult Block(ParseCompoundStatement());
    if(Block.isInvalid()) {
      Actions.ActOnAbortSEHFinallyBlock();
      return Block;
    }
  
    return Actions.ActOnFinishSEHFinallyBlock(FinallyLoc, Block.get());
  }
  
  /// Handle __leave
  ///
  /// seh-leave-statement:
  ///   '__leave' ';'
  ///
  StmtResult Parser::ParseSEHLeaveStatement() {
    SourceLocation LeaveLoc = ConsumeToken();  // eat the '__leave'.
    return Actions.ActOnSEHLeaveStmt(LeaveLoc, getCurScope());
  }
  
  /// ParseLabeledStatement - We have an identifier and a ':' after it.
  ///
  ///       labeled-statement:
  ///         identifier ':' statement
  /// [GNU]   identifier ':' attributes[opt] statement
  ///
  StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs,
                                           ParsedStmtContext StmtCtx) {
    assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
           "Not an identifier!");
  
    // The substatement is always a 'statement', not a 'declaration', but is
    // otherwise in the same context as the labeled-statement.
    StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
  
    Token IdentTok = Tok;  // Save the whole token.
    ConsumeToken();  // eat the identifier.
  
    assert(Tok.is(tok::colon) && "Not a label!");
  
    // identifier ':' statement
    SourceLocation ColonLoc = ConsumeToken();
  
    // Read label attributes, if present.
    StmtResult SubStmt;
    if (Tok.is(tok::kw___attribute)) {
      ParsedAttributes TempAttrs(AttrFactory);
      ParseGNUAttributes(TempAttrs);
  
      // In C++, GNU attributes only apply to the label if they are followed by a
      // semicolon, to disambiguate label attributes from attributes on a labeled
      // declaration.
      //
      // This doesn't quite match what GCC does; if the attribute list is empty
      // and followed by a semicolon, GCC will reject (it appears to parse the
      // attributes as part of a statement in that case). That looks like a bug.
      if (!getLangOpts().CPlusPlus || Tok.is(tok::semi))
        Attrs.takeAllFrom(TempAttrs);
      else {
        StmtVector Stmts;
        SubStmt = ParseStatementOrDeclarationAfterAttributes(Stmts, StmtCtx,
                                                             nullptr, TempAttrs);
        if (!TempAttrs.empty() && !SubStmt.isInvalid())
          SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get());
      }
    }
  
    // If we've not parsed a statement yet, parse one now.
    if (!SubStmt.isInvalid() && !SubStmt.isUsable())
      SubStmt = ParseStatement(nullptr, StmtCtx);
  
    // Broken substmt shouldn't prevent the label from being added to the AST.
    if (SubStmt.isInvalid())
      SubStmt = Actions.ActOnNullStmt(ColonLoc);
  
    LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
                                                IdentTok.getLocation());
    Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
    Attrs.clear();
  
    return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc,
                                  SubStmt.get());
  }
  
  /// ParseCaseStatement
  ///       labeled-statement:
  ///         'case' constant-expression ':' statement
  /// [GNU]   'case' constant-expression '...' constant-expression ':' statement
  ///
  StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
                                        bool MissingCase, ExprResult Expr) {
    assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!");
  
    // The substatement is always a 'statement', not a 'declaration', but is
    // otherwise in the same context as the labeled-statement.
    StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
  
    // It is very very common for code to contain many case statements recursively
    // nested, as in (but usually without indentation):
    //  case 1:
    //    case 2:
    //      case 3:
    //         case 4:
    //           case 5: etc.
    //
    // Parsing this naively works, but is both inefficient and can cause us to run
    // out of stack space in our recursive descent parser.  As a special case,
    // flatten this recursion into an iterative loop.  This is complex and gross,
    // but all the grossness is constrained to ParseCaseStatement (and some
    // weirdness in the actions), so this is just local grossness :).
  
    // TopLevelCase - This is the highest level we have parsed.  'case 1' in the
    // example above.
    StmtResult TopLevelCase(true);
  
    // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
    // gets updated each time a new case is parsed, and whose body is unset so
    // far.  When parsing 'case 4', this is the 'case 3' node.
    Stmt *DeepestParsedCaseStmt = nullptr;
  
    // While we have case statements, eat and stack them.
    SourceLocation ColonLoc;
    do {
      SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() :
                                             ConsumeToken();  // eat the 'case'.
      ColonLoc = SourceLocation();
  
      if (Tok.is(tok::code_completion)) {
        cutOffParsing();
        Actions.CodeCompleteCase(getCurScope());
        return StmtError();
      }
  
      /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
      /// Disable this form of error recovery while we're parsing the case
      /// expression.
      ColonProtectionRAIIObject ColonProtection(*this);
  
      ExprResult LHS;
      if (!MissingCase) {
        LHS = ParseCaseExpression(CaseLoc);
        if (LHS.isInvalid()) {
          // If constant-expression is parsed unsuccessfully, recover by skipping
          // current case statement (moving to the colon that ends it).
          if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
            return StmtError();
        }
      } else {
        LHS = Expr;
        MissingCase = false;
      }
  
      // GNU case range extension.
      SourceLocation DotDotDotLoc;
      ExprResult RHS;
      if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) {
        Diag(DotDotDotLoc, diag::ext_gnu_case_range);
        RHS = ParseCaseExpression(CaseLoc);
        if (RHS.isInvalid()) {
          if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
            return StmtError();
        }
      }
  
      ColonProtection.restore();
  
      if (TryConsumeToken(tok::colon, ColonLoc)) {
      } else if (TryConsumeToken(tok::semi, ColonLoc) ||
                 TryConsumeToken(tok::coloncolon, ColonLoc)) {
        // Treat "case blah;" or "case blah::" as a typo for "case blah:".
        Diag(ColonLoc, diag::err_expected_after)
            << "'case'" << tok::colon
            << FixItHint::CreateReplacement(ColonLoc, ":");
      } else {
        SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
        Diag(ExpectedLoc, diag::err_expected_after)
            << "'case'" << tok::colon
            << FixItHint::CreateInsertion(ExpectedLoc, ":");
        ColonLoc = ExpectedLoc;
      }
  
      StmtResult Case =
          Actions.ActOnCaseStmt(CaseLoc, LHS, DotDotDotLoc, RHS, ColonLoc);
  
      // If we had a sema error parsing this case, then just ignore it and
      // continue parsing the sub-stmt.
      if (Case.isInvalid()) {
        if (TopLevelCase.isInvalid())  // No parsed case stmts.
          return ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
        // Otherwise, just don't add it as a nested case.
      } else {
        // If this is the first case statement we parsed, it becomes TopLevelCase.
        // Otherwise we link it into the current chain.
        Stmt *NextDeepest = Case.get();
        if (TopLevelCase.isInvalid())
          TopLevelCase = Case;
        else
          Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, Case.get());
        DeepestParsedCaseStmt = NextDeepest;
      }
  
      // Handle all case statements.
    } while (Tok.is(tok::kw_case));
  
    // If we found a non-case statement, start by parsing it.
    StmtResult SubStmt;
  
    if (Tok.isNot(tok::r_brace)) {
      SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
    } else {
      // Nicely diagnose the common error "switch (X) { case 4: }", which is
      // not valid.  If ColonLoc doesn't point to a valid text location, there was
      // another parsing error, so avoid producing extra diagnostics.
      if (ColonLoc.isValid()) {
        SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc);
        Diag(AfterColonLoc, diag::err_label_end_of_compound_statement)
          << FixItHint::CreateInsertion(AfterColonLoc, " ;");
      }
      SubStmt = StmtError();
    }
  
    // Install the body into the most deeply-nested case.
    if (DeepestParsedCaseStmt) {
      // Broken sub-stmt shouldn't prevent forming the case statement properly.
      if (SubStmt.isInvalid())
        SubStmt = Actions.ActOnNullStmt(SourceLocation());
      Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
    }
  
    // Return the top level parsed statement tree.
    return TopLevelCase;
  }
  
  /// ParseDefaultStatement
  ///       labeled-statement:
  ///         'default' ':' statement
  /// Note that this does not parse the 'statement' at the end.
  ///
  StmtResult Parser::ParseDefaultStatement(ParsedStmtContext StmtCtx) {
    assert(Tok.is(tok::kw_default) && "Not a default stmt!");
  
    // The substatement is always a 'statement', not a 'declaration', but is
    // otherwise in the same context as the labeled-statement.
    StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
  
    SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
  
    SourceLocation ColonLoc;
    if (TryConsumeToken(tok::colon, ColonLoc)) {
    } else if (TryConsumeToken(tok::semi, ColonLoc)) {
      // Treat "default;" as a typo for "default:".
      Diag(ColonLoc, diag::err_expected_after)
          << "'default'" << tok::colon
          << FixItHint::CreateReplacement(ColonLoc, ":");
    } else {
      SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
      Diag(ExpectedLoc, diag::err_expected_after)
          << "'default'" << tok::colon
          << FixItHint::CreateInsertion(ExpectedLoc, ":");
      ColonLoc = ExpectedLoc;
    }
  
    StmtResult SubStmt;
  
    if (Tok.isNot(tok::r_brace)) {
      SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
    } else {
      // Diagnose the common error "switch (X) {... default: }", which is
      // not valid.
      SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc);
      Diag(AfterColonLoc, diag::err_label_end_of_compound_statement)
        << FixItHint::CreateInsertion(AfterColonLoc, " ;");
      SubStmt = true;
    }
  
    // Broken sub-stmt shouldn't prevent forming the case statement properly.
    if (SubStmt.isInvalid())
      SubStmt = Actions.ActOnNullStmt(ColonLoc);
  
    return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
                                    SubStmt.get(), getCurScope());
  }
  
  StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
    return ParseCompoundStatement(isStmtExpr,
                                  Scope::DeclScope | Scope::CompoundStmtScope);
  }
  
  /// ParseCompoundStatement - Parse a "{}" block.
  ///
  ///       compound-statement: [C99 6.8.2]
  ///         { block-item-list[opt] }
  /// [GNU]   { label-declarations block-item-list } [TODO]
  ///
  ///       block-item-list:
  ///         block-item
  ///         block-item-list block-item
  ///
  ///       block-item:
  ///         declaration
  /// [GNU]   '__extension__' declaration
  ///         statement
  ///
  /// [GNU] label-declarations:
  /// [GNU]   label-declaration
  /// [GNU]   label-declarations label-declaration
  ///
  /// [GNU] label-declaration:
  /// [GNU]   '__label__' identifier-list ';'
  ///
  StmtResult Parser::ParseCompoundStatement(bool isStmtExpr,
                                            unsigned ScopeFlags) {
    assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
  
    // Enter a scope to hold everything within the compound stmt.  Compound
    // statements can always hold declarations.
    ParseScope CompoundScope(this, ScopeFlags);
  
    // Parse the statements in the body.
    return ParseCompoundStatementBody(isStmtExpr);
  }
  
  /// Parse any pragmas at the start of the compound expression. We handle these
  /// separately since some pragmas (FP_CONTRACT) must appear before any C
  /// statement in the compound, but may be intermingled with other pragmas.
  void Parser::ParseCompoundStatementLeadingPragmas() {
    bool checkForPragmas = true;
    while (checkForPragmas) {
      switch (Tok.getKind()) {
      case tok::annot_pragma_vis:
        HandlePragmaVisibility();
        break;
      case tok::annot_pragma_pack:
        HandlePragmaPack();
        break;
      case tok::annot_pragma_msstruct:
        HandlePragmaMSStruct();
        break;
      case tok::annot_pragma_align:
        HandlePragmaAlign();
        break;
      case tok::annot_pragma_weak:
        HandlePragmaWeak();
        break;
      case tok::annot_pragma_weakalias:
        HandlePragmaWeakAlias();
        break;
      case tok::annot_pragma_redefine_extname:
        HandlePragmaRedefineExtname();
        break;
      case tok::annot_pragma_opencl_extension:
        HandlePragmaOpenCLExtension();
        break;
      case tok::annot_pragma_fp_contract:
        HandlePragmaFPContract();
        break;
      case tok::annot_pragma_fp:
        HandlePragmaFP();
        break;
      case tok::annot_pragma_fenv_access:
      case tok::annot_pragma_fenv_access_ms:
        HandlePragmaFEnvAccess();
        break;
      case tok::annot_pragma_fenv_round:
        HandlePragmaFEnvRound();
        break;
      case tok::annot_pragma_float_control:
        HandlePragmaFloatControl();
        break;
      case tok::annot_pragma_ms_pointers_to_members:
        HandlePragmaMSPointersToMembers();
        break;
      case tok::annot_pragma_ms_pragma:
        HandlePragmaMSPragma();
        break;
      case tok::annot_pragma_ms_vtordisp:
        HandlePragmaMSVtorDisp();
        break;
      case tok::annot_pragma_dump:
        HandlePragmaDump();
        break;
      default:
        checkForPragmas = false;
        break;
      }
    }
  
  }
  
  /// Consume any extra semi-colons resulting in null statements,
  /// returning true if any tok::semi were consumed.
  bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
    if (!Tok.is(tok::semi))
      return false;
  
    SourceLocation StartLoc = Tok.getLocation();
    SourceLocation EndLoc;
  
    while (Tok.is(tok::semi) && !Tok.hasLeadingEmptyMacro() &&
           Tok.getLocation().isValid() && !Tok.getLocation().isMacroID()) {
      EndLoc = Tok.getLocation();
  
      // Don't just ConsumeToken() this tok::semi, do store it in AST.
      StmtResult R =
          ParseStatementOrDeclaration(Stmts, ParsedStmtContext::SubStmt);
      if (R.isUsable())
        Stmts.push_back(R.get());
    }
  
    // Did not consume any extra semi.
    if (EndLoc.isInvalid())
      return false;
  
    Diag(StartLoc, diag::warn_null_statement)
        << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc));
    return true;
  }
  
  StmtResult Parser::handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx) {
    bool IsStmtExprResult = false;
    if ((StmtCtx & ParsedStmtContext::InStmtExpr) != ParsedStmtContext()) {
      // For GCC compatibility we skip past NullStmts.
      unsigned LookAhead = 0;
      while (GetLookAheadToken(LookAhead).is(tok::semi)) {
        ++LookAhead;
      }
      // Then look to see if the next two tokens close the statement expression;
      // if so, this expression statement is the last statement in a statment
      // expression.
      IsStmtExprResult = GetLookAheadToken(LookAhead).is(tok::r_brace) &&
                         GetLookAheadToken(LookAhead + 1).is(tok::r_paren);
    }
  
    if (IsStmtExprResult)
      E = Actions.ActOnStmtExprResult(E);
    return Actions.ActOnExprStmt(E, /*DiscardedValue=*/!IsStmtExprResult);
  }
  
  /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
  /// ActOnCompoundStmt action.  This expects the '{' to be the current token, and
  /// consume the '}' at the end of the block.  It does not manipulate the scope
  /// stack.
  StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
    PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
                                  Tok.getLocation(),
                                  "in compound statement ('{}')");
  
    // Record the current FPFeatures, restore on leaving the
    // compound statement.
    Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
  
    InMessageExpressionRAIIObject InMessage(*this, false);
    BalancedDelimiterTracker T(*this, tok::l_brace);
    if (T.consumeOpen())
      return StmtError();
  
    Sema::CompoundScopeRAII CompoundScope(Actions, isStmtExpr);
  
    // Parse any pragmas at the beginning of the compound statement.
    ParseCompoundStatementLeadingPragmas();
    Actions.ActOnAfterCompoundStatementLeadingPragmas();
  
    StmtVector Stmts;
  
    // "__label__ X, Y, Z;" is the GNU "Local Label" extension.  These are
    // only allowed at the start of a compound stmt regardless of the language.
    while (Tok.is(tok::kw___label__)) {
      SourceLocation LabelLoc = ConsumeToken();
  
      SmallVector<Decl *, 8> DeclsInGroup;
      while (true) {
        if (Tok.isNot(tok::identifier)) {
          Diag(Tok, diag::err_expected) << tok::identifier;
          break;
        }
  
        IdentifierInfo *II = Tok.getIdentifierInfo();
        SourceLocation IdLoc = ConsumeToken();
        DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc));
  
        if (!TryConsumeToken(tok::comma))
          break;
      }
  
      DeclSpec DS(AttrFactory);
      DeclGroupPtrTy Res =
          Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
      StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation());
  
      ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
      if (R.isUsable())
        Stmts.push_back(R.get());
    }
  
    ParsedStmtContext SubStmtCtx =
        ParsedStmtContext::Compound |
        (isStmtExpr ? ParsedStmtContext::InStmtExpr : ParsedStmtContext());
  
    while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
           Tok.isNot(tok::eof)) {
      if (Tok.is(tok::annot_pragma_unused)) {
        HandlePragmaUnused();
        continue;
      }
  
      if (ConsumeNullStmt(Stmts))
        continue;
  
      StmtResult R;
      if (Tok.isNot(tok::kw___extension__)) {
        R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
      } else {
        // __extension__ can start declarations and it can also be a unary
        // operator for expressions.  Consume multiple __extension__ markers here
        // until we can determine which is which.
        // FIXME: This loses extension expressions in the AST!
        SourceLocation ExtLoc = ConsumeToken();
        while (Tok.is(tok::kw___extension__))
          ConsumeToken();
  
        ParsedAttributes attrs(AttrFactory);
        MaybeParseCXX11Attributes(attrs, /*MightBeObjCMessageSend*/ true);
  
        // If this is the start of a declaration, parse it as such.
        if (isDeclarationStatement()) {
          // __extension__ silences extension warnings in the subdeclaration.
          // FIXME: Save the __extension__ on the decl as a node somehow?
          ExtensionRAIIObject O(Diags);
  
          SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
          DeclGroupPtrTy Res =
              ParseDeclaration(DeclaratorContext::Block, DeclEnd, attrs);
          R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
        } else {
          // Otherwise this was a unary __extension__ marker.
          ExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
  
          if (Res.isInvalid()) {
            SkipUntil(tok::semi);
            continue;
          }
  
          // Eat the semicolon at the end of stmt and convert the expr into a
          // statement.
          ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
          R = handleExprStmt(Res, SubStmtCtx);
          if (R.isUsable())
            R = Actions.ActOnAttributedStmt(attrs, R.get());
        }
      }
  
      if (R.isUsable())
        Stmts.push_back(R.get());
    }
    // Warn the user that using option `-ffp-eval-method=source` on a
    // 32-bit target and feature `sse` disabled, or using
    // `pragma clang fp eval_method=source` and feature `sse` disabled, is not
    // supported.
    if (!PP.getTargetInfo().supportSourceEvalMethod() &&
        (PP.getLastFPEvalPragmaLocation().isValid() ||
         PP.getCurrentFPEvalMethod() ==
             LangOptions::FPEvalMethodKind::FEM_Source))
      Diag(Tok.getLocation(),
           diag::warn_no_support_for_eval_method_source_on_m32);
  
    SourceLocation CloseLoc = Tok.getLocation();
  
    // We broke out of the while loop because we found a '}' or EOF.
    if (!T.consumeClose()) {
      // If this is the '})' of a statement expression, check that it's written
      // in a sensible way.
      if (isStmtExpr && Tok.is(tok::r_paren))
        checkCompoundToken(CloseLoc, tok::r_brace, CompoundToken::StmtExprEnd);
    } else {
      // Recover by creating a compound statement with what we parsed so far,
      // instead of dropping everything and returning StmtError().
    }
  
    if (T.getCloseLocation().isValid())
      CloseLoc = T.getCloseLocation();
  
    return Actions.ActOnCompoundStmt(T.getOpenLocation(), CloseLoc,
                                     Stmts, isStmtExpr);
  }
  
  /// ParseParenExprOrCondition:
  /// [C  ]     '(' expression ')'
  /// [C++]     '(' condition ')'
  /// [C++1z]   '(' init-statement[opt] condition ')'
  ///
  /// This function parses and performs error recovery on the specified condition
  /// or expression (depending on whether we're in C++ or C mode).  This function
  /// goes out of its way to recover well.  It returns true if there was a parser
  /// error (the right paren couldn't be found), which indicates that the caller
  /// should try to recover harder.  It returns false if the condition is
  /// successfully parsed.  Note that a successful parse can still have semantic
  /// errors in the condition.
  /// Additionally, if LParenLoc and RParenLoc are non-null, it will assign
  /// the location of the outer-most '(' and ')', respectively, to them.
  bool Parser::ParseParenExprOrCondition(StmtResult *InitStmt,
                                         Sema::ConditionResult &Cond,
                                         SourceLocation Loc,
                                         Sema::ConditionKind CK, bool MissingOK,
                                         SourceLocation *LParenLoc,
                                         SourceLocation *RParenLoc) {
    BalancedDelimiterTracker T(*this, tok::l_paren);
    T.consumeOpen();
    SourceLocation Start = Tok.getLocation();
  
    if (getLangOpts().CPlusPlus) {
      Cond = ParseCXXCondition(InitStmt, Loc, CK, MissingOK);
    } else {
      ExprResult CondExpr = ParseExpression();
  
      // If required, convert to a boolean value.
      if (CondExpr.isInvalid())
        Cond = Sema::ConditionError();
      else
        Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK,
                                      MissingOK);
    }
  
    // If the parser was confused by the condition and we don't have a ')', try to
    // recover by skipping ahead to a semi and bailing out.  If condexp is
    // semantically invalid but we have well formed code, keep going.
    if (Cond.isInvalid() && Tok.isNot(tok::r_paren)) {
      SkipUntil(tok::semi);
      // Skipping may have stopped if it found the containing ')'.  If so, we can
      // continue parsing the if statement.
      if (Tok.isNot(tok::r_paren))
        return true;
    }
  
    if (Cond.isInvalid()) {
      ExprResult CondExpr = Actions.CreateRecoveryExpr(
          Start, Tok.getLocation() == Start ? Start : PrevTokLocation, {},
          Actions.PreferredConditionType(CK));
      if (!CondExpr.isInvalid())
        Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK,
                                      MissingOK);
    }
  
    // Either the condition is valid or the rparen is present.
    T.consumeClose();
  
    if (LParenLoc != nullptr) {
      *LParenLoc = T.getOpenLocation();
    }
    if (RParenLoc != nullptr) {
      *RParenLoc = T.getCloseLocation();
    }
  
    // Check for extraneous ')'s to catch things like "if (foo())) {".  We know
    // that all callers are looking for a statement after the condition, so ")"
    // isn't valid.
    while (Tok.is(tok::r_paren)) {
      Diag(Tok, diag::err_extraneous_rparen_in_condition)
        << FixItHint::CreateRemoval(Tok.getLocation());
      ConsumeParen();
    }
  
    return false;
  }
  
  namespace {
  
  enum MisleadingStatementKind { MSK_if, MSK_else, MSK_for, MSK_while };
  
  struct MisleadingIndentationChecker {
    Parser &P;
    SourceLocation StmtLoc;
    SourceLocation PrevLoc;
    unsigned NumDirectives;
    MisleadingStatementKind Kind;
    bool ShouldSkip;
    MisleadingIndentationChecker(Parser &P, MisleadingStatementKind K,
                                 SourceLocation SL)
        : P(P), StmtLoc(SL), PrevLoc(P.getCurToken().getLocation()),
          NumDirectives(P.getPreprocessor().getNumDirectives()), Kind(K),
          ShouldSkip(P.getCurToken().is(tok::l_brace)) {
      if (!P.MisleadingIndentationElseLoc.isInvalid()) {
        StmtLoc = P.MisleadingIndentationElseLoc;
        P.MisleadingIndentationElseLoc = SourceLocation();
      }
      if (Kind == MSK_else && !ShouldSkip)
        P.MisleadingIndentationElseLoc = SL;
    }
  
    /// Compute the column number will aligning tabs on TabStop (-ftabstop), this
    /// gives the visual indentation of the SourceLocation.
    static unsigned getVisualIndentation(SourceManager &SM, SourceLocation Loc) {
      unsigned TabStop = SM.getDiagnostics().getDiagnosticOptions().TabStop;
  
      unsigned ColNo = SM.getSpellingColumnNumber(Loc);
      if (ColNo == 0 || TabStop == 1)
        return ColNo;
  
      std::pair<FileID, unsigned> FIDAndOffset = SM.getDecomposedLoc(Loc);
  
      bool Invalid;
      StringRef BufData = SM.getBufferData(FIDAndOffset.first, &Invalid);
      if (Invalid)
        return 0;
  
      const char *EndPos = BufData.data() + FIDAndOffset.second;
      // FileOffset are 0-based and Column numbers are 1-based
      assert(FIDAndOffset.second + 1 >= ColNo &&
             "Column number smaller than file offset?");
  
      unsigned VisualColumn = 0; // Stored as 0-based column, here.
      // Loop from beginning of line up to Loc's file position, counting columns,
      // expanding tabs.
      for (const char *CurPos = EndPos - (ColNo - 1); CurPos != EndPos;
           ++CurPos) {
        if (*CurPos == '\t')
          // Advance visual column to next tabstop.
          VisualColumn += (TabStop - VisualColumn % TabStop);
        else
          VisualColumn++;
      }
      return VisualColumn + 1;
    }
  
    void Check() {
      Token Tok = P.getCurToken();
      if (P.getActions().getDiagnostics().isIgnored(
              diag::warn_misleading_indentation, Tok.getLocation()) ||
          ShouldSkip || NumDirectives != P.getPreprocessor().getNumDirectives() ||
          Tok.isOneOf(tok::semi, tok::r_brace) || Tok.isAnnotation() ||
          Tok.getLocation().isMacroID() || PrevLoc.isMacroID() ||
          StmtLoc.isMacroID() ||
          (Kind == MSK_else && P.MisleadingIndentationElseLoc.isInvalid())) {
        P.MisleadingIndentationElseLoc = SourceLocation();
        return;
      }
      if (Kind == MSK_else)
        P.MisleadingIndentationElseLoc = SourceLocation();
  
      SourceManager &SM = P.getPreprocessor().getSourceManager();
      unsigned PrevColNum = getVisualIndentation(SM, PrevLoc);
      unsigned CurColNum = getVisualIndentation(SM, Tok.getLocation());
      unsigned StmtColNum = getVisualIndentation(SM, StmtLoc);
  
      if (PrevColNum != 0 && CurColNum != 0 && StmtColNum != 0 &&
          ((PrevColNum > StmtColNum && PrevColNum == CurColNum) ||
           !Tok.isAtStartOfLine()) &&
          SM.getPresumedLineNumber(StmtLoc) !=
              SM.getPresumedLineNumber(Tok.getLocation()) &&
          (Tok.isNot(tok::identifier) ||
           P.getPreprocessor().LookAhead(0).isNot(tok::colon))) {
        P.Diag(Tok.getLocation(), diag::warn_misleading_indentation) << Kind;
        P.Diag(StmtLoc, diag::note_previous_statement);
      }
    }
  };
  
  }
  
  /// ParseIfStatement
  ///       if-statement: [C99 6.8.4.1]
  ///         'if' '(' expression ')' statement
  ///         'if' '(' expression ')' statement 'else' statement
  /// [C++]   'if' '(' condition ')' statement
  /// [C++]   'if' '(' condition ')' statement 'else' statement
  /// [C++23] 'if' '!' [opt] consteval compound-statement
  /// [C++23] 'if' '!' [opt] consteval compound-statement 'else' statement
  ///
  StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
    assert(Tok.is(tok::kw_if) && "Not an if stmt!");
    SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
  
    bool IsConstexpr = false;
    bool IsConsteval = false;
    SourceLocation NotLocation;
    SourceLocation ConstevalLoc;
  
    if (Tok.is(tok::kw_constexpr)) {
      Diag(Tok, getLangOpts().CPlusPlus17 ? diag::warn_cxx14_compat_constexpr_if
                                          : diag::ext_constexpr_if);
      IsConstexpr = true;
      ConsumeToken();
    } else {
      if (Tok.is(tok::exclaim)) {
        NotLocation = ConsumeToken();
      }
  
      if (Tok.is(tok::kw_consteval)) {
        Diag(Tok, getLangOpts().CPlusPlus2b ? diag::warn_cxx20_compat_consteval_if
                                            : diag::ext_consteval_if);
        IsConsteval = true;
        ConstevalLoc = ConsumeToken();
      }
    }
    if (!IsConsteval && (NotLocation.isValid() || Tok.isNot(tok::l_paren))) {
      Diag(Tok, diag::err_expected_lparen_after) << "if";
      SkipUntil(tok::semi);
      return StmtError();
    }
  
    bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
  
    // C99 6.8.4p3 - In C99, the if statement is a block.  This is not
    // the case for C90.
    //
    // C++ 6.4p3:
    // A name introduced by a declaration in a condition is in scope from its
    // point of declaration until the end of the substatements controlled by the
    // condition.
    // C++ 3.3.2p4:
    // Names declared in the for-init-statement, and in the condition of if,
    // while, for, and switch statements are local to the if, while, for, or
    // switch statement (including the controlled statement).
    //
    ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
  
    // Parse the condition.
    StmtResult InitStmt;
    Sema::ConditionResult Cond;
    SourceLocation LParen;
    SourceLocation RParen;
    llvm::Optional<bool> ConstexprCondition;
    if (!IsConsteval) {
  
      if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc,
                                    IsConstexpr ? Sema::ConditionKind::ConstexprIf
                                                : Sema::ConditionKind::Boolean,
                                    /*MissingOK=*/false, &LParen, &RParen))
        return StmtError();
  
      if (IsConstexpr)
        ConstexprCondition = Cond.getKnownValue();
    }
  
    bool IsBracedThen = Tok.is(tok::l_brace);
  
    // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
    // there is no compound stmt.  C90 does not have this clause.  We only do this
    // if the body isn't a compound statement to avoid push/pop in common cases.
    //
    // C++ 6.4p1:
    // The substatement in a selection-statement (each substatement, in the else
    // form of the if statement) implicitly defines a local scope.
    //
    // For C++ we create a scope for the condition and a new scope for
    // substatements because:
    // -When the 'then' scope exits, we want the condition declaration to still be
    //    active for the 'else' scope too.
    // -Sema will detect name clashes by considering declarations of a
    //    'ControlScope' as part of its direct subscope.
    // -If we wanted the condition and substatement to be in the same scope, we
    //    would have to notify ParseStatement not to create a new scope. It's
    //    simpler to let it create a new scope.
    //
    ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, IsBracedThen);
  
    MisleadingIndentationChecker MIChecker(*this, MSK_if, IfLoc);
  
    // Read the 'then' stmt.
    SourceLocation ThenStmtLoc = Tok.getLocation();
  
    SourceLocation InnerStatementTrailingElseLoc;
    StmtResult ThenStmt;
    {
      bool ShouldEnter = ConstexprCondition && !*ConstexprCondition;
      Sema::ExpressionEvaluationContext Context =
          Sema::ExpressionEvaluationContext::DiscardedStatement;
      if (NotLocation.isInvalid() && IsConsteval) {
        Context = Sema::ExpressionEvaluationContext::ImmediateFunctionContext;
        ShouldEnter = true;
      }
  
      EnterExpressionEvaluationContext PotentiallyDiscarded(
          Actions, Context, nullptr,
          Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
      ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
    }
  
    if (Tok.isNot(tok::kw_else))
      MIChecker.Check();
  
    // Pop the 'if' scope if needed.
    InnerScope.Exit();
  
    // If it has an else, parse it.
    SourceLocation ElseLoc;
    SourceLocation ElseStmtLoc;
    StmtResult ElseStmt;
  
    if (Tok.is(tok::kw_else)) {
      if (TrailingElseLoc)
        *TrailingElseLoc = Tok.getLocation();
  
      ElseLoc = ConsumeToken();
      ElseStmtLoc = Tok.getLocation();
  
      // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
      // there is no compound stmt.  C90 does not have this clause.  We only do
      // this if the body isn't a compound statement to avoid push/pop in common
      // cases.
      //
      // C++ 6.4p1:
      // The substatement in a selection-statement (each substatement, in the else
      // form of the if statement) implicitly defines a local scope.
      //
      ParseScope InnerScope(this, Scope::DeclScope, C99orCXX,
                            Tok.is(tok::l_brace));
  
      MisleadingIndentationChecker MIChecker(*this, MSK_else, ElseLoc);
      bool ShouldEnter = ConstexprCondition && *ConstexprCondition;
      Sema::ExpressionEvaluationContext Context =
          Sema::ExpressionEvaluationContext::DiscardedStatement;
      if (NotLocation.isValid() && IsConsteval) {
        Context = Sema::ExpressionEvaluationContext::ImmediateFunctionContext;
        ShouldEnter = true;
      }
  
      EnterExpressionEvaluationContext PotentiallyDiscarded(
          Actions, Context, nullptr,
          Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
      ElseStmt = ParseStatement();
  
      if (ElseStmt.isUsable())
        MIChecker.Check();
  
      // Pop the 'else' scope if needed.
      InnerScope.Exit();
    } else if (Tok.is(tok::code_completion)) {
      cutOffParsing();
      Actions.CodeCompleteAfterIf(getCurScope(), IsBracedThen);
      return StmtError();
    } else if (InnerStatementTrailingElseLoc.isValid()) {
      Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else);
    }
  
    IfScope.Exit();
  
    // If the then or else stmt is invalid and the other is valid (and present),
    // make turn the invalid one into a null stmt to avoid dropping the other
    // part.  If both are invalid, return error.
    if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
        (ThenStmt.isInvalid() && ElseStmt.get() == nullptr) ||
        (ThenStmt.get() == nullptr && ElseStmt.isInvalid())) {
      // Both invalid, or one is invalid and other is non-present: return error.
      return StmtError();
    }
  
    if (IsConsteval) {
      auto IsCompoundStatement = [](const Stmt *S) {
        if (const auto *Outer = dyn_cast_or_null<AttributedStmt>(S))
          S = Outer->getSubStmt();
        return isa_and_nonnull<clang::CompoundStmt>(S);
      };
  
      if (!IsCompoundStatement(ThenStmt.get())) {
        Diag(ConstevalLoc, diag::err_expected_after) << "consteval"
                                                     << "{";
        return StmtError();
      }
      if (!ElseStmt.isUnset() && !IsCompoundStatement(ElseStmt.get())) {
        Diag(ElseLoc, diag::err_expected_after) << "else"
                                                << "{";
        return StmtError();
      }
    }
  
    // Now if either are invalid, replace with a ';'.
    if (ThenStmt.isInvalid())
      ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
    if (ElseStmt.isInvalid())
      ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
  
    IfStatementKind Kind = IfStatementKind::Ordinary;
    if (IsConstexpr)
      Kind = IfStatementKind::Constexpr;
    else if (IsConsteval)
      Kind = NotLocation.isValid() ? IfStatementKind::ConstevalNegated
                                   : IfStatementKind::ConstevalNonNegated;
  
    return Actions.ActOnIfStmt(IfLoc, Kind, LParen, InitStmt.get(), Cond, RParen,
                               ThenStmt.get(), ElseLoc, ElseStmt.get());
  }
  
  /// ParseSwitchStatement
  ///       switch-statement:
  ///         'switch' '(' expression ')' statement
  /// [C++]   'switch' '(' condition ')' statement
  StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
    assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
    SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
  
    if (Tok.isNot(tok::l_paren)) {
      Diag(Tok, diag::err_expected_lparen_after) << "switch";
      SkipUntil(tok::semi);
      return StmtError();
    }
  
    bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
  
    // C99 6.8.4p3 - In C99, the switch statement is a block.  This is
    // not the case for C90.  Start the switch scope.
    //
    // C++ 6.4p3:
    // A name introduced by a declaration in a condition is in scope from its
    // point of declaration until the end of the substatements controlled by the
    // condition.
    // C++ 3.3.2p4:
    // Names declared in the for-init-statement, and in the condition of if,
    // while, for, and switch statements are local to the if, while, for, or
    // switch statement (including the controlled statement).
    //
    unsigned ScopeFlags = Scope::SwitchScope;
    if (C99orCXX)
      ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
    ParseScope SwitchScope(this, ScopeFlags);
  
    // Parse the condition.
    StmtResult InitStmt;
    Sema::ConditionResult Cond;
    SourceLocation LParen;
    SourceLocation RParen;
    if (ParseParenExprOrCondition(&InitStmt, Cond, SwitchLoc,
                                  Sema::ConditionKind::Switch,
                                  /*MissingOK=*/false, &LParen, &RParen))
      return StmtError();
  
    StmtResult Switch = Actions.ActOnStartOfSwitchStmt(
        SwitchLoc, LParen, InitStmt.get(), Cond, RParen);
  
    if (Switch.isInvalid()) {
      // Skip the switch body.
      // FIXME: This is not optimal recovery, but parsing the body is more
      // dangerous due to the presence of case and default statements, which
      // will have no place to connect back with the switch.
      if (Tok.is(tok::l_brace)) {
        ConsumeBrace();
        SkipUntil(tok::r_brace);
      } else
        SkipUntil(tok::semi);
      return Switch;
    }
  
    // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
    // there is no compound stmt.  C90 does not have this clause.  We only do this
    // if the body isn't a compound statement to avoid push/pop in common cases.
    //
    // C++ 6.4p1:
    // The substatement in a selection-statement (each substatement, in the else
    // form of the if statement) implicitly defines a local scope.
    //
    // See comments in ParseIfStatement for why we create a scope for the
    // condition and a new scope for substatement in C++.
    //
    getCurScope()->AddFlags(Scope::BreakScope);
    ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
  
    // We have incremented the mangling number for the SwitchScope and the
    // InnerScope, which is one too many.
    if (C99orCXX)
      getCurScope()->decrementMSManglingNumber();
  
    // Read the body statement.
    StmtResult Body(ParseStatement(TrailingElseLoc));
  
    // Pop the scopes.
    InnerScope.Exit();
    SwitchScope.Exit();
  
    return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get());
  }
  
  /// ParseWhileStatement
  ///       while-statement: [C99 6.8.5.1]
  ///         'while' '(' expression ')' statement
  /// [C++]   'while' '(' condition ')' statement
  StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
    assert(Tok.is(tok::kw_while) && "Not a while stmt!");
    SourceLocation WhileLoc = Tok.getLocation();
    ConsumeToken();  // eat the 'while'.
  
    if (Tok.isNot(tok::l_paren)) {
      Diag(Tok, diag::err_expected_lparen_after) << "while";
      SkipUntil(tok::semi);
      return StmtError();
    }
  
    bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
  
    // C99 6.8.5p5 - In C99, the while statement is a block.  This is not
    // the case for C90.  Start the loop scope.
    //
    // C++ 6.4p3:
    // A name introduced by a declaration in a condition is in scope from its
    // point of declaration until the end of the substatements controlled by the
    // condition.
    // C++ 3.3.2p4:
    // Names declared in the for-init-statement, and in the condition of if,
    // while, for, and switch statements are local to the if, while, for, or
    // switch statement (including the controlled statement).
    //
    unsigned ScopeFlags;
    if (C99orCXX)
      ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
                   Scope::DeclScope  | Scope::ControlScope;
    else
      ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
    ParseScope WhileScope(this, ScopeFlags);
  
    // Parse the condition.
    Sema::ConditionResult Cond;
    SourceLocation LParen;
    SourceLocation RParen;
    if (ParseParenExprOrCondition(nullptr, Cond, WhileLoc,
                                  Sema::ConditionKind::Boolean,
                                  /*MissingOK=*/false, &LParen, &RParen))
      return StmtError();
  
    // C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if
    // there is no compound stmt.  C90 does not have this clause.  We only do this
    // if the body isn't a compound statement to avoid push/pop in common cases.
    //
    // C++ 6.5p2:
    // The substatement in an iteration-statement implicitly defines a local scope
    // which is entered and exited each time through the loop.
    //
    // See comments in ParseIfStatement for why we create a scope for the
    // condition and a new scope for substatement in C++.
    //
    ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
  
    MisleadingIndentationChecker MIChecker(*this, MSK_while, WhileLoc);
  
    // Read the body statement.
    StmtResult Body(ParseStatement(TrailingElseLoc));
  
    if (Body.isUsable())
      MIChecker.Check();
    // Pop the body scope if needed.
    InnerScope.Exit();
    WhileScope.Exit();
  
    if (Cond.isInvalid() || Body.isInvalid())
      return StmtError();
  
    return Actions.ActOnWhileStmt(WhileLoc, LParen, Cond, RParen, Body.get());
  }
  
  /// ParseDoStatement
  ///       do-statement: [C99 6.8.5.2]
  ///         'do' statement 'while' '(' expression ')' ';'
  /// Note: this lets the caller parse the end ';'.
  StmtResult Parser::ParseDoStatement() {
    assert(Tok.is(tok::kw_do) && "Not a do stmt!");
    SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
  
    // C99 6.8.5p5 - In C99, the do statement is a block.  This is not
    // the case for C90.  Start the loop scope.
    unsigned ScopeFlags;
    if (getLangOpts().C99)
      ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
    else
      ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
  
    ParseScope DoScope(this, ScopeFlags);
  
    // C99 6.8.5p5 - In C99, the body of the do statement is a scope, even if
    // there is no compound stmt.  C90 does not have this clause. We only do this
    // if the body isn't a compound statement to avoid push/pop in common cases.
    //
    // C++ 6.5p2:
    // The substatement in an iteration-statement implicitly defines a local scope
    // which is entered and exited each time through the loop.
    //
    bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
    ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
  
    // Read the body statement.
    StmtResult Body(ParseStatement());
  
    // Pop the body scope if needed.
    InnerScope.Exit();
  
    if (Tok.isNot(tok::kw_while)) {
      if (!Body.isInvalid()) {
        Diag(Tok, diag::err_expected_while);
        Diag(DoLoc, diag::note_matching) << "'do'";
        SkipUntil(tok::semi, StopBeforeMatch);
      }
      return StmtError();
    }
    SourceLocation WhileLoc = ConsumeToken();
  
    if (Tok.isNot(tok::l_paren)) {
      Diag(Tok, diag::err_expected_lparen_after) << "do/while";
      SkipUntil(tok::semi, StopBeforeMatch);
      return StmtError();
    }
  
    // Parse the parenthesized expression.
    BalancedDelimiterTracker T(*this, tok::l_paren);
    T.consumeOpen();
  
    // A do-while expression is not a condition, so can't have attributes.
    DiagnoseAndSkipCXX11Attributes();
  
    SourceLocation Start = Tok.getLocation();
    ExprResult Cond = ParseExpression();
    // Correct the typos in condition before closing the scope.
    if (Cond.isUsable())
      Cond = Actions.CorrectDelayedTyposInExpr(Cond);
    else {
      if (!Tok.isOneOf(tok::r_paren, tok::r_square, tok::r_brace))
        SkipUntil(tok::semi);
      Cond = Actions.CreateRecoveryExpr(
          Start, Start == Tok.getLocation() ? Start : PrevTokLocation, {},
          Actions.getASTContext().BoolTy);
    }
    T.consumeClose();
    DoScope.Exit();
  
    if (Cond.isInvalid() || Body.isInvalid())
      return StmtError();
  
    return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, T.getOpenLocation(),
                               Cond.get(), T.getCloseLocation());
  }
  
  bool Parser::isForRangeIdentifier() {
    assert(Tok.is(tok::identifier));
  
    const Token &Next = NextToken();
    if (Next.is(tok::colon))
      return true;
  
    if (Next.isOneOf(tok::l_square, tok::kw_alignas)) {
      TentativeParsingAction PA(*this);
      ConsumeToken();
      SkipCXX11Attributes();
      bool Result = Tok.is(tok::colon);
      PA.Revert();
      return Result;
    }
  
    return false;
  }
  
  /// ParseForStatement
  ///       for-statement: [C99 6.8.5.3]
  ///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
  ///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
  /// [C++]   'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
  /// [C++]       statement
  /// [C++0x] 'for'
  ///             'co_await'[opt]    [Coroutines]
  ///             '(' for-range-declaration ':' for-range-initializer ')'
  ///             statement
  /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
  /// [OBJC2] 'for' '(' expr 'in' expr ')' statement
  ///
  /// [C++] for-init-statement:
  /// [C++]   expression-statement
  /// [C++]   simple-declaration
  /// [C++2b] alias-declaration
  ///
  /// [C++0x] for-range-declaration:
  /// [C++0x]   attribute-specifier-seq[opt] type-specifier-seq declarator
  /// [C++0x] for-range-initializer:
  /// [C++0x]   expression
  /// [C++0x]   braced-init-list            [TODO]
  StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
    assert(Tok.is(tok::kw_for) && "Not a for stmt!");
    SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
  
    SourceLocation CoawaitLoc;
    if (Tok.is(tok::kw_co_await))
      CoawaitLoc = ConsumeToken();
  
    if (Tok.isNot(tok::l_paren)) {
      Diag(Tok, diag::err_expected_lparen_after) << "for";
      SkipUntil(tok::semi);
      return StmtError();
    }
  
    bool C99orCXXorObjC = getLangOpts().C99 || getLangOpts().CPlusPlus ||
      getLangOpts().ObjC;
  
    // C99 6.8.5p5 - In C99, the for statement is a block.  This is not
    // the case for C90.  Start the loop scope.
    //
    // C++ 6.4p3:
    // A name introduced by a declaration in a condition is in scope from its
    // point of declaration until the end of the substatements controlled by the
    // condition.
    // C++ 3.3.2p4:
    // Names declared in the for-init-statement, and in the condition of if,
    // while, for, and switch statements are local to the if, while, for, or
    // switch statement (including the controlled statement).
    // C++ 6.5.3p1:
    // Names declared in the for-init-statement are in the same declarative-region
    // as those declared in the condition.
    //
    unsigned ScopeFlags = 0;
    if (C99orCXXorObjC)
      ScopeFlags = Scope::DeclScope | Scope::ControlScope;
  
    ParseScope ForScope(this, ScopeFlags);
  
    BalancedDelimiterTracker T(*this, tok::l_paren);
    T.consumeOpen();
  
    ExprResult Value;
  
    bool ForEach = false;
    StmtResult FirstPart;
    Sema::ConditionResult SecondPart;
    ExprResult Collection;
    ForRangeInfo ForRangeInfo;
    FullExprArg ThirdPart(Actions);
  
    if (Tok.is(tok::code_completion)) {
      cutOffParsing();
      Actions.CodeCompleteOrdinaryName(getCurScope(),
                                       C99orCXXorObjC? Sema::PCC_ForInit
                                                     : Sema::PCC_Expression);
      return StmtError();
    }
  
    ParsedAttributes attrs(AttrFactory);
    MaybeParseCXX11Attributes(attrs);
  
    SourceLocation EmptyInitStmtSemiLoc;
  
    // Parse the first part of the for specifier.
    if (Tok.is(tok::semi)) {  // for (;
      ProhibitAttributes(attrs);
      // no first part, eat the ';'.
      SourceLocation SemiLoc = Tok.getLocation();
      if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.isMacroID())
        EmptyInitStmtSemiLoc = SemiLoc;
      ConsumeToken();
    } else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) &&
               isForRangeIdentifier()) {
      ProhibitAttributes(attrs);
      IdentifierInfo *Name = Tok.getIdentifierInfo();
      SourceLocation Loc = ConsumeToken();
      MaybeParseCXX11Attributes(attrs);
  
      ForRangeInfo.ColonLoc = ConsumeToken();
      if (Tok.is(tok::l_brace))
        ForRangeInfo.RangeExpr = ParseBraceInitializer();
      else
        ForRangeInfo.RangeExpr = ParseExpression();
  
      Diag(Loc, diag::err_for_range_identifier)
        << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17)
                ? FixItHint::CreateInsertion(Loc, "auto &&")
                : FixItHint());
  
      ForRangeInfo.LoopVar =
          Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name, attrs);
    } else if (isForInitDeclaration()) {  // for (int X = 4;
      ParenBraceBracketBalancer BalancerRAIIObj(*this);
  
      // Parse declaration, which eats the ';'.
      if (!C99orCXXorObjC) {   // Use of C99-style for loops in C90 mode?
        Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
        Diag(Tok, diag::warn_gcc_variable_decl_in_for_loop);
      }
      DeclGroupPtrTy DG;
      if (Tok.is(tok::kw_using)) {
        DG = ParseAliasDeclarationInInitStatement(DeclaratorContext::ForInit,
                                                  attrs);
      } else {
        // In C++0x, "for (T NS:a" might not be a typo for ::
        bool MightBeForRangeStmt = getLangOpts().CPlusPlus;
        ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
  
        SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
        DG = ParseSimpleDeclaration(
            DeclaratorContext::ForInit, DeclEnd, attrs, false,
            MightBeForRangeStmt ? &ForRangeInfo : nullptr);
        FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
        if (ForRangeInfo.ParsedForRangeDecl()) {
          Diag(ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus11
                                          ? diag::warn_cxx98_compat_for_range
                                          : diag::ext_for_range);
          ForRangeInfo.LoopVar = FirstPart;
          FirstPart = StmtResult();
        } else if (Tok.is(tok::semi)) { // for (int x = 4;
          ConsumeToken();
        } else if ((ForEach = isTokIdentifier_in())) {
          Actions.ActOnForEachDeclStmt(DG);
          // ObjC: for (id x in expr)
          ConsumeToken(); // consume 'in'
  
          if (Tok.is(tok::code_completion)) {
            cutOffParsing();
            Actions.CodeCompleteObjCForCollection(getCurScope(), DG);
            return StmtError();
          }
          Collection = ParseExpression();
        } else {
          Diag(Tok, diag::err_expected_semi_for);
        }
      }
    } else {
      ProhibitAttributes(attrs);
      Value = Actions.CorrectDelayedTyposInExpr(ParseExpression());
  
      ForEach = isTokIdentifier_in();
  
      // Turn the expression into a stmt.
      if (!Value.isInvalid()) {
        if (ForEach)
          FirstPart = Actions.ActOnForEachLValueExpr(Value.get());
        else {
          // We already know this is not an init-statement within a for loop, so
          // if we are parsing a C++11 range-based for loop, we should treat this
          // expression statement as being a discarded value expression because
          // we will err below. This way we do not warn on an unused expression
          // that was an error in the first place, like with: for (expr : expr);
          bool IsRangeBasedFor =
              getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon);
          FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor);
        }
      }
  
      if (Tok.is(tok::semi)) {
        ConsumeToken();
      } else if (ForEach) {
        ConsumeToken(); // consume 'in'
  
        if (Tok.is(tok::code_completion)) {
          cutOffParsing();
          Actions.CodeCompleteObjCForCollection(getCurScope(), nullptr);
          return StmtError();
        }
        Collection = ParseExpression();
      } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::colon) && FirstPart.get()) {
        // User tried to write the reasonable, but ill-formed, for-range-statement
        //   for (expr : expr) { ... }
        Diag(Tok, diag::err_for_range_expected_decl)
          << FirstPart.get()->getSourceRange();
        SkipUntil(tok::r_paren, StopBeforeMatch);
        SecondPart = Sema::ConditionError();
      } else {
        if (!Value.isInvalid()) {
          Diag(Tok, diag::err_expected_semi_for);
        } else {
          // Skip until semicolon or rparen, don't consume it.
          SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
          if (Tok.is(tok::semi))
            ConsumeToken();
        }
      }
    }
  
    // Parse the second part of the for specifier.
    if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() &&
        !SecondPart.isInvalid()) {
      // Parse the second part of the for specifier.
      if (Tok.is(tok::semi)) {  // for (...;;
        // no second part.
      } else if (Tok.is(tok::r_paren)) {
        // missing both semicolons.
      } else {
        if (getLangOpts().CPlusPlus) {
          // C++2a: We've parsed an init-statement; we might have a
          // for-range-declaration next.
          bool MightBeForRangeStmt = !ForRangeInfo.ParsedForRangeDecl();
          ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
          SecondPart = ParseCXXCondition(
              nullptr, ForLoc, Sema::ConditionKind::Boolean,
              // FIXME: recovery if we don't see another semi!
              /*MissingOK=*/true, MightBeForRangeStmt ? &ForRangeInfo : nullptr,
              /*EnterForConditionScope*/ true);
  
          if (ForRangeInfo.ParsedForRangeDecl()) {
            Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc()
                                 : ForRangeInfo.ColonLoc,
                 getLangOpts().CPlusPlus20
                     ? diag::warn_cxx17_compat_for_range_init_stmt
                     : diag::ext_for_range_init_stmt)
                << (FirstPart.get() ? FirstPart.get()->getSourceRange()
                                    : SourceRange());
            if (EmptyInitStmtSemiLoc.isValid()) {
              Diag(EmptyInitStmtSemiLoc, diag::warn_empty_init_statement)
                  << /*for-loop*/ 2
                  << FixItHint::CreateRemoval(EmptyInitStmtSemiLoc);
            }
          }
        } else {
          // We permit 'continue' and 'break' in the condition of a for loop.
          getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
  
          ExprResult SecondExpr = ParseExpression();
          if (SecondExpr.isInvalid())
            SecondPart = Sema::ConditionError();
          else
            SecondPart = Actions.ActOnCondition(
                getCurScope(), ForLoc, SecondExpr.get(),
                Sema::ConditionKind::Boolean, /*MissingOK=*/true);
        }
      }
    }
  
    // Enter a break / continue scope, if we didn't already enter one while
    // parsing the second part.
    if (!(getCurScope()->getFlags() & Scope::ContinueScope))
      getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
  
    // Parse the third part of the for statement.
    if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) {
      if (Tok.isNot(tok::semi)) {
        if (!SecondPart.isInvalid())
          Diag(Tok, diag::err_expected_semi_for);
        else
          // Skip until semicolon or rparen, don't consume it.
          SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
      }
  
      if (Tok.is(tok::semi)) {
        ConsumeToken();
      }
  
      if (Tok.isNot(tok::r_paren)) {   // for (...;...;)
        ExprResult Third = ParseExpression();
        // FIXME: The C++11 standard doesn't actually say that this is a
        // discarded-value expression, but it clearly should be.
        ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.get());
      }
    }
    // Match the ')'.
    T.consumeClose();
  
    // C++ Coroutines [stmt.iter]:
    //   'co_await' can only be used for a range-based for statement.
    if (CoawaitLoc.isValid() && !ForRangeInfo.ParsedForRangeDecl()) {
      Diag(CoawaitLoc, diag::err_for_co_await_not_range_for);
      CoawaitLoc = SourceLocation();
    }
  
    if (CoawaitLoc.isValid() && getLangOpts().CPlusPlus20)
      Diag(CoawaitLoc, diag::warn_deprecated_for_co_await);
  
    // We need to perform most of the semantic analysis for a C++0x for-range
    // statememt before parsing the body, in order to be able to deduce the type
    // of an auto-typed loop variable.
    StmtResult ForRangeStmt;
    StmtResult ForEachStmt;
  
    if (ForRangeInfo.ParsedForRangeDecl()) {
      ExprResult CorrectedRange =
          Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get());
      ForRangeStmt = Actions.ActOnCXXForRangeStmt(
          getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
          ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(),
          T.getCloseLocation(), Sema::BFRK_Build);
  
    // Similarly, we need to do the semantic analysis for a for-range
    // statement immediately in order to close over temporaries correctly.
    } else if (ForEach) {
      ForEachStmt = Actions.ActOnObjCForCollectionStmt(ForLoc,
                                                       FirstPart.get(),
                                                       Collection.get(),
                                                       T.getCloseLocation());
    } else {
      // In OpenMP loop region loop control variable must be captured and be
      // private. Perform analysis of first part (if any).
      if (getLangOpts().OpenMP && FirstPart.isUsable()) {
        Actions.ActOnOpenMPLoopInitialization(ForLoc, FirstPart.get());
      }
    }
  
    // C99 6.8.5p5 - In C99, the body of the for statement is a scope, even if
    // there is no compound stmt.  C90 does not have this clause.  We only do this
    // if the body isn't a compound statement to avoid push/pop in common cases.
    //
    // C++ 6.5p2:
    // The substatement in an iteration-statement implicitly defines a local scope
    // which is entered and exited each time through the loop.
    //
    // See comments in ParseIfStatement for why we create a scope for
    // for-init-statement/condition and a new scope for substatement in C++.
    //
    ParseScope InnerScope(this, Scope::DeclScope, C99orCXXorObjC,
                          Tok.is(tok::l_brace));
  
    // The body of the for loop has the same local mangling number as the
    // for-init-statement.
    // It will only be incremented if the body contains other things that would
    // normally increment the mangling number (like a compound statement).
    if (C99orCXXorObjC)
      getCurScope()->decrementMSManglingNumber();
  
    MisleadingIndentationChecker MIChecker(*this, MSK_for, ForLoc);
  
    // Read the body statement.
    StmtResult Body(ParseStatement(TrailingElseLoc));
  
    if (Body.isUsable())
      MIChecker.Check();
  
    // Pop the body scope if needed.
    InnerScope.Exit();
  
    // Leave the for-scope.
    ForScope.Exit();
  
    if (Body.isInvalid())
      return StmtError();
  
    if (ForEach)
     return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(),
                                                Body.get());
  
    if (ForRangeInfo.ParsedForRangeDecl())
      return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
  
    return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(),
                                SecondPart, ThirdPart, T.getCloseLocation(),
                                Body.get());
  }
  
  /// ParseGotoStatement
  ///       jump-statement:
  ///         'goto' identifier ';'
  /// [GNU]   'goto' '*' expression ';'
  ///
  /// Note: this lets the caller parse the end ';'.
  ///
  StmtResult Parser::ParseGotoStatement() {
    assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
    SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
  
    StmtResult Res;
    if (Tok.is(tok::identifier)) {
      LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
                                                  Tok.getLocation());
      Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD);
      ConsumeToken();
    } else if (Tok.is(tok::star)) {
      // GNU indirect goto extension.
      Diag(Tok, diag::ext_gnu_indirect_goto);
      SourceLocation StarLoc = ConsumeToken();
      ExprResult R(ParseExpression());
      if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
        SkipUntil(tok::semi, StopBeforeMatch);
        return StmtError();
      }
      Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.get());
    } else {
      Diag(Tok, diag::err_expected) << tok::identifier;
      return StmtError();
    }
  
    return Res;
  }
  
  /// ParseContinueStatement
  ///       jump-statement:
  ///         'continue' ';'
  ///
  /// Note: this lets the caller parse the end ';'.
  ///
  StmtResult Parser::ParseContinueStatement() {
    SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
    return Actions.ActOnContinueStmt(ContinueLoc, getCurScope());
  }
  
  /// ParseBreakStatement
  ///       jump-statement:
  ///         'break' ';'
  ///
  /// Note: this lets the caller parse the end ';'.
  ///
  StmtResult Parser::ParseBreakStatement() {
    SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
    return Actions.ActOnBreakStmt(BreakLoc, getCurScope());
  }
  
  /// ParseReturnStatement
  ///       jump-statement:
  ///         'return' expression[opt] ';'
  ///         'return' braced-init-list ';'
  ///         'co_return' expression[opt] ';'
  ///         'co_return' braced-init-list ';'
  StmtResult Parser::ParseReturnStatement() {
    assert((Tok.is(tok::kw_return) || Tok.is(tok::kw_co_return)) &&
           "Not a return stmt!");
    bool IsCoreturn = Tok.is(tok::kw_co_return);
    SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
  
    ExprResult R;
    if (Tok.isNot(tok::semi)) {
      if (!IsCoreturn)
        PreferredType.enterReturn(Actions, Tok.getLocation());
      // FIXME: Code completion for co_return.
      if (Tok.is(tok::code_completion) && !IsCoreturn) {
        cutOffParsing();
        Actions.CodeCompleteExpression(getCurScope(),
                                       PreferredType.get(Tok.getLocation()));
        return StmtError();
      }
  
      if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus) {
        R = ParseInitializer();
        if (R.isUsable())
          Diag(R.get()->getBeginLoc(),
               getLangOpts().CPlusPlus11
                   ? diag::warn_cxx98_compat_generalized_initializer_lists
                   : diag::ext_generalized_initializer_lists)
              << R.get()->getSourceRange();
      } else
        R = ParseExpression();
      if (R.isInvalid()) {
        SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
        return StmtError();
      }
    }
    if (IsCoreturn)
      return Actions.ActOnCoreturnStmt(getCurScope(), ReturnLoc, R.get());
    return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope());
  }
  
  StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
                                         ParsedStmtContext StmtCtx,
                                         SourceLocation *TrailingElseLoc,
                                         ParsedAttributes &Attrs) {
    // Create temporary attribute list.
    ParsedAttributes TempAttrs(AttrFactory);
  
    SourceLocation StartLoc = Tok.getLocation();
  
    // Get loop hints and consume annotated token.
    while (Tok.is(tok::annot_pragma_loop_hint)) {
      LoopHint Hint;
      if (!HandlePragmaLoopHint(Hint))
        continue;
  
      ArgsUnion ArgHints[] = {Hint.PragmaNameLoc, Hint.OptionLoc, Hint.StateLoc,
                              ArgsUnion(Hint.ValueExpr)};
      TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr,
                       Hint.PragmaNameLoc->Loc, ArgHints, 4,
                       ParsedAttr::AS_Pragma);
    }
  
    // Get the next statement.
    MaybeParseCXX11Attributes(Attrs);
  
    StmtResult S = ParseStatementOrDeclarationAfterAttributes(
        Stmts, StmtCtx, TrailingElseLoc, Attrs);
  
    Attrs.takeAllFrom(TempAttrs);
  
    // Start of attribute range may already be set for some invalid input.
    // See PR46336.
    if (Attrs.Range.getBegin().isInvalid())
      Attrs.Range.setBegin(StartLoc);
  
    return S;
  }
  
  Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
    assert(Tok.is(tok::l_brace));
    SourceLocation LBraceLoc = Tok.getLocation();
  
    PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, LBraceLoc,
                                        "parsing function body");
  
    // Save and reset current vtordisp stack if we have entered a C++ method body.
    bool IsCXXMethod =
        getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl);
    Sema::PragmaStackSentinelRAII
      PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
  
    // Do not enter a scope for the brace, as the arguments are in the same scope
    // (the function body) as the body itself.  Instead, just read the statement
    // list and put it into a CompoundStmt for safe keeping.
    StmtResult FnBody(ParseCompoundStatementBody());
  
    // If the function body could not be parsed, make a bogus compoundstmt.
    if (FnBody.isInvalid()) {
      Sema::CompoundScopeRAII CompoundScope(Actions);
      FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, None, false);
    }
  
    BodyScope.Exit();
    return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
  }
  
  /// ParseFunctionTryBlock - Parse a C++ function-try-block.
  ///
  ///       function-try-block:
  ///         'try' ctor-initializer[opt] compound-statement handler-seq
  ///
  Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
    assert(Tok.is(tok::kw_try) && "Expected 'try'");
    SourceLocation TryLoc = ConsumeToken();
  
    PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, TryLoc,
                                        "parsing function try block");
  
    // Constructor initializer list?
    if (Tok.is(tok::colon))
      ParseConstructorInitializer(Decl);
    else
      Actions.ActOnDefaultCtorInitializers(Decl);
  
    // Save and reset current vtordisp stack if we have entered a C++ method body.
    bool IsCXXMethod =
        getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl);
    Sema::PragmaStackSentinelRAII
      PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
  
    SourceLocation LBraceLoc = Tok.getLocation();
    StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true));
    // If we failed to parse the try-catch, we just give the function an empty
    // compound statement as the body.
    if (FnBody.isInvalid()) {
      Sema::CompoundScopeRAII CompoundScope(Actions);
      FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, None, false);
    }
  
    BodyScope.Exit();
    return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
  }
  
  bool Parser::trySkippingFunctionBody() {
    assert(SkipFunctionBodies &&
           "Should only be called when SkipFunctionBodies is enabled");
    if (!PP.isCodeCompletionEnabled()) {
      SkipFunctionBody();
      return true;
    }
  
    // We're in code-completion mode. Skip parsing for all function bodies unless
    // the body contains the code-completion point.
    TentativeParsingAction PA(*this);
    bool IsTryCatch = Tok.is(tok::kw_try);
    CachedTokens Toks;
    bool ErrorInPrologue = ConsumeAndStoreFunctionPrologue(Toks);
    if (llvm::any_of(Toks, [](const Token &Tok) {
          return Tok.is(tok::code_completion);
        })) {
      PA.Revert();
      return false;
    }
    if (ErrorInPrologue) {
      PA.Commit();
      SkipMalformedDecl();
      return true;
    }
    if (!SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
      PA.Revert();
      return false;
    }
    while (IsTryCatch && Tok.is(tok::kw_catch)) {
      if (!SkipUntil(tok::l_brace, StopAtCodeCompletion) ||
          !SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
        PA.Revert();
        return false;
      }
    }
    PA.Commit();
    return true;
  }
  
  /// ParseCXXTryBlock - Parse a C++ try-block.
  ///
  ///       try-block:
  ///         'try' compound-statement handler-seq
  ///
  StmtResult Parser::ParseCXXTryBlock() {
    assert(Tok.is(tok::kw_try) && "Expected 'try'");
  
    SourceLocation TryLoc = ConsumeToken();
    return ParseCXXTryBlockCommon(TryLoc);
  }
  
  /// ParseCXXTryBlockCommon - Parse the common part of try-block and
  /// function-try-block.
  ///
  ///       try-block:
  ///         'try' compound-statement handler-seq
  ///
  ///       function-try-block:
  ///         'try' ctor-initializer[opt] compound-statement handler-seq
  ///
  ///       handler-seq:
  ///         handler handler-seq[opt]
  ///
  ///       [Borland] try-block:
  ///         'try' compound-statement seh-except-block
  ///         'try' compound-statement seh-finally-block
  ///
  StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
    if (Tok.isNot(tok::l_brace))
      return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
  
    StmtResult TryBlock(ParseCompoundStatement(
        /*isStmtExpr=*/false, Scope::DeclScope | Scope::TryScope |
                                  Scope::CompoundStmtScope |
                                  (FnTry ? Scope::FnTryCatchScope : 0)));
    if (TryBlock.isInvalid())
      return TryBlock;
  
    // Borland allows SEH-handlers with 'try'
  
    if ((Tok.is(tok::identifier) &&
         Tok.getIdentifierInfo() == getSEHExceptKeyword()) ||
        Tok.is(tok::kw___finally)) {
      // TODO: Factor into common return ParseSEHHandlerCommon(...)
      StmtResult Handler;
      if(Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
        SourceLocation Loc = ConsumeToken();
        Handler = ParseSEHExceptBlock(Loc);
      }
      else {
        SourceLocation Loc = ConsumeToken();
        Handler = ParseSEHFinallyBlock(Loc);
      }
      if(Handler.isInvalid())
        return Handler;
  
      return Actions.ActOnSEHTryBlock(true /* IsCXXTry */,
                                      TryLoc,
                                      TryBlock.get(),
                                      Handler.get());
    }
    else {
      StmtVector Handlers;
  
      // C++11 attributes can't appear here, despite this context seeming
      // statement-like.
      DiagnoseAndSkipCXX11Attributes();
  
      if (Tok.isNot(tok::kw_catch))
        return StmtError(Diag(Tok, diag::err_expected_catch));
      while (Tok.is(tok::kw_catch)) {
        StmtResult Handler(ParseCXXCatchBlock(FnTry));
        if (!Handler.isInvalid())
          Handlers.push_back(Handler.get());
      }
      // Don't bother creating the full statement if we don't have any usable
      // handlers.
      if (Handlers.empty())
        return StmtError();
  
      return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.get(), Handlers);
    }
  }
  
  /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
  ///
  ///   handler:
  ///     'catch' '(' exception-declaration ')' compound-statement
  ///
  ///   exception-declaration:
  ///     attribute-specifier-seq[opt] type-specifier-seq declarator
  ///     attribute-specifier-seq[opt] type-specifier-seq abstract-declarator[opt]
  ///     '...'
  ///
  StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
    assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
  
    SourceLocation CatchLoc = ConsumeToken();
  
    BalancedDelimiterTracker T(*this, tok::l_paren);
    if (T.expectAndConsume())
      return StmtError();
  
    // C++ 3.3.2p3:
    // The name in a catch exception-declaration is local to the handler and
    // shall not be redeclared in the outermost block of the handler.
    ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope |
                                    Scope::CatchScope |
                                    (FnCatch ? Scope::FnTryCatchScope : 0));
  
    // exception-declaration is equivalent to '...' or a parameter-declaration
    // without default arguments.
    Decl *ExceptionDecl = nullptr;
    if (Tok.isNot(tok::ellipsis)) {
      ParsedAttributes Attributes(AttrFactory);
      MaybeParseCXX11Attributes(Attributes);
  
      DeclSpec DS(AttrFactory);
      DS.takeAttributesFrom(Attributes);
  
      if (ParseCXXTypeSpecifierSeq(DS))
        return StmtError();
  
      Declarator ExDecl(DS, DeclaratorContext::CXXCatch);
      ParseDeclarator(ExDecl);
      ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl);
    } else
      ConsumeToken();
  
    T.consumeClose();
    if (T.getCloseLocation().isInvalid())
      return StmtError();
  
    if (Tok.isNot(tok::l_brace))
      return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
  
    // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
    StmtResult Block(ParseCompoundStatement());
    if (Block.isInvalid())
      return Block;
  
    return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.get());
  }
  
  void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
    IfExistsCondition Result;
    if (ParseMicrosoftIfExistsCondition(Result))
      return;
  
    // Handle dependent statements by parsing the braces as a compound statement.
    // This is not the same behavior as Visual C++, which don't treat this as a
    // compound statement, but for Clang's type checking we can't have anything
    // inside these braces escaping to the surrounding code.
    if (Result.Behavior == IEB_Dependent) {
      if (!Tok.is(tok::l_brace)) {
        Diag(Tok, diag::err_expected) << tok::l_brace;
        return;
      }
  
      StmtResult Compound = ParseCompoundStatement();
      if (Compound.isInvalid())
        return;
  
      StmtResult DepResult = Actions.ActOnMSDependentExistsStmt(Result.KeywordLoc,
                                                                Result.IsIfExists,
                                                                Result.SS,
                                                                Result.Name,
                                                                Compound.get());
      if (DepResult.isUsable())
        Stmts.push_back(DepResult.get());
      return;
    }
  
    BalancedDelimiterTracker Braces(*this, tok::l_brace);
    if (Braces.consumeOpen()) {
      Diag(Tok, diag::err_expected) << tok::l_brace;
      return;
    }
  
    switch (Result.Behavior) {
    case IEB_Parse:
      // Parse the statements below.
      break;
  
    case IEB_Dependent:
      llvm_unreachable("Dependent case handled above");
  
    case IEB_Skip:
      Braces.skipToEnd();
      return;
    }
  
    // Condition is true, parse the statements.
    while (Tok.isNot(tok::r_brace)) {
      StmtResult R =
          ParseStatementOrDeclaration(Stmts, ParsedStmtContext::Compound);
      if (R.isUsable())
        Stmts.push_back(R.get());
    }
    Braces.consumeClose();
  }
  