xref: /freebsd-src/contrib/llvm-project/clang/lib/Parse/ParseStmt.cpp (revision d686ce931cab72612a9e1ada9fe99d65e11a32a3)
10b57cec5SDimitry Andric //===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the Statement and Block portions of the Parser
100b57cec5SDimitry Andric // interface.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/AST/PrettyDeclStackTrace.h"
150b57cec5SDimitry Andric #include "clang/Basic/Attributes.h"
160b57cec5SDimitry Andric #include "clang/Basic/PrettyStackTrace.h"
175f757f3fSDimitry Andric #include "clang/Basic/TargetInfo.h"
18bdd1243dSDimitry Andric #include "clang/Basic/TokenKinds.h"
190b57cec5SDimitry Andric #include "clang/Parse/LoopHint.h"
200b57cec5SDimitry Andric #include "clang/Parse/Parser.h"
210b57cec5SDimitry Andric #include "clang/Parse/RAIIObjectsForParser.h"
220b57cec5SDimitry Andric #include "clang/Sema/DeclSpec.h"
2306c3fb27SDimitry Andric #include "clang/Sema/EnterExpressionEvaluationContext.h"
240b57cec5SDimitry Andric #include "clang/Sema/Scope.h"
250fca6ea1SDimitry Andric #include "clang/Sema/SemaCodeCompletion.h"
260fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h"
270fca6ea1SDimitry Andric #include "clang/Sema/SemaOpenMP.h"
280b57cec5SDimitry Andric #include "clang/Sema/TypoCorrection.h"
29fe6060f1SDimitry Andric #include "llvm/ADT/STLExtras.h"
30bdd1243dSDimitry Andric #include <optional>
31fe6060f1SDimitry Andric 
320b57cec5SDimitry Andric using namespace clang;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
350b57cec5SDimitry Andric // C99 6.8: Statements and Blocks.
360b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric /// Parse a standalone statement (for instance, as the body of an 'if',
390b57cec5SDimitry Andric /// 'while', or 'for').
400b57cec5SDimitry Andric StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc,
410b57cec5SDimitry Andric                                   ParsedStmtContext StmtCtx) {
420b57cec5SDimitry Andric   StmtResult Res;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   // We may get back a null statement if we found a #pragma. Keep going until
450b57cec5SDimitry Andric   // we get an actual statement.
460b57cec5SDimitry Andric   StmtVector Stmts;
47bdd1243dSDimitry Andric   do {
480b57cec5SDimitry Andric     Res = ParseStatementOrDeclaration(Stmts, StmtCtx, TrailingElseLoc);
490b57cec5SDimitry Andric   } while (!Res.isInvalid() && !Res.get());
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   return Res;
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric /// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
550b57cec5SDimitry Andric ///       StatementOrDeclaration:
560b57cec5SDimitry Andric ///         statement
570b57cec5SDimitry Andric ///         declaration
580b57cec5SDimitry Andric ///
590b57cec5SDimitry Andric ///       statement:
600b57cec5SDimitry Andric ///         labeled-statement
610b57cec5SDimitry Andric ///         compound-statement
620b57cec5SDimitry Andric ///         expression-statement
630b57cec5SDimitry Andric ///         selection-statement
640b57cec5SDimitry Andric ///         iteration-statement
650b57cec5SDimitry Andric ///         jump-statement
660b57cec5SDimitry Andric /// [C++]   declaration-statement
670b57cec5SDimitry Andric /// [C++]   try-block
680b57cec5SDimitry Andric /// [MS]    seh-try-block
690b57cec5SDimitry Andric /// [OBC]   objc-throw-statement
700b57cec5SDimitry Andric /// [OBC]   objc-try-catch-statement
710b57cec5SDimitry Andric /// [OBC]   objc-synchronized-statement
720b57cec5SDimitry Andric /// [GNU]   asm-statement
730b57cec5SDimitry Andric /// [OMP]   openmp-construct             [TODO]
740b57cec5SDimitry Andric ///
750b57cec5SDimitry Andric ///       labeled-statement:
760b57cec5SDimitry Andric ///         identifier ':' statement
770b57cec5SDimitry Andric ///         'case' constant-expression ':' statement
780b57cec5SDimitry Andric ///         'default' ':' statement
790b57cec5SDimitry Andric ///
800b57cec5SDimitry Andric ///       selection-statement:
810b57cec5SDimitry Andric ///         if-statement
820b57cec5SDimitry Andric ///         switch-statement
830b57cec5SDimitry Andric ///
840b57cec5SDimitry Andric ///       iteration-statement:
850b57cec5SDimitry Andric ///         while-statement
860b57cec5SDimitry Andric ///         do-statement
870b57cec5SDimitry Andric ///         for-statement
880b57cec5SDimitry Andric ///
890b57cec5SDimitry Andric ///       expression-statement:
900b57cec5SDimitry Andric ///         expression[opt] ';'
910b57cec5SDimitry Andric ///
920b57cec5SDimitry Andric ///       jump-statement:
930b57cec5SDimitry Andric ///         'goto' identifier ';'
940b57cec5SDimitry Andric ///         'continue' ';'
950b57cec5SDimitry Andric ///         'break' ';'
960b57cec5SDimitry Andric ///         'return' expression[opt] ';'
970b57cec5SDimitry Andric /// [GNU]   'goto' '*' expression ';'
980b57cec5SDimitry Andric ///
990b57cec5SDimitry Andric /// [OBC] objc-throw-statement:
1000b57cec5SDimitry Andric /// [OBC]   '@' 'throw' expression ';'
1010b57cec5SDimitry Andric /// [OBC]   '@' 'throw' ';'
1020b57cec5SDimitry Andric ///
1030b57cec5SDimitry Andric StmtResult
1040b57cec5SDimitry Andric Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
1050b57cec5SDimitry Andric                                     ParsedStmtContext StmtCtx,
1060b57cec5SDimitry Andric                                     SourceLocation *TrailingElseLoc) {
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   ParenBraceBracketBalancer BalancerRAIIObj(*this);
1090b57cec5SDimitry Andric 
110fe6060f1SDimitry Andric   // Because we're parsing either a statement or a declaration, the order of
111fe6060f1SDimitry Andric   // attribute parsing is important. [[]] attributes at the start of a
112fe6060f1SDimitry Andric   // statement are different from [[]] attributes that follow an __attribute__
113fe6060f1SDimitry Andric   // at the start of the statement. Thus, we're not using MaybeParseAttributes
114fe6060f1SDimitry Andric   // here because we don't want to allow arbitrary orderings.
11581ad6265SDimitry Andric   ParsedAttributes CXX11Attrs(AttrFactory);
11681ad6265SDimitry Andric   MaybeParseCXX11Attributes(CXX11Attrs, /*MightBeObjCMessageSend*/ true);
1170fca6ea1SDimitry Andric   ParsedAttributes GNUOrMSAttrs(AttrFactory);
118fe6060f1SDimitry Andric   if (getLangOpts().OpenCL)
1190fca6ea1SDimitry Andric     MaybeParseGNUAttributes(GNUOrMSAttrs);
1200fca6ea1SDimitry Andric 
1210fca6ea1SDimitry Andric   if (getLangOpts().HLSL)
1220fca6ea1SDimitry Andric     MaybeParseMicrosoftAttributes(GNUOrMSAttrs);
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   StmtResult Res = ParseStatementOrDeclarationAfterAttributes(
1250fca6ea1SDimitry Andric       Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs, GNUOrMSAttrs);
1265ffd83dbSDimitry Andric   MaybeDestroyTemplateIds();
1270b57cec5SDimitry Andric 
12881ad6265SDimitry Andric   // Attributes that are left should all go on the statement, so concatenate the
12981ad6265SDimitry Andric   // two lists.
13081ad6265SDimitry Andric   ParsedAttributes Attrs(AttrFactory);
1310fca6ea1SDimitry Andric   takeAndConcatenateAttrs(CXX11Attrs, GNUOrMSAttrs, Attrs);
13281ad6265SDimitry Andric 
1330b57cec5SDimitry Andric   assert((Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
1340b57cec5SDimitry Andric          "attributes on empty statement");
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   if (Attrs.empty() || Res.isInvalid())
1370b57cec5SDimitry Andric     return Res;
1380b57cec5SDimitry Andric 
139fe6060f1SDimitry Andric   return Actions.ActOnAttributedStmt(Attrs, Res.get());
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric namespace {
1430b57cec5SDimitry Andric class StatementFilterCCC final : public CorrectionCandidateCallback {
1440b57cec5SDimitry Andric public:
1450b57cec5SDimitry Andric   StatementFilterCCC(Token nextTok) : NextToken(nextTok) {
1460b57cec5SDimitry Andric     WantTypeSpecifiers = nextTok.isOneOf(tok::l_paren, tok::less, tok::l_square,
1470b57cec5SDimitry Andric                                          tok::identifier, tok::star, tok::amp);
1480b57cec5SDimitry Andric     WantExpressionKeywords =
1490b57cec5SDimitry Andric         nextTok.isOneOf(tok::l_paren, tok::identifier, tok::arrow, tok::period);
1500b57cec5SDimitry Andric     WantRemainingKeywords =
1510b57cec5SDimitry Andric         nextTok.isOneOf(tok::l_paren, tok::semi, tok::identifier, tok::l_brace);
1520b57cec5SDimitry Andric     WantCXXNamedCasts = false;
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   bool ValidateCandidate(const TypoCorrection &candidate) override {
1560b57cec5SDimitry Andric     if (FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>())
1570b57cec5SDimitry Andric       return !candidate.getCorrectionSpecifier() || isa<ObjCIvarDecl>(FD);
1580b57cec5SDimitry Andric     if (NextToken.is(tok::equal))
1590b57cec5SDimitry Andric       return candidate.getCorrectionDeclAs<VarDecl>();
1600b57cec5SDimitry Andric     if (NextToken.is(tok::period) &&
1610b57cec5SDimitry Andric         candidate.getCorrectionDeclAs<NamespaceDecl>())
1620b57cec5SDimitry Andric       return false;
1630b57cec5SDimitry Andric     return CorrectionCandidateCallback::ValidateCandidate(candidate);
1640b57cec5SDimitry Andric   }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   std::unique_ptr<CorrectionCandidateCallback> clone() override {
167a7dea167SDimitry Andric     return std::make_unique<StatementFilterCCC>(*this);
1680b57cec5SDimitry Andric   }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric private:
1710b57cec5SDimitry Andric   Token NextToken;
1720b57cec5SDimitry Andric };
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
1760b57cec5SDimitry Andric     StmtVector &Stmts, ParsedStmtContext StmtCtx,
17781ad6265SDimitry Andric     SourceLocation *TrailingElseLoc, ParsedAttributes &CXX11Attrs,
17881ad6265SDimitry Andric     ParsedAttributes &GNUAttrs) {
1790b57cec5SDimitry Andric   const char *SemiError = nullptr;
1800b57cec5SDimitry Andric   StmtResult Res;
181a7dea167SDimitry Andric   SourceLocation GNUAttributeLoc;
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   // Cases in this switch statement should fall through if the parser expects
1840b57cec5SDimitry Andric   // the token to end in a semicolon (in which case SemiError should be set),
1850b57cec5SDimitry Andric   // or they directly 'return;' if not.
1860b57cec5SDimitry Andric Retry:
1870b57cec5SDimitry Andric   tok::TokenKind Kind  = Tok.getKind();
1880b57cec5SDimitry Andric   SourceLocation AtLoc;
1890b57cec5SDimitry Andric   switch (Kind) {
1900b57cec5SDimitry Andric   case tok::at: // May be a @try or @throw statement
1910b57cec5SDimitry Andric     {
1920b57cec5SDimitry Andric       AtLoc = ConsumeToken();  // consume @
1930b57cec5SDimitry Andric       return ParseObjCAtStatement(AtLoc, StmtCtx);
1940b57cec5SDimitry Andric     }
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   case tok::code_completion:
1970b57cec5SDimitry Andric     cutOffParsing();
1980fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteOrdinaryName(
1990fca6ea1SDimitry Andric         getCurScope(), SemaCodeCompletion::PCC_Statement);
2000b57cec5SDimitry Andric     return StmtError();
2010b57cec5SDimitry Andric 
202bdd1243dSDimitry Andric   case tok::identifier:
203bdd1243dSDimitry Andric   ParseIdentifier: {
2040b57cec5SDimitry Andric     Token Next = NextToken();
2050b57cec5SDimitry Andric     if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement
20681ad6265SDimitry Andric       // Both C++11 and GNU attributes preceding the label appertain to the
20781ad6265SDimitry Andric       // label, so put them in a single list to pass on to
20881ad6265SDimitry Andric       // ParseLabeledStatement().
20981ad6265SDimitry Andric       ParsedAttributes Attrs(AttrFactory);
21081ad6265SDimitry Andric       takeAndConcatenateAttrs(CXX11Attrs, GNUAttrs, Attrs);
21181ad6265SDimitry Andric 
2120b57cec5SDimitry Andric       // identifier ':' statement
2130b57cec5SDimitry Andric       return ParseLabeledStatement(Attrs, StmtCtx);
2140b57cec5SDimitry Andric     }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric     // Look up the identifier, and typo-correct it to a keyword if it's not
2170b57cec5SDimitry Andric     // found.
2180b57cec5SDimitry Andric     if (Next.isNot(tok::coloncolon)) {
2190b57cec5SDimitry Andric       // Try to limit which sets of keywords should be included in typo
2200b57cec5SDimitry Andric       // correction based on what the next token is.
2210b57cec5SDimitry Andric       StatementFilterCCC CCC(Next);
222a7dea167SDimitry Andric       if (TryAnnotateName(&CCC) == ANK_Error) {
2230b57cec5SDimitry Andric         // Handle errors here by skipping up to the next semicolon or '}', and
2240b57cec5SDimitry Andric         // eat the semicolon if that's what stopped us.
2250b57cec5SDimitry Andric         SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
2260b57cec5SDimitry Andric         if (Tok.is(tok::semi))
2270b57cec5SDimitry Andric           ConsumeToken();
2280b57cec5SDimitry Andric         return StmtError();
2290b57cec5SDimitry Andric       }
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric       // If the identifier was typo-corrected, try again.
2320b57cec5SDimitry Andric       if (Tok.isNot(tok::identifier))
2330b57cec5SDimitry Andric         goto Retry;
2340b57cec5SDimitry Andric     }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric     // Fall through
237bdd1243dSDimitry Andric     [[fallthrough]];
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   default: {
24181ad6265SDimitry Andric     bool HaveAttrs = !CXX11Attrs.empty() || !GNUAttrs.empty();
24281ad6265SDimitry Andric     auto IsStmtAttr = [](ParsedAttr &Attr) { return Attr.isStmtAttr(); };
24381ad6265SDimitry Andric     bool AllAttrsAreStmtAttrs = llvm::all_of(CXX11Attrs, IsStmtAttr) &&
24481ad6265SDimitry Andric                                 llvm::all_of(GNUAttrs, IsStmtAttr);
2450fca6ea1SDimitry Andric     // In C, the grammar production for statement (C23 6.8.1p1) does not allow
2460fca6ea1SDimitry Andric     // for declarations, which is different from C++ (C++23 [stmt.pre]p1). So
2470fca6ea1SDimitry Andric     // in C++, we always allow a declaration, but in C we need to check whether
2480fca6ea1SDimitry Andric     // we're in a statement context that allows declarations. e.g., in C, the
2490fca6ea1SDimitry Andric     // following is invalid: if (1) int x;
2500fca6ea1SDimitry Andric     if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt ||
2510fca6ea1SDimitry Andric          (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
2520fca6ea1SDimitry Andric              ParsedStmtContext()) &&
2530fca6ea1SDimitry Andric         ((GNUAttributeLoc.isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) ||
254fe6060f1SDimitry Andric          isDeclarationStatement())) {
2550b57cec5SDimitry Andric       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
256a7dea167SDimitry Andric       DeclGroupPtrTy Decl;
257a7dea167SDimitry Andric       if (GNUAttributeLoc.isValid()) {
258a7dea167SDimitry Andric         DeclStart = GNUAttributeLoc;
25981ad6265SDimitry Andric         Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, CXX11Attrs,
26081ad6265SDimitry Andric                                 GNUAttrs, &GNUAttributeLoc);
261a7dea167SDimitry Andric       } else {
26281ad6265SDimitry Andric         Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, CXX11Attrs,
26381ad6265SDimitry Andric                                 GNUAttrs);
264a7dea167SDimitry Andric       }
26581ad6265SDimitry Andric       if (CXX11Attrs.Range.getBegin().isValid()) {
26681ad6265SDimitry Andric         // The caller must guarantee that the CXX11Attrs appear before the
26781ad6265SDimitry Andric         // GNUAttrs, and we rely on that here.
26881ad6265SDimitry Andric         assert(GNUAttrs.Range.getBegin().isInvalid() ||
26981ad6265SDimitry Andric                GNUAttrs.Range.getBegin() > CXX11Attrs.Range.getBegin());
27081ad6265SDimitry Andric         DeclStart = CXX11Attrs.Range.getBegin();
27181ad6265SDimitry Andric       } else if (GNUAttrs.Range.getBegin().isValid())
27281ad6265SDimitry Andric         DeclStart = GNUAttrs.Range.getBegin();
2730b57cec5SDimitry Andric       return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
2740b57cec5SDimitry Andric     }
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric     if (Tok.is(tok::r_brace)) {
2770b57cec5SDimitry Andric       Diag(Tok, diag::err_expected_statement);
2780b57cec5SDimitry Andric       return StmtError();
2790b57cec5SDimitry Andric     }
2800b57cec5SDimitry Andric 
281bdd1243dSDimitry Andric     switch (Tok.getKind()) {
282bdd1243dSDimitry Andric #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
283bdd1243dSDimitry Andric #include "clang/Basic/TransformTypeTraits.def"
284bdd1243dSDimitry Andric       if (NextToken().is(tok::less)) {
285bdd1243dSDimitry Andric         Tok.setKind(tok::identifier);
286bdd1243dSDimitry Andric         Diag(Tok, diag::ext_keyword_as_ident)
287bdd1243dSDimitry Andric             << Tok.getIdentifierInfo()->getName() << 0;
288bdd1243dSDimitry Andric         goto ParseIdentifier;
289bdd1243dSDimitry Andric       }
290bdd1243dSDimitry Andric       [[fallthrough]];
291bdd1243dSDimitry Andric     default:
2920b57cec5SDimitry Andric       return ParseExprStatement(StmtCtx);
2930b57cec5SDimitry Andric     }
294bdd1243dSDimitry Andric   }
2950b57cec5SDimitry Andric 
296a7dea167SDimitry Andric   case tok::kw___attribute: {
297a7dea167SDimitry Andric     GNUAttributeLoc = Tok.getLocation();
29881ad6265SDimitry Andric     ParseGNUAttributes(GNUAttrs);
299a7dea167SDimitry Andric     goto Retry;
300a7dea167SDimitry Andric   }
301a7dea167SDimitry Andric 
3020b57cec5SDimitry Andric   case tok::kw_case:                // C99 6.8.1: labeled-statement
3030b57cec5SDimitry Andric     return ParseCaseStatement(StmtCtx);
3040b57cec5SDimitry Andric   case tok::kw_default:             // C99 6.8.1: labeled-statement
3050b57cec5SDimitry Andric     return ParseDefaultStatement(StmtCtx);
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   case tok::l_brace:                // C99 6.8.2: compound-statement
3080b57cec5SDimitry Andric     return ParseCompoundStatement();
3090b57cec5SDimitry Andric   case tok::semi: {                 // C99 6.8.3p3: expression[opt] ';'
3100b57cec5SDimitry Andric     bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro();
3110b57cec5SDimitry Andric     return Actions.ActOnNullStmt(ConsumeToken(), HasLeadingEmptyMacro);
3120b57cec5SDimitry Andric   }
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric   case tok::kw_if:                  // C99 6.8.4.1: if-statement
3150b57cec5SDimitry Andric     return ParseIfStatement(TrailingElseLoc);
3160b57cec5SDimitry Andric   case tok::kw_switch:              // C99 6.8.4.2: switch-statement
3170b57cec5SDimitry Andric     return ParseSwitchStatement(TrailingElseLoc);
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   case tok::kw_while:               // C99 6.8.5.1: while-statement
3200b57cec5SDimitry Andric     return ParseWhileStatement(TrailingElseLoc);
3210b57cec5SDimitry Andric   case tok::kw_do:                  // C99 6.8.5.2: do-statement
3220b57cec5SDimitry Andric     Res = ParseDoStatement();
3230b57cec5SDimitry Andric     SemiError = "do/while";
3240b57cec5SDimitry Andric     break;
3250b57cec5SDimitry Andric   case tok::kw_for:                 // C99 6.8.5.3: for-statement
3260b57cec5SDimitry Andric     return ParseForStatement(TrailingElseLoc);
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   case tok::kw_goto:                // C99 6.8.6.1: goto-statement
3290b57cec5SDimitry Andric     Res = ParseGotoStatement();
3300b57cec5SDimitry Andric     SemiError = "goto";
3310b57cec5SDimitry Andric     break;
3320b57cec5SDimitry Andric   case tok::kw_continue:            // C99 6.8.6.2: continue-statement
3330b57cec5SDimitry Andric     Res = ParseContinueStatement();
3340b57cec5SDimitry Andric     SemiError = "continue";
3350b57cec5SDimitry Andric     break;
3360b57cec5SDimitry Andric   case tok::kw_break:               // C99 6.8.6.3: break-statement
3370b57cec5SDimitry Andric     Res = ParseBreakStatement();
3380b57cec5SDimitry Andric     SemiError = "break";
3390b57cec5SDimitry Andric     break;
3400b57cec5SDimitry Andric   case tok::kw_return:              // C99 6.8.6.4: return-statement
3410b57cec5SDimitry Andric     Res = ParseReturnStatement();
3420b57cec5SDimitry Andric     SemiError = "return";
3430b57cec5SDimitry Andric     break;
3440b57cec5SDimitry Andric   case tok::kw_co_return:            // C++ Coroutines: co_return statement
3450b57cec5SDimitry Andric     Res = ParseReturnStatement();
3460b57cec5SDimitry Andric     SemiError = "co_return";
3470b57cec5SDimitry Andric     break;
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   case tok::kw_asm: {
35081ad6265SDimitry Andric     for (const ParsedAttr &AL : CXX11Attrs)
35106c3fb27SDimitry Andric       // Could be relaxed if asm-related regular keyword attributes are
35206c3fb27SDimitry Andric       // added later.
35306c3fb27SDimitry Andric       (AL.isRegularKeywordAttribute()
35406c3fb27SDimitry Andric            ? Diag(AL.getRange().getBegin(), diag::err_keyword_not_allowed)
35506c3fb27SDimitry Andric            : Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored))
35606c3fb27SDimitry Andric           << AL;
35781ad6265SDimitry Andric     // Prevent these from being interpreted as statement attributes later on.
35881ad6265SDimitry Andric     CXX11Attrs.clear();
35981ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
3600b57cec5SDimitry Andric     bool msAsm = false;
3610b57cec5SDimitry Andric     Res = ParseAsmStatement(msAsm);
3620b57cec5SDimitry Andric     if (msAsm) return Res;
3630b57cec5SDimitry Andric     SemiError = "asm";
3640b57cec5SDimitry Andric     break;
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   case tok::kw___if_exists:
3680b57cec5SDimitry Andric   case tok::kw___if_not_exists:
36981ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
37081ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
3710b57cec5SDimitry Andric     ParseMicrosoftIfExistsStatement(Stmts);
3720b57cec5SDimitry Andric     // An __if_exists block is like a compound statement, but it doesn't create
3730b57cec5SDimitry Andric     // a new scope.
3740b57cec5SDimitry Andric     return StmtEmpty();
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   case tok::kw_try:                 // C++ 15: try-block
3770b57cec5SDimitry Andric     return ParseCXXTryBlock();
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   case tok::kw___try:
38081ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
38181ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
3820b57cec5SDimitry Andric     return ParseSEHTryBlock();
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   case tok::kw___leave:
3850b57cec5SDimitry Andric     Res = ParseSEHLeaveStatement();
3860b57cec5SDimitry Andric     SemiError = "__leave";
3870b57cec5SDimitry Andric     break;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   case tok::annot_pragma_vis:
39081ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
39181ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
3920b57cec5SDimitry Andric     HandlePragmaVisibility();
3930b57cec5SDimitry Andric     return StmtEmpty();
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   case tok::annot_pragma_pack:
39681ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
39781ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
3980b57cec5SDimitry Andric     HandlePragmaPack();
3990b57cec5SDimitry Andric     return StmtEmpty();
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   case tok::annot_pragma_msstruct:
40281ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
40381ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
4040b57cec5SDimitry Andric     HandlePragmaMSStruct();
4050b57cec5SDimitry Andric     return StmtEmpty();
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   case tok::annot_pragma_align:
40881ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
40981ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
4100b57cec5SDimitry Andric     HandlePragmaAlign();
4110b57cec5SDimitry Andric     return StmtEmpty();
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   case tok::annot_pragma_weak:
41481ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
41581ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
4160b57cec5SDimitry Andric     HandlePragmaWeak();
4170b57cec5SDimitry Andric     return StmtEmpty();
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   case tok::annot_pragma_weakalias:
42081ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
42181ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
4220b57cec5SDimitry Andric     HandlePragmaWeakAlias();
4230b57cec5SDimitry Andric     return StmtEmpty();
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   case tok::annot_pragma_redefine_extname:
42681ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
42781ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
4280b57cec5SDimitry Andric     HandlePragmaRedefineExtname();
4290b57cec5SDimitry Andric     return StmtEmpty();
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   case tok::annot_pragma_fp_contract:
43281ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
43381ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
4345ffd83dbSDimitry Andric     Diag(Tok, diag::err_pragma_file_or_compound_scope) << "fp_contract";
4350b57cec5SDimitry Andric     ConsumeAnnotationToken();
4360b57cec5SDimitry Andric     return StmtError();
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric   case tok::annot_pragma_fp:
43981ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
44081ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
4415ffd83dbSDimitry Andric     Diag(Tok, diag::err_pragma_file_or_compound_scope) << "clang fp";
4420b57cec5SDimitry Andric     ConsumeAnnotationToken();
4430b57cec5SDimitry Andric     return StmtError();
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   case tok::annot_pragma_fenv_access:
446349cc55cSDimitry Andric   case tok::annot_pragma_fenv_access_ms:
44781ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
44881ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
449349cc55cSDimitry Andric     Diag(Tok, diag::err_pragma_file_or_compound_scope)
450349cc55cSDimitry Andric         << (Kind == tok::annot_pragma_fenv_access ? "STDC FENV_ACCESS"
451349cc55cSDimitry Andric                                                     : "fenv_access");
452e8d8bef9SDimitry Andric     ConsumeAnnotationToken();
4530b57cec5SDimitry Andric     return StmtEmpty();
4540b57cec5SDimitry Andric 
455e8d8bef9SDimitry Andric   case tok::annot_pragma_fenv_round:
45681ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
45781ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
458e8d8bef9SDimitry Andric     Diag(Tok, diag::err_pragma_file_or_compound_scope) << "STDC FENV_ROUND";
459e8d8bef9SDimitry Andric     ConsumeAnnotationToken();
460e8d8bef9SDimitry Andric     return StmtError();
461e8d8bef9SDimitry Andric 
4625f757f3fSDimitry Andric   case tok::annot_pragma_cx_limited_range:
4635f757f3fSDimitry Andric     ProhibitAttributes(CXX11Attrs);
4645f757f3fSDimitry Andric     ProhibitAttributes(GNUAttrs);
4655f757f3fSDimitry Andric     Diag(Tok, diag::err_pragma_file_or_compound_scope)
4665f757f3fSDimitry Andric         << "STDC CX_LIMITED_RANGE";
4675f757f3fSDimitry Andric     ConsumeAnnotationToken();
4685f757f3fSDimitry Andric     return StmtError();
4695f757f3fSDimitry Andric 
4705ffd83dbSDimitry Andric   case tok::annot_pragma_float_control:
47181ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
47281ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
4735ffd83dbSDimitry Andric     Diag(Tok, diag::err_pragma_file_or_compound_scope) << "float_control";
4745ffd83dbSDimitry Andric     ConsumeAnnotationToken();
4755ffd83dbSDimitry Andric     return StmtError();
4765ffd83dbSDimitry Andric 
4770b57cec5SDimitry Andric   case tok::annot_pragma_opencl_extension:
47881ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
47981ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
4800b57cec5SDimitry Andric     HandlePragmaOpenCLExtension();
4810b57cec5SDimitry Andric     return StmtEmpty();
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   case tok::annot_pragma_captured:
48481ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
48581ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
4860b57cec5SDimitry Andric     return HandlePragmaCaptured();
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric   case tok::annot_pragma_openmp:
489fe6060f1SDimitry Andric     // Prohibit attributes that are not OpenMP attributes, but only before
490fe6060f1SDimitry Andric     // processing a #pragma omp clause.
49181ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
49281ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
493bdd1243dSDimitry Andric     [[fallthrough]];
494fe6060f1SDimitry Andric   case tok::annot_attr_openmp:
495fe6060f1SDimitry Andric     // Do not prohibit attributes if they were OpenMP attributes.
4960b57cec5SDimitry Andric     return ParseOpenMPDeclarativeOrExecutableDirective(StmtCtx);
4970b57cec5SDimitry Andric 
4985f757f3fSDimitry Andric   case tok::annot_pragma_openacc:
4995f757f3fSDimitry Andric     return ParseOpenACCDirectiveStmt();
5005f757f3fSDimitry Andric 
5010b57cec5SDimitry Andric   case tok::annot_pragma_ms_pointers_to_members:
50281ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
50381ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
5040b57cec5SDimitry Andric     HandlePragmaMSPointersToMembers();
5050b57cec5SDimitry Andric     return StmtEmpty();
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   case tok::annot_pragma_ms_pragma:
50881ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
50981ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
5100b57cec5SDimitry Andric     HandlePragmaMSPragma();
5110b57cec5SDimitry Andric     return StmtEmpty();
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   case tok::annot_pragma_ms_vtordisp:
51481ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
51581ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
5160b57cec5SDimitry Andric     HandlePragmaMSVtorDisp();
5170b57cec5SDimitry Andric     return StmtEmpty();
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric   case tok::annot_pragma_loop_hint:
52081ad6265SDimitry Andric     ProhibitAttributes(CXX11Attrs);
52181ad6265SDimitry Andric     ProhibitAttributes(GNUAttrs);
52281ad6265SDimitry Andric     return ParsePragmaLoopHint(Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs);
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric   case tok::annot_pragma_dump:
5250b57cec5SDimitry Andric     HandlePragmaDump();
5260b57cec5SDimitry Andric     return StmtEmpty();
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   case tok::annot_pragma_attribute:
5290b57cec5SDimitry Andric     HandlePragmaAttribute();
5300b57cec5SDimitry Andric     return StmtEmpty();
5310b57cec5SDimitry Andric   }
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric   // If we reached this code, the statement must end in a semicolon.
5340b57cec5SDimitry Andric   if (!TryConsumeToken(tok::semi) && !Res.isInvalid()) {
5350b57cec5SDimitry Andric     // If the result was valid, then we do want to diagnose this.  Use
5360b57cec5SDimitry Andric     // ExpectAndConsume to emit the diagnostic, even though we know it won't
5370b57cec5SDimitry Andric     // succeed.
5380b57cec5SDimitry Andric     ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
5390b57cec5SDimitry Andric     // Skip until we see a } or ;, but don't eat it.
5400b57cec5SDimitry Andric     SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
5410b57cec5SDimitry Andric   }
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   return Res;
5440b57cec5SDimitry Andric }
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric /// Parse an expression statement.
5470b57cec5SDimitry Andric StmtResult Parser::ParseExprStatement(ParsedStmtContext StmtCtx) {
5480b57cec5SDimitry Andric   // If a case keyword is missing, this is where it should be inserted.
5490b57cec5SDimitry Andric   Token OldToken = Tok;
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric   ExprStatementTokLoc = Tok.getLocation();
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric   // expression[opt] ';'
5540b57cec5SDimitry Andric   ExprResult Expr(ParseExpression());
5550b57cec5SDimitry Andric   if (Expr.isInvalid()) {
5560b57cec5SDimitry Andric     // If the expression is invalid, skip ahead to the next semicolon or '}'.
5570b57cec5SDimitry Andric     // Not doing this opens us up to the possibility of infinite loops if
5580b57cec5SDimitry Andric     // ParseExpression does not consume any tokens.
5590b57cec5SDimitry Andric     SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
5600b57cec5SDimitry Andric     if (Tok.is(tok::semi))
5610b57cec5SDimitry Andric       ConsumeToken();
5620b57cec5SDimitry Andric     return Actions.ActOnExprStmtError();
5630b57cec5SDimitry Andric   }
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() &&
5660b57cec5SDimitry Andric       Actions.CheckCaseExpression(Expr.get())) {
5670b57cec5SDimitry Andric     // If a constant expression is followed by a colon inside a switch block,
5680b57cec5SDimitry Andric     // suggest a missing case keyword.
5690b57cec5SDimitry Andric     Diag(OldToken, diag::err_expected_case_before_expression)
5700b57cec5SDimitry Andric       << FixItHint::CreateInsertion(OldToken.getLocation(), "case ");
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric     // Recover parsing as a case statement.
5730b57cec5SDimitry Andric     return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
5740b57cec5SDimitry Andric   }
5750b57cec5SDimitry Andric 
57606c3fb27SDimitry Andric   Token *CurTok = nullptr;
57706c3fb27SDimitry Andric   // Note we shouldn't eat the token since the callback needs it.
5780fca6ea1SDimitry Andric   if (Tok.is(tok::annot_repl_input_end))
57906c3fb27SDimitry Andric     CurTok = &Tok;
58006c3fb27SDimitry Andric   else
5810b57cec5SDimitry Andric     // Otherwise, eat the semicolon.
5820b57cec5SDimitry Andric     ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
58306c3fb27SDimitry Andric 
58406c3fb27SDimitry Andric   StmtResult R = handleExprStmt(Expr, StmtCtx);
58506c3fb27SDimitry Andric   if (CurTok && !R.isInvalid())
58606c3fb27SDimitry Andric     CurTok->setAnnotationValue(R.get());
58706c3fb27SDimitry Andric 
58806c3fb27SDimitry Andric   return R;
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric /// ParseSEHTryBlockCommon
5920b57cec5SDimitry Andric ///
5930b57cec5SDimitry Andric /// seh-try-block:
5940b57cec5SDimitry Andric ///   '__try' compound-statement seh-handler
5950b57cec5SDimitry Andric ///
5960b57cec5SDimitry Andric /// seh-handler:
5970b57cec5SDimitry Andric ///   seh-except-block
5980b57cec5SDimitry Andric ///   seh-finally-block
5990b57cec5SDimitry Andric ///
6000b57cec5SDimitry Andric StmtResult Parser::ParseSEHTryBlock() {
6010b57cec5SDimitry Andric   assert(Tok.is(tok::kw___try) && "Expected '__try'");
6020b57cec5SDimitry Andric   SourceLocation TryLoc = ConsumeToken();
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   if (Tok.isNot(tok::l_brace))
6050b57cec5SDimitry Andric     return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric   StmtResult TryBlock(ParseCompoundStatement(
6080b57cec5SDimitry Andric       /*isStmtExpr=*/false,
6090b57cec5SDimitry Andric       Scope::DeclScope | Scope::CompoundStmtScope | Scope::SEHTryScope));
6100b57cec5SDimitry Andric   if (TryBlock.isInvalid())
6110b57cec5SDimitry Andric     return TryBlock;
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric   StmtResult Handler;
6140b57cec5SDimitry Andric   if (Tok.is(tok::identifier) &&
6150b57cec5SDimitry Andric       Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
6160b57cec5SDimitry Andric     SourceLocation Loc = ConsumeToken();
6170b57cec5SDimitry Andric     Handler = ParseSEHExceptBlock(Loc);
6180b57cec5SDimitry Andric   } else if (Tok.is(tok::kw___finally)) {
6190b57cec5SDimitry Andric     SourceLocation Loc = ConsumeToken();
6200b57cec5SDimitry Andric     Handler = ParseSEHFinallyBlock(Loc);
6210b57cec5SDimitry Andric   } else {
6220b57cec5SDimitry Andric     return StmtError(Diag(Tok, diag::err_seh_expected_handler));
6230b57cec5SDimitry Andric   }
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric   if(Handler.isInvalid())
6260b57cec5SDimitry Andric     return Handler;
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   return Actions.ActOnSEHTryBlock(false /* IsCXXTry */,
6290b57cec5SDimitry Andric                                   TryLoc,
6300b57cec5SDimitry Andric                                   TryBlock.get(),
6310b57cec5SDimitry Andric                                   Handler.get());
6320b57cec5SDimitry Andric }
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric /// ParseSEHExceptBlock - Handle __except
6350b57cec5SDimitry Andric ///
6360b57cec5SDimitry Andric /// seh-except-block:
6370b57cec5SDimitry Andric ///   '__except' '(' seh-filter-expression ')' compound-statement
6380b57cec5SDimitry Andric ///
6390b57cec5SDimitry Andric StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
6400b57cec5SDimitry Andric   PoisonIdentifierRAIIObject raii(Ident__exception_code, false),
6410b57cec5SDimitry Andric     raii2(Ident___exception_code, false),
6420b57cec5SDimitry Andric     raii3(Ident_GetExceptionCode, false);
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric   if (ExpectAndConsume(tok::l_paren))
6450b57cec5SDimitry Andric     return StmtError();
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric   ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope |
6480b57cec5SDimitry Andric                                    Scope::SEHExceptScope);
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   if (getLangOpts().Borland) {
6510b57cec5SDimitry Andric     Ident__exception_info->setIsPoisoned(false);
6520b57cec5SDimitry Andric     Ident___exception_info->setIsPoisoned(false);
6530b57cec5SDimitry Andric     Ident_GetExceptionInfo->setIsPoisoned(false);
6540b57cec5SDimitry Andric   }
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric   ExprResult FilterExpr;
6570b57cec5SDimitry Andric   {
6580b57cec5SDimitry Andric     ParseScopeFlags FilterScope(this, getCurScope()->getFlags() |
6590b57cec5SDimitry Andric                                           Scope::SEHFilterScope);
6600b57cec5SDimitry Andric     FilterExpr = Actions.CorrectDelayedTyposInExpr(ParseExpression());
6610b57cec5SDimitry Andric   }
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   if (getLangOpts().Borland) {
6640b57cec5SDimitry Andric     Ident__exception_info->setIsPoisoned(true);
6650b57cec5SDimitry Andric     Ident___exception_info->setIsPoisoned(true);
6660b57cec5SDimitry Andric     Ident_GetExceptionInfo->setIsPoisoned(true);
6670b57cec5SDimitry Andric   }
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric   if(FilterExpr.isInvalid())
6700b57cec5SDimitry Andric     return StmtError();
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   if (ExpectAndConsume(tok::r_paren))
6730b57cec5SDimitry Andric     return StmtError();
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric   if (Tok.isNot(tok::l_brace))
6760b57cec5SDimitry Andric     return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   StmtResult Block(ParseCompoundStatement());
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric   if(Block.isInvalid())
6810b57cec5SDimitry Andric     return Block;
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric   return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.get(), Block.get());
6840b57cec5SDimitry Andric }
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric /// ParseSEHFinallyBlock - Handle __finally
6870b57cec5SDimitry Andric ///
6880b57cec5SDimitry Andric /// seh-finally-block:
6890b57cec5SDimitry Andric ///   '__finally' compound-statement
6900b57cec5SDimitry Andric ///
6910b57cec5SDimitry Andric StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyLoc) {
6920b57cec5SDimitry Andric   PoisonIdentifierRAIIObject raii(Ident__abnormal_termination, false),
6930b57cec5SDimitry Andric     raii2(Ident___abnormal_termination, false),
6940b57cec5SDimitry Andric     raii3(Ident_AbnormalTermination, false);
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric   if (Tok.isNot(tok::l_brace))
6970b57cec5SDimitry Andric     return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric   ParseScope FinallyScope(this, 0);
7000b57cec5SDimitry Andric   Actions.ActOnStartSEHFinallyBlock();
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric   StmtResult Block(ParseCompoundStatement());
7030b57cec5SDimitry Andric   if(Block.isInvalid()) {
7040b57cec5SDimitry Andric     Actions.ActOnAbortSEHFinallyBlock();
7050b57cec5SDimitry Andric     return Block;
7060b57cec5SDimitry Andric   }
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric   return Actions.ActOnFinishSEHFinallyBlock(FinallyLoc, Block.get());
7090b57cec5SDimitry Andric }
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric /// Handle __leave
7120b57cec5SDimitry Andric ///
7130b57cec5SDimitry Andric /// seh-leave-statement:
7140b57cec5SDimitry Andric ///   '__leave' ';'
7150b57cec5SDimitry Andric ///
7160b57cec5SDimitry Andric StmtResult Parser::ParseSEHLeaveStatement() {
7170b57cec5SDimitry Andric   SourceLocation LeaveLoc = ConsumeToken();  // eat the '__leave'.
7180b57cec5SDimitry Andric   return Actions.ActOnSEHLeaveStmt(LeaveLoc, getCurScope());
7190b57cec5SDimitry Andric }
7200b57cec5SDimitry Andric 
7215f757f3fSDimitry Andric static void DiagnoseLabelFollowedByDecl(Parser &P, const Stmt *SubStmt) {
7225f757f3fSDimitry Andric   // When in C mode (but not Microsoft extensions mode), diagnose use of a
7235f757f3fSDimitry Andric   // label that is followed by a declaration rather than a statement.
7245f757f3fSDimitry Andric   if (!P.getLangOpts().CPlusPlus && !P.getLangOpts().MicrosoftExt &&
7255f757f3fSDimitry Andric       isa<DeclStmt>(SubStmt)) {
7265f757f3fSDimitry Andric     P.Diag(SubStmt->getBeginLoc(),
7275f757f3fSDimitry Andric            P.getLangOpts().C23
7285f757f3fSDimitry Andric                ? diag::warn_c23_compat_label_followed_by_declaration
7295f757f3fSDimitry Andric                : diag::ext_c_label_followed_by_declaration);
7305f757f3fSDimitry Andric   }
7315f757f3fSDimitry Andric }
7325f757f3fSDimitry Andric 
7330b57cec5SDimitry Andric /// ParseLabeledStatement - We have an identifier and a ':' after it.
7340b57cec5SDimitry Andric ///
735bdd1243dSDimitry Andric ///       label:
736bdd1243dSDimitry Andric ///         identifier ':'
737bdd1243dSDimitry Andric /// [GNU]   identifier ':' attributes[opt]
738bdd1243dSDimitry Andric ///
7390b57cec5SDimitry Andric ///       labeled-statement:
740bdd1243dSDimitry Andric ///         label statement
7410b57cec5SDimitry Andric ///
74281ad6265SDimitry Andric StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs,
7430b57cec5SDimitry Andric                                          ParsedStmtContext StmtCtx) {
7440b57cec5SDimitry Andric   assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
7450b57cec5SDimitry Andric          "Not an identifier!");
7460b57cec5SDimitry Andric 
7475f757f3fSDimitry Andric   // [OpenMP 5.1] 2.1.3: A stand-alone directive may not be used in place of a
7485f757f3fSDimitry Andric   // substatement in a selection statement, in place of the loop body in an
7495f757f3fSDimitry Andric   // iteration statement, or in place of the statement that follows a label.
7505f757f3fSDimitry Andric   StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric   Token IdentTok = Tok;  // Save the whole token.
7530b57cec5SDimitry Andric   ConsumeToken();  // eat the identifier.
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric   assert(Tok.is(tok::colon) && "Not a label!");
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric   // identifier ':' statement
7580b57cec5SDimitry Andric   SourceLocation ColonLoc = ConsumeToken();
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric   // Read label attributes, if present.
7610b57cec5SDimitry Andric   StmtResult SubStmt;
7620b57cec5SDimitry Andric   if (Tok.is(tok::kw___attribute)) {
76381ad6265SDimitry Andric     ParsedAttributes TempAttrs(AttrFactory);
7640b57cec5SDimitry Andric     ParseGNUAttributes(TempAttrs);
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric     // In C++, GNU attributes only apply to the label if they are followed by a
7670b57cec5SDimitry Andric     // semicolon, to disambiguate label attributes from attributes on a labeled
7680b57cec5SDimitry Andric     // declaration.
7690b57cec5SDimitry Andric     //
7700b57cec5SDimitry Andric     // This doesn't quite match what GCC does; if the attribute list is empty
7710b57cec5SDimitry Andric     // and followed by a semicolon, GCC will reject (it appears to parse the
7720b57cec5SDimitry Andric     // attributes as part of a statement in that case). That looks like a bug.
7730b57cec5SDimitry Andric     if (!getLangOpts().CPlusPlus || Tok.is(tok::semi))
77481ad6265SDimitry Andric       Attrs.takeAllFrom(TempAttrs);
775fe6060f1SDimitry Andric     else {
7760b57cec5SDimitry Andric       StmtVector Stmts;
77781ad6265SDimitry Andric       ParsedAttributes EmptyCXX11Attrs(AttrFactory);
77881ad6265SDimitry Andric       SubStmt = ParseStatementOrDeclarationAfterAttributes(
77981ad6265SDimitry Andric           Stmts, StmtCtx, nullptr, EmptyCXX11Attrs, TempAttrs);
7800b57cec5SDimitry Andric       if (!TempAttrs.empty() && !SubStmt.isInvalid())
781fe6060f1SDimitry Andric         SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get());
7820b57cec5SDimitry Andric     }
7830b57cec5SDimitry Andric   }
7840b57cec5SDimitry Andric 
785bdd1243dSDimitry Andric   // The label may have no statement following it
786bdd1243dSDimitry Andric   if (SubStmt.isUnset() && Tok.is(tok::r_brace)) {
787bdd1243dSDimitry Andric     DiagnoseLabelAtEndOfCompoundStatement();
788bdd1243dSDimitry Andric     SubStmt = Actions.ActOnNullStmt(ColonLoc);
789bdd1243dSDimitry Andric   }
790bdd1243dSDimitry Andric 
7910b57cec5SDimitry Andric   // If we've not parsed a statement yet, parse one now.
7920b57cec5SDimitry Andric   if (!SubStmt.isInvalid() && !SubStmt.isUsable())
7930b57cec5SDimitry Andric     SubStmt = ParseStatement(nullptr, StmtCtx);
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric   // Broken substmt shouldn't prevent the label from being added to the AST.
7960b57cec5SDimitry Andric   if (SubStmt.isInvalid())
7970b57cec5SDimitry Andric     SubStmt = Actions.ActOnNullStmt(ColonLoc);
7980b57cec5SDimitry Andric 
7995f757f3fSDimitry Andric   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
8005f757f3fSDimitry Andric 
8010b57cec5SDimitry Andric   LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
8020b57cec5SDimitry Andric                                               IdentTok.getLocation());
80381ad6265SDimitry Andric   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
80481ad6265SDimitry Andric   Attrs.clear();
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric   return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc,
8070b57cec5SDimitry Andric                                 SubStmt.get());
8080b57cec5SDimitry Andric }
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric /// ParseCaseStatement
8110b57cec5SDimitry Andric ///       labeled-statement:
8120b57cec5SDimitry Andric ///         'case' constant-expression ':' statement
8130b57cec5SDimitry Andric /// [GNU]   'case' constant-expression '...' constant-expression ':' statement
8140b57cec5SDimitry Andric ///
8150b57cec5SDimitry Andric StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
8160b57cec5SDimitry Andric                                       bool MissingCase, ExprResult Expr) {
8170b57cec5SDimitry Andric   assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!");
8180b57cec5SDimitry Andric 
8195f757f3fSDimitry Andric   // [OpenMP 5.1] 2.1.3: A stand-alone directive may not be used in place of a
8205f757f3fSDimitry Andric   // substatement in a selection statement, in place of the loop body in an
8215f757f3fSDimitry Andric   // iteration statement, or in place of the statement that follows a label.
8225f757f3fSDimitry Andric   StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
8230b57cec5SDimitry Andric 
824bdd1243dSDimitry Andric   // It is very common for code to contain many case statements recursively
8250b57cec5SDimitry Andric   // nested, as in (but usually without indentation):
8260b57cec5SDimitry Andric   //  case 1:
8270b57cec5SDimitry Andric   //    case 2:
8280b57cec5SDimitry Andric   //      case 3:
8290b57cec5SDimitry Andric   //         case 4:
8300b57cec5SDimitry Andric   //           case 5: etc.
8310b57cec5SDimitry Andric   //
8320b57cec5SDimitry Andric   // Parsing this naively works, but is both inefficient and can cause us to run
8330b57cec5SDimitry Andric   // out of stack space in our recursive descent parser.  As a special case,
8340b57cec5SDimitry Andric   // flatten this recursion into an iterative loop.  This is complex and gross,
8350b57cec5SDimitry Andric   // but all the grossness is constrained to ParseCaseStatement (and some
8360b57cec5SDimitry Andric   // weirdness in the actions), so this is just local grossness :).
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric   // TopLevelCase - This is the highest level we have parsed.  'case 1' in the
8390b57cec5SDimitry Andric   // example above.
8400b57cec5SDimitry Andric   StmtResult TopLevelCase(true);
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric   // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
8430b57cec5SDimitry Andric   // gets updated each time a new case is parsed, and whose body is unset so
8440b57cec5SDimitry Andric   // far.  When parsing 'case 4', this is the 'case 3' node.
8450b57cec5SDimitry Andric   Stmt *DeepestParsedCaseStmt = nullptr;
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric   // While we have case statements, eat and stack them.
8480b57cec5SDimitry Andric   SourceLocation ColonLoc;
8490b57cec5SDimitry Andric   do {
8500b57cec5SDimitry Andric     SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() :
8510b57cec5SDimitry Andric                                            ConsumeToken();  // eat the 'case'.
8520b57cec5SDimitry Andric     ColonLoc = SourceLocation();
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric     if (Tok.is(tok::code_completion)) {
8550b57cec5SDimitry Andric       cutOffParsing();
8560fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteCase(getCurScope());
8570b57cec5SDimitry Andric       return StmtError();
8580b57cec5SDimitry Andric     }
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric     /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
8610b57cec5SDimitry Andric     /// Disable this form of error recovery while we're parsing the case
8620b57cec5SDimitry Andric     /// expression.
8630b57cec5SDimitry Andric     ColonProtectionRAIIObject ColonProtection(*this);
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric     ExprResult LHS;
8660b57cec5SDimitry Andric     if (!MissingCase) {
8670b57cec5SDimitry Andric       LHS = ParseCaseExpression(CaseLoc);
8680b57cec5SDimitry Andric       if (LHS.isInvalid()) {
8690b57cec5SDimitry Andric         // If constant-expression is parsed unsuccessfully, recover by skipping
8700b57cec5SDimitry Andric         // current case statement (moving to the colon that ends it).
8710b57cec5SDimitry Andric         if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
8720b57cec5SDimitry Andric           return StmtError();
8730b57cec5SDimitry Andric       }
8740b57cec5SDimitry Andric     } else {
8750b57cec5SDimitry Andric       LHS = Expr;
8760b57cec5SDimitry Andric       MissingCase = false;
8770b57cec5SDimitry Andric     }
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric     // GNU case range extension.
8800b57cec5SDimitry Andric     SourceLocation DotDotDotLoc;
8810b57cec5SDimitry Andric     ExprResult RHS;
8820b57cec5SDimitry Andric     if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) {
8830b57cec5SDimitry Andric       Diag(DotDotDotLoc, diag::ext_gnu_case_range);
8840b57cec5SDimitry Andric       RHS = ParseCaseExpression(CaseLoc);
8850b57cec5SDimitry Andric       if (RHS.isInvalid()) {
8860b57cec5SDimitry Andric         if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
8870b57cec5SDimitry Andric           return StmtError();
8880b57cec5SDimitry Andric       }
8890b57cec5SDimitry Andric     }
8900b57cec5SDimitry Andric 
8910b57cec5SDimitry Andric     ColonProtection.restore();
8920b57cec5SDimitry Andric 
8930b57cec5SDimitry Andric     if (TryConsumeToken(tok::colon, ColonLoc)) {
8940b57cec5SDimitry Andric     } else if (TryConsumeToken(tok::semi, ColonLoc) ||
8950b57cec5SDimitry Andric                TryConsumeToken(tok::coloncolon, ColonLoc)) {
8960b57cec5SDimitry Andric       // Treat "case blah;" or "case blah::" as a typo for "case blah:".
8970b57cec5SDimitry Andric       Diag(ColonLoc, diag::err_expected_after)
8980b57cec5SDimitry Andric           << "'case'" << tok::colon
8990b57cec5SDimitry Andric           << FixItHint::CreateReplacement(ColonLoc, ":");
9000b57cec5SDimitry Andric     } else {
9010b57cec5SDimitry Andric       SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
9020b57cec5SDimitry Andric       Diag(ExpectedLoc, diag::err_expected_after)
9030b57cec5SDimitry Andric           << "'case'" << tok::colon
9040b57cec5SDimitry Andric           << FixItHint::CreateInsertion(ExpectedLoc, ":");
9050b57cec5SDimitry Andric       ColonLoc = ExpectedLoc;
9060b57cec5SDimitry Andric     }
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric     StmtResult Case =
9090b57cec5SDimitry Andric         Actions.ActOnCaseStmt(CaseLoc, LHS, DotDotDotLoc, RHS, ColonLoc);
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric     // If we had a sema error parsing this case, then just ignore it and
9120b57cec5SDimitry Andric     // continue parsing the sub-stmt.
9130b57cec5SDimitry Andric     if (Case.isInvalid()) {
9140b57cec5SDimitry Andric       if (TopLevelCase.isInvalid())  // No parsed case stmts.
9150b57cec5SDimitry Andric         return ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
9160b57cec5SDimitry Andric       // Otherwise, just don't add it as a nested case.
9170b57cec5SDimitry Andric     } else {
9180b57cec5SDimitry Andric       // If this is the first case statement we parsed, it becomes TopLevelCase.
9190b57cec5SDimitry Andric       // Otherwise we link it into the current chain.
9200b57cec5SDimitry Andric       Stmt *NextDeepest = Case.get();
9210b57cec5SDimitry Andric       if (TopLevelCase.isInvalid())
9220b57cec5SDimitry Andric         TopLevelCase = Case;
9230b57cec5SDimitry Andric       else
9240b57cec5SDimitry Andric         Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, Case.get());
9250b57cec5SDimitry Andric       DeepestParsedCaseStmt = NextDeepest;
9260b57cec5SDimitry Andric     }
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric     // Handle all case statements.
9290b57cec5SDimitry Andric   } while (Tok.is(tok::kw_case));
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric   // If we found a non-case statement, start by parsing it.
9320b57cec5SDimitry Andric   StmtResult SubStmt;
9330b57cec5SDimitry Andric 
934bdd1243dSDimitry Andric   if (Tok.is(tok::r_brace)) {
935bdd1243dSDimitry Andric     // "switch (X) { case 4: }", is valid and is treated as if label was
936bdd1243dSDimitry Andric     // followed by a null statement.
937bdd1243dSDimitry Andric     DiagnoseLabelAtEndOfCompoundStatement();
938bdd1243dSDimitry Andric     SubStmt = Actions.ActOnNullStmt(ColonLoc);
9390b57cec5SDimitry Andric   } else {
940bdd1243dSDimitry Andric     SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
9410b57cec5SDimitry Andric   }
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric   // Install the body into the most deeply-nested case.
9440b57cec5SDimitry Andric   if (DeepestParsedCaseStmt) {
9450b57cec5SDimitry Andric     // Broken sub-stmt shouldn't prevent forming the case statement properly.
9460b57cec5SDimitry Andric     if (SubStmt.isInvalid())
9470b57cec5SDimitry Andric       SubStmt = Actions.ActOnNullStmt(SourceLocation());
9485f757f3fSDimitry Andric     DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
9490b57cec5SDimitry Andric     Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
9500b57cec5SDimitry Andric   }
9510b57cec5SDimitry Andric 
9520b57cec5SDimitry Andric   // Return the top level parsed statement tree.
9530b57cec5SDimitry Andric   return TopLevelCase;
9540b57cec5SDimitry Andric }
9550b57cec5SDimitry Andric 
9560b57cec5SDimitry Andric /// ParseDefaultStatement
9570b57cec5SDimitry Andric ///       labeled-statement:
9580b57cec5SDimitry Andric ///         'default' ':' statement
9590b57cec5SDimitry Andric /// Note that this does not parse the 'statement' at the end.
9600b57cec5SDimitry Andric ///
9610b57cec5SDimitry Andric StmtResult Parser::ParseDefaultStatement(ParsedStmtContext StmtCtx) {
9620b57cec5SDimitry Andric   assert(Tok.is(tok::kw_default) && "Not a default stmt!");
9630b57cec5SDimitry Andric 
9645f757f3fSDimitry Andric   // [OpenMP 5.1] 2.1.3: A stand-alone directive may not be used in place of a
9655f757f3fSDimitry Andric   // substatement in a selection statement, in place of the loop body in an
9665f757f3fSDimitry Andric   // iteration statement, or in place of the statement that follows a label.
9675f757f3fSDimitry Andric   StmtCtx &= ~ParsedStmtContext::AllowStandaloneOpenMPDirectives;
9680b57cec5SDimitry Andric 
9690b57cec5SDimitry Andric   SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric   SourceLocation ColonLoc;
9720b57cec5SDimitry Andric   if (TryConsumeToken(tok::colon, ColonLoc)) {
9730b57cec5SDimitry Andric   } else if (TryConsumeToken(tok::semi, ColonLoc)) {
9740b57cec5SDimitry Andric     // Treat "default;" as a typo for "default:".
9750b57cec5SDimitry Andric     Diag(ColonLoc, diag::err_expected_after)
9760b57cec5SDimitry Andric         << "'default'" << tok::colon
9770b57cec5SDimitry Andric         << FixItHint::CreateReplacement(ColonLoc, ":");
9780b57cec5SDimitry Andric   } else {
9790b57cec5SDimitry Andric     SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
9800b57cec5SDimitry Andric     Diag(ExpectedLoc, diag::err_expected_after)
9810b57cec5SDimitry Andric         << "'default'" << tok::colon
9820b57cec5SDimitry Andric         << FixItHint::CreateInsertion(ExpectedLoc, ":");
9830b57cec5SDimitry Andric     ColonLoc = ExpectedLoc;
9840b57cec5SDimitry Andric   }
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric   StmtResult SubStmt;
9870b57cec5SDimitry Andric 
988bdd1243dSDimitry Andric   if (Tok.is(tok::r_brace)) {
989bdd1243dSDimitry Andric     // "switch (X) {... default: }", is valid and is treated as if label was
990bdd1243dSDimitry Andric     // followed by a null statement.
991bdd1243dSDimitry Andric     DiagnoseLabelAtEndOfCompoundStatement();
992bdd1243dSDimitry Andric     SubStmt = Actions.ActOnNullStmt(ColonLoc);
9930b57cec5SDimitry Andric   } else {
994bdd1243dSDimitry Andric     SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
9950b57cec5SDimitry Andric   }
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric   // Broken sub-stmt shouldn't prevent forming the case statement properly.
9980b57cec5SDimitry Andric   if (SubStmt.isInvalid())
9990b57cec5SDimitry Andric     SubStmt = Actions.ActOnNullStmt(ColonLoc);
10000b57cec5SDimitry Andric 
10015f757f3fSDimitry Andric   DiagnoseLabelFollowedByDecl(*this, SubStmt.get());
10020b57cec5SDimitry Andric   return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
10030b57cec5SDimitry Andric                                   SubStmt.get(), getCurScope());
10040b57cec5SDimitry Andric }
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
10070b57cec5SDimitry Andric   return ParseCompoundStatement(isStmtExpr,
10080b57cec5SDimitry Andric                                 Scope::DeclScope | Scope::CompoundStmtScope);
10090b57cec5SDimitry Andric }
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric /// ParseCompoundStatement - Parse a "{}" block.
10120b57cec5SDimitry Andric ///
10130b57cec5SDimitry Andric ///       compound-statement: [C99 6.8.2]
10140b57cec5SDimitry Andric ///         { block-item-list[opt] }
10150b57cec5SDimitry Andric /// [GNU]   { label-declarations block-item-list } [TODO]
10160b57cec5SDimitry Andric ///
10170b57cec5SDimitry Andric ///       block-item-list:
10180b57cec5SDimitry Andric ///         block-item
10190b57cec5SDimitry Andric ///         block-item-list block-item
10200b57cec5SDimitry Andric ///
10210b57cec5SDimitry Andric ///       block-item:
10220b57cec5SDimitry Andric ///         declaration
10230b57cec5SDimitry Andric /// [GNU]   '__extension__' declaration
10240b57cec5SDimitry Andric ///         statement
10250b57cec5SDimitry Andric ///
10260b57cec5SDimitry Andric /// [GNU] label-declarations:
10270b57cec5SDimitry Andric /// [GNU]   label-declaration
10280b57cec5SDimitry Andric /// [GNU]   label-declarations label-declaration
10290b57cec5SDimitry Andric ///
10300b57cec5SDimitry Andric /// [GNU] label-declaration:
10310b57cec5SDimitry Andric /// [GNU]   '__label__' identifier-list ';'
10320b57cec5SDimitry Andric ///
10330b57cec5SDimitry Andric StmtResult Parser::ParseCompoundStatement(bool isStmtExpr,
10340b57cec5SDimitry Andric                                           unsigned ScopeFlags) {
1035bdd1243dSDimitry Andric   assert(Tok.is(tok::l_brace) && "Not a compound stmt!");
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric   // Enter a scope to hold everything within the compound stmt.  Compound
10380b57cec5SDimitry Andric   // statements can always hold declarations.
10390b57cec5SDimitry Andric   ParseScope CompoundScope(this, ScopeFlags);
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric   // Parse the statements in the body.
10420b57cec5SDimitry Andric   return ParseCompoundStatementBody(isStmtExpr);
10430b57cec5SDimitry Andric }
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric /// Parse any pragmas at the start of the compound expression. We handle these
10460b57cec5SDimitry Andric /// separately since some pragmas (FP_CONTRACT) must appear before any C
10470b57cec5SDimitry Andric /// statement in the compound, but may be intermingled with other pragmas.
10480b57cec5SDimitry Andric void Parser::ParseCompoundStatementLeadingPragmas() {
10490b57cec5SDimitry Andric   bool checkForPragmas = true;
10500b57cec5SDimitry Andric   while (checkForPragmas) {
10510b57cec5SDimitry Andric     switch (Tok.getKind()) {
10520b57cec5SDimitry Andric     case tok::annot_pragma_vis:
10530b57cec5SDimitry Andric       HandlePragmaVisibility();
10540b57cec5SDimitry Andric       break;
10550b57cec5SDimitry Andric     case tok::annot_pragma_pack:
10560b57cec5SDimitry Andric       HandlePragmaPack();
10570b57cec5SDimitry Andric       break;
10580b57cec5SDimitry Andric     case tok::annot_pragma_msstruct:
10590b57cec5SDimitry Andric       HandlePragmaMSStruct();
10600b57cec5SDimitry Andric       break;
10610b57cec5SDimitry Andric     case tok::annot_pragma_align:
10620b57cec5SDimitry Andric       HandlePragmaAlign();
10630b57cec5SDimitry Andric       break;
10640b57cec5SDimitry Andric     case tok::annot_pragma_weak:
10650b57cec5SDimitry Andric       HandlePragmaWeak();
10660b57cec5SDimitry Andric       break;
10670b57cec5SDimitry Andric     case tok::annot_pragma_weakalias:
10680b57cec5SDimitry Andric       HandlePragmaWeakAlias();
10690b57cec5SDimitry Andric       break;
10700b57cec5SDimitry Andric     case tok::annot_pragma_redefine_extname:
10710b57cec5SDimitry Andric       HandlePragmaRedefineExtname();
10720b57cec5SDimitry Andric       break;
10730b57cec5SDimitry Andric     case tok::annot_pragma_opencl_extension:
10740b57cec5SDimitry Andric       HandlePragmaOpenCLExtension();
10750b57cec5SDimitry Andric       break;
10760b57cec5SDimitry Andric     case tok::annot_pragma_fp_contract:
10770b57cec5SDimitry Andric       HandlePragmaFPContract();
10780b57cec5SDimitry Andric       break;
10790b57cec5SDimitry Andric     case tok::annot_pragma_fp:
10800b57cec5SDimitry Andric       HandlePragmaFP();
10810b57cec5SDimitry Andric       break;
10820b57cec5SDimitry Andric     case tok::annot_pragma_fenv_access:
1083349cc55cSDimitry Andric     case tok::annot_pragma_fenv_access_ms:
10840b57cec5SDimitry Andric       HandlePragmaFEnvAccess();
10850b57cec5SDimitry Andric       break;
1086e8d8bef9SDimitry Andric     case tok::annot_pragma_fenv_round:
1087e8d8bef9SDimitry Andric       HandlePragmaFEnvRound();
1088e8d8bef9SDimitry Andric       break;
10895f757f3fSDimitry Andric     case tok::annot_pragma_cx_limited_range:
10905f757f3fSDimitry Andric       HandlePragmaCXLimitedRange();
10915f757f3fSDimitry Andric       break;
10925ffd83dbSDimitry Andric     case tok::annot_pragma_float_control:
10935ffd83dbSDimitry Andric       HandlePragmaFloatControl();
10945ffd83dbSDimitry Andric       break;
10950b57cec5SDimitry Andric     case tok::annot_pragma_ms_pointers_to_members:
10960b57cec5SDimitry Andric       HandlePragmaMSPointersToMembers();
10970b57cec5SDimitry Andric       break;
10980b57cec5SDimitry Andric     case tok::annot_pragma_ms_pragma:
10990b57cec5SDimitry Andric       HandlePragmaMSPragma();
11000b57cec5SDimitry Andric       break;
11010b57cec5SDimitry Andric     case tok::annot_pragma_ms_vtordisp:
11020b57cec5SDimitry Andric       HandlePragmaMSVtorDisp();
11030b57cec5SDimitry Andric       break;
11040b57cec5SDimitry Andric     case tok::annot_pragma_dump:
11050b57cec5SDimitry Andric       HandlePragmaDump();
11060b57cec5SDimitry Andric       break;
11070b57cec5SDimitry Andric     default:
11080b57cec5SDimitry Andric       checkForPragmas = false;
11090b57cec5SDimitry Andric       break;
11100b57cec5SDimitry Andric     }
11110b57cec5SDimitry Andric   }
11120b57cec5SDimitry Andric 
11130b57cec5SDimitry Andric }
11140b57cec5SDimitry Andric 
1115bdd1243dSDimitry Andric void Parser::DiagnoseLabelAtEndOfCompoundStatement() {
1116bdd1243dSDimitry Andric   if (getLangOpts().CPlusPlus) {
111706c3fb27SDimitry Andric     Diag(Tok, getLangOpts().CPlusPlus23
1118bdd1243dSDimitry Andric                   ? diag::warn_cxx20_compat_label_end_of_compound_statement
1119bdd1243dSDimitry Andric                   : diag::ext_cxx_label_end_of_compound_statement);
1120bdd1243dSDimitry Andric   } else {
11215f757f3fSDimitry Andric     Diag(Tok, getLangOpts().C23
11225f757f3fSDimitry Andric                   ? diag::warn_c23_compat_label_end_of_compound_statement
1123bdd1243dSDimitry Andric                   : diag::ext_c_label_end_of_compound_statement);
1124bdd1243dSDimitry Andric   }
1125bdd1243dSDimitry Andric }
1126bdd1243dSDimitry Andric 
11270b57cec5SDimitry Andric /// Consume any extra semi-colons resulting in null statements,
11280b57cec5SDimitry Andric /// returning true if any tok::semi were consumed.
11290b57cec5SDimitry Andric bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
11300b57cec5SDimitry Andric   if (!Tok.is(tok::semi))
11310b57cec5SDimitry Andric     return false;
11320b57cec5SDimitry Andric 
11330b57cec5SDimitry Andric   SourceLocation StartLoc = Tok.getLocation();
11340b57cec5SDimitry Andric   SourceLocation EndLoc;
11350b57cec5SDimitry Andric 
11360b57cec5SDimitry Andric   while (Tok.is(tok::semi) && !Tok.hasLeadingEmptyMacro() &&
11370b57cec5SDimitry Andric          Tok.getLocation().isValid() && !Tok.getLocation().isMacroID()) {
11380b57cec5SDimitry Andric     EndLoc = Tok.getLocation();
11390b57cec5SDimitry Andric 
11400b57cec5SDimitry Andric     // Don't just ConsumeToken() this tok::semi, do store it in AST.
11410b57cec5SDimitry Andric     StmtResult R =
11420b57cec5SDimitry Andric         ParseStatementOrDeclaration(Stmts, ParsedStmtContext::SubStmt);
11430b57cec5SDimitry Andric     if (R.isUsable())
11440b57cec5SDimitry Andric       Stmts.push_back(R.get());
11450b57cec5SDimitry Andric   }
11460b57cec5SDimitry Andric 
11470b57cec5SDimitry Andric   // Did not consume any extra semi.
11480b57cec5SDimitry Andric   if (EndLoc.isInvalid())
11490b57cec5SDimitry Andric     return false;
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric   Diag(StartLoc, diag::warn_null_statement)
11520b57cec5SDimitry Andric       << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc));
11530b57cec5SDimitry Andric   return true;
11540b57cec5SDimitry Andric }
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric StmtResult Parser::handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx) {
11570b57cec5SDimitry Andric   bool IsStmtExprResult = false;
11580b57cec5SDimitry Andric   if ((StmtCtx & ParsedStmtContext::InStmtExpr) != ParsedStmtContext()) {
11590b57cec5SDimitry Andric     // For GCC compatibility we skip past NullStmts.
11600b57cec5SDimitry Andric     unsigned LookAhead = 0;
11610b57cec5SDimitry Andric     while (GetLookAheadToken(LookAhead).is(tok::semi)) {
11620b57cec5SDimitry Andric       ++LookAhead;
11630b57cec5SDimitry Andric     }
11640b57cec5SDimitry Andric     // Then look to see if the next two tokens close the statement expression;
116506c3fb27SDimitry Andric     // if so, this expression statement is the last statement in a statement
11660b57cec5SDimitry Andric     // expression.
11670b57cec5SDimitry Andric     IsStmtExprResult = GetLookAheadToken(LookAhead).is(tok::r_brace) &&
11680b57cec5SDimitry Andric                        GetLookAheadToken(LookAhead + 1).is(tok::r_paren);
11690b57cec5SDimitry Andric   }
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric   if (IsStmtExprResult)
11720b57cec5SDimitry Andric     E = Actions.ActOnStmtExprResult(E);
11730b57cec5SDimitry Andric   return Actions.ActOnExprStmt(E, /*DiscardedValue=*/!IsStmtExprResult);
11740b57cec5SDimitry Andric }
11750b57cec5SDimitry Andric 
1176bdd1243dSDimitry Andric /// ParseCompoundStatementBody - Parse a sequence of statements optionally
1177bdd1243dSDimitry Andric /// followed by a label and invoke the ActOnCompoundStmt action.  This expects
1178bdd1243dSDimitry Andric /// the '{' to be the current token, and consume the '}' at the end of the
1179bdd1243dSDimitry Andric /// block.  It does not manipulate the scope stack.
11800b57cec5SDimitry Andric StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
11810b57cec5SDimitry Andric   PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
11820b57cec5SDimitry Andric                                 Tok.getLocation(),
11830b57cec5SDimitry Andric                                 "in compound statement ('{}')");
11840b57cec5SDimitry Andric 
1185e8d8bef9SDimitry Andric   // Record the current FPFeatures, restore on leaving the
11860b57cec5SDimitry Andric   // compound statement.
1187e8d8bef9SDimitry Andric   Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
11880b57cec5SDimitry Andric 
11890b57cec5SDimitry Andric   InMessageExpressionRAIIObject InMessage(*this, false);
11900b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_brace);
11910b57cec5SDimitry Andric   if (T.consumeOpen())
11920b57cec5SDimitry Andric     return StmtError();
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric   Sema::CompoundScopeRAII CompoundScope(Actions, isStmtExpr);
11950b57cec5SDimitry Andric 
11960b57cec5SDimitry Andric   // Parse any pragmas at the beginning of the compound statement.
11970b57cec5SDimitry Andric   ParseCompoundStatementLeadingPragmas();
1198e8d8bef9SDimitry Andric   Actions.ActOnAfterCompoundStatementLeadingPragmas();
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric   StmtVector Stmts;
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric   // "__label__ X, Y, Z;" is the GNU "Local Label" extension.  These are
12030b57cec5SDimitry Andric   // only allowed at the start of a compound stmt regardless of the language.
12040b57cec5SDimitry Andric   while (Tok.is(tok::kw___label__)) {
12050b57cec5SDimitry Andric     SourceLocation LabelLoc = ConsumeToken();
12060b57cec5SDimitry Andric 
12070b57cec5SDimitry Andric     SmallVector<Decl *, 8> DeclsInGroup;
120804eeddc0SDimitry Andric     while (true) {
12090b57cec5SDimitry Andric       if (Tok.isNot(tok::identifier)) {
12100b57cec5SDimitry Andric         Diag(Tok, diag::err_expected) << tok::identifier;
12110b57cec5SDimitry Andric         break;
12120b57cec5SDimitry Andric       }
12130b57cec5SDimitry Andric 
12140b57cec5SDimitry Andric       IdentifierInfo *II = Tok.getIdentifierInfo();
12150b57cec5SDimitry Andric       SourceLocation IdLoc = ConsumeToken();
12160b57cec5SDimitry Andric       DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc));
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric       if (!TryConsumeToken(tok::comma))
12190b57cec5SDimitry Andric         break;
12200b57cec5SDimitry Andric     }
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric     DeclSpec DS(AttrFactory);
12230b57cec5SDimitry Andric     DeclGroupPtrTy Res =
12240b57cec5SDimitry Andric         Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
12250b57cec5SDimitry Andric     StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation());
12260b57cec5SDimitry Andric 
12270b57cec5SDimitry Andric     ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
12280b57cec5SDimitry Andric     if (R.isUsable())
12290b57cec5SDimitry Andric       Stmts.push_back(R.get());
12300b57cec5SDimitry Andric   }
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric   ParsedStmtContext SubStmtCtx =
12330b57cec5SDimitry Andric       ParsedStmtContext::Compound |
12340b57cec5SDimitry Andric       (isStmtExpr ? ParsedStmtContext::InStmtExpr : ParsedStmtContext());
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric   while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
12370b57cec5SDimitry Andric          Tok.isNot(tok::eof)) {
12380b57cec5SDimitry Andric     if (Tok.is(tok::annot_pragma_unused)) {
12390b57cec5SDimitry Andric       HandlePragmaUnused();
12400b57cec5SDimitry Andric       continue;
12410b57cec5SDimitry Andric     }
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric     if (ConsumeNullStmt(Stmts))
12440b57cec5SDimitry Andric       continue;
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric     StmtResult R;
12470b57cec5SDimitry Andric     if (Tok.isNot(tok::kw___extension__)) {
12480b57cec5SDimitry Andric       R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
12490b57cec5SDimitry Andric     } else {
12500b57cec5SDimitry Andric       // __extension__ can start declarations and it can also be a unary
12510b57cec5SDimitry Andric       // operator for expressions.  Consume multiple __extension__ markers here
12520b57cec5SDimitry Andric       // until we can determine which is which.
12530b57cec5SDimitry Andric       // FIXME: This loses extension expressions in the AST!
12540b57cec5SDimitry Andric       SourceLocation ExtLoc = ConsumeToken();
12550b57cec5SDimitry Andric       while (Tok.is(tok::kw___extension__))
12560b57cec5SDimitry Andric         ConsumeToken();
12570b57cec5SDimitry Andric 
125881ad6265SDimitry Andric       ParsedAttributes attrs(AttrFactory);
125981ad6265SDimitry Andric       MaybeParseCXX11Attributes(attrs, /*MightBeObjCMessageSend*/ true);
12600b57cec5SDimitry Andric 
12610b57cec5SDimitry Andric       // If this is the start of a declaration, parse it as such.
12620b57cec5SDimitry Andric       if (isDeclarationStatement()) {
12630b57cec5SDimitry Andric         // __extension__ silences extension warnings in the subdeclaration.
12640b57cec5SDimitry Andric         // FIXME: Save the __extension__ on the decl as a node somehow?
12650b57cec5SDimitry Andric         ExtensionRAIIObject O(Diags);
12660b57cec5SDimitry Andric 
12670b57cec5SDimitry Andric         SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
126881ad6265SDimitry Andric         ParsedAttributes DeclSpecAttrs(AttrFactory);
126981ad6265SDimitry Andric         DeclGroupPtrTy Res = ParseDeclaration(DeclaratorContext::Block, DeclEnd,
127081ad6265SDimitry Andric                                               attrs, DeclSpecAttrs);
12710b57cec5SDimitry Andric         R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
12720b57cec5SDimitry Andric       } else {
12730b57cec5SDimitry Andric         // Otherwise this was a unary __extension__ marker.
12740b57cec5SDimitry Andric         ExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
12750b57cec5SDimitry Andric 
12760b57cec5SDimitry Andric         if (Res.isInvalid()) {
12770b57cec5SDimitry Andric           SkipUntil(tok::semi);
12780b57cec5SDimitry Andric           continue;
12790b57cec5SDimitry Andric         }
12800b57cec5SDimitry Andric 
12810b57cec5SDimitry Andric         // Eat the semicolon at the end of stmt and convert the expr into a
12820b57cec5SDimitry Andric         // statement.
12830b57cec5SDimitry Andric         ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
12840b57cec5SDimitry Andric         R = handleExprStmt(Res, SubStmtCtx);
12850b57cec5SDimitry Andric         if (R.isUsable())
1286fe6060f1SDimitry Andric           R = Actions.ActOnAttributedStmt(attrs, R.get());
12870b57cec5SDimitry Andric       }
12880b57cec5SDimitry Andric     }
12890b57cec5SDimitry Andric 
12900b57cec5SDimitry Andric     if (R.isUsable())
12910b57cec5SDimitry Andric       Stmts.push_back(R.get());
12920b57cec5SDimitry Andric   }
129381ad6265SDimitry Andric   // Warn the user that using option `-ffp-eval-method=source` on a
129481ad6265SDimitry Andric   // 32-bit target and feature `sse` disabled, or using
129581ad6265SDimitry Andric   // `pragma clang fp eval_method=source` and feature `sse` disabled, is not
129681ad6265SDimitry Andric   // supported.
129781ad6265SDimitry Andric   if (!PP.getTargetInfo().supportSourceEvalMethod() &&
129881ad6265SDimitry Andric       (PP.getLastFPEvalPragmaLocation().isValid() ||
129981ad6265SDimitry Andric        PP.getCurrentFPEvalMethod() ==
130081ad6265SDimitry Andric            LangOptions::FPEvalMethodKind::FEM_Source))
130181ad6265SDimitry Andric     Diag(Tok.getLocation(),
130281ad6265SDimitry Andric          diag::warn_no_support_for_eval_method_source_on_m32);
13030b57cec5SDimitry Andric 
13040b57cec5SDimitry Andric   SourceLocation CloseLoc = Tok.getLocation();
13050b57cec5SDimitry Andric 
13060b57cec5SDimitry Andric   // We broke out of the while loop because we found a '}' or EOF.
1307e8d8bef9SDimitry Andric   if (!T.consumeClose()) {
1308e8d8bef9SDimitry Andric     // If this is the '})' of a statement expression, check that it's written
1309e8d8bef9SDimitry Andric     // in a sensible way.
1310e8d8bef9SDimitry Andric     if (isStmtExpr && Tok.is(tok::r_paren))
1311e8d8bef9SDimitry Andric       checkCompoundToken(CloseLoc, tok::r_brace, CompoundToken::StmtExprEnd);
1312e8d8bef9SDimitry Andric   } else {
13130b57cec5SDimitry Andric     // Recover by creating a compound statement with what we parsed so far,
1314e8d8bef9SDimitry Andric     // instead of dropping everything and returning StmtError().
1315e8d8bef9SDimitry Andric   }
1316e8d8bef9SDimitry Andric 
1317e8d8bef9SDimitry Andric   if (T.getCloseLocation().isValid())
13180b57cec5SDimitry Andric     CloseLoc = T.getCloseLocation();
13190b57cec5SDimitry Andric 
13200b57cec5SDimitry Andric   return Actions.ActOnCompoundStmt(T.getOpenLocation(), CloseLoc,
13210b57cec5SDimitry Andric                                    Stmts, isStmtExpr);
13220b57cec5SDimitry Andric }
13230b57cec5SDimitry Andric 
13240b57cec5SDimitry Andric /// ParseParenExprOrCondition:
13250b57cec5SDimitry Andric /// [C  ]     '(' expression ')'
13260b57cec5SDimitry Andric /// [C++]     '(' condition ')'
13270b57cec5SDimitry Andric /// [C++1z]   '(' init-statement[opt] condition ')'
13280b57cec5SDimitry Andric ///
13290b57cec5SDimitry Andric /// This function parses and performs error recovery on the specified condition
13300b57cec5SDimitry Andric /// or expression (depending on whether we're in C++ or C mode).  This function
13310b57cec5SDimitry Andric /// goes out of its way to recover well.  It returns true if there was a parser
13320b57cec5SDimitry Andric /// error (the right paren couldn't be found), which indicates that the caller
13330b57cec5SDimitry Andric /// should try to recover harder.  It returns false if the condition is
13340b57cec5SDimitry Andric /// successfully parsed.  Note that a successful parse can still have semantic
13350b57cec5SDimitry Andric /// errors in the condition.
1336bdd1243dSDimitry Andric /// Additionally, it will assign the location of the outer-most '(' and ')',
1337bdd1243dSDimitry Andric /// to LParenLoc and RParenLoc, respectively.
13380b57cec5SDimitry Andric bool Parser::ParseParenExprOrCondition(StmtResult *InitStmt,
13390b57cec5SDimitry Andric                                        Sema::ConditionResult &Cond,
13400b57cec5SDimitry Andric                                        SourceLocation Loc,
1341bdd1243dSDimitry Andric                                        Sema::ConditionKind CK,
1342bdd1243dSDimitry Andric                                        SourceLocation &LParenLoc,
1343bdd1243dSDimitry Andric                                        SourceLocation &RParenLoc) {
13440b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren);
13450b57cec5SDimitry Andric   T.consumeOpen();
134604eeddc0SDimitry Andric   SourceLocation Start = Tok.getLocation();
13470b57cec5SDimitry Andric 
134804eeddc0SDimitry Andric   if (getLangOpts().CPlusPlus) {
1349bdd1243dSDimitry Andric     Cond = ParseCXXCondition(InitStmt, Loc, CK, false);
135004eeddc0SDimitry Andric   } else {
13510b57cec5SDimitry Andric     ExprResult CondExpr = ParseExpression();
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric     // If required, convert to a boolean value.
13540b57cec5SDimitry Andric     if (CondExpr.isInvalid())
13550b57cec5SDimitry Andric       Cond = Sema::ConditionError();
13560b57cec5SDimitry Andric     else
135704eeddc0SDimitry Andric       Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK,
1358bdd1243dSDimitry Andric                                     /*MissingOK=*/false);
13590b57cec5SDimitry Andric   }
13600b57cec5SDimitry Andric 
13610b57cec5SDimitry Andric   // If the parser was confused by the condition and we don't have a ')', try to
13620b57cec5SDimitry Andric   // recover by skipping ahead to a semi and bailing out.  If condexp is
13630b57cec5SDimitry Andric   // semantically invalid but we have well formed code, keep going.
13640b57cec5SDimitry Andric   if (Cond.isInvalid() && Tok.isNot(tok::r_paren)) {
13650b57cec5SDimitry Andric     SkipUntil(tok::semi);
13660b57cec5SDimitry Andric     // Skipping may have stopped if it found the containing ')'.  If so, we can
13670b57cec5SDimitry Andric     // continue parsing the if statement.
13680b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren))
13690b57cec5SDimitry Andric       return true;
13700b57cec5SDimitry Andric   }
13710b57cec5SDimitry Andric 
137204eeddc0SDimitry Andric   if (Cond.isInvalid()) {
137304eeddc0SDimitry Andric     ExprResult CondExpr = Actions.CreateRecoveryExpr(
137404eeddc0SDimitry Andric         Start, Tok.getLocation() == Start ? Start : PrevTokLocation, {},
137504eeddc0SDimitry Andric         Actions.PreferredConditionType(CK));
137604eeddc0SDimitry Andric     if (!CondExpr.isInvalid())
137704eeddc0SDimitry Andric       Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK,
1378bdd1243dSDimitry Andric                                     /*MissingOK=*/false);
137904eeddc0SDimitry Andric   }
138004eeddc0SDimitry Andric 
138104eeddc0SDimitry Andric   // Either the condition is valid or the rparen is present.
13820b57cec5SDimitry Andric   T.consumeClose();
1383bdd1243dSDimitry Andric   LParenLoc = T.getOpenLocation();
1384bdd1243dSDimitry Andric   RParenLoc = T.getCloseLocation();
13855ffd83dbSDimitry Andric 
13860b57cec5SDimitry Andric   // Check for extraneous ')'s to catch things like "if (foo())) {".  We know
13870b57cec5SDimitry Andric   // that all callers are looking for a statement after the condition, so ")"
13880b57cec5SDimitry Andric   // isn't valid.
13890b57cec5SDimitry Andric   while (Tok.is(tok::r_paren)) {
13900b57cec5SDimitry Andric     Diag(Tok, diag::err_extraneous_rparen_in_condition)
13910b57cec5SDimitry Andric       << FixItHint::CreateRemoval(Tok.getLocation());
13920b57cec5SDimitry Andric     ConsumeParen();
13930b57cec5SDimitry Andric   }
13940b57cec5SDimitry Andric 
13950b57cec5SDimitry Andric   return false;
13960b57cec5SDimitry Andric }
13970b57cec5SDimitry Andric 
1398480093f4SDimitry Andric namespace {
1399480093f4SDimitry Andric 
1400480093f4SDimitry Andric enum MisleadingStatementKind { MSK_if, MSK_else, MSK_for, MSK_while };
1401480093f4SDimitry Andric 
1402480093f4SDimitry Andric struct MisleadingIndentationChecker {
1403480093f4SDimitry Andric   Parser &P;
1404480093f4SDimitry Andric   SourceLocation StmtLoc;
1405480093f4SDimitry Andric   SourceLocation PrevLoc;
1406480093f4SDimitry Andric   unsigned NumDirectives;
1407480093f4SDimitry Andric   MisleadingStatementKind Kind;
1408480093f4SDimitry Andric   bool ShouldSkip;
1409480093f4SDimitry Andric   MisleadingIndentationChecker(Parser &P, MisleadingStatementKind K,
1410480093f4SDimitry Andric                                SourceLocation SL)
1411480093f4SDimitry Andric       : P(P), StmtLoc(SL), PrevLoc(P.getCurToken().getLocation()),
1412480093f4SDimitry Andric         NumDirectives(P.getPreprocessor().getNumDirectives()), Kind(K),
1413480093f4SDimitry Andric         ShouldSkip(P.getCurToken().is(tok::l_brace)) {
1414480093f4SDimitry Andric     if (!P.MisleadingIndentationElseLoc.isInvalid()) {
1415480093f4SDimitry Andric       StmtLoc = P.MisleadingIndentationElseLoc;
1416480093f4SDimitry Andric       P.MisleadingIndentationElseLoc = SourceLocation();
1417480093f4SDimitry Andric     }
1418480093f4SDimitry Andric     if (Kind == MSK_else && !ShouldSkip)
1419480093f4SDimitry Andric       P.MisleadingIndentationElseLoc = SL;
1420480093f4SDimitry Andric   }
1421480093f4SDimitry Andric 
1422480093f4SDimitry Andric   /// Compute the column number will aligning tabs on TabStop (-ftabstop), this
1423480093f4SDimitry Andric   /// gives the visual indentation of the SourceLocation.
1424480093f4SDimitry Andric   static unsigned getVisualIndentation(SourceManager &SM, SourceLocation Loc) {
1425480093f4SDimitry Andric     unsigned TabStop = SM.getDiagnostics().getDiagnosticOptions().TabStop;
1426480093f4SDimitry Andric 
1427480093f4SDimitry Andric     unsigned ColNo = SM.getSpellingColumnNumber(Loc);
1428480093f4SDimitry Andric     if (ColNo == 0 || TabStop == 1)
1429480093f4SDimitry Andric       return ColNo;
1430480093f4SDimitry Andric 
1431480093f4SDimitry Andric     std::pair<FileID, unsigned> FIDAndOffset = SM.getDecomposedLoc(Loc);
1432480093f4SDimitry Andric 
1433480093f4SDimitry Andric     bool Invalid;
1434480093f4SDimitry Andric     StringRef BufData = SM.getBufferData(FIDAndOffset.first, &Invalid);
1435480093f4SDimitry Andric     if (Invalid)
1436480093f4SDimitry Andric       return 0;
1437480093f4SDimitry Andric 
1438480093f4SDimitry Andric     const char *EndPos = BufData.data() + FIDAndOffset.second;
1439480093f4SDimitry Andric     // FileOffset are 0-based and Column numbers are 1-based
1440480093f4SDimitry Andric     assert(FIDAndOffset.second + 1 >= ColNo &&
1441480093f4SDimitry Andric            "Column number smaller than file offset?");
1442480093f4SDimitry Andric 
1443480093f4SDimitry Andric     unsigned VisualColumn = 0; // Stored as 0-based column, here.
1444480093f4SDimitry Andric     // Loop from beginning of line up to Loc's file position, counting columns,
1445480093f4SDimitry Andric     // expanding tabs.
1446480093f4SDimitry Andric     for (const char *CurPos = EndPos - (ColNo - 1); CurPos != EndPos;
1447480093f4SDimitry Andric          ++CurPos) {
1448480093f4SDimitry Andric       if (*CurPos == '\t')
1449480093f4SDimitry Andric         // Advance visual column to next tabstop.
1450480093f4SDimitry Andric         VisualColumn += (TabStop - VisualColumn % TabStop);
1451480093f4SDimitry Andric       else
1452480093f4SDimitry Andric         VisualColumn++;
1453480093f4SDimitry Andric     }
1454480093f4SDimitry Andric     return VisualColumn + 1;
1455480093f4SDimitry Andric   }
1456480093f4SDimitry Andric 
1457480093f4SDimitry Andric   void Check() {
1458480093f4SDimitry Andric     Token Tok = P.getCurToken();
1459480093f4SDimitry Andric     if (P.getActions().getDiagnostics().isIgnored(
1460480093f4SDimitry Andric             diag::warn_misleading_indentation, Tok.getLocation()) ||
1461480093f4SDimitry Andric         ShouldSkip || NumDirectives != P.getPreprocessor().getNumDirectives() ||
1462480093f4SDimitry Andric         Tok.isOneOf(tok::semi, tok::r_brace) || Tok.isAnnotation() ||
1463480093f4SDimitry Andric         Tok.getLocation().isMacroID() || PrevLoc.isMacroID() ||
1464480093f4SDimitry Andric         StmtLoc.isMacroID() ||
1465480093f4SDimitry Andric         (Kind == MSK_else && P.MisleadingIndentationElseLoc.isInvalid())) {
1466480093f4SDimitry Andric       P.MisleadingIndentationElseLoc = SourceLocation();
1467480093f4SDimitry Andric       return;
1468480093f4SDimitry Andric     }
1469480093f4SDimitry Andric     if (Kind == MSK_else)
1470480093f4SDimitry Andric       P.MisleadingIndentationElseLoc = SourceLocation();
1471480093f4SDimitry Andric 
1472480093f4SDimitry Andric     SourceManager &SM = P.getPreprocessor().getSourceManager();
1473480093f4SDimitry Andric     unsigned PrevColNum = getVisualIndentation(SM, PrevLoc);
1474480093f4SDimitry Andric     unsigned CurColNum = getVisualIndentation(SM, Tok.getLocation());
1475480093f4SDimitry Andric     unsigned StmtColNum = getVisualIndentation(SM, StmtLoc);
1476480093f4SDimitry Andric 
1477480093f4SDimitry Andric     if (PrevColNum != 0 && CurColNum != 0 && StmtColNum != 0 &&
1478480093f4SDimitry Andric         ((PrevColNum > StmtColNum && PrevColNum == CurColNum) ||
1479480093f4SDimitry Andric          !Tok.isAtStartOfLine()) &&
1480480093f4SDimitry Andric         SM.getPresumedLineNumber(StmtLoc) !=
1481480093f4SDimitry Andric             SM.getPresumedLineNumber(Tok.getLocation()) &&
1482480093f4SDimitry Andric         (Tok.isNot(tok::identifier) ||
1483480093f4SDimitry Andric          P.getPreprocessor().LookAhead(0).isNot(tok::colon))) {
1484480093f4SDimitry Andric       P.Diag(Tok.getLocation(), diag::warn_misleading_indentation) << Kind;
1485480093f4SDimitry Andric       P.Diag(StmtLoc, diag::note_previous_statement);
1486480093f4SDimitry Andric     }
1487480093f4SDimitry Andric   }
1488480093f4SDimitry Andric };
1489480093f4SDimitry Andric 
1490480093f4SDimitry Andric }
14910b57cec5SDimitry Andric 
14920b57cec5SDimitry Andric /// ParseIfStatement
14930b57cec5SDimitry Andric ///       if-statement: [C99 6.8.4.1]
14940b57cec5SDimitry Andric ///         'if' '(' expression ')' statement
14950b57cec5SDimitry Andric ///         'if' '(' expression ')' statement 'else' statement
14960b57cec5SDimitry Andric /// [C++]   'if' '(' condition ')' statement
14970b57cec5SDimitry Andric /// [C++]   'if' '(' condition ')' statement 'else' statement
1498349cc55cSDimitry Andric /// [C++23] 'if' '!' [opt] consteval compound-statement
1499349cc55cSDimitry Andric /// [C++23] 'if' '!' [opt] consteval compound-statement 'else' statement
15000b57cec5SDimitry Andric ///
15010b57cec5SDimitry Andric StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
15020b57cec5SDimitry Andric   assert(Tok.is(tok::kw_if) && "Not an if stmt!");
15030b57cec5SDimitry Andric   SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
15040b57cec5SDimitry Andric 
15050b57cec5SDimitry Andric   bool IsConstexpr = false;
1506349cc55cSDimitry Andric   bool IsConsteval = false;
1507349cc55cSDimitry Andric   SourceLocation NotLocation;
1508349cc55cSDimitry Andric   SourceLocation ConstevalLoc;
1509349cc55cSDimitry Andric 
15100b57cec5SDimitry Andric   if (Tok.is(tok::kw_constexpr)) {
1511*d686ce93SDimitry Andric     // C23 supports constexpr keyword, but only for object definitions.
1512*d686ce93SDimitry Andric     if (getLangOpts().CPlusPlus) {
15130b57cec5SDimitry Andric       Diag(Tok, getLangOpts().CPlusPlus17 ? diag::warn_cxx14_compat_constexpr_if
15140b57cec5SDimitry Andric                                           : diag::ext_constexpr_if);
15150b57cec5SDimitry Andric       IsConstexpr = true;
15160b57cec5SDimitry Andric       ConsumeToken();
1517*d686ce93SDimitry Andric     }
1518349cc55cSDimitry Andric   } else {
1519349cc55cSDimitry Andric     if (Tok.is(tok::exclaim)) {
1520349cc55cSDimitry Andric       NotLocation = ConsumeToken();
15210b57cec5SDimitry Andric     }
15220b57cec5SDimitry Andric 
1523349cc55cSDimitry Andric     if (Tok.is(tok::kw_consteval)) {
152406c3fb27SDimitry Andric       Diag(Tok, getLangOpts().CPlusPlus23 ? diag::warn_cxx20_compat_consteval_if
1525349cc55cSDimitry Andric                                           : diag::ext_consteval_if);
1526349cc55cSDimitry Andric       IsConsteval = true;
1527349cc55cSDimitry Andric       ConstevalLoc = ConsumeToken();
1528349cc55cSDimitry Andric     }
1529349cc55cSDimitry Andric   }
1530349cc55cSDimitry Andric   if (!IsConsteval && (NotLocation.isValid() || Tok.isNot(tok::l_paren))) {
15310b57cec5SDimitry Andric     Diag(Tok, diag::err_expected_lparen_after) << "if";
15320b57cec5SDimitry Andric     SkipUntil(tok::semi);
15330b57cec5SDimitry Andric     return StmtError();
15340b57cec5SDimitry Andric   }
15350b57cec5SDimitry Andric 
15360b57cec5SDimitry Andric   bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
15370b57cec5SDimitry Andric 
15380b57cec5SDimitry Andric   // C99 6.8.4p3 - In C99, the if statement is a block.  This is not
15390b57cec5SDimitry Andric   // the case for C90.
15400b57cec5SDimitry Andric   //
15410b57cec5SDimitry Andric   // C++ 6.4p3:
15420b57cec5SDimitry Andric   // A name introduced by a declaration in a condition is in scope from its
15430b57cec5SDimitry Andric   // point of declaration until the end of the substatements controlled by the
15440b57cec5SDimitry Andric   // condition.
15450b57cec5SDimitry Andric   // C++ 3.3.2p4:
15460b57cec5SDimitry Andric   // Names declared in the for-init-statement, and in the condition of if,
15470b57cec5SDimitry Andric   // while, for, and switch statements are local to the if, while, for, or
15480b57cec5SDimitry Andric   // switch statement (including the controlled statement).
15490b57cec5SDimitry Andric   //
15500b57cec5SDimitry Andric   ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
15510b57cec5SDimitry Andric 
15520b57cec5SDimitry Andric   // Parse the condition.
15530b57cec5SDimitry Andric   StmtResult InitStmt;
15540b57cec5SDimitry Andric   Sema::ConditionResult Cond;
1555e8d8bef9SDimitry Andric   SourceLocation LParen;
1556e8d8bef9SDimitry Andric   SourceLocation RParen;
1557bdd1243dSDimitry Andric   std::optional<bool> ConstexprCondition;
1558349cc55cSDimitry Andric   if (!IsConsteval) {
1559349cc55cSDimitry Andric 
15600b57cec5SDimitry Andric     if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc,
15610b57cec5SDimitry Andric                                   IsConstexpr ? Sema::ConditionKind::ConstexprIf
1562e8d8bef9SDimitry Andric                                               : Sema::ConditionKind::Boolean,
1563bdd1243dSDimitry Andric                                   LParen, RParen))
15640b57cec5SDimitry Andric       return StmtError();
15650b57cec5SDimitry Andric 
15660b57cec5SDimitry Andric     if (IsConstexpr)
15670b57cec5SDimitry Andric       ConstexprCondition = Cond.getKnownValue();
1568349cc55cSDimitry Andric   }
15690b57cec5SDimitry Andric 
15705ffd83dbSDimitry Andric   bool IsBracedThen = Tok.is(tok::l_brace);
15715ffd83dbSDimitry Andric 
15720b57cec5SDimitry Andric   // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
15730b57cec5SDimitry Andric   // there is no compound stmt.  C90 does not have this clause.  We only do this
15740b57cec5SDimitry Andric   // if the body isn't a compound statement to avoid push/pop in common cases.
15750b57cec5SDimitry Andric   //
15760b57cec5SDimitry Andric   // C++ 6.4p1:
15770b57cec5SDimitry Andric   // The substatement in a selection-statement (each substatement, in the else
15780b57cec5SDimitry Andric   // form of the if statement) implicitly defines a local scope.
15790b57cec5SDimitry Andric   //
15800b57cec5SDimitry Andric   // For C++ we create a scope for the condition and a new scope for
15810b57cec5SDimitry Andric   // substatements because:
15820b57cec5SDimitry Andric   // -When the 'then' scope exits, we want the condition declaration to still be
15830b57cec5SDimitry Andric   //    active for the 'else' scope too.
15840b57cec5SDimitry Andric   // -Sema will detect name clashes by considering declarations of a
15850b57cec5SDimitry Andric   //    'ControlScope' as part of its direct subscope.
15860b57cec5SDimitry Andric   // -If we wanted the condition and substatement to be in the same scope, we
15870b57cec5SDimitry Andric   //    would have to notify ParseStatement not to create a new scope. It's
15880b57cec5SDimitry Andric   //    simpler to let it create a new scope.
15890b57cec5SDimitry Andric   //
15905ffd83dbSDimitry Andric   ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, IsBracedThen);
15910b57cec5SDimitry Andric 
1592480093f4SDimitry Andric   MisleadingIndentationChecker MIChecker(*this, MSK_if, IfLoc);
1593480093f4SDimitry Andric 
15940b57cec5SDimitry Andric   // Read the 'then' stmt.
15950b57cec5SDimitry Andric   SourceLocation ThenStmtLoc = Tok.getLocation();
15960b57cec5SDimitry Andric 
15970b57cec5SDimitry Andric   SourceLocation InnerStatementTrailingElseLoc;
15980b57cec5SDimitry Andric   StmtResult ThenStmt;
15990b57cec5SDimitry Andric   {
1600349cc55cSDimitry Andric     bool ShouldEnter = ConstexprCondition && !*ConstexprCondition;
1601349cc55cSDimitry Andric     Sema::ExpressionEvaluationContext Context =
1602349cc55cSDimitry Andric         Sema::ExpressionEvaluationContext::DiscardedStatement;
1603349cc55cSDimitry Andric     if (NotLocation.isInvalid() && IsConsteval) {
1604349cc55cSDimitry Andric       Context = Sema::ExpressionEvaluationContext::ImmediateFunctionContext;
1605349cc55cSDimitry Andric       ShouldEnter = true;
1606349cc55cSDimitry Andric     }
1607349cc55cSDimitry Andric 
16080b57cec5SDimitry Andric     EnterExpressionEvaluationContext PotentiallyDiscarded(
1609349cc55cSDimitry Andric         Actions, Context, nullptr,
1610349cc55cSDimitry Andric         Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
16110b57cec5SDimitry Andric     ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
16120b57cec5SDimitry Andric   }
16130b57cec5SDimitry Andric 
1614480093f4SDimitry Andric   if (Tok.isNot(tok::kw_else))
1615480093f4SDimitry Andric     MIChecker.Check();
1616480093f4SDimitry Andric 
16170b57cec5SDimitry Andric   // Pop the 'if' scope if needed.
16180b57cec5SDimitry Andric   InnerScope.Exit();
16190b57cec5SDimitry Andric 
16200b57cec5SDimitry Andric   // If it has an else, parse it.
16210b57cec5SDimitry Andric   SourceLocation ElseLoc;
16220b57cec5SDimitry Andric   SourceLocation ElseStmtLoc;
16230b57cec5SDimitry Andric   StmtResult ElseStmt;
16240b57cec5SDimitry Andric 
16250b57cec5SDimitry Andric   if (Tok.is(tok::kw_else)) {
16260b57cec5SDimitry Andric     if (TrailingElseLoc)
16270b57cec5SDimitry Andric       *TrailingElseLoc = Tok.getLocation();
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric     ElseLoc = ConsumeToken();
16300b57cec5SDimitry Andric     ElseStmtLoc = Tok.getLocation();
16310b57cec5SDimitry Andric 
16320b57cec5SDimitry Andric     // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
16330b57cec5SDimitry Andric     // there is no compound stmt.  C90 does not have this clause.  We only do
16340b57cec5SDimitry Andric     // this if the body isn't a compound statement to avoid push/pop in common
16350b57cec5SDimitry Andric     // cases.
16360b57cec5SDimitry Andric     //
16370b57cec5SDimitry Andric     // C++ 6.4p1:
16380b57cec5SDimitry Andric     // The substatement in a selection-statement (each substatement, in the else
16390b57cec5SDimitry Andric     // form of the if statement) implicitly defines a local scope.
16400b57cec5SDimitry Andric     //
16410b57cec5SDimitry Andric     ParseScope InnerScope(this, Scope::DeclScope, C99orCXX,
16420b57cec5SDimitry Andric                           Tok.is(tok::l_brace));
16430b57cec5SDimitry Andric 
1644480093f4SDimitry Andric     MisleadingIndentationChecker MIChecker(*this, MSK_else, ElseLoc);
1645349cc55cSDimitry Andric     bool ShouldEnter = ConstexprCondition && *ConstexprCondition;
1646349cc55cSDimitry Andric     Sema::ExpressionEvaluationContext Context =
1647349cc55cSDimitry Andric         Sema::ExpressionEvaluationContext::DiscardedStatement;
1648349cc55cSDimitry Andric     if (NotLocation.isValid() && IsConsteval) {
1649349cc55cSDimitry Andric       Context = Sema::ExpressionEvaluationContext::ImmediateFunctionContext;
1650349cc55cSDimitry Andric       ShouldEnter = true;
1651349cc55cSDimitry Andric     }
1652480093f4SDimitry Andric 
16530b57cec5SDimitry Andric     EnterExpressionEvaluationContext PotentiallyDiscarded(
1654349cc55cSDimitry Andric         Actions, Context, nullptr,
1655349cc55cSDimitry Andric         Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
16560b57cec5SDimitry Andric     ElseStmt = ParseStatement();
16570b57cec5SDimitry Andric 
1658480093f4SDimitry Andric     if (ElseStmt.isUsable())
1659480093f4SDimitry Andric       MIChecker.Check();
1660480093f4SDimitry Andric 
16610b57cec5SDimitry Andric     // Pop the 'else' scope if needed.
16620b57cec5SDimitry Andric     InnerScope.Exit();
16630b57cec5SDimitry Andric   } else if (Tok.is(tok::code_completion)) {
16640b57cec5SDimitry Andric     cutOffParsing();
16650fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteAfterIf(getCurScope(), IsBracedThen);
16660b57cec5SDimitry Andric     return StmtError();
16670b57cec5SDimitry Andric   } else if (InnerStatementTrailingElseLoc.isValid()) {
16680b57cec5SDimitry Andric     Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else);
16690b57cec5SDimitry Andric   }
16700b57cec5SDimitry Andric 
16710b57cec5SDimitry Andric   IfScope.Exit();
16720b57cec5SDimitry Andric 
16730b57cec5SDimitry Andric   // If the then or else stmt is invalid and the other is valid (and present),
167406c3fb27SDimitry Andric   // turn the invalid one into a null stmt to avoid dropping the other
16750b57cec5SDimitry Andric   // part.  If both are invalid, return error.
16760b57cec5SDimitry Andric   if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
16770b57cec5SDimitry Andric       (ThenStmt.isInvalid() && ElseStmt.get() == nullptr) ||
16780b57cec5SDimitry Andric       (ThenStmt.get() == nullptr && ElseStmt.isInvalid())) {
16790b57cec5SDimitry Andric     // Both invalid, or one is invalid and other is non-present: return error.
16800b57cec5SDimitry Andric     return StmtError();
16810b57cec5SDimitry Andric   }
16820b57cec5SDimitry Andric 
1683349cc55cSDimitry Andric   if (IsConsteval) {
1684349cc55cSDimitry Andric     auto IsCompoundStatement = [](const Stmt *S) {
168506c3fb27SDimitry Andric       if (const auto *Outer = dyn_cast_if_present<AttributedStmt>(S))
1686349cc55cSDimitry Andric         S = Outer->getSubStmt();
1687349cc55cSDimitry Andric       return isa_and_nonnull<clang::CompoundStmt>(S);
1688349cc55cSDimitry Andric     };
1689349cc55cSDimitry Andric 
1690349cc55cSDimitry Andric     if (!IsCompoundStatement(ThenStmt.get())) {
1691349cc55cSDimitry Andric       Diag(ConstevalLoc, diag::err_expected_after) << "consteval"
1692349cc55cSDimitry Andric                                                    << "{";
1693349cc55cSDimitry Andric       return StmtError();
1694349cc55cSDimitry Andric     }
1695349cc55cSDimitry Andric     if (!ElseStmt.isUnset() && !IsCompoundStatement(ElseStmt.get())) {
1696349cc55cSDimitry Andric       Diag(ElseLoc, diag::err_expected_after) << "else"
1697349cc55cSDimitry Andric                                               << "{";
1698349cc55cSDimitry Andric       return StmtError();
1699349cc55cSDimitry Andric     }
1700349cc55cSDimitry Andric   }
1701349cc55cSDimitry Andric 
17020b57cec5SDimitry Andric   // Now if either are invalid, replace with a ';'.
17030b57cec5SDimitry Andric   if (ThenStmt.isInvalid())
17040b57cec5SDimitry Andric     ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
17050b57cec5SDimitry Andric   if (ElseStmt.isInvalid())
17060b57cec5SDimitry Andric     ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
17070b57cec5SDimitry Andric 
1708349cc55cSDimitry Andric   IfStatementKind Kind = IfStatementKind::Ordinary;
1709349cc55cSDimitry Andric   if (IsConstexpr)
1710349cc55cSDimitry Andric     Kind = IfStatementKind::Constexpr;
1711349cc55cSDimitry Andric   else if (IsConsteval)
1712349cc55cSDimitry Andric     Kind = NotLocation.isValid() ? IfStatementKind::ConstevalNegated
1713349cc55cSDimitry Andric                                  : IfStatementKind::ConstevalNonNegated;
1714349cc55cSDimitry Andric 
1715349cc55cSDimitry Andric   return Actions.ActOnIfStmt(IfLoc, Kind, LParen, InitStmt.get(), Cond, RParen,
1716349cc55cSDimitry Andric                              ThenStmt.get(), ElseLoc, ElseStmt.get());
17170b57cec5SDimitry Andric }
17180b57cec5SDimitry Andric 
17190b57cec5SDimitry Andric /// ParseSwitchStatement
17200b57cec5SDimitry Andric ///       switch-statement:
17210b57cec5SDimitry Andric ///         'switch' '(' expression ')' statement
17220b57cec5SDimitry Andric /// [C++]   'switch' '(' condition ')' statement
17230b57cec5SDimitry Andric StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
17240b57cec5SDimitry Andric   assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
17250b57cec5SDimitry Andric   SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
17260b57cec5SDimitry Andric 
17270b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
17280b57cec5SDimitry Andric     Diag(Tok, diag::err_expected_lparen_after) << "switch";
17290b57cec5SDimitry Andric     SkipUntil(tok::semi);
17300b57cec5SDimitry Andric     return StmtError();
17310b57cec5SDimitry Andric   }
17320b57cec5SDimitry Andric 
17330b57cec5SDimitry Andric   bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
17340b57cec5SDimitry Andric 
17350b57cec5SDimitry Andric   // C99 6.8.4p3 - In C99, the switch statement is a block.  This is
17360b57cec5SDimitry Andric   // not the case for C90.  Start the switch scope.
17370b57cec5SDimitry Andric   //
17380b57cec5SDimitry Andric   // C++ 6.4p3:
17390b57cec5SDimitry Andric   // A name introduced by a declaration in a condition is in scope from its
17400b57cec5SDimitry Andric   // point of declaration until the end of the substatements controlled by the
17410b57cec5SDimitry Andric   // condition.
17420b57cec5SDimitry Andric   // C++ 3.3.2p4:
17430b57cec5SDimitry Andric   // Names declared in the for-init-statement, and in the condition of if,
17440b57cec5SDimitry Andric   // while, for, and switch statements are local to the if, while, for, or
17450b57cec5SDimitry Andric   // switch statement (including the controlled statement).
17460b57cec5SDimitry Andric   //
17470b57cec5SDimitry Andric   unsigned ScopeFlags = Scope::SwitchScope;
17480b57cec5SDimitry Andric   if (C99orCXX)
17490b57cec5SDimitry Andric     ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
17500b57cec5SDimitry Andric   ParseScope SwitchScope(this, ScopeFlags);
17510b57cec5SDimitry Andric 
17520b57cec5SDimitry Andric   // Parse the condition.
17530b57cec5SDimitry Andric   StmtResult InitStmt;
17540b57cec5SDimitry Andric   Sema::ConditionResult Cond;
1755e8d8bef9SDimitry Andric   SourceLocation LParen;
1756e8d8bef9SDimitry Andric   SourceLocation RParen;
17570b57cec5SDimitry Andric   if (ParseParenExprOrCondition(&InitStmt, Cond, SwitchLoc,
1758bdd1243dSDimitry Andric                                 Sema::ConditionKind::Switch, LParen, RParen))
17590b57cec5SDimitry Andric     return StmtError();
17600b57cec5SDimitry Andric 
1761e8d8bef9SDimitry Andric   StmtResult Switch = Actions.ActOnStartOfSwitchStmt(
1762e8d8bef9SDimitry Andric       SwitchLoc, LParen, InitStmt.get(), Cond, RParen);
17630b57cec5SDimitry Andric 
17640b57cec5SDimitry Andric   if (Switch.isInvalid()) {
17650b57cec5SDimitry Andric     // Skip the switch body.
17660b57cec5SDimitry Andric     // FIXME: This is not optimal recovery, but parsing the body is more
17670b57cec5SDimitry Andric     // dangerous due to the presence of case and default statements, which
17680b57cec5SDimitry Andric     // will have no place to connect back with the switch.
17690b57cec5SDimitry Andric     if (Tok.is(tok::l_brace)) {
17700b57cec5SDimitry Andric       ConsumeBrace();
17710b57cec5SDimitry Andric       SkipUntil(tok::r_brace);
17720b57cec5SDimitry Andric     } else
17730b57cec5SDimitry Andric       SkipUntil(tok::semi);
17740b57cec5SDimitry Andric     return Switch;
17750b57cec5SDimitry Andric   }
17760b57cec5SDimitry Andric 
17770b57cec5SDimitry Andric   // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
17780b57cec5SDimitry Andric   // there is no compound stmt.  C90 does not have this clause.  We only do this
17790b57cec5SDimitry Andric   // if the body isn't a compound statement to avoid push/pop in common cases.
17800b57cec5SDimitry Andric   //
17810b57cec5SDimitry Andric   // C++ 6.4p1:
17820b57cec5SDimitry Andric   // The substatement in a selection-statement (each substatement, in the else
17830b57cec5SDimitry Andric   // form of the if statement) implicitly defines a local scope.
17840b57cec5SDimitry Andric   //
17850b57cec5SDimitry Andric   // See comments in ParseIfStatement for why we create a scope for the
17860b57cec5SDimitry Andric   // condition and a new scope for substatement in C++.
17870b57cec5SDimitry Andric   //
17880b57cec5SDimitry Andric   getCurScope()->AddFlags(Scope::BreakScope);
17890b57cec5SDimitry Andric   ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
17900b57cec5SDimitry Andric 
17910b57cec5SDimitry Andric   // We have incremented the mangling number for the SwitchScope and the
17920b57cec5SDimitry Andric   // InnerScope, which is one too many.
17930b57cec5SDimitry Andric   if (C99orCXX)
17940b57cec5SDimitry Andric     getCurScope()->decrementMSManglingNumber();
17950b57cec5SDimitry Andric 
17960b57cec5SDimitry Andric   // Read the body statement.
17970b57cec5SDimitry Andric   StmtResult Body(ParseStatement(TrailingElseLoc));
17980b57cec5SDimitry Andric 
17990b57cec5SDimitry Andric   // Pop the scopes.
18000b57cec5SDimitry Andric   InnerScope.Exit();
18010b57cec5SDimitry Andric   SwitchScope.Exit();
18020b57cec5SDimitry Andric 
18030b57cec5SDimitry Andric   return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get());
18040b57cec5SDimitry Andric }
18050b57cec5SDimitry Andric 
18060b57cec5SDimitry Andric /// ParseWhileStatement
18070b57cec5SDimitry Andric ///       while-statement: [C99 6.8.5.1]
18080b57cec5SDimitry Andric ///         'while' '(' expression ')' statement
18090b57cec5SDimitry Andric /// [C++]   'while' '(' condition ')' statement
18100b57cec5SDimitry Andric StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
18110b57cec5SDimitry Andric   assert(Tok.is(tok::kw_while) && "Not a while stmt!");
18120b57cec5SDimitry Andric   SourceLocation WhileLoc = Tok.getLocation();
18130b57cec5SDimitry Andric   ConsumeToken();  // eat the 'while'.
18140b57cec5SDimitry Andric 
18150b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
18160b57cec5SDimitry Andric     Diag(Tok, diag::err_expected_lparen_after) << "while";
18170b57cec5SDimitry Andric     SkipUntil(tok::semi);
18180b57cec5SDimitry Andric     return StmtError();
18190b57cec5SDimitry Andric   }
18200b57cec5SDimitry Andric 
18210b57cec5SDimitry Andric   bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
18220b57cec5SDimitry Andric 
18230b57cec5SDimitry Andric   // C99 6.8.5p5 - In C99, the while statement is a block.  This is not
18240b57cec5SDimitry Andric   // the case for C90.  Start the loop scope.
18250b57cec5SDimitry Andric   //
18260b57cec5SDimitry Andric   // C++ 6.4p3:
18270b57cec5SDimitry Andric   // A name introduced by a declaration in a condition is in scope from its
18280b57cec5SDimitry Andric   // point of declaration until the end of the substatements controlled by the
18290b57cec5SDimitry Andric   // condition.
18300b57cec5SDimitry Andric   // C++ 3.3.2p4:
18310b57cec5SDimitry Andric   // Names declared in the for-init-statement, and in the condition of if,
18320b57cec5SDimitry Andric   // while, for, and switch statements are local to the if, while, for, or
18330b57cec5SDimitry Andric   // switch statement (including the controlled statement).
18340b57cec5SDimitry Andric   //
18350b57cec5SDimitry Andric   unsigned ScopeFlags;
18360b57cec5SDimitry Andric   if (C99orCXX)
18370b57cec5SDimitry Andric     ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
18380b57cec5SDimitry Andric                  Scope::DeclScope  | Scope::ControlScope;
18390b57cec5SDimitry Andric   else
18400b57cec5SDimitry Andric     ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
18410b57cec5SDimitry Andric   ParseScope WhileScope(this, ScopeFlags);
18420b57cec5SDimitry Andric 
18430b57cec5SDimitry Andric   // Parse the condition.
18440b57cec5SDimitry Andric   Sema::ConditionResult Cond;
18455ffd83dbSDimitry Andric   SourceLocation LParen;
18465ffd83dbSDimitry Andric   SourceLocation RParen;
18470b57cec5SDimitry Andric   if (ParseParenExprOrCondition(nullptr, Cond, WhileLoc,
1848bdd1243dSDimitry Andric                                 Sema::ConditionKind::Boolean, LParen, RParen))
18490b57cec5SDimitry Andric     return StmtError();
18500b57cec5SDimitry Andric 
18510b57cec5SDimitry Andric   // C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if
18520b57cec5SDimitry Andric   // there is no compound stmt.  C90 does not have this clause.  We only do this
18530b57cec5SDimitry Andric   // if the body isn't a compound statement to avoid push/pop in common cases.
18540b57cec5SDimitry Andric   //
18550b57cec5SDimitry Andric   // C++ 6.5p2:
18560b57cec5SDimitry Andric   // The substatement in an iteration-statement implicitly defines a local scope
18570b57cec5SDimitry Andric   // which is entered and exited each time through the loop.
18580b57cec5SDimitry Andric   //
18590b57cec5SDimitry Andric   // See comments in ParseIfStatement for why we create a scope for the
18600b57cec5SDimitry Andric   // condition and a new scope for substatement in C++.
18610b57cec5SDimitry Andric   //
18620b57cec5SDimitry Andric   ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
18630b57cec5SDimitry Andric 
1864480093f4SDimitry Andric   MisleadingIndentationChecker MIChecker(*this, MSK_while, WhileLoc);
1865480093f4SDimitry Andric 
18660b57cec5SDimitry Andric   // Read the body statement.
18670b57cec5SDimitry Andric   StmtResult Body(ParseStatement(TrailingElseLoc));
18680b57cec5SDimitry Andric 
1869480093f4SDimitry Andric   if (Body.isUsable())
1870480093f4SDimitry Andric     MIChecker.Check();
18710b57cec5SDimitry Andric   // Pop the body scope if needed.
18720b57cec5SDimitry Andric   InnerScope.Exit();
18730b57cec5SDimitry Andric   WhileScope.Exit();
18740b57cec5SDimitry Andric 
18750b57cec5SDimitry Andric   if (Cond.isInvalid() || Body.isInvalid())
18760b57cec5SDimitry Andric     return StmtError();
18770b57cec5SDimitry Andric 
18785ffd83dbSDimitry Andric   return Actions.ActOnWhileStmt(WhileLoc, LParen, Cond, RParen, Body.get());
18790b57cec5SDimitry Andric }
18800b57cec5SDimitry Andric 
18810b57cec5SDimitry Andric /// ParseDoStatement
18820b57cec5SDimitry Andric ///       do-statement: [C99 6.8.5.2]
18830b57cec5SDimitry Andric ///         'do' statement 'while' '(' expression ')' ';'
18840b57cec5SDimitry Andric /// Note: this lets the caller parse the end ';'.
18850b57cec5SDimitry Andric StmtResult Parser::ParseDoStatement() {
18860b57cec5SDimitry Andric   assert(Tok.is(tok::kw_do) && "Not a do stmt!");
18870b57cec5SDimitry Andric   SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
18880b57cec5SDimitry Andric 
18890b57cec5SDimitry Andric   // C99 6.8.5p5 - In C99, the do statement is a block.  This is not
18900b57cec5SDimitry Andric   // the case for C90.  Start the loop scope.
18910b57cec5SDimitry Andric   unsigned ScopeFlags;
18920b57cec5SDimitry Andric   if (getLangOpts().C99)
18930b57cec5SDimitry Andric     ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
18940b57cec5SDimitry Andric   else
18950b57cec5SDimitry Andric     ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
18960b57cec5SDimitry Andric 
18970b57cec5SDimitry Andric   ParseScope DoScope(this, ScopeFlags);
18980b57cec5SDimitry Andric 
18990b57cec5SDimitry Andric   // C99 6.8.5p5 - In C99, the body of the do statement is a scope, even if
19000b57cec5SDimitry Andric   // there is no compound stmt.  C90 does not have this clause. We only do this
19010b57cec5SDimitry Andric   // if the body isn't a compound statement to avoid push/pop in common cases.
19020b57cec5SDimitry Andric   //
19030b57cec5SDimitry Andric   // C++ 6.5p2:
19040b57cec5SDimitry Andric   // The substatement in an iteration-statement implicitly defines a local scope
19050b57cec5SDimitry Andric   // which is entered and exited each time through the loop.
19060b57cec5SDimitry Andric   //
19070b57cec5SDimitry Andric   bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
19080b57cec5SDimitry Andric   ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
19090b57cec5SDimitry Andric 
19100b57cec5SDimitry Andric   // Read the body statement.
19110b57cec5SDimitry Andric   StmtResult Body(ParseStatement());
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric   // Pop the body scope if needed.
19140b57cec5SDimitry Andric   InnerScope.Exit();
19150b57cec5SDimitry Andric 
19160b57cec5SDimitry Andric   if (Tok.isNot(tok::kw_while)) {
19170b57cec5SDimitry Andric     if (!Body.isInvalid()) {
19180b57cec5SDimitry Andric       Diag(Tok, diag::err_expected_while);
19190b57cec5SDimitry Andric       Diag(DoLoc, diag::note_matching) << "'do'";
19200b57cec5SDimitry Andric       SkipUntil(tok::semi, StopBeforeMatch);
19210b57cec5SDimitry Andric     }
19220b57cec5SDimitry Andric     return StmtError();
19230b57cec5SDimitry Andric   }
19240b57cec5SDimitry Andric   SourceLocation WhileLoc = ConsumeToken();
19250b57cec5SDimitry Andric 
19260b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
19270b57cec5SDimitry Andric     Diag(Tok, diag::err_expected_lparen_after) << "do/while";
19280b57cec5SDimitry Andric     SkipUntil(tok::semi, StopBeforeMatch);
19290b57cec5SDimitry Andric     return StmtError();
19300b57cec5SDimitry Andric   }
19310b57cec5SDimitry Andric 
19320b57cec5SDimitry Andric   // Parse the parenthesized expression.
19330b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren);
19340b57cec5SDimitry Andric   T.consumeOpen();
19350b57cec5SDimitry Andric 
19360b57cec5SDimitry Andric   // A do-while expression is not a condition, so can't have attributes.
19370b57cec5SDimitry Andric   DiagnoseAndSkipCXX11Attributes();
19380b57cec5SDimitry Andric 
193904eeddc0SDimitry Andric   SourceLocation Start = Tok.getLocation();
19400b57cec5SDimitry Andric   ExprResult Cond = ParseExpression();
19410b57cec5SDimitry Andric   // Correct the typos in condition before closing the scope.
19420b57cec5SDimitry Andric   if (Cond.isUsable())
19435f757f3fSDimitry Andric     Cond = Actions.CorrectDelayedTyposInExpr(Cond, /*InitDecl=*/nullptr,
19445f757f3fSDimitry Andric                                              /*RecoverUncorrectedTypos=*/true);
194504eeddc0SDimitry Andric   else {
194604eeddc0SDimitry Andric     if (!Tok.isOneOf(tok::r_paren, tok::r_square, tok::r_brace))
194704eeddc0SDimitry Andric       SkipUntil(tok::semi);
194804eeddc0SDimitry Andric     Cond = Actions.CreateRecoveryExpr(
194904eeddc0SDimitry Andric         Start, Start == Tok.getLocation() ? Start : PrevTokLocation, {},
195004eeddc0SDimitry Andric         Actions.getASTContext().BoolTy);
195104eeddc0SDimitry Andric   }
19520b57cec5SDimitry Andric   T.consumeClose();
19530b57cec5SDimitry Andric   DoScope.Exit();
19540b57cec5SDimitry Andric 
19550b57cec5SDimitry Andric   if (Cond.isInvalid() || Body.isInvalid())
19560b57cec5SDimitry Andric     return StmtError();
19570b57cec5SDimitry Andric 
19580b57cec5SDimitry Andric   return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, T.getOpenLocation(),
19590b57cec5SDimitry Andric                              Cond.get(), T.getCloseLocation());
19600b57cec5SDimitry Andric }
19610b57cec5SDimitry Andric 
19620b57cec5SDimitry Andric bool Parser::isForRangeIdentifier() {
19630b57cec5SDimitry Andric   assert(Tok.is(tok::identifier));
19640b57cec5SDimitry Andric 
19650b57cec5SDimitry Andric   const Token &Next = NextToken();
19660b57cec5SDimitry Andric   if (Next.is(tok::colon))
19670b57cec5SDimitry Andric     return true;
19680b57cec5SDimitry Andric 
19690b57cec5SDimitry Andric   if (Next.isOneOf(tok::l_square, tok::kw_alignas)) {
19700b57cec5SDimitry Andric     TentativeParsingAction PA(*this);
19710b57cec5SDimitry Andric     ConsumeToken();
19720b57cec5SDimitry Andric     SkipCXX11Attributes();
19730b57cec5SDimitry Andric     bool Result = Tok.is(tok::colon);
19740b57cec5SDimitry Andric     PA.Revert();
19750b57cec5SDimitry Andric     return Result;
19760b57cec5SDimitry Andric   }
19770b57cec5SDimitry Andric 
19780b57cec5SDimitry Andric   return false;
19790b57cec5SDimitry Andric }
19800b57cec5SDimitry Andric 
19810b57cec5SDimitry Andric /// ParseForStatement
19820b57cec5SDimitry Andric ///       for-statement: [C99 6.8.5.3]
19830b57cec5SDimitry Andric ///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
19840b57cec5SDimitry Andric ///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
19850b57cec5SDimitry Andric /// [C++]   'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
19860b57cec5SDimitry Andric /// [C++]       statement
19870b57cec5SDimitry Andric /// [C++0x] 'for'
19880b57cec5SDimitry Andric ///             'co_await'[opt]    [Coroutines]
19890b57cec5SDimitry Andric ///             '(' for-range-declaration ':' for-range-initializer ')'
19900b57cec5SDimitry Andric ///             statement
19910b57cec5SDimitry Andric /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
19920b57cec5SDimitry Andric /// [OBJC2] 'for' '(' expr 'in' expr ')' statement
19930b57cec5SDimitry Andric ///
19940b57cec5SDimitry Andric /// [C++] for-init-statement:
19950b57cec5SDimitry Andric /// [C++]   expression-statement
19960b57cec5SDimitry Andric /// [C++]   simple-declaration
199706c3fb27SDimitry Andric /// [C++23] alias-declaration
19980b57cec5SDimitry Andric ///
19990b57cec5SDimitry Andric /// [C++0x] for-range-declaration:
20000b57cec5SDimitry Andric /// [C++0x]   attribute-specifier-seq[opt] type-specifier-seq declarator
20010b57cec5SDimitry Andric /// [C++0x] for-range-initializer:
20020b57cec5SDimitry Andric /// [C++0x]   expression
20030b57cec5SDimitry Andric /// [C++0x]   braced-init-list            [TODO]
20040b57cec5SDimitry Andric StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
20050b57cec5SDimitry Andric   assert(Tok.is(tok::kw_for) && "Not a for stmt!");
20060b57cec5SDimitry Andric   SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
20070b57cec5SDimitry Andric 
20080b57cec5SDimitry Andric   SourceLocation CoawaitLoc;
20090b57cec5SDimitry Andric   if (Tok.is(tok::kw_co_await))
20100b57cec5SDimitry Andric     CoawaitLoc = ConsumeToken();
20110b57cec5SDimitry Andric 
20120b57cec5SDimitry Andric   if (Tok.isNot(tok::l_paren)) {
20130b57cec5SDimitry Andric     Diag(Tok, diag::err_expected_lparen_after) << "for";
20140b57cec5SDimitry Andric     SkipUntil(tok::semi);
20150b57cec5SDimitry Andric     return StmtError();
20160b57cec5SDimitry Andric   }
20170b57cec5SDimitry Andric 
20180b57cec5SDimitry Andric   bool C99orCXXorObjC = getLangOpts().C99 || getLangOpts().CPlusPlus ||
20190b57cec5SDimitry Andric     getLangOpts().ObjC;
20200b57cec5SDimitry Andric 
20210b57cec5SDimitry Andric   // C99 6.8.5p5 - In C99, the for statement is a block.  This is not
20220b57cec5SDimitry Andric   // the case for C90.  Start the loop scope.
20230b57cec5SDimitry Andric   //
20240b57cec5SDimitry Andric   // C++ 6.4p3:
20250b57cec5SDimitry Andric   // A name introduced by a declaration in a condition is in scope from its
20260b57cec5SDimitry Andric   // point of declaration until the end of the substatements controlled by the
20270b57cec5SDimitry Andric   // condition.
20280b57cec5SDimitry Andric   // C++ 3.3.2p4:
20290b57cec5SDimitry Andric   // Names declared in the for-init-statement, and in the condition of if,
20300b57cec5SDimitry Andric   // while, for, and switch statements are local to the if, while, for, or
20310b57cec5SDimitry Andric   // switch statement (including the controlled statement).
20320b57cec5SDimitry Andric   // C++ 6.5.3p1:
20330b57cec5SDimitry Andric   // Names declared in the for-init-statement are in the same declarative-region
20340b57cec5SDimitry Andric   // as those declared in the condition.
20350b57cec5SDimitry Andric   //
20360b57cec5SDimitry Andric   unsigned ScopeFlags = 0;
20370b57cec5SDimitry Andric   if (C99orCXXorObjC)
20380b57cec5SDimitry Andric     ScopeFlags = Scope::DeclScope | Scope::ControlScope;
20390b57cec5SDimitry Andric 
20400b57cec5SDimitry Andric   ParseScope ForScope(this, ScopeFlags);
20410b57cec5SDimitry Andric 
20420b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren);
20430b57cec5SDimitry Andric   T.consumeOpen();
20440b57cec5SDimitry Andric 
20450b57cec5SDimitry Andric   ExprResult Value;
20460b57cec5SDimitry Andric 
20470b57cec5SDimitry Andric   bool ForEach = false;
20480b57cec5SDimitry Andric   StmtResult FirstPart;
20490b57cec5SDimitry Andric   Sema::ConditionResult SecondPart;
20500b57cec5SDimitry Andric   ExprResult Collection;
20510b57cec5SDimitry Andric   ForRangeInfo ForRangeInfo;
20520b57cec5SDimitry Andric   FullExprArg ThirdPart(Actions);
20530b57cec5SDimitry Andric 
20540b57cec5SDimitry Andric   if (Tok.is(tok::code_completion)) {
2055fe6060f1SDimitry Andric     cutOffParsing();
20560fca6ea1SDimitry Andric     Actions.CodeCompletion().CodeCompleteOrdinaryName(
20570fca6ea1SDimitry Andric         getCurScope(), C99orCXXorObjC ? SemaCodeCompletion::PCC_ForInit
20580fca6ea1SDimitry Andric                                       : SemaCodeCompletion::PCC_Expression);
20590b57cec5SDimitry Andric     return StmtError();
20600b57cec5SDimitry Andric   }
20610b57cec5SDimitry Andric 
206281ad6265SDimitry Andric   ParsedAttributes attrs(AttrFactory);
20630b57cec5SDimitry Andric   MaybeParseCXX11Attributes(attrs);
20640b57cec5SDimitry Andric 
20650b57cec5SDimitry Andric   SourceLocation EmptyInitStmtSemiLoc;
20660b57cec5SDimitry Andric 
20670b57cec5SDimitry Andric   // Parse the first part of the for specifier.
20680b57cec5SDimitry Andric   if (Tok.is(tok::semi)) {  // for (;
20690b57cec5SDimitry Andric     ProhibitAttributes(attrs);
20700b57cec5SDimitry Andric     // no first part, eat the ';'.
20710b57cec5SDimitry Andric     SourceLocation SemiLoc = Tok.getLocation();
20720b57cec5SDimitry Andric     if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.isMacroID())
20730b57cec5SDimitry Andric       EmptyInitStmtSemiLoc = SemiLoc;
20740b57cec5SDimitry Andric     ConsumeToken();
20750b57cec5SDimitry Andric   } else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) &&
20760b57cec5SDimitry Andric              isForRangeIdentifier()) {
20770b57cec5SDimitry Andric     ProhibitAttributes(attrs);
20780b57cec5SDimitry Andric     IdentifierInfo *Name = Tok.getIdentifierInfo();
20790b57cec5SDimitry Andric     SourceLocation Loc = ConsumeToken();
20800b57cec5SDimitry Andric     MaybeParseCXX11Attributes(attrs);
20810b57cec5SDimitry Andric 
20820b57cec5SDimitry Andric     ForRangeInfo.ColonLoc = ConsumeToken();
20830b57cec5SDimitry Andric     if (Tok.is(tok::l_brace))
20840b57cec5SDimitry Andric       ForRangeInfo.RangeExpr = ParseBraceInitializer();
20850b57cec5SDimitry Andric     else
20860b57cec5SDimitry Andric       ForRangeInfo.RangeExpr = ParseExpression();
20870b57cec5SDimitry Andric 
20880b57cec5SDimitry Andric     Diag(Loc, diag::err_for_range_identifier)
20890b57cec5SDimitry Andric       << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17)
20900b57cec5SDimitry Andric               ? FixItHint::CreateInsertion(Loc, "auto &&")
20910b57cec5SDimitry Andric               : FixItHint());
20920b57cec5SDimitry Andric 
209381ad6265SDimitry Andric     ForRangeInfo.LoopVar =
209481ad6265SDimitry Andric         Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name, attrs);
20950b57cec5SDimitry Andric   } else if (isForInitDeclaration()) {  // for (int X = 4;
20960b57cec5SDimitry Andric     ParenBraceBracketBalancer BalancerRAIIObj(*this);
20970b57cec5SDimitry Andric 
20980b57cec5SDimitry Andric     // Parse declaration, which eats the ';'.
20990b57cec5SDimitry Andric     if (!C99orCXXorObjC) {   // Use of C99-style for loops in C90 mode?
21000b57cec5SDimitry Andric       Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
21010b57cec5SDimitry Andric       Diag(Tok, diag::warn_gcc_variable_decl_in_for_loop);
21020b57cec5SDimitry Andric     }
2103349cc55cSDimitry Andric     DeclGroupPtrTy DG;
210406c3fb27SDimitry Andric     SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
2105349cc55cSDimitry Andric     if (Tok.is(tok::kw_using)) {
2106349cc55cSDimitry Andric       DG = ParseAliasDeclarationInInitStatement(DeclaratorContext::ForInit,
2107349cc55cSDimitry Andric                                                 attrs);
210806c3fb27SDimitry Andric       FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
2109349cc55cSDimitry Andric     } else {
21100b57cec5SDimitry Andric       // In C++0x, "for (T NS:a" might not be a typo for ::
21110b57cec5SDimitry Andric       bool MightBeForRangeStmt = getLangOpts().CPlusPlus;
21120b57cec5SDimitry Andric       ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
211381ad6265SDimitry Andric       ParsedAttributes DeclSpecAttrs(AttrFactory);
2114349cc55cSDimitry Andric       DG = ParseSimpleDeclaration(
211581ad6265SDimitry Andric           DeclaratorContext::ForInit, DeclEnd, attrs, DeclSpecAttrs, false,
21160b57cec5SDimitry Andric           MightBeForRangeStmt ? &ForRangeInfo : nullptr);
21170b57cec5SDimitry Andric       FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
21180b57cec5SDimitry Andric       if (ForRangeInfo.ParsedForRangeDecl()) {
2119349cc55cSDimitry Andric         Diag(ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus11
2120349cc55cSDimitry Andric                                         ? diag::warn_cxx98_compat_for_range
2121349cc55cSDimitry Andric                                         : diag::ext_for_range);
21220b57cec5SDimitry Andric         ForRangeInfo.LoopVar = FirstPart;
21230b57cec5SDimitry Andric         FirstPart = StmtResult();
21240b57cec5SDimitry Andric       } else if (Tok.is(tok::semi)) { // for (int x = 4;
21250b57cec5SDimitry Andric         ConsumeToken();
21260b57cec5SDimitry Andric       } else if ((ForEach = isTokIdentifier_in())) {
21270b57cec5SDimitry Andric         Actions.ActOnForEachDeclStmt(DG);
21280b57cec5SDimitry Andric         // ObjC: for (id x in expr)
21290b57cec5SDimitry Andric         ConsumeToken(); // consume 'in'
21300b57cec5SDimitry Andric 
21310b57cec5SDimitry Andric         if (Tok.is(tok::code_completion)) {
21320b57cec5SDimitry Andric           cutOffParsing();
21330fca6ea1SDimitry Andric           Actions.CodeCompletion().CodeCompleteObjCForCollection(getCurScope(),
21340fca6ea1SDimitry Andric                                                                  DG);
21350b57cec5SDimitry Andric           return StmtError();
21360b57cec5SDimitry Andric         }
21370b57cec5SDimitry Andric         Collection = ParseExpression();
21380b57cec5SDimitry Andric       } else {
21390b57cec5SDimitry Andric         Diag(Tok, diag::err_expected_semi_for);
21400b57cec5SDimitry Andric       }
2141349cc55cSDimitry Andric     }
21420b57cec5SDimitry Andric   } else {
21430b57cec5SDimitry Andric     ProhibitAttributes(attrs);
21440b57cec5SDimitry Andric     Value = Actions.CorrectDelayedTyposInExpr(ParseExpression());
21450b57cec5SDimitry Andric 
21460b57cec5SDimitry Andric     ForEach = isTokIdentifier_in();
21470b57cec5SDimitry Andric 
21480b57cec5SDimitry Andric     // Turn the expression into a stmt.
21490b57cec5SDimitry Andric     if (!Value.isInvalid()) {
21500b57cec5SDimitry Andric       if (ForEach)
21510b57cec5SDimitry Andric         FirstPart = Actions.ActOnForEachLValueExpr(Value.get());
21520b57cec5SDimitry Andric       else {
21530b57cec5SDimitry Andric         // We already know this is not an init-statement within a for loop, so
21540b57cec5SDimitry Andric         // if we are parsing a C++11 range-based for loop, we should treat this
21550b57cec5SDimitry Andric         // expression statement as being a discarded value expression because
21560b57cec5SDimitry Andric         // we will err below. This way we do not warn on an unused expression
21570b57cec5SDimitry Andric         // that was an error in the first place, like with: for (expr : expr);
21580b57cec5SDimitry Andric         bool IsRangeBasedFor =
21590b57cec5SDimitry Andric             getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon);
21600b57cec5SDimitry Andric         FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor);
21610b57cec5SDimitry Andric       }
21620b57cec5SDimitry Andric     }
21630b57cec5SDimitry Andric 
21640b57cec5SDimitry Andric     if (Tok.is(tok::semi)) {
21650b57cec5SDimitry Andric       ConsumeToken();
21660b57cec5SDimitry Andric     } else if (ForEach) {
21670b57cec5SDimitry Andric       ConsumeToken(); // consume 'in'
21680b57cec5SDimitry Andric 
21690b57cec5SDimitry Andric       if (Tok.is(tok::code_completion)) {
21700b57cec5SDimitry Andric         cutOffParsing();
21710fca6ea1SDimitry Andric         Actions.CodeCompletion().CodeCompleteObjCForCollection(getCurScope(),
21720fca6ea1SDimitry Andric                                                                nullptr);
21730b57cec5SDimitry Andric         return StmtError();
21740b57cec5SDimitry Andric       }
21750b57cec5SDimitry Andric       Collection = ParseExpression();
21760b57cec5SDimitry Andric     } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::colon) && FirstPart.get()) {
21770b57cec5SDimitry Andric       // User tried to write the reasonable, but ill-formed, for-range-statement
21780b57cec5SDimitry Andric       //   for (expr : expr) { ... }
21790b57cec5SDimitry Andric       Diag(Tok, diag::err_for_range_expected_decl)
21800b57cec5SDimitry Andric         << FirstPart.get()->getSourceRange();
21810b57cec5SDimitry Andric       SkipUntil(tok::r_paren, StopBeforeMatch);
21820b57cec5SDimitry Andric       SecondPart = Sema::ConditionError();
21830b57cec5SDimitry Andric     } else {
21840b57cec5SDimitry Andric       if (!Value.isInvalid()) {
21850b57cec5SDimitry Andric         Diag(Tok, diag::err_expected_semi_for);
21860b57cec5SDimitry Andric       } else {
21870b57cec5SDimitry Andric         // Skip until semicolon or rparen, don't consume it.
21880b57cec5SDimitry Andric         SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
21890b57cec5SDimitry Andric         if (Tok.is(tok::semi))
21900b57cec5SDimitry Andric           ConsumeToken();
21910b57cec5SDimitry Andric       }
21920b57cec5SDimitry Andric     }
21930b57cec5SDimitry Andric   }
21940b57cec5SDimitry Andric 
21950b57cec5SDimitry Andric   // Parse the second part of the for specifier.
21960b57cec5SDimitry Andric   if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() &&
21970b57cec5SDimitry Andric       !SecondPart.isInvalid()) {
21980b57cec5SDimitry Andric     // Parse the second part of the for specifier.
21990b57cec5SDimitry Andric     if (Tok.is(tok::semi)) {  // for (...;;
22000b57cec5SDimitry Andric       // no second part.
22010b57cec5SDimitry Andric     } else if (Tok.is(tok::r_paren)) {
22020b57cec5SDimitry Andric       // missing both semicolons.
22030b57cec5SDimitry Andric     } else {
22040b57cec5SDimitry Andric       if (getLangOpts().CPlusPlus) {
22050b57cec5SDimitry Andric         // C++2a: We've parsed an init-statement; we might have a
22060b57cec5SDimitry Andric         // for-range-declaration next.
22070b57cec5SDimitry Andric         bool MightBeForRangeStmt = !ForRangeInfo.ParsedForRangeDecl();
22080b57cec5SDimitry Andric         ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
22095f757f3fSDimitry Andric         SourceLocation SecondPartStart = Tok.getLocation();
22105f757f3fSDimitry Andric         Sema::ConditionKind CK = Sema::ConditionKind::Boolean;
221104eeddc0SDimitry Andric         SecondPart = ParseCXXCondition(
22125f757f3fSDimitry Andric             /*InitStmt=*/nullptr, ForLoc, CK,
221304eeddc0SDimitry Andric             // FIXME: recovery if we don't see another semi!
221404eeddc0SDimitry Andric             /*MissingOK=*/true, MightBeForRangeStmt ? &ForRangeInfo : nullptr,
22155f757f3fSDimitry Andric             /*EnterForConditionScope=*/true);
22160b57cec5SDimitry Andric 
22170b57cec5SDimitry Andric         if (ForRangeInfo.ParsedForRangeDecl()) {
22180b57cec5SDimitry Andric           Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc()
22190b57cec5SDimitry Andric                                : ForRangeInfo.ColonLoc,
22205ffd83dbSDimitry Andric                getLangOpts().CPlusPlus20
22210b57cec5SDimitry Andric                    ? diag::warn_cxx17_compat_for_range_init_stmt
22220b57cec5SDimitry Andric                    : diag::ext_for_range_init_stmt)
22230b57cec5SDimitry Andric               << (FirstPart.get() ? FirstPart.get()->getSourceRange()
22240b57cec5SDimitry Andric                                   : SourceRange());
22250b57cec5SDimitry Andric           if (EmptyInitStmtSemiLoc.isValid()) {
22260b57cec5SDimitry Andric             Diag(EmptyInitStmtSemiLoc, diag::warn_empty_init_statement)
22270b57cec5SDimitry Andric                 << /*for-loop*/ 2
22280b57cec5SDimitry Andric                 << FixItHint::CreateRemoval(EmptyInitStmtSemiLoc);
22290b57cec5SDimitry Andric           }
22300b57cec5SDimitry Andric         }
22315f757f3fSDimitry Andric 
22325f757f3fSDimitry Andric         if (SecondPart.isInvalid()) {
22335f757f3fSDimitry Andric           ExprResult CondExpr = Actions.CreateRecoveryExpr(
22345f757f3fSDimitry Andric               SecondPartStart,
22355f757f3fSDimitry Andric               Tok.getLocation() == SecondPartStart ? SecondPartStart
22365f757f3fSDimitry Andric                                                    : PrevTokLocation,
22375f757f3fSDimitry Andric               {}, Actions.PreferredConditionType(CK));
22385f757f3fSDimitry Andric           if (!CondExpr.isInvalid())
22395f757f3fSDimitry Andric             SecondPart = Actions.ActOnCondition(getCurScope(), ForLoc,
22405f757f3fSDimitry Andric                                                 CondExpr.get(), CK,
22415f757f3fSDimitry Andric                                                 /*MissingOK=*/false);
22425f757f3fSDimitry Andric         }
22435f757f3fSDimitry Andric 
22440b57cec5SDimitry Andric       } else {
2245fe6060f1SDimitry Andric         // We permit 'continue' and 'break' in the condition of a for loop.
2246fe6060f1SDimitry Andric         getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
2247fe6060f1SDimitry Andric 
22480b57cec5SDimitry Andric         ExprResult SecondExpr = ParseExpression();
22490b57cec5SDimitry Andric         if (SecondExpr.isInvalid())
22500b57cec5SDimitry Andric           SecondPart = Sema::ConditionError();
22510b57cec5SDimitry Andric         else
225204eeddc0SDimitry Andric           SecondPart = Actions.ActOnCondition(
225304eeddc0SDimitry Andric               getCurScope(), ForLoc, SecondExpr.get(),
225404eeddc0SDimitry Andric               Sema::ConditionKind::Boolean, /*MissingOK=*/true);
22550b57cec5SDimitry Andric       }
22560b57cec5SDimitry Andric     }
22570b57cec5SDimitry Andric   }
22580b57cec5SDimitry Andric 
2259fe6060f1SDimitry Andric   // Enter a break / continue scope, if we didn't already enter one while
2260fe6060f1SDimitry Andric   // parsing the second part.
226181ad6265SDimitry Andric   if (!getCurScope()->isContinueScope())
2262fe6060f1SDimitry Andric     getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
2263fe6060f1SDimitry Andric 
22640b57cec5SDimitry Andric   // Parse the third part of the for statement.
22650b57cec5SDimitry Andric   if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) {
22660b57cec5SDimitry Andric     if (Tok.isNot(tok::semi)) {
22670b57cec5SDimitry Andric       if (!SecondPart.isInvalid())
22680b57cec5SDimitry Andric         Diag(Tok, diag::err_expected_semi_for);
22690b57cec5SDimitry Andric       SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
22700b57cec5SDimitry Andric     }
22710b57cec5SDimitry Andric 
22720b57cec5SDimitry Andric     if (Tok.is(tok::semi)) {
22730b57cec5SDimitry Andric       ConsumeToken();
22740b57cec5SDimitry Andric     }
22750b57cec5SDimitry Andric 
22760b57cec5SDimitry Andric     if (Tok.isNot(tok::r_paren)) {   // for (...;...;)
22770b57cec5SDimitry Andric       ExprResult Third = ParseExpression();
22780b57cec5SDimitry Andric       // FIXME: The C++11 standard doesn't actually say that this is a
22790b57cec5SDimitry Andric       // discarded-value expression, but it clearly should be.
22800b57cec5SDimitry Andric       ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.get());
22810b57cec5SDimitry Andric     }
22820b57cec5SDimitry Andric   }
22830b57cec5SDimitry Andric   // Match the ')'.
22840b57cec5SDimitry Andric   T.consumeClose();
22850b57cec5SDimitry Andric 
22860b57cec5SDimitry Andric   // C++ Coroutines [stmt.iter]:
22870b57cec5SDimitry Andric   //   'co_await' can only be used for a range-based for statement.
22880b57cec5SDimitry Andric   if (CoawaitLoc.isValid() && !ForRangeInfo.ParsedForRangeDecl()) {
22890b57cec5SDimitry Andric     Diag(CoawaitLoc, diag::err_for_co_await_not_range_for);
22900b57cec5SDimitry Andric     CoawaitLoc = SourceLocation();
22910b57cec5SDimitry Andric   }
22920b57cec5SDimitry Andric 
22934824e7fdSDimitry Andric   if (CoawaitLoc.isValid() && getLangOpts().CPlusPlus20)
22944824e7fdSDimitry Andric     Diag(CoawaitLoc, diag::warn_deprecated_for_co_await);
22954824e7fdSDimitry Andric 
22960b57cec5SDimitry Andric   // We need to perform most of the semantic analysis for a C++0x for-range
22970b57cec5SDimitry Andric   // statememt before parsing the body, in order to be able to deduce the type
22980b57cec5SDimitry Andric   // of an auto-typed loop variable.
22990b57cec5SDimitry Andric   StmtResult ForRangeStmt;
23000b57cec5SDimitry Andric   StmtResult ForEachStmt;
23010b57cec5SDimitry Andric 
23020b57cec5SDimitry Andric   if (ForRangeInfo.ParsedForRangeDecl()) {
23030b57cec5SDimitry Andric     ExprResult CorrectedRange =
23040b57cec5SDimitry Andric         Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get());
23050b57cec5SDimitry Andric     ForRangeStmt = Actions.ActOnCXXForRangeStmt(
23060b57cec5SDimitry Andric         getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
23070b57cec5SDimitry Andric         ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(),
23080fca6ea1SDimitry Andric         T.getCloseLocation(), Sema::BFRK_Build,
23090fca6ea1SDimitry Andric         ForRangeInfo.LifetimeExtendTemps);
23100fca6ea1SDimitry Andric   } else if (ForEach) {
23110b57cec5SDimitry Andric     // Similarly, we need to do the semantic analysis for a for-range
23120b57cec5SDimitry Andric     // statement immediately in order to close over temporaries correctly.
23130fca6ea1SDimitry Andric     ForEachStmt = Actions.ObjC().ActOnObjCForCollectionStmt(
23140fca6ea1SDimitry Andric         ForLoc, FirstPart.get(), Collection.get(), T.getCloseLocation());
23150b57cec5SDimitry Andric   } else {
23160b57cec5SDimitry Andric     // In OpenMP loop region loop control variable must be captured and be
23170b57cec5SDimitry Andric     // private. Perform analysis of first part (if any).
23180b57cec5SDimitry Andric     if (getLangOpts().OpenMP && FirstPart.isUsable()) {
23190fca6ea1SDimitry Andric       Actions.OpenMP().ActOnOpenMPLoopInitialization(ForLoc, FirstPart.get());
23200b57cec5SDimitry Andric     }
23210b57cec5SDimitry Andric   }
23220b57cec5SDimitry Andric 
23230b57cec5SDimitry Andric   // C99 6.8.5p5 - In C99, the body of the for statement is a scope, even if
23240b57cec5SDimitry Andric   // there is no compound stmt.  C90 does not have this clause.  We only do this
23250b57cec5SDimitry Andric   // if the body isn't a compound statement to avoid push/pop in common cases.
23260b57cec5SDimitry Andric   //
23270b57cec5SDimitry Andric   // C++ 6.5p2:
23280b57cec5SDimitry Andric   // The substatement in an iteration-statement implicitly defines a local scope
23290b57cec5SDimitry Andric   // which is entered and exited each time through the loop.
23300b57cec5SDimitry Andric   //
23310b57cec5SDimitry Andric   // See comments in ParseIfStatement for why we create a scope for
23320b57cec5SDimitry Andric   // for-init-statement/condition and a new scope for substatement in C++.
23330b57cec5SDimitry Andric   //
23340b57cec5SDimitry Andric   ParseScope InnerScope(this, Scope::DeclScope, C99orCXXorObjC,
23350b57cec5SDimitry Andric                         Tok.is(tok::l_brace));
23360b57cec5SDimitry Andric 
23370b57cec5SDimitry Andric   // The body of the for loop has the same local mangling number as the
23380b57cec5SDimitry Andric   // for-init-statement.
23390b57cec5SDimitry Andric   // It will only be incremented if the body contains other things that would
23400b57cec5SDimitry Andric   // normally increment the mangling number (like a compound statement).
23410b57cec5SDimitry Andric   if (C99orCXXorObjC)
23420b57cec5SDimitry Andric     getCurScope()->decrementMSManglingNumber();
23430b57cec5SDimitry Andric 
2344480093f4SDimitry Andric   MisleadingIndentationChecker MIChecker(*this, MSK_for, ForLoc);
2345480093f4SDimitry Andric 
23460b57cec5SDimitry Andric   // Read the body statement.
23470b57cec5SDimitry Andric   StmtResult Body(ParseStatement(TrailingElseLoc));
23480b57cec5SDimitry Andric 
2349480093f4SDimitry Andric   if (Body.isUsable())
2350480093f4SDimitry Andric     MIChecker.Check();
2351480093f4SDimitry Andric 
23520b57cec5SDimitry Andric   // Pop the body scope if needed.
23530b57cec5SDimitry Andric   InnerScope.Exit();
23540b57cec5SDimitry Andric 
23550b57cec5SDimitry Andric   // Leave the for-scope.
23560b57cec5SDimitry Andric   ForScope.Exit();
23570b57cec5SDimitry Andric 
23580b57cec5SDimitry Andric   if (Body.isInvalid())
23590b57cec5SDimitry Andric     return StmtError();
23600b57cec5SDimitry Andric 
23610b57cec5SDimitry Andric   if (ForEach)
23620fca6ea1SDimitry Andric     return Actions.ObjC().FinishObjCForCollectionStmt(ForEachStmt.get(),
23630b57cec5SDimitry Andric                                                       Body.get());
23640b57cec5SDimitry Andric 
23650b57cec5SDimitry Andric   if (ForRangeInfo.ParsedForRangeDecl())
23660b57cec5SDimitry Andric     return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
23670b57cec5SDimitry Andric 
23680b57cec5SDimitry Andric   return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(),
23690b57cec5SDimitry Andric                               SecondPart, ThirdPart, T.getCloseLocation(),
23700b57cec5SDimitry Andric                               Body.get());
23710b57cec5SDimitry Andric }
23720b57cec5SDimitry Andric 
23730b57cec5SDimitry Andric /// ParseGotoStatement
23740b57cec5SDimitry Andric ///       jump-statement:
23750b57cec5SDimitry Andric ///         'goto' identifier ';'
23760b57cec5SDimitry Andric /// [GNU]   'goto' '*' expression ';'
23770b57cec5SDimitry Andric ///
23780b57cec5SDimitry Andric /// Note: this lets the caller parse the end ';'.
23790b57cec5SDimitry Andric ///
23800b57cec5SDimitry Andric StmtResult Parser::ParseGotoStatement() {
23810b57cec5SDimitry Andric   assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
23820b57cec5SDimitry Andric   SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
23830b57cec5SDimitry Andric 
23840b57cec5SDimitry Andric   StmtResult Res;
23850b57cec5SDimitry Andric   if (Tok.is(tok::identifier)) {
23860b57cec5SDimitry Andric     LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
23870b57cec5SDimitry Andric                                                 Tok.getLocation());
23880b57cec5SDimitry Andric     Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD);
23890b57cec5SDimitry Andric     ConsumeToken();
23900b57cec5SDimitry Andric   } else if (Tok.is(tok::star)) {
23910b57cec5SDimitry Andric     // GNU indirect goto extension.
23920b57cec5SDimitry Andric     Diag(Tok, diag::ext_gnu_indirect_goto);
23930b57cec5SDimitry Andric     SourceLocation StarLoc = ConsumeToken();
23940b57cec5SDimitry Andric     ExprResult R(ParseExpression());
23950b57cec5SDimitry Andric     if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
23960b57cec5SDimitry Andric       SkipUntil(tok::semi, StopBeforeMatch);
23970b57cec5SDimitry Andric       return StmtError();
23980b57cec5SDimitry Andric     }
23990b57cec5SDimitry Andric     Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.get());
24000b57cec5SDimitry Andric   } else {
24010b57cec5SDimitry Andric     Diag(Tok, diag::err_expected) << tok::identifier;
24020b57cec5SDimitry Andric     return StmtError();
24030b57cec5SDimitry Andric   }
24040b57cec5SDimitry Andric 
24050b57cec5SDimitry Andric   return Res;
24060b57cec5SDimitry Andric }
24070b57cec5SDimitry Andric 
24080b57cec5SDimitry Andric /// ParseContinueStatement
24090b57cec5SDimitry Andric ///       jump-statement:
24100b57cec5SDimitry Andric ///         'continue' ';'
24110b57cec5SDimitry Andric ///
24120b57cec5SDimitry Andric /// Note: this lets the caller parse the end ';'.
24130b57cec5SDimitry Andric ///
24140b57cec5SDimitry Andric StmtResult Parser::ParseContinueStatement() {
24150b57cec5SDimitry Andric   SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
24160b57cec5SDimitry Andric   return Actions.ActOnContinueStmt(ContinueLoc, getCurScope());
24170b57cec5SDimitry Andric }
24180b57cec5SDimitry Andric 
24190b57cec5SDimitry Andric /// ParseBreakStatement
24200b57cec5SDimitry Andric ///       jump-statement:
24210b57cec5SDimitry Andric ///         'break' ';'
24220b57cec5SDimitry Andric ///
24230b57cec5SDimitry Andric /// Note: this lets the caller parse the end ';'.
24240b57cec5SDimitry Andric ///
24250b57cec5SDimitry Andric StmtResult Parser::ParseBreakStatement() {
24260b57cec5SDimitry Andric   SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
24270b57cec5SDimitry Andric   return Actions.ActOnBreakStmt(BreakLoc, getCurScope());
24280b57cec5SDimitry Andric }
24290b57cec5SDimitry Andric 
24300b57cec5SDimitry Andric /// ParseReturnStatement
24310b57cec5SDimitry Andric ///       jump-statement:
24320b57cec5SDimitry Andric ///         'return' expression[opt] ';'
24330b57cec5SDimitry Andric ///         'return' braced-init-list ';'
24340b57cec5SDimitry Andric ///         'co_return' expression[opt] ';'
24350b57cec5SDimitry Andric ///         'co_return' braced-init-list ';'
24360b57cec5SDimitry Andric StmtResult Parser::ParseReturnStatement() {
24370b57cec5SDimitry Andric   assert((Tok.is(tok::kw_return) || Tok.is(tok::kw_co_return)) &&
24380b57cec5SDimitry Andric          "Not a return stmt!");
24390b57cec5SDimitry Andric   bool IsCoreturn = Tok.is(tok::kw_co_return);
24400b57cec5SDimitry Andric   SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
24410b57cec5SDimitry Andric 
24420b57cec5SDimitry Andric   ExprResult R;
24430b57cec5SDimitry Andric   if (Tok.isNot(tok::semi)) {
24440b57cec5SDimitry Andric     if (!IsCoreturn)
24450b57cec5SDimitry Andric       PreferredType.enterReturn(Actions, Tok.getLocation());
24460b57cec5SDimitry Andric     // FIXME: Code completion for co_return.
24470b57cec5SDimitry Andric     if (Tok.is(tok::code_completion) && !IsCoreturn) {
2448fe6060f1SDimitry Andric       cutOffParsing();
24490fca6ea1SDimitry Andric       Actions.CodeCompletion().CodeCompleteExpression(
24500fca6ea1SDimitry Andric           getCurScope(), PreferredType.get(Tok.getLocation()));
24510b57cec5SDimitry Andric       return StmtError();
24520b57cec5SDimitry Andric     }
24530b57cec5SDimitry Andric 
24540b57cec5SDimitry Andric     if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus) {
24550b57cec5SDimitry Andric       R = ParseInitializer();
24560b57cec5SDimitry Andric       if (R.isUsable())
24570b57cec5SDimitry Andric         Diag(R.get()->getBeginLoc(),
24580b57cec5SDimitry Andric              getLangOpts().CPlusPlus11
24590b57cec5SDimitry Andric                  ? diag::warn_cxx98_compat_generalized_initializer_lists
24600b57cec5SDimitry Andric                  : diag::ext_generalized_initializer_lists)
24610b57cec5SDimitry Andric             << R.get()->getSourceRange();
24620b57cec5SDimitry Andric     } else
24630b57cec5SDimitry Andric       R = ParseExpression();
24640b57cec5SDimitry Andric     if (R.isInvalid()) {
24650b57cec5SDimitry Andric       SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
24660b57cec5SDimitry Andric       return StmtError();
24670b57cec5SDimitry Andric     }
24680b57cec5SDimitry Andric   }
24690b57cec5SDimitry Andric   if (IsCoreturn)
24700b57cec5SDimitry Andric     return Actions.ActOnCoreturnStmt(getCurScope(), ReturnLoc, R.get());
24710b57cec5SDimitry Andric   return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope());
24720b57cec5SDimitry Andric }
24730b57cec5SDimitry Andric 
24740b57cec5SDimitry Andric StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
24750b57cec5SDimitry Andric                                        ParsedStmtContext StmtCtx,
24760b57cec5SDimitry Andric                                        SourceLocation *TrailingElseLoc,
247781ad6265SDimitry Andric                                        ParsedAttributes &Attrs) {
24780b57cec5SDimitry Andric   // Create temporary attribute list.
247981ad6265SDimitry Andric   ParsedAttributes TempAttrs(AttrFactory);
24800b57cec5SDimitry Andric 
24815ffd83dbSDimitry Andric   SourceLocation StartLoc = Tok.getLocation();
24825ffd83dbSDimitry Andric 
24830b57cec5SDimitry Andric   // Get loop hints and consume annotated token.
24840b57cec5SDimitry Andric   while (Tok.is(tok::annot_pragma_loop_hint)) {
24850b57cec5SDimitry Andric     LoopHint Hint;
24860b57cec5SDimitry Andric     if (!HandlePragmaLoopHint(Hint))
24870b57cec5SDimitry Andric       continue;
24880b57cec5SDimitry Andric 
24890b57cec5SDimitry Andric     ArgsUnion ArgHints[] = {Hint.PragmaNameLoc, Hint.OptionLoc, Hint.StateLoc,
24900b57cec5SDimitry Andric                             ArgsUnion(Hint.ValueExpr)};
24910b57cec5SDimitry Andric     TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr,
24920b57cec5SDimitry Andric                      Hint.PragmaNameLoc->Loc, ArgHints, 4,
249306c3fb27SDimitry Andric                      ParsedAttr::Form::Pragma());
24940b57cec5SDimitry Andric   }
24950b57cec5SDimitry Andric 
24960b57cec5SDimitry Andric   // Get the next statement.
24970b57cec5SDimitry Andric   MaybeParseCXX11Attributes(Attrs);
24980b57cec5SDimitry Andric 
249981ad6265SDimitry Andric   ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
25000b57cec5SDimitry Andric   StmtResult S = ParseStatementOrDeclarationAfterAttributes(
250181ad6265SDimitry Andric       Stmts, StmtCtx, TrailingElseLoc, Attrs, EmptyDeclSpecAttrs);
25020b57cec5SDimitry Andric 
25030b57cec5SDimitry Andric   Attrs.takeAllFrom(TempAttrs);
25045ffd83dbSDimitry Andric 
25055ffd83dbSDimitry Andric   // Start of attribute range may already be set for some invalid input.
25065ffd83dbSDimitry Andric   // See PR46336.
25075ffd83dbSDimitry Andric   if (Attrs.Range.getBegin().isInvalid())
25085ffd83dbSDimitry Andric     Attrs.Range.setBegin(StartLoc);
25095ffd83dbSDimitry Andric 
25100b57cec5SDimitry Andric   return S;
25110b57cec5SDimitry Andric }
25120b57cec5SDimitry Andric 
25130b57cec5SDimitry Andric Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
25140b57cec5SDimitry Andric   assert(Tok.is(tok::l_brace));
25150b57cec5SDimitry Andric   SourceLocation LBraceLoc = Tok.getLocation();
25160b57cec5SDimitry Andric 
25170b57cec5SDimitry Andric   PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, LBraceLoc,
25180b57cec5SDimitry Andric                                       "parsing function body");
25190b57cec5SDimitry Andric 
25200b57cec5SDimitry Andric   // Save and reset current vtordisp stack if we have entered a C++ method body.
25210b57cec5SDimitry Andric   bool IsCXXMethod =
25220b57cec5SDimitry Andric       getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl);
25230b57cec5SDimitry Andric   Sema::PragmaStackSentinelRAII
25240b57cec5SDimitry Andric     PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
25250b57cec5SDimitry Andric 
25260b57cec5SDimitry Andric   // Do not enter a scope for the brace, as the arguments are in the same scope
25270b57cec5SDimitry Andric   // (the function body) as the body itself.  Instead, just read the statement
25280b57cec5SDimitry Andric   // list and put it into a CompoundStmt for safe keeping.
25290b57cec5SDimitry Andric   StmtResult FnBody(ParseCompoundStatementBody());
25300b57cec5SDimitry Andric 
25310b57cec5SDimitry Andric   // If the function body could not be parsed, make a bogus compoundstmt.
25320b57cec5SDimitry Andric   if (FnBody.isInvalid()) {
25330b57cec5SDimitry Andric     Sema::CompoundScopeRAII CompoundScope(Actions);
2534bdd1243dSDimitry Andric     FnBody =
2535bdd1243dSDimitry Andric         Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, std::nullopt, false);
25360b57cec5SDimitry Andric   }
25370b57cec5SDimitry Andric 
25380b57cec5SDimitry Andric   BodyScope.Exit();
25390b57cec5SDimitry Andric   return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
25400b57cec5SDimitry Andric }
25410b57cec5SDimitry Andric 
25420b57cec5SDimitry Andric /// ParseFunctionTryBlock - Parse a C++ function-try-block.
25430b57cec5SDimitry Andric ///
25440b57cec5SDimitry Andric ///       function-try-block:
25450b57cec5SDimitry Andric ///         'try' ctor-initializer[opt] compound-statement handler-seq
25460b57cec5SDimitry Andric ///
25470b57cec5SDimitry Andric Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
25480b57cec5SDimitry Andric   assert(Tok.is(tok::kw_try) && "Expected 'try'");
25490b57cec5SDimitry Andric   SourceLocation TryLoc = ConsumeToken();
25500b57cec5SDimitry Andric 
25510b57cec5SDimitry Andric   PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, TryLoc,
25520b57cec5SDimitry Andric                                       "parsing function try block");
25530b57cec5SDimitry Andric 
25540b57cec5SDimitry Andric   // Constructor initializer list?
25550b57cec5SDimitry Andric   if (Tok.is(tok::colon))
25560b57cec5SDimitry Andric     ParseConstructorInitializer(Decl);
25570b57cec5SDimitry Andric   else
25580b57cec5SDimitry Andric     Actions.ActOnDefaultCtorInitializers(Decl);
25590b57cec5SDimitry Andric 
25600b57cec5SDimitry Andric   // Save and reset current vtordisp stack if we have entered a C++ method body.
25610b57cec5SDimitry Andric   bool IsCXXMethod =
25620b57cec5SDimitry Andric       getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl);
25630b57cec5SDimitry Andric   Sema::PragmaStackSentinelRAII
25640b57cec5SDimitry Andric     PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
25650b57cec5SDimitry Andric 
25660b57cec5SDimitry Andric   SourceLocation LBraceLoc = Tok.getLocation();
25670b57cec5SDimitry Andric   StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true));
25680b57cec5SDimitry Andric   // If we failed to parse the try-catch, we just give the function an empty
25690b57cec5SDimitry Andric   // compound statement as the body.
25700b57cec5SDimitry Andric   if (FnBody.isInvalid()) {
25710b57cec5SDimitry Andric     Sema::CompoundScopeRAII CompoundScope(Actions);
2572bdd1243dSDimitry Andric     FnBody =
2573bdd1243dSDimitry Andric         Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, std::nullopt, false);
25740b57cec5SDimitry Andric   }
25750b57cec5SDimitry Andric 
25760b57cec5SDimitry Andric   BodyScope.Exit();
25770b57cec5SDimitry Andric   return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
25780b57cec5SDimitry Andric }
25790b57cec5SDimitry Andric 
25800b57cec5SDimitry Andric bool Parser::trySkippingFunctionBody() {
25810b57cec5SDimitry Andric   assert(SkipFunctionBodies &&
25820b57cec5SDimitry Andric          "Should only be called when SkipFunctionBodies is enabled");
25830b57cec5SDimitry Andric   if (!PP.isCodeCompletionEnabled()) {
25840b57cec5SDimitry Andric     SkipFunctionBody();
25850b57cec5SDimitry Andric     return true;
25860b57cec5SDimitry Andric   }
25870b57cec5SDimitry Andric 
25880b57cec5SDimitry Andric   // We're in code-completion mode. Skip parsing for all function bodies unless
25890b57cec5SDimitry Andric   // the body contains the code-completion point.
25900b57cec5SDimitry Andric   TentativeParsingAction PA(*this);
25910b57cec5SDimitry Andric   bool IsTryCatch = Tok.is(tok::kw_try);
25920b57cec5SDimitry Andric   CachedTokens Toks;
25930b57cec5SDimitry Andric   bool ErrorInPrologue = ConsumeAndStoreFunctionPrologue(Toks);
25940b57cec5SDimitry Andric   if (llvm::any_of(Toks, [](const Token &Tok) {
25950b57cec5SDimitry Andric         return Tok.is(tok::code_completion);
25960b57cec5SDimitry Andric       })) {
25970b57cec5SDimitry Andric     PA.Revert();
25980b57cec5SDimitry Andric     return false;
25990b57cec5SDimitry Andric   }
26000b57cec5SDimitry Andric   if (ErrorInPrologue) {
26010b57cec5SDimitry Andric     PA.Commit();
26020b57cec5SDimitry Andric     SkipMalformedDecl();
26030b57cec5SDimitry Andric     return true;
26040b57cec5SDimitry Andric   }
26050b57cec5SDimitry Andric   if (!SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
26060b57cec5SDimitry Andric     PA.Revert();
26070b57cec5SDimitry Andric     return false;
26080b57cec5SDimitry Andric   }
26090b57cec5SDimitry Andric   while (IsTryCatch && Tok.is(tok::kw_catch)) {
26100b57cec5SDimitry Andric     if (!SkipUntil(tok::l_brace, StopAtCodeCompletion) ||
26110b57cec5SDimitry Andric         !SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
26120b57cec5SDimitry Andric       PA.Revert();
26130b57cec5SDimitry Andric       return false;
26140b57cec5SDimitry Andric     }
26150b57cec5SDimitry Andric   }
26160b57cec5SDimitry Andric   PA.Commit();
26170b57cec5SDimitry Andric   return true;
26180b57cec5SDimitry Andric }
26190b57cec5SDimitry Andric 
26200b57cec5SDimitry Andric /// ParseCXXTryBlock - Parse a C++ try-block.
26210b57cec5SDimitry Andric ///
26220b57cec5SDimitry Andric ///       try-block:
26230b57cec5SDimitry Andric ///         'try' compound-statement handler-seq
26240b57cec5SDimitry Andric ///
26250b57cec5SDimitry Andric StmtResult Parser::ParseCXXTryBlock() {
26260b57cec5SDimitry Andric   assert(Tok.is(tok::kw_try) && "Expected 'try'");
26270b57cec5SDimitry Andric 
26280b57cec5SDimitry Andric   SourceLocation TryLoc = ConsumeToken();
26290b57cec5SDimitry Andric   return ParseCXXTryBlockCommon(TryLoc);
26300b57cec5SDimitry Andric }
26310b57cec5SDimitry Andric 
26320b57cec5SDimitry Andric /// ParseCXXTryBlockCommon - Parse the common part of try-block and
26330b57cec5SDimitry Andric /// function-try-block.
26340b57cec5SDimitry Andric ///
26350b57cec5SDimitry Andric ///       try-block:
26360b57cec5SDimitry Andric ///         'try' compound-statement handler-seq
26370b57cec5SDimitry Andric ///
26380b57cec5SDimitry Andric ///       function-try-block:
26390b57cec5SDimitry Andric ///         'try' ctor-initializer[opt] compound-statement handler-seq
26400b57cec5SDimitry Andric ///
26410b57cec5SDimitry Andric ///       handler-seq:
26420b57cec5SDimitry Andric ///         handler handler-seq[opt]
26430b57cec5SDimitry Andric ///
26440b57cec5SDimitry Andric ///       [Borland] try-block:
26450b57cec5SDimitry Andric ///         'try' compound-statement seh-except-block
26460b57cec5SDimitry Andric ///         'try' compound-statement seh-finally-block
26470b57cec5SDimitry Andric ///
26480b57cec5SDimitry Andric StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
26490b57cec5SDimitry Andric   if (Tok.isNot(tok::l_brace))
26500b57cec5SDimitry Andric     return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
26510b57cec5SDimitry Andric 
26520b57cec5SDimitry Andric   StmtResult TryBlock(ParseCompoundStatement(
26530b57cec5SDimitry Andric       /*isStmtExpr=*/false, Scope::DeclScope | Scope::TryScope |
26540b57cec5SDimitry Andric                                 Scope::CompoundStmtScope |
26550b57cec5SDimitry Andric                                 (FnTry ? Scope::FnTryCatchScope : 0)));
26560b57cec5SDimitry Andric   if (TryBlock.isInvalid())
26570b57cec5SDimitry Andric     return TryBlock;
26580b57cec5SDimitry Andric 
26590b57cec5SDimitry Andric   // Borland allows SEH-handlers with 'try'
26600b57cec5SDimitry Andric 
26610b57cec5SDimitry Andric   if ((Tok.is(tok::identifier) &&
26620b57cec5SDimitry Andric        Tok.getIdentifierInfo() == getSEHExceptKeyword()) ||
26630b57cec5SDimitry Andric       Tok.is(tok::kw___finally)) {
26640b57cec5SDimitry Andric     // TODO: Factor into common return ParseSEHHandlerCommon(...)
26650b57cec5SDimitry Andric     StmtResult Handler;
26660b57cec5SDimitry Andric     if(Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
26670b57cec5SDimitry Andric       SourceLocation Loc = ConsumeToken();
26680b57cec5SDimitry Andric       Handler = ParseSEHExceptBlock(Loc);
26690b57cec5SDimitry Andric     }
26700b57cec5SDimitry Andric     else {
26710b57cec5SDimitry Andric       SourceLocation Loc = ConsumeToken();
26720b57cec5SDimitry Andric       Handler = ParseSEHFinallyBlock(Loc);
26730b57cec5SDimitry Andric     }
26740b57cec5SDimitry Andric     if(Handler.isInvalid())
26750b57cec5SDimitry Andric       return Handler;
26760b57cec5SDimitry Andric 
26770b57cec5SDimitry Andric     return Actions.ActOnSEHTryBlock(true /* IsCXXTry */,
26780b57cec5SDimitry Andric                                     TryLoc,
26790b57cec5SDimitry Andric                                     TryBlock.get(),
26800b57cec5SDimitry Andric                                     Handler.get());
26810b57cec5SDimitry Andric   }
26820b57cec5SDimitry Andric   else {
26830b57cec5SDimitry Andric     StmtVector Handlers;
26840b57cec5SDimitry Andric 
26850b57cec5SDimitry Andric     // C++11 attributes can't appear here, despite this context seeming
26860b57cec5SDimitry Andric     // statement-like.
26870b57cec5SDimitry Andric     DiagnoseAndSkipCXX11Attributes();
26880b57cec5SDimitry Andric 
26890b57cec5SDimitry Andric     if (Tok.isNot(tok::kw_catch))
26900b57cec5SDimitry Andric       return StmtError(Diag(Tok, diag::err_expected_catch));
26910b57cec5SDimitry Andric     while (Tok.is(tok::kw_catch)) {
26920b57cec5SDimitry Andric       StmtResult Handler(ParseCXXCatchBlock(FnTry));
26930b57cec5SDimitry Andric       if (!Handler.isInvalid())
26940b57cec5SDimitry Andric         Handlers.push_back(Handler.get());
26950b57cec5SDimitry Andric     }
26960b57cec5SDimitry Andric     // Don't bother creating the full statement if we don't have any usable
26970b57cec5SDimitry Andric     // handlers.
26980b57cec5SDimitry Andric     if (Handlers.empty())
26990b57cec5SDimitry Andric       return StmtError();
27000b57cec5SDimitry Andric 
27010b57cec5SDimitry Andric     return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.get(), Handlers);
27020b57cec5SDimitry Andric   }
27030b57cec5SDimitry Andric }
27040b57cec5SDimitry Andric 
27050b57cec5SDimitry Andric /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
27060b57cec5SDimitry Andric ///
27070b57cec5SDimitry Andric ///   handler:
27080b57cec5SDimitry Andric ///     'catch' '(' exception-declaration ')' compound-statement
27090b57cec5SDimitry Andric ///
27100b57cec5SDimitry Andric ///   exception-declaration:
27110b57cec5SDimitry Andric ///     attribute-specifier-seq[opt] type-specifier-seq declarator
27120b57cec5SDimitry Andric ///     attribute-specifier-seq[opt] type-specifier-seq abstract-declarator[opt]
27130b57cec5SDimitry Andric ///     '...'
27140b57cec5SDimitry Andric ///
27150b57cec5SDimitry Andric StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
27160b57cec5SDimitry Andric   assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
27170b57cec5SDimitry Andric 
27180b57cec5SDimitry Andric   SourceLocation CatchLoc = ConsumeToken();
27190b57cec5SDimitry Andric 
27200b57cec5SDimitry Andric   BalancedDelimiterTracker T(*this, tok::l_paren);
27210b57cec5SDimitry Andric   if (T.expectAndConsume())
27220b57cec5SDimitry Andric     return StmtError();
27230b57cec5SDimitry Andric 
27240b57cec5SDimitry Andric   // C++ 3.3.2p3:
27250b57cec5SDimitry Andric   // The name in a catch exception-declaration is local to the handler and
27260b57cec5SDimitry Andric   // shall not be redeclared in the outermost block of the handler.
27270b57cec5SDimitry Andric   ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope |
27280b57cec5SDimitry Andric                                   Scope::CatchScope |
27290b57cec5SDimitry Andric                                   (FnCatch ? Scope::FnTryCatchScope : 0));
27300b57cec5SDimitry Andric 
27310b57cec5SDimitry Andric   // exception-declaration is equivalent to '...' or a parameter-declaration
27320b57cec5SDimitry Andric   // without default arguments.
27330b57cec5SDimitry Andric   Decl *ExceptionDecl = nullptr;
27340b57cec5SDimitry Andric   if (Tok.isNot(tok::ellipsis)) {
273581ad6265SDimitry Andric     ParsedAttributes Attributes(AttrFactory);
27360b57cec5SDimitry Andric     MaybeParseCXX11Attributes(Attributes);
27370b57cec5SDimitry Andric 
27380b57cec5SDimitry Andric     DeclSpec DS(AttrFactory);
27390b57cec5SDimitry Andric 
27400b57cec5SDimitry Andric     if (ParseCXXTypeSpecifierSeq(DS))
27410b57cec5SDimitry Andric       return StmtError();
27420b57cec5SDimitry Andric 
274381ad6265SDimitry Andric     Declarator ExDecl(DS, Attributes, DeclaratorContext::CXXCatch);
27440b57cec5SDimitry Andric     ParseDeclarator(ExDecl);
27450b57cec5SDimitry Andric     ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl);
27460b57cec5SDimitry Andric   } else
27470b57cec5SDimitry Andric     ConsumeToken();
27480b57cec5SDimitry Andric 
27490b57cec5SDimitry Andric   T.consumeClose();
27500b57cec5SDimitry Andric   if (T.getCloseLocation().isInvalid())
27510b57cec5SDimitry Andric     return StmtError();
27520b57cec5SDimitry Andric 
27530b57cec5SDimitry Andric   if (Tok.isNot(tok::l_brace))
27540b57cec5SDimitry Andric     return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
27550b57cec5SDimitry Andric 
27560b57cec5SDimitry Andric   // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
27570b57cec5SDimitry Andric   StmtResult Block(ParseCompoundStatement());
27580b57cec5SDimitry Andric   if (Block.isInvalid())
27590b57cec5SDimitry Andric     return Block;
27600b57cec5SDimitry Andric 
27610b57cec5SDimitry Andric   return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.get());
27620b57cec5SDimitry Andric }
27630b57cec5SDimitry Andric 
27640b57cec5SDimitry Andric void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
27650b57cec5SDimitry Andric   IfExistsCondition Result;
27660b57cec5SDimitry Andric   if (ParseMicrosoftIfExistsCondition(Result))
27670b57cec5SDimitry Andric     return;
27680b57cec5SDimitry Andric 
27690b57cec5SDimitry Andric   // Handle dependent statements by parsing the braces as a compound statement.
27700b57cec5SDimitry Andric   // This is not the same behavior as Visual C++, which don't treat this as a
27710b57cec5SDimitry Andric   // compound statement, but for Clang's type checking we can't have anything
27720b57cec5SDimitry Andric   // inside these braces escaping to the surrounding code.
27730b57cec5SDimitry Andric   if (Result.Behavior == IEB_Dependent) {
27740b57cec5SDimitry Andric     if (!Tok.is(tok::l_brace)) {
27750b57cec5SDimitry Andric       Diag(Tok, diag::err_expected) << tok::l_brace;
27760b57cec5SDimitry Andric       return;
27770b57cec5SDimitry Andric     }
27780b57cec5SDimitry Andric 
27790b57cec5SDimitry Andric     StmtResult Compound = ParseCompoundStatement();
27800b57cec5SDimitry Andric     if (Compound.isInvalid())
27810b57cec5SDimitry Andric       return;
27820b57cec5SDimitry Andric 
27830b57cec5SDimitry Andric     StmtResult DepResult = Actions.ActOnMSDependentExistsStmt(Result.KeywordLoc,
27840b57cec5SDimitry Andric                                                               Result.IsIfExists,
27850b57cec5SDimitry Andric                                                               Result.SS,
27860b57cec5SDimitry Andric                                                               Result.Name,
27870b57cec5SDimitry Andric                                                               Compound.get());
27880b57cec5SDimitry Andric     if (DepResult.isUsable())
27890b57cec5SDimitry Andric       Stmts.push_back(DepResult.get());
27900b57cec5SDimitry Andric     return;
27910b57cec5SDimitry Andric   }
27920b57cec5SDimitry Andric 
27930b57cec5SDimitry Andric   BalancedDelimiterTracker Braces(*this, tok::l_brace);
27940b57cec5SDimitry Andric   if (Braces.consumeOpen()) {
27950b57cec5SDimitry Andric     Diag(Tok, diag::err_expected) << tok::l_brace;
27960b57cec5SDimitry Andric     return;
27970b57cec5SDimitry Andric   }
27980b57cec5SDimitry Andric 
27990b57cec5SDimitry Andric   switch (Result.Behavior) {
28000b57cec5SDimitry Andric   case IEB_Parse:
28010b57cec5SDimitry Andric     // Parse the statements below.
28020b57cec5SDimitry Andric     break;
28030b57cec5SDimitry Andric 
28040b57cec5SDimitry Andric   case IEB_Dependent:
28050b57cec5SDimitry Andric     llvm_unreachable("Dependent case handled above");
28060b57cec5SDimitry Andric 
28070b57cec5SDimitry Andric   case IEB_Skip:
28080b57cec5SDimitry Andric     Braces.skipToEnd();
28090b57cec5SDimitry Andric     return;
28100b57cec5SDimitry Andric   }
28110b57cec5SDimitry Andric 
28120b57cec5SDimitry Andric   // Condition is true, parse the statements.
28130b57cec5SDimitry Andric   while (Tok.isNot(tok::r_brace)) {
28140b57cec5SDimitry Andric     StmtResult R =
28150b57cec5SDimitry Andric         ParseStatementOrDeclaration(Stmts, ParsedStmtContext::Compound);
28160b57cec5SDimitry Andric     if (R.isUsable())
28170b57cec5SDimitry Andric       Stmts.push_back(R.get());
28180b57cec5SDimitry Andric   }
28190b57cec5SDimitry Andric   Braces.consumeClose();
28200b57cec5SDimitry Andric }
2821