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