xref: /openbsd-src/gnu/llvm/clang/lib/Parse/ParseStmt.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements the Statement and Block portions of the Parser
10e5dd7070Spatrick // interface.
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick 
14e5dd7070Spatrick #include "clang/AST/PrettyDeclStackTrace.h"
15e5dd7070Spatrick #include "clang/Basic/Attributes.h"
16e5dd7070Spatrick #include "clang/Basic/PrettyStackTrace.h"
17*12c85518Srobert #include "clang/Basic/TokenKinds.h"
18e5dd7070Spatrick #include "clang/Parse/LoopHint.h"
19e5dd7070Spatrick #include "clang/Parse/Parser.h"
20e5dd7070Spatrick #include "clang/Parse/RAIIObjectsForParser.h"
21e5dd7070Spatrick #include "clang/Sema/DeclSpec.h"
22e5dd7070Spatrick #include "clang/Sema/Scope.h"
23e5dd7070Spatrick #include "clang/Sema/TypoCorrection.h"
24a9ac8606Spatrick #include "llvm/ADT/STLExtras.h"
25*12c85518Srobert #include <optional>
26a9ac8606Spatrick 
27e5dd7070Spatrick using namespace clang;
28e5dd7070Spatrick 
29e5dd7070Spatrick //===----------------------------------------------------------------------===//
30e5dd7070Spatrick // C99 6.8: Statements and Blocks.
31e5dd7070Spatrick //===----------------------------------------------------------------------===//
32e5dd7070Spatrick 
33e5dd7070Spatrick /// Parse a standalone statement (for instance, as the body of an 'if',
34e5dd7070Spatrick /// 'while', or 'for').
ParseStatement(SourceLocation * TrailingElseLoc,ParsedStmtContext StmtCtx)35e5dd7070Spatrick StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc,
36e5dd7070Spatrick                                   ParsedStmtContext StmtCtx) {
37e5dd7070Spatrick   StmtResult Res;
38e5dd7070Spatrick 
39e5dd7070Spatrick   // We may get back a null statement if we found a #pragma. Keep going until
40e5dd7070Spatrick   // we get an actual statement.
41e5dd7070Spatrick   StmtVector Stmts;
42*12c85518Srobert   do {
43e5dd7070Spatrick     Res = ParseStatementOrDeclaration(Stmts, StmtCtx, TrailingElseLoc);
44e5dd7070Spatrick   } while (!Res.isInvalid() && !Res.get());
45e5dd7070Spatrick 
46e5dd7070Spatrick   return Res;
47e5dd7070Spatrick }
48e5dd7070Spatrick 
49e5dd7070Spatrick /// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
50e5dd7070Spatrick ///       StatementOrDeclaration:
51e5dd7070Spatrick ///         statement
52e5dd7070Spatrick ///         declaration
53e5dd7070Spatrick ///
54e5dd7070Spatrick ///       statement:
55e5dd7070Spatrick ///         labeled-statement
56e5dd7070Spatrick ///         compound-statement
57e5dd7070Spatrick ///         expression-statement
58e5dd7070Spatrick ///         selection-statement
59e5dd7070Spatrick ///         iteration-statement
60e5dd7070Spatrick ///         jump-statement
61e5dd7070Spatrick /// [C++]   declaration-statement
62e5dd7070Spatrick /// [C++]   try-block
63e5dd7070Spatrick /// [MS]    seh-try-block
64e5dd7070Spatrick /// [OBC]   objc-throw-statement
65e5dd7070Spatrick /// [OBC]   objc-try-catch-statement
66e5dd7070Spatrick /// [OBC]   objc-synchronized-statement
67e5dd7070Spatrick /// [GNU]   asm-statement
68e5dd7070Spatrick /// [OMP]   openmp-construct             [TODO]
69e5dd7070Spatrick ///
70e5dd7070Spatrick ///       labeled-statement:
71e5dd7070Spatrick ///         identifier ':' statement
72e5dd7070Spatrick ///         'case' constant-expression ':' statement
73e5dd7070Spatrick ///         'default' ':' statement
74e5dd7070Spatrick ///
75e5dd7070Spatrick ///       selection-statement:
76e5dd7070Spatrick ///         if-statement
77e5dd7070Spatrick ///         switch-statement
78e5dd7070Spatrick ///
79e5dd7070Spatrick ///       iteration-statement:
80e5dd7070Spatrick ///         while-statement
81e5dd7070Spatrick ///         do-statement
82e5dd7070Spatrick ///         for-statement
83e5dd7070Spatrick ///
84e5dd7070Spatrick ///       expression-statement:
85e5dd7070Spatrick ///         expression[opt] ';'
86e5dd7070Spatrick ///
87e5dd7070Spatrick ///       jump-statement:
88e5dd7070Spatrick ///         'goto' identifier ';'
89e5dd7070Spatrick ///         'continue' ';'
90e5dd7070Spatrick ///         'break' ';'
91e5dd7070Spatrick ///         'return' expression[opt] ';'
92e5dd7070Spatrick /// [GNU]   'goto' '*' expression ';'
93e5dd7070Spatrick ///
94e5dd7070Spatrick /// [OBC] objc-throw-statement:
95e5dd7070Spatrick /// [OBC]   '@' 'throw' expression ';'
96e5dd7070Spatrick /// [OBC]   '@' 'throw' ';'
97e5dd7070Spatrick ///
98e5dd7070Spatrick StmtResult
ParseStatementOrDeclaration(StmtVector & Stmts,ParsedStmtContext StmtCtx,SourceLocation * TrailingElseLoc)99e5dd7070Spatrick Parser::ParseStatementOrDeclaration(StmtVector &Stmts,
100e5dd7070Spatrick                                     ParsedStmtContext StmtCtx,
101e5dd7070Spatrick                                     SourceLocation *TrailingElseLoc) {
102e5dd7070Spatrick 
103e5dd7070Spatrick   ParenBraceBracketBalancer BalancerRAIIObj(*this);
104e5dd7070Spatrick 
105a9ac8606Spatrick   // Because we're parsing either a statement or a declaration, the order of
106a9ac8606Spatrick   // attribute parsing is important. [[]] attributes at the start of a
107a9ac8606Spatrick   // statement are different from [[]] attributes that follow an __attribute__
108a9ac8606Spatrick   // at the start of the statement. Thus, we're not using MaybeParseAttributes
109a9ac8606Spatrick   // here because we don't want to allow arbitrary orderings.
110*12c85518Srobert   ParsedAttributes CXX11Attrs(AttrFactory);
111*12c85518Srobert   MaybeParseCXX11Attributes(CXX11Attrs, /*MightBeObjCMessageSend*/ true);
112*12c85518Srobert   ParsedAttributes GNUAttrs(AttrFactory);
113a9ac8606Spatrick   if (getLangOpts().OpenCL)
114*12c85518Srobert     MaybeParseGNUAttributes(GNUAttrs);
115e5dd7070Spatrick 
116e5dd7070Spatrick   StmtResult Res = ParseStatementOrDeclarationAfterAttributes(
117*12c85518Srobert       Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs, GNUAttrs);
118ec727ea7Spatrick   MaybeDestroyTemplateIds();
119e5dd7070Spatrick 
120*12c85518Srobert   // Attributes that are left should all go on the statement, so concatenate the
121*12c85518Srobert   // two lists.
122*12c85518Srobert   ParsedAttributes Attrs(AttrFactory);
123*12c85518Srobert   takeAndConcatenateAttrs(CXX11Attrs, GNUAttrs, Attrs);
124*12c85518Srobert 
125e5dd7070Spatrick   assert((Attrs.empty() || Res.isInvalid() || Res.isUsable()) &&
126e5dd7070Spatrick          "attributes on empty statement");
127e5dd7070Spatrick 
128e5dd7070Spatrick   if (Attrs.empty() || Res.isInvalid())
129e5dd7070Spatrick     return Res;
130e5dd7070Spatrick 
131a9ac8606Spatrick   return Actions.ActOnAttributedStmt(Attrs, Res.get());
132e5dd7070Spatrick }
133e5dd7070Spatrick 
134e5dd7070Spatrick namespace {
135e5dd7070Spatrick class StatementFilterCCC final : public CorrectionCandidateCallback {
136e5dd7070Spatrick public:
StatementFilterCCC(Token nextTok)137e5dd7070Spatrick   StatementFilterCCC(Token nextTok) : NextToken(nextTok) {
138e5dd7070Spatrick     WantTypeSpecifiers = nextTok.isOneOf(tok::l_paren, tok::less, tok::l_square,
139e5dd7070Spatrick                                          tok::identifier, tok::star, tok::amp);
140e5dd7070Spatrick     WantExpressionKeywords =
141e5dd7070Spatrick         nextTok.isOneOf(tok::l_paren, tok::identifier, tok::arrow, tok::period);
142e5dd7070Spatrick     WantRemainingKeywords =
143e5dd7070Spatrick         nextTok.isOneOf(tok::l_paren, tok::semi, tok::identifier, tok::l_brace);
144e5dd7070Spatrick     WantCXXNamedCasts = false;
145e5dd7070Spatrick   }
146e5dd7070Spatrick 
ValidateCandidate(const TypoCorrection & candidate)147e5dd7070Spatrick   bool ValidateCandidate(const TypoCorrection &candidate) override {
148e5dd7070Spatrick     if (FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>())
149e5dd7070Spatrick       return !candidate.getCorrectionSpecifier() || isa<ObjCIvarDecl>(FD);
150e5dd7070Spatrick     if (NextToken.is(tok::equal))
151e5dd7070Spatrick       return candidate.getCorrectionDeclAs<VarDecl>();
152e5dd7070Spatrick     if (NextToken.is(tok::period) &&
153e5dd7070Spatrick         candidate.getCorrectionDeclAs<NamespaceDecl>())
154e5dd7070Spatrick       return false;
155e5dd7070Spatrick     return CorrectionCandidateCallback::ValidateCandidate(candidate);
156e5dd7070Spatrick   }
157e5dd7070Spatrick 
clone()158e5dd7070Spatrick   std::unique_ptr<CorrectionCandidateCallback> clone() override {
159e5dd7070Spatrick     return std::make_unique<StatementFilterCCC>(*this);
160e5dd7070Spatrick   }
161e5dd7070Spatrick 
162e5dd7070Spatrick private:
163e5dd7070Spatrick   Token NextToken;
164e5dd7070Spatrick };
165e5dd7070Spatrick }
166e5dd7070Spatrick 
ParseStatementOrDeclarationAfterAttributes(StmtVector & Stmts,ParsedStmtContext StmtCtx,SourceLocation * TrailingElseLoc,ParsedAttributes & CXX11Attrs,ParsedAttributes & GNUAttrs)167e5dd7070Spatrick StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(
168e5dd7070Spatrick     StmtVector &Stmts, ParsedStmtContext StmtCtx,
169*12c85518Srobert     SourceLocation *TrailingElseLoc, ParsedAttributes &CXX11Attrs,
170*12c85518Srobert     ParsedAttributes &GNUAttrs) {
171e5dd7070Spatrick   const char *SemiError = nullptr;
172e5dd7070Spatrick   StmtResult Res;
173e5dd7070Spatrick   SourceLocation GNUAttributeLoc;
174e5dd7070Spatrick 
175e5dd7070Spatrick   // Cases in this switch statement should fall through if the parser expects
176e5dd7070Spatrick   // the token to end in a semicolon (in which case SemiError should be set),
177e5dd7070Spatrick   // or they directly 'return;' if not.
178e5dd7070Spatrick Retry:
179e5dd7070Spatrick   tok::TokenKind Kind  = Tok.getKind();
180e5dd7070Spatrick   SourceLocation AtLoc;
181e5dd7070Spatrick   switch (Kind) {
182e5dd7070Spatrick   case tok::at: // May be a @try or @throw statement
183e5dd7070Spatrick     {
184e5dd7070Spatrick       AtLoc = ConsumeToken();  // consume @
185e5dd7070Spatrick       return ParseObjCAtStatement(AtLoc, StmtCtx);
186e5dd7070Spatrick     }
187e5dd7070Spatrick 
188e5dd7070Spatrick   case tok::code_completion:
189e5dd7070Spatrick     cutOffParsing();
190a9ac8606Spatrick     Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement);
191e5dd7070Spatrick     return StmtError();
192e5dd7070Spatrick 
193*12c85518Srobert   case tok::identifier:
194*12c85518Srobert   ParseIdentifier: {
195e5dd7070Spatrick     Token Next = NextToken();
196e5dd7070Spatrick     if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement
197*12c85518Srobert       // Both C++11 and GNU attributes preceding the label appertain to the
198*12c85518Srobert       // label, so put them in a single list to pass on to
199*12c85518Srobert       // ParseLabeledStatement().
200*12c85518Srobert       ParsedAttributes Attrs(AttrFactory);
201*12c85518Srobert       takeAndConcatenateAttrs(CXX11Attrs, GNUAttrs, Attrs);
202*12c85518Srobert 
203e5dd7070Spatrick       // identifier ':' statement
204e5dd7070Spatrick       return ParseLabeledStatement(Attrs, StmtCtx);
205e5dd7070Spatrick     }
206e5dd7070Spatrick 
207e5dd7070Spatrick     // Look up the identifier, and typo-correct it to a keyword if it's not
208e5dd7070Spatrick     // found.
209e5dd7070Spatrick     if (Next.isNot(tok::coloncolon)) {
210e5dd7070Spatrick       // Try to limit which sets of keywords should be included in typo
211e5dd7070Spatrick       // correction based on what the next token is.
212e5dd7070Spatrick       StatementFilterCCC CCC(Next);
213e5dd7070Spatrick       if (TryAnnotateName(&CCC) == ANK_Error) {
214e5dd7070Spatrick         // Handle errors here by skipping up to the next semicolon or '}', and
215e5dd7070Spatrick         // eat the semicolon if that's what stopped us.
216e5dd7070Spatrick         SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
217e5dd7070Spatrick         if (Tok.is(tok::semi))
218e5dd7070Spatrick           ConsumeToken();
219e5dd7070Spatrick         return StmtError();
220e5dd7070Spatrick       }
221e5dd7070Spatrick 
222e5dd7070Spatrick       // If the identifier was typo-corrected, try again.
223e5dd7070Spatrick       if (Tok.isNot(tok::identifier))
224e5dd7070Spatrick         goto Retry;
225e5dd7070Spatrick     }
226e5dd7070Spatrick 
227e5dd7070Spatrick     // Fall through
228*12c85518Srobert     [[fallthrough]];
229e5dd7070Spatrick   }
230e5dd7070Spatrick 
231e5dd7070Spatrick   default: {
232*12c85518Srobert     bool HaveAttrs = !CXX11Attrs.empty() || !GNUAttrs.empty();
233*12c85518Srobert     auto IsStmtAttr = [](ParsedAttr &Attr) { return Attr.isStmtAttr(); };
234*12c85518Srobert     bool AllAttrsAreStmtAttrs = llvm::all_of(CXX11Attrs, IsStmtAttr) &&
235*12c85518Srobert                                 llvm::all_of(GNUAttrs, IsStmtAttr);
236e5dd7070Spatrick     if ((getLangOpts().CPlusPlus || getLangOpts().MicrosoftExt ||
237e5dd7070Spatrick          (StmtCtx & ParsedStmtContext::AllowDeclarationsInC) !=
238e5dd7070Spatrick              ParsedStmtContext()) &&
239*12c85518Srobert         ((GNUAttributeLoc.isValid() && !(HaveAttrs && AllAttrsAreStmtAttrs)) ||
240a9ac8606Spatrick          isDeclarationStatement())) {
241e5dd7070Spatrick       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
242e5dd7070Spatrick       DeclGroupPtrTy Decl;
243e5dd7070Spatrick       if (GNUAttributeLoc.isValid()) {
244e5dd7070Spatrick         DeclStart = GNUAttributeLoc;
245*12c85518Srobert         Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, CXX11Attrs,
246*12c85518Srobert                                 GNUAttrs, &GNUAttributeLoc);
247e5dd7070Spatrick       } else {
248*12c85518Srobert         Decl = ParseDeclaration(DeclaratorContext::Block, DeclEnd, CXX11Attrs,
249*12c85518Srobert                                 GNUAttrs);
250e5dd7070Spatrick       }
251*12c85518Srobert       if (CXX11Attrs.Range.getBegin().isValid()) {
252*12c85518Srobert         // The caller must guarantee that the CXX11Attrs appear before the
253*12c85518Srobert         // GNUAttrs, and we rely on that here.
254*12c85518Srobert         assert(GNUAttrs.Range.getBegin().isInvalid() ||
255*12c85518Srobert                GNUAttrs.Range.getBegin() > CXX11Attrs.Range.getBegin());
256*12c85518Srobert         DeclStart = CXX11Attrs.Range.getBegin();
257*12c85518Srobert       } else if (GNUAttrs.Range.getBegin().isValid())
258*12c85518Srobert         DeclStart = GNUAttrs.Range.getBegin();
259e5dd7070Spatrick       return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
260e5dd7070Spatrick     }
261e5dd7070Spatrick 
262e5dd7070Spatrick     if (Tok.is(tok::r_brace)) {
263e5dd7070Spatrick       Diag(Tok, diag::err_expected_statement);
264e5dd7070Spatrick       return StmtError();
265e5dd7070Spatrick     }
266e5dd7070Spatrick 
267*12c85518Srobert     switch (Tok.getKind()) {
268*12c85518Srobert #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
269*12c85518Srobert #include "clang/Basic/TransformTypeTraits.def"
270*12c85518Srobert       if (NextToken().is(tok::less)) {
271*12c85518Srobert         Tok.setKind(tok::identifier);
272*12c85518Srobert         Diag(Tok, diag::ext_keyword_as_ident)
273*12c85518Srobert             << Tok.getIdentifierInfo()->getName() << 0;
274*12c85518Srobert         goto ParseIdentifier;
275*12c85518Srobert       }
276*12c85518Srobert       [[fallthrough]];
277*12c85518Srobert     default:
278e5dd7070Spatrick       return ParseExprStatement(StmtCtx);
279e5dd7070Spatrick     }
280*12c85518Srobert   }
281e5dd7070Spatrick 
282e5dd7070Spatrick   case tok::kw___attribute: {
283e5dd7070Spatrick     GNUAttributeLoc = Tok.getLocation();
284*12c85518Srobert     ParseGNUAttributes(GNUAttrs);
285e5dd7070Spatrick     goto Retry;
286e5dd7070Spatrick   }
287e5dd7070Spatrick 
288e5dd7070Spatrick   case tok::kw_case:                // C99 6.8.1: labeled-statement
289e5dd7070Spatrick     return ParseCaseStatement(StmtCtx);
290e5dd7070Spatrick   case tok::kw_default:             // C99 6.8.1: labeled-statement
291e5dd7070Spatrick     return ParseDefaultStatement(StmtCtx);
292e5dd7070Spatrick 
293e5dd7070Spatrick   case tok::l_brace:                // C99 6.8.2: compound-statement
294e5dd7070Spatrick     return ParseCompoundStatement();
295e5dd7070Spatrick   case tok::semi: {                 // C99 6.8.3p3: expression[opt] ';'
296e5dd7070Spatrick     bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro();
297e5dd7070Spatrick     return Actions.ActOnNullStmt(ConsumeToken(), HasLeadingEmptyMacro);
298e5dd7070Spatrick   }
299e5dd7070Spatrick 
300e5dd7070Spatrick   case tok::kw_if:                  // C99 6.8.4.1: if-statement
301e5dd7070Spatrick     return ParseIfStatement(TrailingElseLoc);
302e5dd7070Spatrick   case tok::kw_switch:              // C99 6.8.4.2: switch-statement
303e5dd7070Spatrick     return ParseSwitchStatement(TrailingElseLoc);
304e5dd7070Spatrick 
305e5dd7070Spatrick   case tok::kw_while:               // C99 6.8.5.1: while-statement
306e5dd7070Spatrick     return ParseWhileStatement(TrailingElseLoc);
307e5dd7070Spatrick   case tok::kw_do:                  // C99 6.8.5.2: do-statement
308e5dd7070Spatrick     Res = ParseDoStatement();
309e5dd7070Spatrick     SemiError = "do/while";
310e5dd7070Spatrick     break;
311e5dd7070Spatrick   case tok::kw_for:                 // C99 6.8.5.3: for-statement
312e5dd7070Spatrick     return ParseForStatement(TrailingElseLoc);
313e5dd7070Spatrick 
314e5dd7070Spatrick   case tok::kw_goto:                // C99 6.8.6.1: goto-statement
315e5dd7070Spatrick     Res = ParseGotoStatement();
316e5dd7070Spatrick     SemiError = "goto";
317e5dd7070Spatrick     break;
318e5dd7070Spatrick   case tok::kw_continue:            // C99 6.8.6.2: continue-statement
319e5dd7070Spatrick     Res = ParseContinueStatement();
320e5dd7070Spatrick     SemiError = "continue";
321e5dd7070Spatrick     break;
322e5dd7070Spatrick   case tok::kw_break:               // C99 6.8.6.3: break-statement
323e5dd7070Spatrick     Res = ParseBreakStatement();
324e5dd7070Spatrick     SemiError = "break";
325e5dd7070Spatrick     break;
326e5dd7070Spatrick   case tok::kw_return:              // C99 6.8.6.4: return-statement
327e5dd7070Spatrick     Res = ParseReturnStatement();
328e5dd7070Spatrick     SemiError = "return";
329e5dd7070Spatrick     break;
330e5dd7070Spatrick   case tok::kw_co_return:            // C++ Coroutines: co_return statement
331e5dd7070Spatrick     Res = ParseReturnStatement();
332e5dd7070Spatrick     SemiError = "co_return";
333e5dd7070Spatrick     break;
334e5dd7070Spatrick 
335e5dd7070Spatrick   case tok::kw_asm: {
336*12c85518Srobert     for (const ParsedAttr &AL : CXX11Attrs)
337*12c85518Srobert       Diag(AL.getRange().getBegin(), diag::warn_attribute_ignored) << AL;
338*12c85518Srobert     // Prevent these from being interpreted as statement attributes later on.
339*12c85518Srobert     CXX11Attrs.clear();
340*12c85518Srobert     ProhibitAttributes(GNUAttrs);
341e5dd7070Spatrick     bool msAsm = false;
342e5dd7070Spatrick     Res = ParseAsmStatement(msAsm);
343e5dd7070Spatrick     if (msAsm) return Res;
344e5dd7070Spatrick     SemiError = "asm";
345e5dd7070Spatrick     break;
346e5dd7070Spatrick   }
347e5dd7070Spatrick 
348e5dd7070Spatrick   case tok::kw___if_exists:
349e5dd7070Spatrick   case tok::kw___if_not_exists:
350*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
351*12c85518Srobert     ProhibitAttributes(GNUAttrs);
352e5dd7070Spatrick     ParseMicrosoftIfExistsStatement(Stmts);
353e5dd7070Spatrick     // An __if_exists block is like a compound statement, but it doesn't create
354e5dd7070Spatrick     // a new scope.
355e5dd7070Spatrick     return StmtEmpty();
356e5dd7070Spatrick 
357e5dd7070Spatrick   case tok::kw_try:                 // C++ 15: try-block
358e5dd7070Spatrick     return ParseCXXTryBlock();
359e5dd7070Spatrick 
360e5dd7070Spatrick   case tok::kw___try:
361*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
362*12c85518Srobert     ProhibitAttributes(GNUAttrs);
363e5dd7070Spatrick     return ParseSEHTryBlock();
364e5dd7070Spatrick 
365e5dd7070Spatrick   case tok::kw___leave:
366e5dd7070Spatrick     Res = ParseSEHLeaveStatement();
367e5dd7070Spatrick     SemiError = "__leave";
368e5dd7070Spatrick     break;
369e5dd7070Spatrick 
370e5dd7070Spatrick   case tok::annot_pragma_vis:
371*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
372*12c85518Srobert     ProhibitAttributes(GNUAttrs);
373e5dd7070Spatrick     HandlePragmaVisibility();
374e5dd7070Spatrick     return StmtEmpty();
375e5dd7070Spatrick 
376e5dd7070Spatrick   case tok::annot_pragma_pack:
377*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
378*12c85518Srobert     ProhibitAttributes(GNUAttrs);
379e5dd7070Spatrick     HandlePragmaPack();
380e5dd7070Spatrick     return StmtEmpty();
381e5dd7070Spatrick 
382e5dd7070Spatrick   case tok::annot_pragma_msstruct:
383*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
384*12c85518Srobert     ProhibitAttributes(GNUAttrs);
385e5dd7070Spatrick     HandlePragmaMSStruct();
386e5dd7070Spatrick     return StmtEmpty();
387e5dd7070Spatrick 
388e5dd7070Spatrick   case tok::annot_pragma_align:
389*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
390*12c85518Srobert     ProhibitAttributes(GNUAttrs);
391e5dd7070Spatrick     HandlePragmaAlign();
392e5dd7070Spatrick     return StmtEmpty();
393e5dd7070Spatrick 
394e5dd7070Spatrick   case tok::annot_pragma_weak:
395*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
396*12c85518Srobert     ProhibitAttributes(GNUAttrs);
397e5dd7070Spatrick     HandlePragmaWeak();
398e5dd7070Spatrick     return StmtEmpty();
399e5dd7070Spatrick 
400e5dd7070Spatrick   case tok::annot_pragma_weakalias:
401*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
402*12c85518Srobert     ProhibitAttributes(GNUAttrs);
403e5dd7070Spatrick     HandlePragmaWeakAlias();
404e5dd7070Spatrick     return StmtEmpty();
405e5dd7070Spatrick 
406e5dd7070Spatrick   case tok::annot_pragma_redefine_extname:
407*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
408*12c85518Srobert     ProhibitAttributes(GNUAttrs);
409e5dd7070Spatrick     HandlePragmaRedefineExtname();
410e5dd7070Spatrick     return StmtEmpty();
411e5dd7070Spatrick 
412e5dd7070Spatrick   case tok::annot_pragma_fp_contract:
413*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
414*12c85518Srobert     ProhibitAttributes(GNUAttrs);
415ec727ea7Spatrick     Diag(Tok, diag::err_pragma_file_or_compound_scope) << "fp_contract";
416e5dd7070Spatrick     ConsumeAnnotationToken();
417e5dd7070Spatrick     return StmtError();
418e5dd7070Spatrick 
419e5dd7070Spatrick   case tok::annot_pragma_fp:
420*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
421*12c85518Srobert     ProhibitAttributes(GNUAttrs);
422ec727ea7Spatrick     Diag(Tok, diag::err_pragma_file_or_compound_scope) << "clang fp";
423e5dd7070Spatrick     ConsumeAnnotationToken();
424e5dd7070Spatrick     return StmtError();
425e5dd7070Spatrick 
426e5dd7070Spatrick   case tok::annot_pragma_fenv_access:
427*12c85518Srobert   case tok::annot_pragma_fenv_access_ms:
428*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
429*12c85518Srobert     ProhibitAttributes(GNUAttrs);
430*12c85518Srobert     Diag(Tok, diag::err_pragma_file_or_compound_scope)
431*12c85518Srobert         << (Kind == tok::annot_pragma_fenv_access ? "STDC FENV_ACCESS"
432*12c85518Srobert                                                     : "fenv_access");
433a9ac8606Spatrick     ConsumeAnnotationToken();
434e5dd7070Spatrick     return StmtEmpty();
435e5dd7070Spatrick 
436a9ac8606Spatrick   case tok::annot_pragma_fenv_round:
437*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
438*12c85518Srobert     ProhibitAttributes(GNUAttrs);
439a9ac8606Spatrick     Diag(Tok, diag::err_pragma_file_or_compound_scope) << "STDC FENV_ROUND";
440a9ac8606Spatrick     ConsumeAnnotationToken();
441a9ac8606Spatrick     return StmtError();
442a9ac8606Spatrick 
443ec727ea7Spatrick   case tok::annot_pragma_float_control:
444*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
445*12c85518Srobert     ProhibitAttributes(GNUAttrs);
446ec727ea7Spatrick     Diag(Tok, diag::err_pragma_file_or_compound_scope) << "float_control";
447ec727ea7Spatrick     ConsumeAnnotationToken();
448ec727ea7Spatrick     return StmtError();
449ec727ea7Spatrick 
450e5dd7070Spatrick   case tok::annot_pragma_opencl_extension:
451*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
452*12c85518Srobert     ProhibitAttributes(GNUAttrs);
453e5dd7070Spatrick     HandlePragmaOpenCLExtension();
454e5dd7070Spatrick     return StmtEmpty();
455e5dd7070Spatrick 
456e5dd7070Spatrick   case tok::annot_pragma_captured:
457*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
458*12c85518Srobert     ProhibitAttributes(GNUAttrs);
459e5dd7070Spatrick     return HandlePragmaCaptured();
460e5dd7070Spatrick 
461e5dd7070Spatrick   case tok::annot_pragma_openmp:
462a9ac8606Spatrick     // Prohibit attributes that are not OpenMP attributes, but only before
463a9ac8606Spatrick     // processing a #pragma omp clause.
464*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
465*12c85518Srobert     ProhibitAttributes(GNUAttrs);
466*12c85518Srobert     [[fallthrough]];
467a9ac8606Spatrick   case tok::annot_attr_openmp:
468a9ac8606Spatrick     // Do not prohibit attributes if they were OpenMP attributes.
469e5dd7070Spatrick     return ParseOpenMPDeclarativeOrExecutableDirective(StmtCtx);
470e5dd7070Spatrick 
471e5dd7070Spatrick   case tok::annot_pragma_ms_pointers_to_members:
472*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
473*12c85518Srobert     ProhibitAttributes(GNUAttrs);
474e5dd7070Spatrick     HandlePragmaMSPointersToMembers();
475e5dd7070Spatrick     return StmtEmpty();
476e5dd7070Spatrick 
477e5dd7070Spatrick   case tok::annot_pragma_ms_pragma:
478*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
479*12c85518Srobert     ProhibitAttributes(GNUAttrs);
480e5dd7070Spatrick     HandlePragmaMSPragma();
481e5dd7070Spatrick     return StmtEmpty();
482e5dd7070Spatrick 
483e5dd7070Spatrick   case tok::annot_pragma_ms_vtordisp:
484*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
485*12c85518Srobert     ProhibitAttributes(GNUAttrs);
486e5dd7070Spatrick     HandlePragmaMSVtorDisp();
487e5dd7070Spatrick     return StmtEmpty();
488e5dd7070Spatrick 
489e5dd7070Spatrick   case tok::annot_pragma_loop_hint:
490*12c85518Srobert     ProhibitAttributes(CXX11Attrs);
491*12c85518Srobert     ProhibitAttributes(GNUAttrs);
492*12c85518Srobert     return ParsePragmaLoopHint(Stmts, StmtCtx, TrailingElseLoc, CXX11Attrs);
493e5dd7070Spatrick 
494e5dd7070Spatrick   case tok::annot_pragma_dump:
495e5dd7070Spatrick     HandlePragmaDump();
496e5dd7070Spatrick     return StmtEmpty();
497e5dd7070Spatrick 
498e5dd7070Spatrick   case tok::annot_pragma_attribute:
499e5dd7070Spatrick     HandlePragmaAttribute();
500e5dd7070Spatrick     return StmtEmpty();
501e5dd7070Spatrick   }
502e5dd7070Spatrick 
503e5dd7070Spatrick   // If we reached this code, the statement must end in a semicolon.
504e5dd7070Spatrick   if (!TryConsumeToken(tok::semi) && !Res.isInvalid()) {
505e5dd7070Spatrick     // If the result was valid, then we do want to diagnose this.  Use
506e5dd7070Spatrick     // ExpectAndConsume to emit the diagnostic, even though we know it won't
507e5dd7070Spatrick     // succeed.
508e5dd7070Spatrick     ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
509e5dd7070Spatrick     // Skip until we see a } or ;, but don't eat it.
510e5dd7070Spatrick     SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
511e5dd7070Spatrick   }
512e5dd7070Spatrick 
513e5dd7070Spatrick   return Res;
514e5dd7070Spatrick }
515e5dd7070Spatrick 
516e5dd7070Spatrick /// Parse an expression statement.
ParseExprStatement(ParsedStmtContext StmtCtx)517e5dd7070Spatrick StmtResult Parser::ParseExprStatement(ParsedStmtContext StmtCtx) {
518e5dd7070Spatrick   // If a case keyword is missing, this is where it should be inserted.
519e5dd7070Spatrick   Token OldToken = Tok;
520e5dd7070Spatrick 
521e5dd7070Spatrick   ExprStatementTokLoc = Tok.getLocation();
522e5dd7070Spatrick 
523e5dd7070Spatrick   // expression[opt] ';'
524e5dd7070Spatrick   ExprResult Expr(ParseExpression());
525e5dd7070Spatrick   if (Expr.isInvalid()) {
526e5dd7070Spatrick     // If the expression is invalid, skip ahead to the next semicolon or '}'.
527e5dd7070Spatrick     // Not doing this opens us up to the possibility of infinite loops if
528e5dd7070Spatrick     // ParseExpression does not consume any tokens.
529e5dd7070Spatrick     SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
530e5dd7070Spatrick     if (Tok.is(tok::semi))
531e5dd7070Spatrick       ConsumeToken();
532e5dd7070Spatrick     return Actions.ActOnExprStmtError();
533e5dd7070Spatrick   }
534e5dd7070Spatrick 
535e5dd7070Spatrick   if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() &&
536e5dd7070Spatrick       Actions.CheckCaseExpression(Expr.get())) {
537e5dd7070Spatrick     // If a constant expression is followed by a colon inside a switch block,
538e5dd7070Spatrick     // suggest a missing case keyword.
539e5dd7070Spatrick     Diag(OldToken, diag::err_expected_case_before_expression)
540e5dd7070Spatrick       << FixItHint::CreateInsertion(OldToken.getLocation(), "case ");
541e5dd7070Spatrick 
542e5dd7070Spatrick     // Recover parsing as a case statement.
543e5dd7070Spatrick     return ParseCaseStatement(StmtCtx, /*MissingCase=*/true, Expr);
544e5dd7070Spatrick   }
545e5dd7070Spatrick 
546e5dd7070Spatrick   // Otherwise, eat the semicolon.
547e5dd7070Spatrick   ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
548e5dd7070Spatrick   return handleExprStmt(Expr, StmtCtx);
549e5dd7070Spatrick }
550e5dd7070Spatrick 
551e5dd7070Spatrick /// ParseSEHTryBlockCommon
552e5dd7070Spatrick ///
553e5dd7070Spatrick /// seh-try-block:
554e5dd7070Spatrick ///   '__try' compound-statement seh-handler
555e5dd7070Spatrick ///
556e5dd7070Spatrick /// seh-handler:
557e5dd7070Spatrick ///   seh-except-block
558e5dd7070Spatrick ///   seh-finally-block
559e5dd7070Spatrick ///
ParseSEHTryBlock()560e5dd7070Spatrick StmtResult Parser::ParseSEHTryBlock() {
561e5dd7070Spatrick   assert(Tok.is(tok::kw___try) && "Expected '__try'");
562e5dd7070Spatrick   SourceLocation TryLoc = ConsumeToken();
563e5dd7070Spatrick 
564e5dd7070Spatrick   if (Tok.isNot(tok::l_brace))
565e5dd7070Spatrick     return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
566e5dd7070Spatrick 
567e5dd7070Spatrick   StmtResult TryBlock(ParseCompoundStatement(
568e5dd7070Spatrick       /*isStmtExpr=*/false,
569e5dd7070Spatrick       Scope::DeclScope | Scope::CompoundStmtScope | Scope::SEHTryScope));
570e5dd7070Spatrick   if (TryBlock.isInvalid())
571e5dd7070Spatrick     return TryBlock;
572e5dd7070Spatrick 
573e5dd7070Spatrick   StmtResult Handler;
574e5dd7070Spatrick   if (Tok.is(tok::identifier) &&
575e5dd7070Spatrick       Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
576e5dd7070Spatrick     SourceLocation Loc = ConsumeToken();
577e5dd7070Spatrick     Handler = ParseSEHExceptBlock(Loc);
578e5dd7070Spatrick   } else if (Tok.is(tok::kw___finally)) {
579e5dd7070Spatrick     SourceLocation Loc = ConsumeToken();
580e5dd7070Spatrick     Handler = ParseSEHFinallyBlock(Loc);
581e5dd7070Spatrick   } else {
582e5dd7070Spatrick     return StmtError(Diag(Tok, diag::err_seh_expected_handler));
583e5dd7070Spatrick   }
584e5dd7070Spatrick 
585e5dd7070Spatrick   if(Handler.isInvalid())
586e5dd7070Spatrick     return Handler;
587e5dd7070Spatrick 
588e5dd7070Spatrick   return Actions.ActOnSEHTryBlock(false /* IsCXXTry */,
589e5dd7070Spatrick                                   TryLoc,
590e5dd7070Spatrick                                   TryBlock.get(),
591e5dd7070Spatrick                                   Handler.get());
592e5dd7070Spatrick }
593e5dd7070Spatrick 
594e5dd7070Spatrick /// ParseSEHExceptBlock - Handle __except
595e5dd7070Spatrick ///
596e5dd7070Spatrick /// seh-except-block:
597e5dd7070Spatrick ///   '__except' '(' seh-filter-expression ')' compound-statement
598e5dd7070Spatrick ///
ParseSEHExceptBlock(SourceLocation ExceptLoc)599e5dd7070Spatrick StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) {
600e5dd7070Spatrick   PoisonIdentifierRAIIObject raii(Ident__exception_code, false),
601e5dd7070Spatrick     raii2(Ident___exception_code, false),
602e5dd7070Spatrick     raii3(Ident_GetExceptionCode, false);
603e5dd7070Spatrick 
604e5dd7070Spatrick   if (ExpectAndConsume(tok::l_paren))
605e5dd7070Spatrick     return StmtError();
606e5dd7070Spatrick 
607e5dd7070Spatrick   ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope |
608e5dd7070Spatrick                                    Scope::SEHExceptScope);
609e5dd7070Spatrick 
610e5dd7070Spatrick   if (getLangOpts().Borland) {
611e5dd7070Spatrick     Ident__exception_info->setIsPoisoned(false);
612e5dd7070Spatrick     Ident___exception_info->setIsPoisoned(false);
613e5dd7070Spatrick     Ident_GetExceptionInfo->setIsPoisoned(false);
614e5dd7070Spatrick   }
615e5dd7070Spatrick 
616e5dd7070Spatrick   ExprResult FilterExpr;
617e5dd7070Spatrick   {
618e5dd7070Spatrick     ParseScopeFlags FilterScope(this, getCurScope()->getFlags() |
619e5dd7070Spatrick                                           Scope::SEHFilterScope);
620e5dd7070Spatrick     FilterExpr = Actions.CorrectDelayedTyposInExpr(ParseExpression());
621e5dd7070Spatrick   }
622e5dd7070Spatrick 
623e5dd7070Spatrick   if (getLangOpts().Borland) {
624e5dd7070Spatrick     Ident__exception_info->setIsPoisoned(true);
625e5dd7070Spatrick     Ident___exception_info->setIsPoisoned(true);
626e5dd7070Spatrick     Ident_GetExceptionInfo->setIsPoisoned(true);
627e5dd7070Spatrick   }
628e5dd7070Spatrick 
629e5dd7070Spatrick   if(FilterExpr.isInvalid())
630e5dd7070Spatrick     return StmtError();
631e5dd7070Spatrick 
632e5dd7070Spatrick   if (ExpectAndConsume(tok::r_paren))
633e5dd7070Spatrick     return StmtError();
634e5dd7070Spatrick 
635e5dd7070Spatrick   if (Tok.isNot(tok::l_brace))
636e5dd7070Spatrick     return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
637e5dd7070Spatrick 
638e5dd7070Spatrick   StmtResult Block(ParseCompoundStatement());
639e5dd7070Spatrick 
640e5dd7070Spatrick   if(Block.isInvalid())
641e5dd7070Spatrick     return Block;
642e5dd7070Spatrick 
643e5dd7070Spatrick   return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.get(), Block.get());
644e5dd7070Spatrick }
645e5dd7070Spatrick 
646e5dd7070Spatrick /// ParseSEHFinallyBlock - Handle __finally
647e5dd7070Spatrick ///
648e5dd7070Spatrick /// seh-finally-block:
649e5dd7070Spatrick ///   '__finally' compound-statement
650e5dd7070Spatrick ///
ParseSEHFinallyBlock(SourceLocation FinallyLoc)651e5dd7070Spatrick StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyLoc) {
652e5dd7070Spatrick   PoisonIdentifierRAIIObject raii(Ident__abnormal_termination, false),
653e5dd7070Spatrick     raii2(Ident___abnormal_termination, false),
654e5dd7070Spatrick     raii3(Ident_AbnormalTermination, false);
655e5dd7070Spatrick 
656e5dd7070Spatrick   if (Tok.isNot(tok::l_brace))
657e5dd7070Spatrick     return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
658e5dd7070Spatrick 
659e5dd7070Spatrick   ParseScope FinallyScope(this, 0);
660e5dd7070Spatrick   Actions.ActOnStartSEHFinallyBlock();
661e5dd7070Spatrick 
662e5dd7070Spatrick   StmtResult Block(ParseCompoundStatement());
663e5dd7070Spatrick   if(Block.isInvalid()) {
664e5dd7070Spatrick     Actions.ActOnAbortSEHFinallyBlock();
665e5dd7070Spatrick     return Block;
666e5dd7070Spatrick   }
667e5dd7070Spatrick 
668e5dd7070Spatrick   return Actions.ActOnFinishSEHFinallyBlock(FinallyLoc, Block.get());
669e5dd7070Spatrick }
670e5dd7070Spatrick 
671e5dd7070Spatrick /// Handle __leave
672e5dd7070Spatrick ///
673e5dd7070Spatrick /// seh-leave-statement:
674e5dd7070Spatrick ///   '__leave' ';'
675e5dd7070Spatrick ///
ParseSEHLeaveStatement()676e5dd7070Spatrick StmtResult Parser::ParseSEHLeaveStatement() {
677e5dd7070Spatrick   SourceLocation LeaveLoc = ConsumeToken();  // eat the '__leave'.
678e5dd7070Spatrick   return Actions.ActOnSEHLeaveStmt(LeaveLoc, getCurScope());
679e5dd7070Spatrick }
680e5dd7070Spatrick 
681e5dd7070Spatrick /// ParseLabeledStatement - We have an identifier and a ':' after it.
682e5dd7070Spatrick ///
683*12c85518Srobert ///       label:
684*12c85518Srobert ///         identifier ':'
685*12c85518Srobert /// [GNU]   identifier ':' attributes[opt]
686e5dd7070Spatrick ///
687*12c85518Srobert ///       labeled-statement:
688*12c85518Srobert ///         label statement
689*12c85518Srobert ///
ParseLabeledStatement(ParsedAttributes & Attrs,ParsedStmtContext StmtCtx)690*12c85518Srobert StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs,
691e5dd7070Spatrick                                          ParsedStmtContext StmtCtx) {
692e5dd7070Spatrick   assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
693e5dd7070Spatrick          "Not an identifier!");
694e5dd7070Spatrick 
695e5dd7070Spatrick   // The substatement is always a 'statement', not a 'declaration', but is
696e5dd7070Spatrick   // otherwise in the same context as the labeled-statement.
697e5dd7070Spatrick   StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
698e5dd7070Spatrick 
699e5dd7070Spatrick   Token IdentTok = Tok;  // Save the whole token.
700e5dd7070Spatrick   ConsumeToken();  // eat the identifier.
701e5dd7070Spatrick 
702e5dd7070Spatrick   assert(Tok.is(tok::colon) && "Not a label!");
703e5dd7070Spatrick 
704e5dd7070Spatrick   // identifier ':' statement
705e5dd7070Spatrick   SourceLocation ColonLoc = ConsumeToken();
706e5dd7070Spatrick 
707e5dd7070Spatrick   // Read label attributes, if present.
708e5dd7070Spatrick   StmtResult SubStmt;
709e5dd7070Spatrick   if (Tok.is(tok::kw___attribute)) {
710*12c85518Srobert     ParsedAttributes TempAttrs(AttrFactory);
711e5dd7070Spatrick     ParseGNUAttributes(TempAttrs);
712e5dd7070Spatrick 
713e5dd7070Spatrick     // In C++, GNU attributes only apply to the label if they are followed by a
714e5dd7070Spatrick     // semicolon, to disambiguate label attributes from attributes on a labeled
715e5dd7070Spatrick     // declaration.
716e5dd7070Spatrick     //
717e5dd7070Spatrick     // This doesn't quite match what GCC does; if the attribute list is empty
718e5dd7070Spatrick     // and followed by a semicolon, GCC will reject (it appears to parse the
719e5dd7070Spatrick     // attributes as part of a statement in that case). That looks like a bug.
720e5dd7070Spatrick     if (!getLangOpts().CPlusPlus || Tok.is(tok::semi))
721*12c85518Srobert       Attrs.takeAllFrom(TempAttrs);
722a9ac8606Spatrick     else {
723e5dd7070Spatrick       StmtVector Stmts;
724*12c85518Srobert       ParsedAttributes EmptyCXX11Attrs(AttrFactory);
725*12c85518Srobert       SubStmt = ParseStatementOrDeclarationAfterAttributes(
726*12c85518Srobert           Stmts, StmtCtx, nullptr, EmptyCXX11Attrs, TempAttrs);
727e5dd7070Spatrick       if (!TempAttrs.empty() && !SubStmt.isInvalid())
728a9ac8606Spatrick         SubStmt = Actions.ActOnAttributedStmt(TempAttrs, SubStmt.get());
729e5dd7070Spatrick     }
730e5dd7070Spatrick   }
731e5dd7070Spatrick 
732*12c85518Srobert   // The label may have no statement following it
733*12c85518Srobert   if (SubStmt.isUnset() && Tok.is(tok::r_brace)) {
734*12c85518Srobert     DiagnoseLabelAtEndOfCompoundStatement();
735*12c85518Srobert     SubStmt = Actions.ActOnNullStmt(ColonLoc);
736*12c85518Srobert   }
737*12c85518Srobert 
738e5dd7070Spatrick   // If we've not parsed a statement yet, parse one now.
739e5dd7070Spatrick   if (!SubStmt.isInvalid() && !SubStmt.isUsable())
740e5dd7070Spatrick     SubStmt = ParseStatement(nullptr, StmtCtx);
741e5dd7070Spatrick 
742e5dd7070Spatrick   // Broken substmt shouldn't prevent the label from being added to the AST.
743e5dd7070Spatrick   if (SubStmt.isInvalid())
744e5dd7070Spatrick     SubStmt = Actions.ActOnNullStmt(ColonLoc);
745e5dd7070Spatrick 
746e5dd7070Spatrick   LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(),
747e5dd7070Spatrick                                               IdentTok.getLocation());
748*12c85518Srobert   Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs);
749*12c85518Srobert   Attrs.clear();
750e5dd7070Spatrick 
751e5dd7070Spatrick   return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc,
752e5dd7070Spatrick                                 SubStmt.get());
753e5dd7070Spatrick }
754e5dd7070Spatrick 
755e5dd7070Spatrick /// ParseCaseStatement
756e5dd7070Spatrick ///       labeled-statement:
757e5dd7070Spatrick ///         'case' constant-expression ':' statement
758e5dd7070Spatrick /// [GNU]   'case' constant-expression '...' constant-expression ':' statement
759e5dd7070Spatrick ///
ParseCaseStatement(ParsedStmtContext StmtCtx,bool MissingCase,ExprResult Expr)760e5dd7070Spatrick StmtResult Parser::ParseCaseStatement(ParsedStmtContext StmtCtx,
761e5dd7070Spatrick                                       bool MissingCase, ExprResult Expr) {
762e5dd7070Spatrick   assert((MissingCase || Tok.is(tok::kw_case)) && "Not a case stmt!");
763e5dd7070Spatrick 
764e5dd7070Spatrick   // The substatement is always a 'statement', not a 'declaration', but is
765e5dd7070Spatrick   // otherwise in the same context as the labeled-statement.
766e5dd7070Spatrick   StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
767e5dd7070Spatrick 
768*12c85518Srobert   // It is very common for code to contain many case statements recursively
769e5dd7070Spatrick   // nested, as in (but usually without indentation):
770e5dd7070Spatrick   //  case 1:
771e5dd7070Spatrick   //    case 2:
772e5dd7070Spatrick   //      case 3:
773e5dd7070Spatrick   //         case 4:
774e5dd7070Spatrick   //           case 5: etc.
775e5dd7070Spatrick   //
776e5dd7070Spatrick   // Parsing this naively works, but is both inefficient and can cause us to run
777e5dd7070Spatrick   // out of stack space in our recursive descent parser.  As a special case,
778e5dd7070Spatrick   // flatten this recursion into an iterative loop.  This is complex and gross,
779e5dd7070Spatrick   // but all the grossness is constrained to ParseCaseStatement (and some
780e5dd7070Spatrick   // weirdness in the actions), so this is just local grossness :).
781e5dd7070Spatrick 
782e5dd7070Spatrick   // TopLevelCase - This is the highest level we have parsed.  'case 1' in the
783e5dd7070Spatrick   // example above.
784e5dd7070Spatrick   StmtResult TopLevelCase(true);
785e5dd7070Spatrick 
786e5dd7070Spatrick   // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
787e5dd7070Spatrick   // gets updated each time a new case is parsed, and whose body is unset so
788e5dd7070Spatrick   // far.  When parsing 'case 4', this is the 'case 3' node.
789e5dd7070Spatrick   Stmt *DeepestParsedCaseStmt = nullptr;
790e5dd7070Spatrick 
791e5dd7070Spatrick   // While we have case statements, eat and stack them.
792e5dd7070Spatrick   SourceLocation ColonLoc;
793e5dd7070Spatrick   do {
794e5dd7070Spatrick     SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() :
795e5dd7070Spatrick                                            ConsumeToken();  // eat the 'case'.
796e5dd7070Spatrick     ColonLoc = SourceLocation();
797e5dd7070Spatrick 
798e5dd7070Spatrick     if (Tok.is(tok::code_completion)) {
799e5dd7070Spatrick       cutOffParsing();
800a9ac8606Spatrick       Actions.CodeCompleteCase(getCurScope());
801e5dd7070Spatrick       return StmtError();
802e5dd7070Spatrick     }
803e5dd7070Spatrick 
804e5dd7070Spatrick     /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
805e5dd7070Spatrick     /// Disable this form of error recovery while we're parsing the case
806e5dd7070Spatrick     /// expression.
807e5dd7070Spatrick     ColonProtectionRAIIObject ColonProtection(*this);
808e5dd7070Spatrick 
809e5dd7070Spatrick     ExprResult LHS;
810e5dd7070Spatrick     if (!MissingCase) {
811e5dd7070Spatrick       LHS = ParseCaseExpression(CaseLoc);
812e5dd7070Spatrick       if (LHS.isInvalid()) {
813e5dd7070Spatrick         // If constant-expression is parsed unsuccessfully, recover by skipping
814e5dd7070Spatrick         // current case statement (moving to the colon that ends it).
815e5dd7070Spatrick         if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
816e5dd7070Spatrick           return StmtError();
817e5dd7070Spatrick       }
818e5dd7070Spatrick     } else {
819e5dd7070Spatrick       LHS = Expr;
820e5dd7070Spatrick       MissingCase = false;
821e5dd7070Spatrick     }
822e5dd7070Spatrick 
823e5dd7070Spatrick     // GNU case range extension.
824e5dd7070Spatrick     SourceLocation DotDotDotLoc;
825e5dd7070Spatrick     ExprResult RHS;
826e5dd7070Spatrick     if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) {
827e5dd7070Spatrick       Diag(DotDotDotLoc, diag::ext_gnu_case_range);
828e5dd7070Spatrick       RHS = ParseCaseExpression(CaseLoc);
829e5dd7070Spatrick       if (RHS.isInvalid()) {
830e5dd7070Spatrick         if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch))
831e5dd7070Spatrick           return StmtError();
832e5dd7070Spatrick       }
833e5dd7070Spatrick     }
834e5dd7070Spatrick 
835e5dd7070Spatrick     ColonProtection.restore();
836e5dd7070Spatrick 
837e5dd7070Spatrick     if (TryConsumeToken(tok::colon, ColonLoc)) {
838e5dd7070Spatrick     } else if (TryConsumeToken(tok::semi, ColonLoc) ||
839e5dd7070Spatrick                TryConsumeToken(tok::coloncolon, ColonLoc)) {
840e5dd7070Spatrick       // Treat "case blah;" or "case blah::" as a typo for "case blah:".
841e5dd7070Spatrick       Diag(ColonLoc, diag::err_expected_after)
842e5dd7070Spatrick           << "'case'" << tok::colon
843e5dd7070Spatrick           << FixItHint::CreateReplacement(ColonLoc, ":");
844e5dd7070Spatrick     } else {
845e5dd7070Spatrick       SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
846e5dd7070Spatrick       Diag(ExpectedLoc, diag::err_expected_after)
847e5dd7070Spatrick           << "'case'" << tok::colon
848e5dd7070Spatrick           << FixItHint::CreateInsertion(ExpectedLoc, ":");
849e5dd7070Spatrick       ColonLoc = ExpectedLoc;
850e5dd7070Spatrick     }
851e5dd7070Spatrick 
852e5dd7070Spatrick     StmtResult Case =
853e5dd7070Spatrick         Actions.ActOnCaseStmt(CaseLoc, LHS, DotDotDotLoc, RHS, ColonLoc);
854e5dd7070Spatrick 
855e5dd7070Spatrick     // If we had a sema error parsing this case, then just ignore it and
856e5dd7070Spatrick     // continue parsing the sub-stmt.
857e5dd7070Spatrick     if (Case.isInvalid()) {
858e5dd7070Spatrick       if (TopLevelCase.isInvalid())  // No parsed case stmts.
859e5dd7070Spatrick         return ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
860e5dd7070Spatrick       // Otherwise, just don't add it as a nested case.
861e5dd7070Spatrick     } else {
862e5dd7070Spatrick       // If this is the first case statement we parsed, it becomes TopLevelCase.
863e5dd7070Spatrick       // Otherwise we link it into the current chain.
864e5dd7070Spatrick       Stmt *NextDeepest = Case.get();
865e5dd7070Spatrick       if (TopLevelCase.isInvalid())
866e5dd7070Spatrick         TopLevelCase = Case;
867e5dd7070Spatrick       else
868e5dd7070Spatrick         Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, Case.get());
869e5dd7070Spatrick       DeepestParsedCaseStmt = NextDeepest;
870e5dd7070Spatrick     }
871e5dd7070Spatrick 
872e5dd7070Spatrick     // Handle all case statements.
873e5dd7070Spatrick   } while (Tok.is(tok::kw_case));
874e5dd7070Spatrick 
875e5dd7070Spatrick   // If we found a non-case statement, start by parsing it.
876e5dd7070Spatrick   StmtResult SubStmt;
877e5dd7070Spatrick 
878*12c85518Srobert   if (Tok.is(tok::r_brace)) {
879*12c85518Srobert     // "switch (X) { case 4: }", is valid and is treated as if label was
880*12c85518Srobert     // followed by a null statement.
881*12c85518Srobert     DiagnoseLabelAtEndOfCompoundStatement();
882*12c85518Srobert     SubStmt = Actions.ActOnNullStmt(ColonLoc);
883e5dd7070Spatrick   } else {
884*12c85518Srobert     SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
885e5dd7070Spatrick   }
886e5dd7070Spatrick 
887e5dd7070Spatrick   // Install the body into the most deeply-nested case.
888e5dd7070Spatrick   if (DeepestParsedCaseStmt) {
889e5dd7070Spatrick     // Broken sub-stmt shouldn't prevent forming the case statement properly.
890e5dd7070Spatrick     if (SubStmt.isInvalid())
891e5dd7070Spatrick       SubStmt = Actions.ActOnNullStmt(SourceLocation());
892e5dd7070Spatrick     Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get());
893e5dd7070Spatrick   }
894e5dd7070Spatrick 
895e5dd7070Spatrick   // Return the top level parsed statement tree.
896e5dd7070Spatrick   return TopLevelCase;
897e5dd7070Spatrick }
898e5dd7070Spatrick 
899e5dd7070Spatrick /// ParseDefaultStatement
900e5dd7070Spatrick ///       labeled-statement:
901e5dd7070Spatrick ///         'default' ':' statement
902e5dd7070Spatrick /// Note that this does not parse the 'statement' at the end.
903e5dd7070Spatrick ///
ParseDefaultStatement(ParsedStmtContext StmtCtx)904e5dd7070Spatrick StmtResult Parser::ParseDefaultStatement(ParsedStmtContext StmtCtx) {
905e5dd7070Spatrick   assert(Tok.is(tok::kw_default) && "Not a default stmt!");
906e5dd7070Spatrick 
907e5dd7070Spatrick   // The substatement is always a 'statement', not a 'declaration', but is
908e5dd7070Spatrick   // otherwise in the same context as the labeled-statement.
909e5dd7070Spatrick   StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
910e5dd7070Spatrick 
911e5dd7070Spatrick   SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
912e5dd7070Spatrick 
913e5dd7070Spatrick   SourceLocation ColonLoc;
914e5dd7070Spatrick   if (TryConsumeToken(tok::colon, ColonLoc)) {
915e5dd7070Spatrick   } else if (TryConsumeToken(tok::semi, ColonLoc)) {
916e5dd7070Spatrick     // Treat "default;" as a typo for "default:".
917e5dd7070Spatrick     Diag(ColonLoc, diag::err_expected_after)
918e5dd7070Spatrick         << "'default'" << tok::colon
919e5dd7070Spatrick         << FixItHint::CreateReplacement(ColonLoc, ":");
920e5dd7070Spatrick   } else {
921e5dd7070Spatrick     SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation);
922e5dd7070Spatrick     Diag(ExpectedLoc, diag::err_expected_after)
923e5dd7070Spatrick         << "'default'" << tok::colon
924e5dd7070Spatrick         << FixItHint::CreateInsertion(ExpectedLoc, ":");
925e5dd7070Spatrick     ColonLoc = ExpectedLoc;
926e5dd7070Spatrick   }
927e5dd7070Spatrick 
928e5dd7070Spatrick   StmtResult SubStmt;
929e5dd7070Spatrick 
930*12c85518Srobert   if (Tok.is(tok::r_brace)) {
931*12c85518Srobert     // "switch (X) {... default: }", is valid and is treated as if label was
932*12c85518Srobert     // followed by a null statement.
933*12c85518Srobert     DiagnoseLabelAtEndOfCompoundStatement();
934*12c85518Srobert     SubStmt = Actions.ActOnNullStmt(ColonLoc);
935e5dd7070Spatrick   } else {
936*12c85518Srobert     SubStmt = ParseStatement(/*TrailingElseLoc=*/nullptr, StmtCtx);
937e5dd7070Spatrick   }
938e5dd7070Spatrick 
939e5dd7070Spatrick   // Broken sub-stmt shouldn't prevent forming the case statement properly.
940e5dd7070Spatrick   if (SubStmt.isInvalid())
941e5dd7070Spatrick     SubStmt = Actions.ActOnNullStmt(ColonLoc);
942e5dd7070Spatrick 
943e5dd7070Spatrick   return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
944e5dd7070Spatrick                                   SubStmt.get(), getCurScope());
945e5dd7070Spatrick }
946e5dd7070Spatrick 
ParseCompoundStatement(bool isStmtExpr)947e5dd7070Spatrick StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
948e5dd7070Spatrick   return ParseCompoundStatement(isStmtExpr,
949e5dd7070Spatrick                                 Scope::DeclScope | Scope::CompoundStmtScope);
950e5dd7070Spatrick }
951e5dd7070Spatrick 
952e5dd7070Spatrick /// ParseCompoundStatement - Parse a "{}" block.
953e5dd7070Spatrick ///
954e5dd7070Spatrick ///       compound-statement: [C99 6.8.2]
955e5dd7070Spatrick ///         { block-item-list[opt] }
956e5dd7070Spatrick /// [GNU]   { label-declarations block-item-list } [TODO]
957e5dd7070Spatrick ///
958e5dd7070Spatrick ///       block-item-list:
959e5dd7070Spatrick ///         block-item
960e5dd7070Spatrick ///         block-item-list block-item
961e5dd7070Spatrick ///
962e5dd7070Spatrick ///       block-item:
963e5dd7070Spatrick ///         declaration
964e5dd7070Spatrick /// [GNU]   '__extension__' declaration
965e5dd7070Spatrick ///         statement
966e5dd7070Spatrick ///
967e5dd7070Spatrick /// [GNU] label-declarations:
968e5dd7070Spatrick /// [GNU]   label-declaration
969e5dd7070Spatrick /// [GNU]   label-declarations label-declaration
970e5dd7070Spatrick ///
971e5dd7070Spatrick /// [GNU] label-declaration:
972e5dd7070Spatrick /// [GNU]   '__label__' identifier-list ';'
973e5dd7070Spatrick ///
ParseCompoundStatement(bool isStmtExpr,unsigned ScopeFlags)974e5dd7070Spatrick StmtResult Parser::ParseCompoundStatement(bool isStmtExpr,
975e5dd7070Spatrick                                           unsigned ScopeFlags) {
976*12c85518Srobert   assert(Tok.is(tok::l_brace) && "Not a compound stmt!");
977e5dd7070Spatrick 
978e5dd7070Spatrick   // Enter a scope to hold everything within the compound stmt.  Compound
979e5dd7070Spatrick   // statements can always hold declarations.
980e5dd7070Spatrick   ParseScope CompoundScope(this, ScopeFlags);
981e5dd7070Spatrick 
982e5dd7070Spatrick   // Parse the statements in the body.
983e5dd7070Spatrick   return ParseCompoundStatementBody(isStmtExpr);
984e5dd7070Spatrick }
985e5dd7070Spatrick 
986e5dd7070Spatrick /// Parse any pragmas at the start of the compound expression. We handle these
987e5dd7070Spatrick /// separately since some pragmas (FP_CONTRACT) must appear before any C
988e5dd7070Spatrick /// statement in the compound, but may be intermingled with other pragmas.
ParseCompoundStatementLeadingPragmas()989e5dd7070Spatrick void Parser::ParseCompoundStatementLeadingPragmas() {
990e5dd7070Spatrick   bool checkForPragmas = true;
991e5dd7070Spatrick   while (checkForPragmas) {
992e5dd7070Spatrick     switch (Tok.getKind()) {
993e5dd7070Spatrick     case tok::annot_pragma_vis:
994e5dd7070Spatrick       HandlePragmaVisibility();
995e5dd7070Spatrick       break;
996e5dd7070Spatrick     case tok::annot_pragma_pack:
997e5dd7070Spatrick       HandlePragmaPack();
998e5dd7070Spatrick       break;
999e5dd7070Spatrick     case tok::annot_pragma_msstruct:
1000e5dd7070Spatrick       HandlePragmaMSStruct();
1001e5dd7070Spatrick       break;
1002e5dd7070Spatrick     case tok::annot_pragma_align:
1003e5dd7070Spatrick       HandlePragmaAlign();
1004e5dd7070Spatrick       break;
1005e5dd7070Spatrick     case tok::annot_pragma_weak:
1006e5dd7070Spatrick       HandlePragmaWeak();
1007e5dd7070Spatrick       break;
1008e5dd7070Spatrick     case tok::annot_pragma_weakalias:
1009e5dd7070Spatrick       HandlePragmaWeakAlias();
1010e5dd7070Spatrick       break;
1011e5dd7070Spatrick     case tok::annot_pragma_redefine_extname:
1012e5dd7070Spatrick       HandlePragmaRedefineExtname();
1013e5dd7070Spatrick       break;
1014e5dd7070Spatrick     case tok::annot_pragma_opencl_extension:
1015e5dd7070Spatrick       HandlePragmaOpenCLExtension();
1016e5dd7070Spatrick       break;
1017e5dd7070Spatrick     case tok::annot_pragma_fp_contract:
1018e5dd7070Spatrick       HandlePragmaFPContract();
1019e5dd7070Spatrick       break;
1020e5dd7070Spatrick     case tok::annot_pragma_fp:
1021e5dd7070Spatrick       HandlePragmaFP();
1022e5dd7070Spatrick       break;
1023e5dd7070Spatrick     case tok::annot_pragma_fenv_access:
1024*12c85518Srobert     case tok::annot_pragma_fenv_access_ms:
1025e5dd7070Spatrick       HandlePragmaFEnvAccess();
1026e5dd7070Spatrick       break;
1027a9ac8606Spatrick     case tok::annot_pragma_fenv_round:
1028a9ac8606Spatrick       HandlePragmaFEnvRound();
1029a9ac8606Spatrick       break;
1030ec727ea7Spatrick     case tok::annot_pragma_float_control:
1031ec727ea7Spatrick       HandlePragmaFloatControl();
1032ec727ea7Spatrick       break;
1033e5dd7070Spatrick     case tok::annot_pragma_ms_pointers_to_members:
1034e5dd7070Spatrick       HandlePragmaMSPointersToMembers();
1035e5dd7070Spatrick       break;
1036e5dd7070Spatrick     case tok::annot_pragma_ms_pragma:
1037e5dd7070Spatrick       HandlePragmaMSPragma();
1038e5dd7070Spatrick       break;
1039e5dd7070Spatrick     case tok::annot_pragma_ms_vtordisp:
1040e5dd7070Spatrick       HandlePragmaMSVtorDisp();
1041e5dd7070Spatrick       break;
1042e5dd7070Spatrick     case tok::annot_pragma_dump:
1043e5dd7070Spatrick       HandlePragmaDump();
1044e5dd7070Spatrick       break;
1045e5dd7070Spatrick     default:
1046e5dd7070Spatrick       checkForPragmas = false;
1047e5dd7070Spatrick       break;
1048e5dd7070Spatrick     }
1049e5dd7070Spatrick   }
1050e5dd7070Spatrick 
1051e5dd7070Spatrick }
1052e5dd7070Spatrick 
DiagnoseLabelAtEndOfCompoundStatement()1053*12c85518Srobert void Parser::DiagnoseLabelAtEndOfCompoundStatement() {
1054*12c85518Srobert   if (getLangOpts().CPlusPlus) {
1055*12c85518Srobert     Diag(Tok, getLangOpts().CPlusPlus2b
1056*12c85518Srobert                   ? diag::warn_cxx20_compat_label_end_of_compound_statement
1057*12c85518Srobert                   : diag::ext_cxx_label_end_of_compound_statement);
1058*12c85518Srobert   } else {
1059*12c85518Srobert     Diag(Tok, getLangOpts().C2x
1060*12c85518Srobert                   ? diag::warn_c2x_compat_label_end_of_compound_statement
1061*12c85518Srobert                   : diag::ext_c_label_end_of_compound_statement);
1062*12c85518Srobert   }
1063*12c85518Srobert }
1064*12c85518Srobert 
1065e5dd7070Spatrick /// Consume any extra semi-colons resulting in null statements,
1066e5dd7070Spatrick /// returning true if any tok::semi were consumed.
ConsumeNullStmt(StmtVector & Stmts)1067e5dd7070Spatrick bool Parser::ConsumeNullStmt(StmtVector &Stmts) {
1068e5dd7070Spatrick   if (!Tok.is(tok::semi))
1069e5dd7070Spatrick     return false;
1070e5dd7070Spatrick 
1071e5dd7070Spatrick   SourceLocation StartLoc = Tok.getLocation();
1072e5dd7070Spatrick   SourceLocation EndLoc;
1073e5dd7070Spatrick 
1074e5dd7070Spatrick   while (Tok.is(tok::semi) && !Tok.hasLeadingEmptyMacro() &&
1075e5dd7070Spatrick          Tok.getLocation().isValid() && !Tok.getLocation().isMacroID()) {
1076e5dd7070Spatrick     EndLoc = Tok.getLocation();
1077e5dd7070Spatrick 
1078e5dd7070Spatrick     // Don't just ConsumeToken() this tok::semi, do store it in AST.
1079e5dd7070Spatrick     StmtResult R =
1080e5dd7070Spatrick         ParseStatementOrDeclaration(Stmts, ParsedStmtContext::SubStmt);
1081e5dd7070Spatrick     if (R.isUsable())
1082e5dd7070Spatrick       Stmts.push_back(R.get());
1083e5dd7070Spatrick   }
1084e5dd7070Spatrick 
1085e5dd7070Spatrick   // Did not consume any extra semi.
1086e5dd7070Spatrick   if (EndLoc.isInvalid())
1087e5dd7070Spatrick     return false;
1088e5dd7070Spatrick 
1089e5dd7070Spatrick   Diag(StartLoc, diag::warn_null_statement)
1090e5dd7070Spatrick       << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc));
1091e5dd7070Spatrick   return true;
1092e5dd7070Spatrick }
1093e5dd7070Spatrick 
handleExprStmt(ExprResult E,ParsedStmtContext StmtCtx)1094e5dd7070Spatrick StmtResult Parser::handleExprStmt(ExprResult E, ParsedStmtContext StmtCtx) {
1095e5dd7070Spatrick   bool IsStmtExprResult = false;
1096e5dd7070Spatrick   if ((StmtCtx & ParsedStmtContext::InStmtExpr) != ParsedStmtContext()) {
1097e5dd7070Spatrick     // For GCC compatibility we skip past NullStmts.
1098e5dd7070Spatrick     unsigned LookAhead = 0;
1099e5dd7070Spatrick     while (GetLookAheadToken(LookAhead).is(tok::semi)) {
1100e5dd7070Spatrick       ++LookAhead;
1101e5dd7070Spatrick     }
1102e5dd7070Spatrick     // Then look to see if the next two tokens close the statement expression;
1103e5dd7070Spatrick     // if so, this expression statement is the last statement in a statment
1104e5dd7070Spatrick     // expression.
1105e5dd7070Spatrick     IsStmtExprResult = GetLookAheadToken(LookAhead).is(tok::r_brace) &&
1106e5dd7070Spatrick                        GetLookAheadToken(LookAhead + 1).is(tok::r_paren);
1107e5dd7070Spatrick   }
1108e5dd7070Spatrick 
1109e5dd7070Spatrick   if (IsStmtExprResult)
1110e5dd7070Spatrick     E = Actions.ActOnStmtExprResult(E);
1111e5dd7070Spatrick   return Actions.ActOnExprStmt(E, /*DiscardedValue=*/!IsStmtExprResult);
1112e5dd7070Spatrick }
1113e5dd7070Spatrick 
1114*12c85518Srobert /// ParseCompoundStatementBody - Parse a sequence of statements optionally
1115*12c85518Srobert /// followed by a label and invoke the ActOnCompoundStmt action.  This expects
1116*12c85518Srobert /// the '{' to be the current token, and consume the '}' at the end of the
1117*12c85518Srobert /// block.  It does not manipulate the scope stack.
ParseCompoundStatementBody(bool isStmtExpr)1118e5dd7070Spatrick StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
1119e5dd7070Spatrick   PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
1120e5dd7070Spatrick                                 Tok.getLocation(),
1121e5dd7070Spatrick                                 "in compound statement ('{}')");
1122e5dd7070Spatrick 
1123a9ac8606Spatrick   // Record the current FPFeatures, restore on leaving the
1124e5dd7070Spatrick   // compound statement.
1125a9ac8606Spatrick   Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
1126e5dd7070Spatrick 
1127e5dd7070Spatrick   InMessageExpressionRAIIObject InMessage(*this, false);
1128e5dd7070Spatrick   BalancedDelimiterTracker T(*this, tok::l_brace);
1129e5dd7070Spatrick   if (T.consumeOpen())
1130e5dd7070Spatrick     return StmtError();
1131e5dd7070Spatrick 
1132e5dd7070Spatrick   Sema::CompoundScopeRAII CompoundScope(Actions, isStmtExpr);
1133e5dd7070Spatrick 
1134e5dd7070Spatrick   // Parse any pragmas at the beginning of the compound statement.
1135e5dd7070Spatrick   ParseCompoundStatementLeadingPragmas();
1136a9ac8606Spatrick   Actions.ActOnAfterCompoundStatementLeadingPragmas();
1137e5dd7070Spatrick 
1138e5dd7070Spatrick   StmtVector Stmts;
1139e5dd7070Spatrick 
1140e5dd7070Spatrick   // "__label__ X, Y, Z;" is the GNU "Local Label" extension.  These are
1141e5dd7070Spatrick   // only allowed at the start of a compound stmt regardless of the language.
1142e5dd7070Spatrick   while (Tok.is(tok::kw___label__)) {
1143e5dd7070Spatrick     SourceLocation LabelLoc = ConsumeToken();
1144e5dd7070Spatrick 
1145e5dd7070Spatrick     SmallVector<Decl *, 8> DeclsInGroup;
1146*12c85518Srobert     while (true) {
1147e5dd7070Spatrick       if (Tok.isNot(tok::identifier)) {
1148e5dd7070Spatrick         Diag(Tok, diag::err_expected) << tok::identifier;
1149e5dd7070Spatrick         break;
1150e5dd7070Spatrick       }
1151e5dd7070Spatrick 
1152e5dd7070Spatrick       IdentifierInfo *II = Tok.getIdentifierInfo();
1153e5dd7070Spatrick       SourceLocation IdLoc = ConsumeToken();
1154e5dd7070Spatrick       DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc));
1155e5dd7070Spatrick 
1156e5dd7070Spatrick       if (!TryConsumeToken(tok::comma))
1157e5dd7070Spatrick         break;
1158e5dd7070Spatrick     }
1159e5dd7070Spatrick 
1160e5dd7070Spatrick     DeclSpec DS(AttrFactory);
1161e5dd7070Spatrick     DeclGroupPtrTy Res =
1162e5dd7070Spatrick         Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
1163e5dd7070Spatrick     StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation());
1164e5dd7070Spatrick 
1165e5dd7070Spatrick     ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
1166e5dd7070Spatrick     if (R.isUsable())
1167e5dd7070Spatrick       Stmts.push_back(R.get());
1168e5dd7070Spatrick   }
1169e5dd7070Spatrick 
1170e5dd7070Spatrick   ParsedStmtContext SubStmtCtx =
1171e5dd7070Spatrick       ParsedStmtContext::Compound |
1172e5dd7070Spatrick       (isStmtExpr ? ParsedStmtContext::InStmtExpr : ParsedStmtContext());
1173e5dd7070Spatrick 
1174e5dd7070Spatrick   while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
1175e5dd7070Spatrick          Tok.isNot(tok::eof)) {
1176e5dd7070Spatrick     if (Tok.is(tok::annot_pragma_unused)) {
1177e5dd7070Spatrick       HandlePragmaUnused();
1178e5dd7070Spatrick       continue;
1179e5dd7070Spatrick     }
1180e5dd7070Spatrick 
1181e5dd7070Spatrick     if (ConsumeNullStmt(Stmts))
1182e5dd7070Spatrick       continue;
1183e5dd7070Spatrick 
1184e5dd7070Spatrick     StmtResult R;
1185e5dd7070Spatrick     if (Tok.isNot(tok::kw___extension__)) {
1186e5dd7070Spatrick       R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
1187e5dd7070Spatrick     } else {
1188e5dd7070Spatrick       // __extension__ can start declarations and it can also be a unary
1189e5dd7070Spatrick       // operator for expressions.  Consume multiple __extension__ markers here
1190e5dd7070Spatrick       // until we can determine which is which.
1191e5dd7070Spatrick       // FIXME: This loses extension expressions in the AST!
1192e5dd7070Spatrick       SourceLocation ExtLoc = ConsumeToken();
1193e5dd7070Spatrick       while (Tok.is(tok::kw___extension__))
1194e5dd7070Spatrick         ConsumeToken();
1195e5dd7070Spatrick 
1196*12c85518Srobert       ParsedAttributes attrs(AttrFactory);
1197*12c85518Srobert       MaybeParseCXX11Attributes(attrs, /*MightBeObjCMessageSend*/ true);
1198e5dd7070Spatrick 
1199e5dd7070Spatrick       // If this is the start of a declaration, parse it as such.
1200e5dd7070Spatrick       if (isDeclarationStatement()) {
1201e5dd7070Spatrick         // __extension__ silences extension warnings in the subdeclaration.
1202e5dd7070Spatrick         // FIXME: Save the __extension__ on the decl as a node somehow?
1203e5dd7070Spatrick         ExtensionRAIIObject O(Diags);
1204e5dd7070Spatrick 
1205e5dd7070Spatrick         SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
1206*12c85518Srobert         ParsedAttributes DeclSpecAttrs(AttrFactory);
1207*12c85518Srobert         DeclGroupPtrTy Res = ParseDeclaration(DeclaratorContext::Block, DeclEnd,
1208*12c85518Srobert                                               attrs, DeclSpecAttrs);
1209e5dd7070Spatrick         R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
1210e5dd7070Spatrick       } else {
1211e5dd7070Spatrick         // Otherwise this was a unary __extension__ marker.
1212e5dd7070Spatrick         ExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
1213e5dd7070Spatrick 
1214e5dd7070Spatrick         if (Res.isInvalid()) {
1215e5dd7070Spatrick           SkipUntil(tok::semi);
1216e5dd7070Spatrick           continue;
1217e5dd7070Spatrick         }
1218e5dd7070Spatrick 
1219e5dd7070Spatrick         // Eat the semicolon at the end of stmt and convert the expr into a
1220e5dd7070Spatrick         // statement.
1221e5dd7070Spatrick         ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
1222e5dd7070Spatrick         R = handleExprStmt(Res, SubStmtCtx);
1223e5dd7070Spatrick         if (R.isUsable())
1224a9ac8606Spatrick           R = Actions.ActOnAttributedStmt(attrs, R.get());
1225e5dd7070Spatrick       }
1226e5dd7070Spatrick     }
1227e5dd7070Spatrick 
1228e5dd7070Spatrick     if (R.isUsable())
1229e5dd7070Spatrick       Stmts.push_back(R.get());
1230e5dd7070Spatrick   }
1231*12c85518Srobert   // Warn the user that using option `-ffp-eval-method=source` on a
1232*12c85518Srobert   // 32-bit target and feature `sse` disabled, or using
1233*12c85518Srobert   // `pragma clang fp eval_method=source` and feature `sse` disabled, is not
1234*12c85518Srobert   // supported.
1235*12c85518Srobert   if (!PP.getTargetInfo().supportSourceEvalMethod() &&
1236*12c85518Srobert       (PP.getLastFPEvalPragmaLocation().isValid() ||
1237*12c85518Srobert        PP.getCurrentFPEvalMethod() ==
1238*12c85518Srobert            LangOptions::FPEvalMethodKind::FEM_Source))
1239*12c85518Srobert     Diag(Tok.getLocation(),
1240*12c85518Srobert          diag::warn_no_support_for_eval_method_source_on_m32);
1241e5dd7070Spatrick 
1242e5dd7070Spatrick   SourceLocation CloseLoc = Tok.getLocation();
1243e5dd7070Spatrick 
1244e5dd7070Spatrick   // We broke out of the while loop because we found a '}' or EOF.
1245a9ac8606Spatrick   if (!T.consumeClose()) {
1246a9ac8606Spatrick     // If this is the '})' of a statement expression, check that it's written
1247a9ac8606Spatrick     // in a sensible way.
1248a9ac8606Spatrick     if (isStmtExpr && Tok.is(tok::r_paren))
1249a9ac8606Spatrick       checkCompoundToken(CloseLoc, tok::r_brace, CompoundToken::StmtExprEnd);
1250a9ac8606Spatrick   } else {
1251e5dd7070Spatrick     // Recover by creating a compound statement with what we parsed so far,
1252a9ac8606Spatrick     // instead of dropping everything and returning StmtError().
1253a9ac8606Spatrick   }
1254a9ac8606Spatrick 
1255a9ac8606Spatrick   if (T.getCloseLocation().isValid())
1256e5dd7070Spatrick     CloseLoc = T.getCloseLocation();
1257e5dd7070Spatrick 
1258e5dd7070Spatrick   return Actions.ActOnCompoundStmt(T.getOpenLocation(), CloseLoc,
1259e5dd7070Spatrick                                    Stmts, isStmtExpr);
1260e5dd7070Spatrick }
1261e5dd7070Spatrick 
1262e5dd7070Spatrick /// ParseParenExprOrCondition:
1263e5dd7070Spatrick /// [C  ]     '(' expression ')'
1264e5dd7070Spatrick /// [C++]     '(' condition ')'
1265e5dd7070Spatrick /// [C++1z]   '(' init-statement[opt] condition ')'
1266e5dd7070Spatrick ///
1267e5dd7070Spatrick /// This function parses and performs error recovery on the specified condition
1268e5dd7070Spatrick /// or expression (depending on whether we're in C++ or C mode).  This function
1269e5dd7070Spatrick /// goes out of its way to recover well.  It returns true if there was a parser
1270e5dd7070Spatrick /// error (the right paren couldn't be found), which indicates that the caller
1271e5dd7070Spatrick /// should try to recover harder.  It returns false if the condition is
1272e5dd7070Spatrick /// successfully parsed.  Note that a successful parse can still have semantic
1273e5dd7070Spatrick /// errors in the condition.
1274*12c85518Srobert /// Additionally, it will assign the location of the outer-most '(' and ')',
1275*12c85518Srobert /// to LParenLoc and RParenLoc, respectively.
ParseParenExprOrCondition(StmtResult * InitStmt,Sema::ConditionResult & Cond,SourceLocation Loc,Sema::ConditionKind CK,SourceLocation & LParenLoc,SourceLocation & RParenLoc)1276e5dd7070Spatrick bool Parser::ParseParenExprOrCondition(StmtResult *InitStmt,
1277e5dd7070Spatrick                                        Sema::ConditionResult &Cond,
1278e5dd7070Spatrick                                        SourceLocation Loc,
1279ec727ea7Spatrick                                        Sema::ConditionKind CK,
1280*12c85518Srobert                                        SourceLocation &LParenLoc,
1281*12c85518Srobert                                        SourceLocation &RParenLoc) {
1282e5dd7070Spatrick   BalancedDelimiterTracker T(*this, tok::l_paren);
1283e5dd7070Spatrick   T.consumeOpen();
1284*12c85518Srobert   SourceLocation Start = Tok.getLocation();
1285e5dd7070Spatrick 
1286*12c85518Srobert   if (getLangOpts().CPlusPlus) {
1287*12c85518Srobert     Cond = ParseCXXCondition(InitStmt, Loc, CK, false);
1288*12c85518Srobert   } else {
1289e5dd7070Spatrick     ExprResult CondExpr = ParseExpression();
1290e5dd7070Spatrick 
1291e5dd7070Spatrick     // If required, convert to a boolean value.
1292e5dd7070Spatrick     if (CondExpr.isInvalid())
1293e5dd7070Spatrick       Cond = Sema::ConditionError();
1294e5dd7070Spatrick     else
1295*12c85518Srobert       Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK,
1296*12c85518Srobert                                     /*MissingOK=*/false);
1297e5dd7070Spatrick   }
1298e5dd7070Spatrick 
1299e5dd7070Spatrick   // If the parser was confused by the condition and we don't have a ')', try to
1300e5dd7070Spatrick   // recover by skipping ahead to a semi and bailing out.  If condexp is
1301e5dd7070Spatrick   // semantically invalid but we have well formed code, keep going.
1302e5dd7070Spatrick   if (Cond.isInvalid() && Tok.isNot(tok::r_paren)) {
1303e5dd7070Spatrick     SkipUntil(tok::semi);
1304e5dd7070Spatrick     // Skipping may have stopped if it found the containing ')'.  If so, we can
1305e5dd7070Spatrick     // continue parsing the if statement.
1306e5dd7070Spatrick     if (Tok.isNot(tok::r_paren))
1307e5dd7070Spatrick       return true;
1308e5dd7070Spatrick   }
1309e5dd7070Spatrick 
1310*12c85518Srobert   if (Cond.isInvalid()) {
1311*12c85518Srobert     ExprResult CondExpr = Actions.CreateRecoveryExpr(
1312*12c85518Srobert         Start, Tok.getLocation() == Start ? Start : PrevTokLocation, {},
1313*12c85518Srobert         Actions.PreferredConditionType(CK));
1314*12c85518Srobert     if (!CondExpr.isInvalid())
1315*12c85518Srobert       Cond = Actions.ActOnCondition(getCurScope(), Loc, CondExpr.get(), CK,
1316*12c85518Srobert                                     /*MissingOK=*/false);
1317*12c85518Srobert   }
1318e5dd7070Spatrick 
1319*12c85518Srobert   // Either the condition is valid or the rparen is present.
1320*12c85518Srobert   T.consumeClose();
1321*12c85518Srobert   LParenLoc = T.getOpenLocation();
1322*12c85518Srobert   RParenLoc = T.getCloseLocation();
1323ec727ea7Spatrick 
1324e5dd7070Spatrick   // Check for extraneous ')'s to catch things like "if (foo())) {".  We know
1325e5dd7070Spatrick   // that all callers are looking for a statement after the condition, so ")"
1326e5dd7070Spatrick   // isn't valid.
1327e5dd7070Spatrick   while (Tok.is(tok::r_paren)) {
1328e5dd7070Spatrick     Diag(Tok, diag::err_extraneous_rparen_in_condition)
1329e5dd7070Spatrick       << FixItHint::CreateRemoval(Tok.getLocation());
1330e5dd7070Spatrick     ConsumeParen();
1331e5dd7070Spatrick   }
1332e5dd7070Spatrick 
1333e5dd7070Spatrick   return false;
1334e5dd7070Spatrick }
1335e5dd7070Spatrick 
1336e5dd7070Spatrick namespace {
1337e5dd7070Spatrick 
1338e5dd7070Spatrick enum MisleadingStatementKind { MSK_if, MSK_else, MSK_for, MSK_while };
1339e5dd7070Spatrick 
1340e5dd7070Spatrick struct MisleadingIndentationChecker {
1341e5dd7070Spatrick   Parser &P;
1342e5dd7070Spatrick   SourceLocation StmtLoc;
1343e5dd7070Spatrick   SourceLocation PrevLoc;
1344e5dd7070Spatrick   unsigned NumDirectives;
1345e5dd7070Spatrick   MisleadingStatementKind Kind;
1346e5dd7070Spatrick   bool ShouldSkip;
MisleadingIndentationChecker__anona4f1bbbe0311::MisleadingIndentationChecker1347e5dd7070Spatrick   MisleadingIndentationChecker(Parser &P, MisleadingStatementKind K,
1348e5dd7070Spatrick                                SourceLocation SL)
1349e5dd7070Spatrick       : P(P), StmtLoc(SL), PrevLoc(P.getCurToken().getLocation()),
1350e5dd7070Spatrick         NumDirectives(P.getPreprocessor().getNumDirectives()), Kind(K),
1351e5dd7070Spatrick         ShouldSkip(P.getCurToken().is(tok::l_brace)) {
1352e5dd7070Spatrick     if (!P.MisleadingIndentationElseLoc.isInvalid()) {
1353e5dd7070Spatrick       StmtLoc = P.MisleadingIndentationElseLoc;
1354e5dd7070Spatrick       P.MisleadingIndentationElseLoc = SourceLocation();
1355e5dd7070Spatrick     }
1356e5dd7070Spatrick     if (Kind == MSK_else && !ShouldSkip)
1357e5dd7070Spatrick       P.MisleadingIndentationElseLoc = SL;
1358e5dd7070Spatrick   }
1359e5dd7070Spatrick 
1360e5dd7070Spatrick   /// Compute the column number will aligning tabs on TabStop (-ftabstop), this
1361e5dd7070Spatrick   /// gives the visual indentation of the SourceLocation.
getVisualIndentation__anona4f1bbbe0311::MisleadingIndentationChecker1362e5dd7070Spatrick   static unsigned getVisualIndentation(SourceManager &SM, SourceLocation Loc) {
1363e5dd7070Spatrick     unsigned TabStop = SM.getDiagnostics().getDiagnosticOptions().TabStop;
1364e5dd7070Spatrick 
1365e5dd7070Spatrick     unsigned ColNo = SM.getSpellingColumnNumber(Loc);
1366e5dd7070Spatrick     if (ColNo == 0 || TabStop == 1)
1367e5dd7070Spatrick       return ColNo;
1368e5dd7070Spatrick 
1369e5dd7070Spatrick     std::pair<FileID, unsigned> FIDAndOffset = SM.getDecomposedLoc(Loc);
1370e5dd7070Spatrick 
1371e5dd7070Spatrick     bool Invalid;
1372e5dd7070Spatrick     StringRef BufData = SM.getBufferData(FIDAndOffset.first, &Invalid);
1373e5dd7070Spatrick     if (Invalid)
1374e5dd7070Spatrick       return 0;
1375e5dd7070Spatrick 
1376e5dd7070Spatrick     const char *EndPos = BufData.data() + FIDAndOffset.second;
1377e5dd7070Spatrick     // FileOffset are 0-based and Column numbers are 1-based
1378e5dd7070Spatrick     assert(FIDAndOffset.second + 1 >= ColNo &&
1379e5dd7070Spatrick            "Column number smaller than file offset?");
1380e5dd7070Spatrick 
1381e5dd7070Spatrick     unsigned VisualColumn = 0; // Stored as 0-based column, here.
1382e5dd7070Spatrick     // Loop from beginning of line up to Loc's file position, counting columns,
1383e5dd7070Spatrick     // expanding tabs.
1384e5dd7070Spatrick     for (const char *CurPos = EndPos - (ColNo - 1); CurPos != EndPos;
1385e5dd7070Spatrick          ++CurPos) {
1386e5dd7070Spatrick       if (*CurPos == '\t')
1387e5dd7070Spatrick         // Advance visual column to next tabstop.
1388e5dd7070Spatrick         VisualColumn += (TabStop - VisualColumn % TabStop);
1389e5dd7070Spatrick       else
1390e5dd7070Spatrick         VisualColumn++;
1391e5dd7070Spatrick     }
1392e5dd7070Spatrick     return VisualColumn + 1;
1393e5dd7070Spatrick   }
1394e5dd7070Spatrick 
Check__anona4f1bbbe0311::MisleadingIndentationChecker1395e5dd7070Spatrick   void Check() {
1396e5dd7070Spatrick     Token Tok = P.getCurToken();
1397e5dd7070Spatrick     if (P.getActions().getDiagnostics().isIgnored(
1398e5dd7070Spatrick             diag::warn_misleading_indentation, Tok.getLocation()) ||
1399e5dd7070Spatrick         ShouldSkip || NumDirectives != P.getPreprocessor().getNumDirectives() ||
1400e5dd7070Spatrick         Tok.isOneOf(tok::semi, tok::r_brace) || Tok.isAnnotation() ||
1401e5dd7070Spatrick         Tok.getLocation().isMacroID() || PrevLoc.isMacroID() ||
1402e5dd7070Spatrick         StmtLoc.isMacroID() ||
1403e5dd7070Spatrick         (Kind == MSK_else && P.MisleadingIndentationElseLoc.isInvalid())) {
1404e5dd7070Spatrick       P.MisleadingIndentationElseLoc = SourceLocation();
1405e5dd7070Spatrick       return;
1406e5dd7070Spatrick     }
1407e5dd7070Spatrick     if (Kind == MSK_else)
1408e5dd7070Spatrick       P.MisleadingIndentationElseLoc = SourceLocation();
1409e5dd7070Spatrick 
1410e5dd7070Spatrick     SourceManager &SM = P.getPreprocessor().getSourceManager();
1411e5dd7070Spatrick     unsigned PrevColNum = getVisualIndentation(SM, PrevLoc);
1412e5dd7070Spatrick     unsigned CurColNum = getVisualIndentation(SM, Tok.getLocation());
1413e5dd7070Spatrick     unsigned StmtColNum = getVisualIndentation(SM, StmtLoc);
1414e5dd7070Spatrick 
1415e5dd7070Spatrick     if (PrevColNum != 0 && CurColNum != 0 && StmtColNum != 0 &&
1416e5dd7070Spatrick         ((PrevColNum > StmtColNum && PrevColNum == CurColNum) ||
1417e5dd7070Spatrick          !Tok.isAtStartOfLine()) &&
1418e5dd7070Spatrick         SM.getPresumedLineNumber(StmtLoc) !=
1419e5dd7070Spatrick             SM.getPresumedLineNumber(Tok.getLocation()) &&
1420e5dd7070Spatrick         (Tok.isNot(tok::identifier) ||
1421e5dd7070Spatrick          P.getPreprocessor().LookAhead(0).isNot(tok::colon))) {
1422e5dd7070Spatrick       P.Diag(Tok.getLocation(), diag::warn_misleading_indentation) << Kind;
1423e5dd7070Spatrick       P.Diag(StmtLoc, diag::note_previous_statement);
1424e5dd7070Spatrick     }
1425e5dd7070Spatrick   }
1426e5dd7070Spatrick };
1427e5dd7070Spatrick 
1428e5dd7070Spatrick }
1429e5dd7070Spatrick 
1430e5dd7070Spatrick /// ParseIfStatement
1431e5dd7070Spatrick ///       if-statement: [C99 6.8.4.1]
1432e5dd7070Spatrick ///         'if' '(' expression ')' statement
1433e5dd7070Spatrick ///         'if' '(' expression ')' statement 'else' statement
1434e5dd7070Spatrick /// [C++]   'if' '(' condition ')' statement
1435e5dd7070Spatrick /// [C++]   'if' '(' condition ')' statement 'else' statement
1436*12c85518Srobert /// [C++23] 'if' '!' [opt] consteval compound-statement
1437*12c85518Srobert /// [C++23] 'if' '!' [opt] consteval compound-statement 'else' statement
1438e5dd7070Spatrick ///
ParseIfStatement(SourceLocation * TrailingElseLoc)1439e5dd7070Spatrick StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) {
1440e5dd7070Spatrick   assert(Tok.is(tok::kw_if) && "Not an if stmt!");
1441e5dd7070Spatrick   SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
1442e5dd7070Spatrick 
1443e5dd7070Spatrick   bool IsConstexpr = false;
1444*12c85518Srobert   bool IsConsteval = false;
1445*12c85518Srobert   SourceLocation NotLocation;
1446*12c85518Srobert   SourceLocation ConstevalLoc;
1447*12c85518Srobert 
1448e5dd7070Spatrick   if (Tok.is(tok::kw_constexpr)) {
1449e5dd7070Spatrick     Diag(Tok, getLangOpts().CPlusPlus17 ? diag::warn_cxx14_compat_constexpr_if
1450e5dd7070Spatrick                                         : diag::ext_constexpr_if);
1451e5dd7070Spatrick     IsConstexpr = true;
1452e5dd7070Spatrick     ConsumeToken();
1453*12c85518Srobert   } else {
1454*12c85518Srobert     if (Tok.is(tok::exclaim)) {
1455*12c85518Srobert       NotLocation = ConsumeToken();
1456e5dd7070Spatrick     }
1457e5dd7070Spatrick 
1458*12c85518Srobert     if (Tok.is(tok::kw_consteval)) {
1459*12c85518Srobert       Diag(Tok, getLangOpts().CPlusPlus2b ? diag::warn_cxx20_compat_consteval_if
1460*12c85518Srobert                                           : diag::ext_consteval_if);
1461*12c85518Srobert       IsConsteval = true;
1462*12c85518Srobert       ConstevalLoc = ConsumeToken();
1463*12c85518Srobert     }
1464*12c85518Srobert   }
1465*12c85518Srobert   if (!IsConsteval && (NotLocation.isValid() || Tok.isNot(tok::l_paren))) {
1466e5dd7070Spatrick     Diag(Tok, diag::err_expected_lparen_after) << "if";
1467e5dd7070Spatrick     SkipUntil(tok::semi);
1468e5dd7070Spatrick     return StmtError();
1469e5dd7070Spatrick   }
1470e5dd7070Spatrick 
1471e5dd7070Spatrick   bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
1472e5dd7070Spatrick 
1473e5dd7070Spatrick   // C99 6.8.4p3 - In C99, the if statement is a block.  This is not
1474e5dd7070Spatrick   // the case for C90.
1475e5dd7070Spatrick   //
1476e5dd7070Spatrick   // C++ 6.4p3:
1477e5dd7070Spatrick   // A name introduced by a declaration in a condition is in scope from its
1478e5dd7070Spatrick   // point of declaration until the end of the substatements controlled by the
1479e5dd7070Spatrick   // condition.
1480e5dd7070Spatrick   // C++ 3.3.2p4:
1481e5dd7070Spatrick   // Names declared in the for-init-statement, and in the condition of if,
1482e5dd7070Spatrick   // while, for, and switch statements are local to the if, while, for, or
1483e5dd7070Spatrick   // switch statement (including the controlled statement).
1484e5dd7070Spatrick   //
1485e5dd7070Spatrick   ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
1486e5dd7070Spatrick 
1487e5dd7070Spatrick   // Parse the condition.
1488e5dd7070Spatrick   StmtResult InitStmt;
1489e5dd7070Spatrick   Sema::ConditionResult Cond;
1490a9ac8606Spatrick   SourceLocation LParen;
1491a9ac8606Spatrick   SourceLocation RParen;
1492*12c85518Srobert   std::optional<bool> ConstexprCondition;
1493*12c85518Srobert   if (!IsConsteval) {
1494*12c85518Srobert 
1495e5dd7070Spatrick     if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc,
1496e5dd7070Spatrick                                   IsConstexpr ? Sema::ConditionKind::ConstexprIf
1497a9ac8606Spatrick                                               : Sema::ConditionKind::Boolean,
1498*12c85518Srobert                                   LParen, RParen))
1499e5dd7070Spatrick       return StmtError();
1500e5dd7070Spatrick 
1501e5dd7070Spatrick     if (IsConstexpr)
1502e5dd7070Spatrick       ConstexprCondition = Cond.getKnownValue();
1503*12c85518Srobert   }
1504e5dd7070Spatrick 
1505ec727ea7Spatrick   bool IsBracedThen = Tok.is(tok::l_brace);
1506ec727ea7Spatrick 
1507e5dd7070Spatrick   // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
1508e5dd7070Spatrick   // there is no compound stmt.  C90 does not have this clause.  We only do this
1509e5dd7070Spatrick   // if the body isn't a compound statement to avoid push/pop in common cases.
1510e5dd7070Spatrick   //
1511e5dd7070Spatrick   // C++ 6.4p1:
1512e5dd7070Spatrick   // The substatement in a selection-statement (each substatement, in the else
1513e5dd7070Spatrick   // form of the if statement) implicitly defines a local scope.
1514e5dd7070Spatrick   //
1515e5dd7070Spatrick   // For C++ we create a scope for the condition and a new scope for
1516e5dd7070Spatrick   // substatements because:
1517e5dd7070Spatrick   // -When the 'then' scope exits, we want the condition declaration to still be
1518e5dd7070Spatrick   //    active for the 'else' scope too.
1519e5dd7070Spatrick   // -Sema will detect name clashes by considering declarations of a
1520e5dd7070Spatrick   //    'ControlScope' as part of its direct subscope.
1521e5dd7070Spatrick   // -If we wanted the condition and substatement to be in the same scope, we
1522e5dd7070Spatrick   //    would have to notify ParseStatement not to create a new scope. It's
1523e5dd7070Spatrick   //    simpler to let it create a new scope.
1524e5dd7070Spatrick   //
1525ec727ea7Spatrick   ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, IsBracedThen);
1526e5dd7070Spatrick 
1527e5dd7070Spatrick   MisleadingIndentationChecker MIChecker(*this, MSK_if, IfLoc);
1528e5dd7070Spatrick 
1529e5dd7070Spatrick   // Read the 'then' stmt.
1530e5dd7070Spatrick   SourceLocation ThenStmtLoc = Tok.getLocation();
1531e5dd7070Spatrick 
1532e5dd7070Spatrick   SourceLocation InnerStatementTrailingElseLoc;
1533e5dd7070Spatrick   StmtResult ThenStmt;
1534e5dd7070Spatrick   {
1535*12c85518Srobert     bool ShouldEnter = ConstexprCondition && !*ConstexprCondition;
1536*12c85518Srobert     Sema::ExpressionEvaluationContext Context =
1537*12c85518Srobert         Sema::ExpressionEvaluationContext::DiscardedStatement;
1538*12c85518Srobert     if (NotLocation.isInvalid() && IsConsteval) {
1539*12c85518Srobert       Context = Sema::ExpressionEvaluationContext::ImmediateFunctionContext;
1540*12c85518Srobert       ShouldEnter = true;
1541*12c85518Srobert     }
1542*12c85518Srobert 
1543e5dd7070Spatrick     EnterExpressionEvaluationContext PotentiallyDiscarded(
1544*12c85518Srobert         Actions, Context, nullptr,
1545*12c85518Srobert         Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
1546e5dd7070Spatrick     ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc);
1547e5dd7070Spatrick   }
1548e5dd7070Spatrick 
1549e5dd7070Spatrick   if (Tok.isNot(tok::kw_else))
1550e5dd7070Spatrick     MIChecker.Check();
1551e5dd7070Spatrick 
1552e5dd7070Spatrick   // Pop the 'if' scope if needed.
1553e5dd7070Spatrick   InnerScope.Exit();
1554e5dd7070Spatrick 
1555e5dd7070Spatrick   // If it has an else, parse it.
1556e5dd7070Spatrick   SourceLocation ElseLoc;
1557e5dd7070Spatrick   SourceLocation ElseStmtLoc;
1558e5dd7070Spatrick   StmtResult ElseStmt;
1559e5dd7070Spatrick 
1560e5dd7070Spatrick   if (Tok.is(tok::kw_else)) {
1561e5dd7070Spatrick     if (TrailingElseLoc)
1562e5dd7070Spatrick       *TrailingElseLoc = Tok.getLocation();
1563e5dd7070Spatrick 
1564e5dd7070Spatrick     ElseLoc = ConsumeToken();
1565e5dd7070Spatrick     ElseStmtLoc = Tok.getLocation();
1566e5dd7070Spatrick 
1567e5dd7070Spatrick     // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
1568e5dd7070Spatrick     // there is no compound stmt.  C90 does not have this clause.  We only do
1569e5dd7070Spatrick     // this if the body isn't a compound statement to avoid push/pop in common
1570e5dd7070Spatrick     // cases.
1571e5dd7070Spatrick     //
1572e5dd7070Spatrick     // C++ 6.4p1:
1573e5dd7070Spatrick     // The substatement in a selection-statement (each substatement, in the else
1574e5dd7070Spatrick     // form of the if statement) implicitly defines a local scope.
1575e5dd7070Spatrick     //
1576e5dd7070Spatrick     ParseScope InnerScope(this, Scope::DeclScope, C99orCXX,
1577e5dd7070Spatrick                           Tok.is(tok::l_brace));
1578e5dd7070Spatrick 
1579e5dd7070Spatrick     MisleadingIndentationChecker MIChecker(*this, MSK_else, ElseLoc);
1580*12c85518Srobert     bool ShouldEnter = ConstexprCondition && *ConstexprCondition;
1581*12c85518Srobert     Sema::ExpressionEvaluationContext Context =
1582*12c85518Srobert         Sema::ExpressionEvaluationContext::DiscardedStatement;
1583*12c85518Srobert     if (NotLocation.isValid() && IsConsteval) {
1584*12c85518Srobert       Context = Sema::ExpressionEvaluationContext::ImmediateFunctionContext;
1585*12c85518Srobert       ShouldEnter = true;
1586*12c85518Srobert     }
1587e5dd7070Spatrick 
1588e5dd7070Spatrick     EnterExpressionEvaluationContext PotentiallyDiscarded(
1589*12c85518Srobert         Actions, Context, nullptr,
1590*12c85518Srobert         Sema::ExpressionEvaluationContextRecord::EK_Other, ShouldEnter);
1591e5dd7070Spatrick     ElseStmt = ParseStatement();
1592e5dd7070Spatrick 
1593e5dd7070Spatrick     if (ElseStmt.isUsable())
1594e5dd7070Spatrick       MIChecker.Check();
1595e5dd7070Spatrick 
1596e5dd7070Spatrick     // Pop the 'else' scope if needed.
1597e5dd7070Spatrick     InnerScope.Exit();
1598e5dd7070Spatrick   } else if (Tok.is(tok::code_completion)) {
1599e5dd7070Spatrick     cutOffParsing();
1600a9ac8606Spatrick     Actions.CodeCompleteAfterIf(getCurScope(), IsBracedThen);
1601e5dd7070Spatrick     return StmtError();
1602e5dd7070Spatrick   } else if (InnerStatementTrailingElseLoc.isValid()) {
1603e5dd7070Spatrick     Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else);
1604e5dd7070Spatrick   }
1605e5dd7070Spatrick 
1606e5dd7070Spatrick   IfScope.Exit();
1607e5dd7070Spatrick 
1608e5dd7070Spatrick   // If the then or else stmt is invalid and the other is valid (and present),
1609e5dd7070Spatrick   // make turn the invalid one into a null stmt to avoid dropping the other
1610e5dd7070Spatrick   // part.  If both are invalid, return error.
1611e5dd7070Spatrick   if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
1612e5dd7070Spatrick       (ThenStmt.isInvalid() && ElseStmt.get() == nullptr) ||
1613e5dd7070Spatrick       (ThenStmt.get() == nullptr && ElseStmt.isInvalid())) {
1614e5dd7070Spatrick     // Both invalid, or one is invalid and other is non-present: return error.
1615e5dd7070Spatrick     return StmtError();
1616e5dd7070Spatrick   }
1617e5dd7070Spatrick 
1618*12c85518Srobert   if (IsConsteval) {
1619*12c85518Srobert     auto IsCompoundStatement = [](const Stmt *S) {
1620*12c85518Srobert       if (const auto *Outer = dyn_cast_or_null<AttributedStmt>(S))
1621*12c85518Srobert         S = Outer->getSubStmt();
1622*12c85518Srobert       return isa_and_nonnull<clang::CompoundStmt>(S);
1623*12c85518Srobert     };
1624*12c85518Srobert 
1625*12c85518Srobert     if (!IsCompoundStatement(ThenStmt.get())) {
1626*12c85518Srobert       Diag(ConstevalLoc, diag::err_expected_after) << "consteval"
1627*12c85518Srobert                                                    << "{";
1628*12c85518Srobert       return StmtError();
1629*12c85518Srobert     }
1630*12c85518Srobert     if (!ElseStmt.isUnset() && !IsCompoundStatement(ElseStmt.get())) {
1631*12c85518Srobert       Diag(ElseLoc, diag::err_expected_after) << "else"
1632*12c85518Srobert                                               << "{";
1633*12c85518Srobert       return StmtError();
1634*12c85518Srobert     }
1635*12c85518Srobert   }
1636*12c85518Srobert 
1637e5dd7070Spatrick   // Now if either are invalid, replace with a ';'.
1638e5dd7070Spatrick   if (ThenStmt.isInvalid())
1639e5dd7070Spatrick     ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
1640e5dd7070Spatrick   if (ElseStmt.isInvalid())
1641e5dd7070Spatrick     ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
1642e5dd7070Spatrick 
1643*12c85518Srobert   IfStatementKind Kind = IfStatementKind::Ordinary;
1644*12c85518Srobert   if (IsConstexpr)
1645*12c85518Srobert     Kind = IfStatementKind::Constexpr;
1646*12c85518Srobert   else if (IsConsteval)
1647*12c85518Srobert     Kind = NotLocation.isValid() ? IfStatementKind::ConstevalNegated
1648*12c85518Srobert                                  : IfStatementKind::ConstevalNonNegated;
1649*12c85518Srobert 
1650*12c85518Srobert   return Actions.ActOnIfStmt(IfLoc, Kind, LParen, InitStmt.get(), Cond, RParen,
1651*12c85518Srobert                              ThenStmt.get(), ElseLoc, ElseStmt.get());
1652e5dd7070Spatrick }
1653e5dd7070Spatrick 
1654e5dd7070Spatrick /// ParseSwitchStatement
1655e5dd7070Spatrick ///       switch-statement:
1656e5dd7070Spatrick ///         'switch' '(' expression ')' statement
1657e5dd7070Spatrick /// [C++]   'switch' '(' condition ')' statement
ParseSwitchStatement(SourceLocation * TrailingElseLoc)1658e5dd7070Spatrick StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
1659e5dd7070Spatrick   assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
1660e5dd7070Spatrick   SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
1661e5dd7070Spatrick 
1662e5dd7070Spatrick   if (Tok.isNot(tok::l_paren)) {
1663e5dd7070Spatrick     Diag(Tok, diag::err_expected_lparen_after) << "switch";
1664e5dd7070Spatrick     SkipUntil(tok::semi);
1665e5dd7070Spatrick     return StmtError();
1666e5dd7070Spatrick   }
1667e5dd7070Spatrick 
1668e5dd7070Spatrick   bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
1669e5dd7070Spatrick 
1670e5dd7070Spatrick   // C99 6.8.4p3 - In C99, the switch statement is a block.  This is
1671e5dd7070Spatrick   // not the case for C90.  Start the switch scope.
1672e5dd7070Spatrick   //
1673e5dd7070Spatrick   // C++ 6.4p3:
1674e5dd7070Spatrick   // A name introduced by a declaration in a condition is in scope from its
1675e5dd7070Spatrick   // point of declaration until the end of the substatements controlled by the
1676e5dd7070Spatrick   // condition.
1677e5dd7070Spatrick   // C++ 3.3.2p4:
1678e5dd7070Spatrick   // Names declared in the for-init-statement, and in the condition of if,
1679e5dd7070Spatrick   // while, for, and switch statements are local to the if, while, for, or
1680e5dd7070Spatrick   // switch statement (including the controlled statement).
1681e5dd7070Spatrick   //
1682e5dd7070Spatrick   unsigned ScopeFlags = Scope::SwitchScope;
1683e5dd7070Spatrick   if (C99orCXX)
1684e5dd7070Spatrick     ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
1685e5dd7070Spatrick   ParseScope SwitchScope(this, ScopeFlags);
1686e5dd7070Spatrick 
1687e5dd7070Spatrick   // Parse the condition.
1688e5dd7070Spatrick   StmtResult InitStmt;
1689e5dd7070Spatrick   Sema::ConditionResult Cond;
1690a9ac8606Spatrick   SourceLocation LParen;
1691a9ac8606Spatrick   SourceLocation RParen;
1692e5dd7070Spatrick   if (ParseParenExprOrCondition(&InitStmt, Cond, SwitchLoc,
1693*12c85518Srobert                                 Sema::ConditionKind::Switch, LParen, RParen))
1694e5dd7070Spatrick     return StmtError();
1695e5dd7070Spatrick 
1696a9ac8606Spatrick   StmtResult Switch = Actions.ActOnStartOfSwitchStmt(
1697a9ac8606Spatrick       SwitchLoc, LParen, InitStmt.get(), Cond, RParen);
1698e5dd7070Spatrick 
1699e5dd7070Spatrick   if (Switch.isInvalid()) {
1700e5dd7070Spatrick     // Skip the switch body.
1701e5dd7070Spatrick     // FIXME: This is not optimal recovery, but parsing the body is more
1702e5dd7070Spatrick     // dangerous due to the presence of case and default statements, which
1703e5dd7070Spatrick     // will have no place to connect back with the switch.
1704e5dd7070Spatrick     if (Tok.is(tok::l_brace)) {
1705e5dd7070Spatrick       ConsumeBrace();
1706e5dd7070Spatrick       SkipUntil(tok::r_brace);
1707e5dd7070Spatrick     } else
1708e5dd7070Spatrick       SkipUntil(tok::semi);
1709e5dd7070Spatrick     return Switch;
1710e5dd7070Spatrick   }
1711e5dd7070Spatrick 
1712e5dd7070Spatrick   // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
1713e5dd7070Spatrick   // there is no compound stmt.  C90 does not have this clause.  We only do this
1714e5dd7070Spatrick   // if the body isn't a compound statement to avoid push/pop in common cases.
1715e5dd7070Spatrick   //
1716e5dd7070Spatrick   // C++ 6.4p1:
1717e5dd7070Spatrick   // The substatement in a selection-statement (each substatement, in the else
1718e5dd7070Spatrick   // form of the if statement) implicitly defines a local scope.
1719e5dd7070Spatrick   //
1720e5dd7070Spatrick   // See comments in ParseIfStatement for why we create a scope for the
1721e5dd7070Spatrick   // condition and a new scope for substatement in C++.
1722e5dd7070Spatrick   //
1723e5dd7070Spatrick   getCurScope()->AddFlags(Scope::BreakScope);
1724e5dd7070Spatrick   ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
1725e5dd7070Spatrick 
1726e5dd7070Spatrick   // We have incremented the mangling number for the SwitchScope and the
1727e5dd7070Spatrick   // InnerScope, which is one too many.
1728e5dd7070Spatrick   if (C99orCXX)
1729e5dd7070Spatrick     getCurScope()->decrementMSManglingNumber();
1730e5dd7070Spatrick 
1731e5dd7070Spatrick   // Read the body statement.
1732e5dd7070Spatrick   StmtResult Body(ParseStatement(TrailingElseLoc));
1733e5dd7070Spatrick 
1734e5dd7070Spatrick   // Pop the scopes.
1735e5dd7070Spatrick   InnerScope.Exit();
1736e5dd7070Spatrick   SwitchScope.Exit();
1737e5dd7070Spatrick 
1738e5dd7070Spatrick   return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get());
1739e5dd7070Spatrick }
1740e5dd7070Spatrick 
1741e5dd7070Spatrick /// ParseWhileStatement
1742e5dd7070Spatrick ///       while-statement: [C99 6.8.5.1]
1743e5dd7070Spatrick ///         'while' '(' expression ')' statement
1744e5dd7070Spatrick /// [C++]   'while' '(' condition ')' statement
ParseWhileStatement(SourceLocation * TrailingElseLoc)1745e5dd7070Spatrick StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) {
1746e5dd7070Spatrick   assert(Tok.is(tok::kw_while) && "Not a while stmt!");
1747e5dd7070Spatrick   SourceLocation WhileLoc = Tok.getLocation();
1748e5dd7070Spatrick   ConsumeToken();  // eat the 'while'.
1749e5dd7070Spatrick 
1750e5dd7070Spatrick   if (Tok.isNot(tok::l_paren)) {
1751e5dd7070Spatrick     Diag(Tok, diag::err_expected_lparen_after) << "while";
1752e5dd7070Spatrick     SkipUntil(tok::semi);
1753e5dd7070Spatrick     return StmtError();
1754e5dd7070Spatrick   }
1755e5dd7070Spatrick 
1756e5dd7070Spatrick   bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
1757e5dd7070Spatrick 
1758e5dd7070Spatrick   // C99 6.8.5p5 - In C99, the while statement is a block.  This is not
1759e5dd7070Spatrick   // the case for C90.  Start the loop scope.
1760e5dd7070Spatrick   //
1761e5dd7070Spatrick   // C++ 6.4p3:
1762e5dd7070Spatrick   // A name introduced by a declaration in a condition is in scope from its
1763e5dd7070Spatrick   // point of declaration until the end of the substatements controlled by the
1764e5dd7070Spatrick   // condition.
1765e5dd7070Spatrick   // C++ 3.3.2p4:
1766e5dd7070Spatrick   // Names declared in the for-init-statement, and in the condition of if,
1767e5dd7070Spatrick   // while, for, and switch statements are local to the if, while, for, or
1768e5dd7070Spatrick   // switch statement (including the controlled statement).
1769e5dd7070Spatrick   //
1770e5dd7070Spatrick   unsigned ScopeFlags;
1771e5dd7070Spatrick   if (C99orCXX)
1772e5dd7070Spatrick     ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
1773e5dd7070Spatrick                  Scope::DeclScope  | Scope::ControlScope;
1774e5dd7070Spatrick   else
1775e5dd7070Spatrick     ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
1776e5dd7070Spatrick   ParseScope WhileScope(this, ScopeFlags);
1777e5dd7070Spatrick 
1778e5dd7070Spatrick   // Parse the condition.
1779e5dd7070Spatrick   Sema::ConditionResult Cond;
1780ec727ea7Spatrick   SourceLocation LParen;
1781ec727ea7Spatrick   SourceLocation RParen;
1782e5dd7070Spatrick   if (ParseParenExprOrCondition(nullptr, Cond, WhileLoc,
1783*12c85518Srobert                                 Sema::ConditionKind::Boolean, LParen, RParen))
1784e5dd7070Spatrick     return StmtError();
1785e5dd7070Spatrick 
1786e5dd7070Spatrick   // C99 6.8.5p5 - In C99, the body of the while statement is a scope, even if
1787e5dd7070Spatrick   // there is no compound stmt.  C90 does not have this clause.  We only do this
1788e5dd7070Spatrick   // if the body isn't a compound statement to avoid push/pop in common cases.
1789e5dd7070Spatrick   //
1790e5dd7070Spatrick   // C++ 6.5p2:
1791e5dd7070Spatrick   // The substatement in an iteration-statement implicitly defines a local scope
1792e5dd7070Spatrick   // which is entered and exited each time through the loop.
1793e5dd7070Spatrick   //
1794e5dd7070Spatrick   // See comments in ParseIfStatement for why we create a scope for the
1795e5dd7070Spatrick   // condition and a new scope for substatement in C++.
1796e5dd7070Spatrick   //
1797e5dd7070Spatrick   ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
1798e5dd7070Spatrick 
1799e5dd7070Spatrick   MisleadingIndentationChecker MIChecker(*this, MSK_while, WhileLoc);
1800e5dd7070Spatrick 
1801e5dd7070Spatrick   // Read the body statement.
1802e5dd7070Spatrick   StmtResult Body(ParseStatement(TrailingElseLoc));
1803e5dd7070Spatrick 
1804e5dd7070Spatrick   if (Body.isUsable())
1805e5dd7070Spatrick     MIChecker.Check();
1806e5dd7070Spatrick   // Pop the body scope if needed.
1807e5dd7070Spatrick   InnerScope.Exit();
1808e5dd7070Spatrick   WhileScope.Exit();
1809e5dd7070Spatrick 
1810e5dd7070Spatrick   if (Cond.isInvalid() || Body.isInvalid())
1811e5dd7070Spatrick     return StmtError();
1812e5dd7070Spatrick 
1813ec727ea7Spatrick   return Actions.ActOnWhileStmt(WhileLoc, LParen, Cond, RParen, Body.get());
1814e5dd7070Spatrick }
1815e5dd7070Spatrick 
1816e5dd7070Spatrick /// ParseDoStatement
1817e5dd7070Spatrick ///       do-statement: [C99 6.8.5.2]
1818e5dd7070Spatrick ///         'do' statement 'while' '(' expression ')' ';'
1819e5dd7070Spatrick /// Note: this lets the caller parse the end ';'.
ParseDoStatement()1820e5dd7070Spatrick StmtResult Parser::ParseDoStatement() {
1821e5dd7070Spatrick   assert(Tok.is(tok::kw_do) && "Not a do stmt!");
1822e5dd7070Spatrick   SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
1823e5dd7070Spatrick 
1824e5dd7070Spatrick   // C99 6.8.5p5 - In C99, the do statement is a block.  This is not
1825e5dd7070Spatrick   // the case for C90.  Start the loop scope.
1826e5dd7070Spatrick   unsigned ScopeFlags;
1827e5dd7070Spatrick   if (getLangOpts().C99)
1828e5dd7070Spatrick     ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
1829e5dd7070Spatrick   else
1830e5dd7070Spatrick     ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
1831e5dd7070Spatrick 
1832e5dd7070Spatrick   ParseScope DoScope(this, ScopeFlags);
1833e5dd7070Spatrick 
1834e5dd7070Spatrick   // C99 6.8.5p5 - In C99, the body of the do statement is a scope, even if
1835e5dd7070Spatrick   // there is no compound stmt.  C90 does not have this clause. We only do this
1836e5dd7070Spatrick   // if the body isn't a compound statement to avoid push/pop in common cases.
1837e5dd7070Spatrick   //
1838e5dd7070Spatrick   // C++ 6.5p2:
1839e5dd7070Spatrick   // The substatement in an iteration-statement implicitly defines a local scope
1840e5dd7070Spatrick   // which is entered and exited each time through the loop.
1841e5dd7070Spatrick   //
1842e5dd7070Spatrick   bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus;
1843e5dd7070Spatrick   ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace));
1844e5dd7070Spatrick 
1845e5dd7070Spatrick   // Read the body statement.
1846e5dd7070Spatrick   StmtResult Body(ParseStatement());
1847e5dd7070Spatrick 
1848e5dd7070Spatrick   // Pop the body scope if needed.
1849e5dd7070Spatrick   InnerScope.Exit();
1850e5dd7070Spatrick 
1851e5dd7070Spatrick   if (Tok.isNot(tok::kw_while)) {
1852e5dd7070Spatrick     if (!Body.isInvalid()) {
1853e5dd7070Spatrick       Diag(Tok, diag::err_expected_while);
1854e5dd7070Spatrick       Diag(DoLoc, diag::note_matching) << "'do'";
1855e5dd7070Spatrick       SkipUntil(tok::semi, StopBeforeMatch);
1856e5dd7070Spatrick     }
1857e5dd7070Spatrick     return StmtError();
1858e5dd7070Spatrick   }
1859e5dd7070Spatrick   SourceLocation WhileLoc = ConsumeToken();
1860e5dd7070Spatrick 
1861e5dd7070Spatrick   if (Tok.isNot(tok::l_paren)) {
1862e5dd7070Spatrick     Diag(Tok, diag::err_expected_lparen_after) << "do/while";
1863e5dd7070Spatrick     SkipUntil(tok::semi, StopBeforeMatch);
1864e5dd7070Spatrick     return StmtError();
1865e5dd7070Spatrick   }
1866e5dd7070Spatrick 
1867e5dd7070Spatrick   // Parse the parenthesized expression.
1868e5dd7070Spatrick   BalancedDelimiterTracker T(*this, tok::l_paren);
1869e5dd7070Spatrick   T.consumeOpen();
1870e5dd7070Spatrick 
1871e5dd7070Spatrick   // A do-while expression is not a condition, so can't have attributes.
1872e5dd7070Spatrick   DiagnoseAndSkipCXX11Attributes();
1873e5dd7070Spatrick 
1874*12c85518Srobert   SourceLocation Start = Tok.getLocation();
1875e5dd7070Spatrick   ExprResult Cond = ParseExpression();
1876e5dd7070Spatrick   // Correct the typos in condition before closing the scope.
1877e5dd7070Spatrick   if (Cond.isUsable())
1878e5dd7070Spatrick     Cond = Actions.CorrectDelayedTyposInExpr(Cond);
1879*12c85518Srobert   else {
1880*12c85518Srobert     if (!Tok.isOneOf(tok::r_paren, tok::r_square, tok::r_brace))
1881*12c85518Srobert       SkipUntil(tok::semi);
1882*12c85518Srobert     Cond = Actions.CreateRecoveryExpr(
1883*12c85518Srobert         Start, Start == Tok.getLocation() ? Start : PrevTokLocation, {},
1884*12c85518Srobert         Actions.getASTContext().BoolTy);
1885*12c85518Srobert   }
1886e5dd7070Spatrick   T.consumeClose();
1887e5dd7070Spatrick   DoScope.Exit();
1888e5dd7070Spatrick 
1889e5dd7070Spatrick   if (Cond.isInvalid() || Body.isInvalid())
1890e5dd7070Spatrick     return StmtError();
1891e5dd7070Spatrick 
1892e5dd7070Spatrick   return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, T.getOpenLocation(),
1893e5dd7070Spatrick                              Cond.get(), T.getCloseLocation());
1894e5dd7070Spatrick }
1895e5dd7070Spatrick 
isForRangeIdentifier()1896e5dd7070Spatrick bool Parser::isForRangeIdentifier() {
1897e5dd7070Spatrick   assert(Tok.is(tok::identifier));
1898e5dd7070Spatrick 
1899e5dd7070Spatrick   const Token &Next = NextToken();
1900e5dd7070Spatrick   if (Next.is(tok::colon))
1901e5dd7070Spatrick     return true;
1902e5dd7070Spatrick 
1903e5dd7070Spatrick   if (Next.isOneOf(tok::l_square, tok::kw_alignas)) {
1904e5dd7070Spatrick     TentativeParsingAction PA(*this);
1905e5dd7070Spatrick     ConsumeToken();
1906e5dd7070Spatrick     SkipCXX11Attributes();
1907e5dd7070Spatrick     bool Result = Tok.is(tok::colon);
1908e5dd7070Spatrick     PA.Revert();
1909e5dd7070Spatrick     return Result;
1910e5dd7070Spatrick   }
1911e5dd7070Spatrick 
1912e5dd7070Spatrick   return false;
1913e5dd7070Spatrick }
1914e5dd7070Spatrick 
1915e5dd7070Spatrick /// ParseForStatement
1916e5dd7070Spatrick ///       for-statement: [C99 6.8.5.3]
1917e5dd7070Spatrick ///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
1918e5dd7070Spatrick ///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
1919e5dd7070Spatrick /// [C++]   'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
1920e5dd7070Spatrick /// [C++]       statement
1921e5dd7070Spatrick /// [C++0x] 'for'
1922e5dd7070Spatrick ///             'co_await'[opt]    [Coroutines]
1923e5dd7070Spatrick ///             '(' for-range-declaration ':' for-range-initializer ')'
1924e5dd7070Spatrick ///             statement
1925e5dd7070Spatrick /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
1926e5dd7070Spatrick /// [OBJC2] 'for' '(' expr 'in' expr ')' statement
1927e5dd7070Spatrick ///
1928e5dd7070Spatrick /// [C++] for-init-statement:
1929e5dd7070Spatrick /// [C++]   expression-statement
1930e5dd7070Spatrick /// [C++]   simple-declaration
1931*12c85518Srobert /// [C++2b] alias-declaration
1932e5dd7070Spatrick ///
1933e5dd7070Spatrick /// [C++0x] for-range-declaration:
1934e5dd7070Spatrick /// [C++0x]   attribute-specifier-seq[opt] type-specifier-seq declarator
1935e5dd7070Spatrick /// [C++0x] for-range-initializer:
1936e5dd7070Spatrick /// [C++0x]   expression
1937e5dd7070Spatrick /// [C++0x]   braced-init-list            [TODO]
ParseForStatement(SourceLocation * TrailingElseLoc)1938e5dd7070Spatrick StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
1939e5dd7070Spatrick   assert(Tok.is(tok::kw_for) && "Not a for stmt!");
1940e5dd7070Spatrick   SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
1941e5dd7070Spatrick 
1942e5dd7070Spatrick   SourceLocation CoawaitLoc;
1943e5dd7070Spatrick   if (Tok.is(tok::kw_co_await))
1944e5dd7070Spatrick     CoawaitLoc = ConsumeToken();
1945e5dd7070Spatrick 
1946e5dd7070Spatrick   if (Tok.isNot(tok::l_paren)) {
1947e5dd7070Spatrick     Diag(Tok, diag::err_expected_lparen_after) << "for";
1948e5dd7070Spatrick     SkipUntil(tok::semi);
1949e5dd7070Spatrick     return StmtError();
1950e5dd7070Spatrick   }
1951e5dd7070Spatrick 
1952e5dd7070Spatrick   bool C99orCXXorObjC = getLangOpts().C99 || getLangOpts().CPlusPlus ||
1953e5dd7070Spatrick     getLangOpts().ObjC;
1954e5dd7070Spatrick 
1955e5dd7070Spatrick   // C99 6.8.5p5 - In C99, the for statement is a block.  This is not
1956e5dd7070Spatrick   // the case for C90.  Start the loop scope.
1957e5dd7070Spatrick   //
1958e5dd7070Spatrick   // C++ 6.4p3:
1959e5dd7070Spatrick   // A name introduced by a declaration in a condition is in scope from its
1960e5dd7070Spatrick   // point of declaration until the end of the substatements controlled by the
1961e5dd7070Spatrick   // condition.
1962e5dd7070Spatrick   // C++ 3.3.2p4:
1963e5dd7070Spatrick   // Names declared in the for-init-statement, and in the condition of if,
1964e5dd7070Spatrick   // while, for, and switch statements are local to the if, while, for, or
1965e5dd7070Spatrick   // switch statement (including the controlled statement).
1966e5dd7070Spatrick   // C++ 6.5.3p1:
1967e5dd7070Spatrick   // Names declared in the for-init-statement are in the same declarative-region
1968e5dd7070Spatrick   // as those declared in the condition.
1969e5dd7070Spatrick   //
1970e5dd7070Spatrick   unsigned ScopeFlags = 0;
1971e5dd7070Spatrick   if (C99orCXXorObjC)
1972e5dd7070Spatrick     ScopeFlags = Scope::DeclScope | Scope::ControlScope;
1973e5dd7070Spatrick 
1974e5dd7070Spatrick   ParseScope ForScope(this, ScopeFlags);
1975e5dd7070Spatrick 
1976e5dd7070Spatrick   BalancedDelimiterTracker T(*this, tok::l_paren);
1977e5dd7070Spatrick   T.consumeOpen();
1978e5dd7070Spatrick 
1979e5dd7070Spatrick   ExprResult Value;
1980e5dd7070Spatrick 
1981e5dd7070Spatrick   bool ForEach = false;
1982e5dd7070Spatrick   StmtResult FirstPart;
1983e5dd7070Spatrick   Sema::ConditionResult SecondPart;
1984e5dd7070Spatrick   ExprResult Collection;
1985e5dd7070Spatrick   ForRangeInfo ForRangeInfo;
1986e5dd7070Spatrick   FullExprArg ThirdPart(Actions);
1987e5dd7070Spatrick 
1988e5dd7070Spatrick   if (Tok.is(tok::code_completion)) {
1989a9ac8606Spatrick     cutOffParsing();
1990e5dd7070Spatrick     Actions.CodeCompleteOrdinaryName(getCurScope(),
1991e5dd7070Spatrick                                      C99orCXXorObjC? Sema::PCC_ForInit
1992e5dd7070Spatrick                                                    : Sema::PCC_Expression);
1993e5dd7070Spatrick     return StmtError();
1994e5dd7070Spatrick   }
1995e5dd7070Spatrick 
1996*12c85518Srobert   ParsedAttributes attrs(AttrFactory);
1997e5dd7070Spatrick   MaybeParseCXX11Attributes(attrs);
1998e5dd7070Spatrick 
1999e5dd7070Spatrick   SourceLocation EmptyInitStmtSemiLoc;
2000e5dd7070Spatrick 
2001e5dd7070Spatrick   // Parse the first part of the for specifier.
2002e5dd7070Spatrick   if (Tok.is(tok::semi)) {  // for (;
2003e5dd7070Spatrick     ProhibitAttributes(attrs);
2004e5dd7070Spatrick     // no first part, eat the ';'.
2005e5dd7070Spatrick     SourceLocation SemiLoc = Tok.getLocation();
2006e5dd7070Spatrick     if (!Tok.hasLeadingEmptyMacro() && !SemiLoc.isMacroID())
2007e5dd7070Spatrick       EmptyInitStmtSemiLoc = SemiLoc;
2008e5dd7070Spatrick     ConsumeToken();
2009e5dd7070Spatrick   } else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) &&
2010e5dd7070Spatrick              isForRangeIdentifier()) {
2011e5dd7070Spatrick     ProhibitAttributes(attrs);
2012e5dd7070Spatrick     IdentifierInfo *Name = Tok.getIdentifierInfo();
2013e5dd7070Spatrick     SourceLocation Loc = ConsumeToken();
2014e5dd7070Spatrick     MaybeParseCXX11Attributes(attrs);
2015e5dd7070Spatrick 
2016e5dd7070Spatrick     ForRangeInfo.ColonLoc = ConsumeToken();
2017e5dd7070Spatrick     if (Tok.is(tok::l_brace))
2018e5dd7070Spatrick       ForRangeInfo.RangeExpr = ParseBraceInitializer();
2019e5dd7070Spatrick     else
2020e5dd7070Spatrick       ForRangeInfo.RangeExpr = ParseExpression();
2021e5dd7070Spatrick 
2022e5dd7070Spatrick     Diag(Loc, diag::err_for_range_identifier)
2023e5dd7070Spatrick       << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus17)
2024e5dd7070Spatrick               ? FixItHint::CreateInsertion(Loc, "auto &&")
2025e5dd7070Spatrick               : FixItHint());
2026e5dd7070Spatrick 
2027*12c85518Srobert     ForRangeInfo.LoopVar =
2028*12c85518Srobert         Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name, attrs);
2029e5dd7070Spatrick   } else if (isForInitDeclaration()) {  // for (int X = 4;
2030e5dd7070Spatrick     ParenBraceBracketBalancer BalancerRAIIObj(*this);
2031e5dd7070Spatrick 
2032e5dd7070Spatrick     // Parse declaration, which eats the ';'.
2033e5dd7070Spatrick     if (!C99orCXXorObjC) {   // Use of C99-style for loops in C90 mode?
2034e5dd7070Spatrick       Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
2035e5dd7070Spatrick       Diag(Tok, diag::warn_gcc_variable_decl_in_for_loop);
2036e5dd7070Spatrick     }
2037*12c85518Srobert     DeclGroupPtrTy DG;
2038*12c85518Srobert     if (Tok.is(tok::kw_using)) {
2039*12c85518Srobert       DG = ParseAliasDeclarationInInitStatement(DeclaratorContext::ForInit,
2040*12c85518Srobert                                                 attrs);
2041*12c85518Srobert     } else {
2042e5dd7070Spatrick       // In C++0x, "for (T NS:a" might not be a typo for ::
2043e5dd7070Spatrick       bool MightBeForRangeStmt = getLangOpts().CPlusPlus;
2044e5dd7070Spatrick       ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
2045e5dd7070Spatrick 
2046e5dd7070Spatrick       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
2047*12c85518Srobert       ParsedAttributes DeclSpecAttrs(AttrFactory);
2048*12c85518Srobert       DG = ParseSimpleDeclaration(
2049*12c85518Srobert           DeclaratorContext::ForInit, DeclEnd, attrs, DeclSpecAttrs, false,
2050e5dd7070Spatrick           MightBeForRangeStmt ? &ForRangeInfo : nullptr);
2051e5dd7070Spatrick       FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
2052e5dd7070Spatrick       if (ForRangeInfo.ParsedForRangeDecl()) {
2053*12c85518Srobert         Diag(ForRangeInfo.ColonLoc, getLangOpts().CPlusPlus11
2054*12c85518Srobert                                         ? diag::warn_cxx98_compat_for_range
2055*12c85518Srobert                                         : diag::ext_for_range);
2056e5dd7070Spatrick         ForRangeInfo.LoopVar = FirstPart;
2057e5dd7070Spatrick         FirstPart = StmtResult();
2058e5dd7070Spatrick       } else if (Tok.is(tok::semi)) { // for (int x = 4;
2059e5dd7070Spatrick         ConsumeToken();
2060e5dd7070Spatrick       } else if ((ForEach = isTokIdentifier_in())) {
2061e5dd7070Spatrick         Actions.ActOnForEachDeclStmt(DG);
2062e5dd7070Spatrick         // ObjC: for (id x in expr)
2063e5dd7070Spatrick         ConsumeToken(); // consume 'in'
2064e5dd7070Spatrick 
2065e5dd7070Spatrick         if (Tok.is(tok::code_completion)) {
2066e5dd7070Spatrick           cutOffParsing();
2067a9ac8606Spatrick           Actions.CodeCompleteObjCForCollection(getCurScope(), DG);
2068e5dd7070Spatrick           return StmtError();
2069e5dd7070Spatrick         }
2070e5dd7070Spatrick         Collection = ParseExpression();
2071e5dd7070Spatrick       } else {
2072e5dd7070Spatrick         Diag(Tok, diag::err_expected_semi_for);
2073e5dd7070Spatrick       }
2074*12c85518Srobert     }
2075e5dd7070Spatrick   } else {
2076e5dd7070Spatrick     ProhibitAttributes(attrs);
2077e5dd7070Spatrick     Value = Actions.CorrectDelayedTyposInExpr(ParseExpression());
2078e5dd7070Spatrick 
2079e5dd7070Spatrick     ForEach = isTokIdentifier_in();
2080e5dd7070Spatrick 
2081e5dd7070Spatrick     // Turn the expression into a stmt.
2082e5dd7070Spatrick     if (!Value.isInvalid()) {
2083e5dd7070Spatrick       if (ForEach)
2084e5dd7070Spatrick         FirstPart = Actions.ActOnForEachLValueExpr(Value.get());
2085e5dd7070Spatrick       else {
2086e5dd7070Spatrick         // We already know this is not an init-statement within a for loop, so
2087e5dd7070Spatrick         // if we are parsing a C++11 range-based for loop, we should treat this
2088e5dd7070Spatrick         // expression statement as being a discarded value expression because
2089e5dd7070Spatrick         // we will err below. This way we do not warn on an unused expression
2090e5dd7070Spatrick         // that was an error in the first place, like with: for (expr : expr);
2091e5dd7070Spatrick         bool IsRangeBasedFor =
2092e5dd7070Spatrick             getLangOpts().CPlusPlus11 && !ForEach && Tok.is(tok::colon);
2093e5dd7070Spatrick         FirstPart = Actions.ActOnExprStmt(Value, !IsRangeBasedFor);
2094e5dd7070Spatrick       }
2095e5dd7070Spatrick     }
2096e5dd7070Spatrick 
2097e5dd7070Spatrick     if (Tok.is(tok::semi)) {
2098e5dd7070Spatrick       ConsumeToken();
2099e5dd7070Spatrick     } else if (ForEach) {
2100e5dd7070Spatrick       ConsumeToken(); // consume 'in'
2101e5dd7070Spatrick 
2102e5dd7070Spatrick       if (Tok.is(tok::code_completion)) {
2103e5dd7070Spatrick         cutOffParsing();
2104a9ac8606Spatrick         Actions.CodeCompleteObjCForCollection(getCurScope(), nullptr);
2105e5dd7070Spatrick         return StmtError();
2106e5dd7070Spatrick       }
2107e5dd7070Spatrick       Collection = ParseExpression();
2108e5dd7070Spatrick     } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::colon) && FirstPart.get()) {
2109e5dd7070Spatrick       // User tried to write the reasonable, but ill-formed, for-range-statement
2110e5dd7070Spatrick       //   for (expr : expr) { ... }
2111e5dd7070Spatrick       Diag(Tok, diag::err_for_range_expected_decl)
2112e5dd7070Spatrick         << FirstPart.get()->getSourceRange();
2113e5dd7070Spatrick       SkipUntil(tok::r_paren, StopBeforeMatch);
2114e5dd7070Spatrick       SecondPart = Sema::ConditionError();
2115e5dd7070Spatrick     } else {
2116e5dd7070Spatrick       if (!Value.isInvalid()) {
2117e5dd7070Spatrick         Diag(Tok, diag::err_expected_semi_for);
2118e5dd7070Spatrick       } else {
2119e5dd7070Spatrick         // Skip until semicolon or rparen, don't consume it.
2120e5dd7070Spatrick         SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
2121e5dd7070Spatrick         if (Tok.is(tok::semi))
2122e5dd7070Spatrick           ConsumeToken();
2123e5dd7070Spatrick       }
2124e5dd7070Spatrick     }
2125e5dd7070Spatrick   }
2126e5dd7070Spatrick 
2127e5dd7070Spatrick   // Parse the second part of the for specifier.
2128e5dd7070Spatrick   if (!ForEach && !ForRangeInfo.ParsedForRangeDecl() &&
2129e5dd7070Spatrick       !SecondPart.isInvalid()) {
2130e5dd7070Spatrick     // Parse the second part of the for specifier.
2131e5dd7070Spatrick     if (Tok.is(tok::semi)) {  // for (...;;
2132e5dd7070Spatrick       // no second part.
2133e5dd7070Spatrick     } else if (Tok.is(tok::r_paren)) {
2134e5dd7070Spatrick       // missing both semicolons.
2135e5dd7070Spatrick     } else {
2136e5dd7070Spatrick       if (getLangOpts().CPlusPlus) {
2137e5dd7070Spatrick         // C++2a: We've parsed an init-statement; we might have a
2138e5dd7070Spatrick         // for-range-declaration next.
2139e5dd7070Spatrick         bool MightBeForRangeStmt = !ForRangeInfo.ParsedForRangeDecl();
2140e5dd7070Spatrick         ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
2141*12c85518Srobert         SecondPart = ParseCXXCondition(
2142*12c85518Srobert             nullptr, ForLoc, Sema::ConditionKind::Boolean,
2143*12c85518Srobert             // FIXME: recovery if we don't see another semi!
2144*12c85518Srobert             /*MissingOK=*/true, MightBeForRangeStmt ? &ForRangeInfo : nullptr,
2145a9ac8606Spatrick             /*EnterForConditionScope*/ true);
2146e5dd7070Spatrick 
2147e5dd7070Spatrick         if (ForRangeInfo.ParsedForRangeDecl()) {
2148e5dd7070Spatrick           Diag(FirstPart.get() ? FirstPart.get()->getBeginLoc()
2149e5dd7070Spatrick                                : ForRangeInfo.ColonLoc,
2150ec727ea7Spatrick                getLangOpts().CPlusPlus20
2151e5dd7070Spatrick                    ? diag::warn_cxx17_compat_for_range_init_stmt
2152e5dd7070Spatrick                    : diag::ext_for_range_init_stmt)
2153e5dd7070Spatrick               << (FirstPart.get() ? FirstPart.get()->getSourceRange()
2154e5dd7070Spatrick                                   : SourceRange());
2155e5dd7070Spatrick           if (EmptyInitStmtSemiLoc.isValid()) {
2156e5dd7070Spatrick             Diag(EmptyInitStmtSemiLoc, diag::warn_empty_init_statement)
2157e5dd7070Spatrick                 << /*for-loop*/ 2
2158e5dd7070Spatrick                 << FixItHint::CreateRemoval(EmptyInitStmtSemiLoc);
2159e5dd7070Spatrick           }
2160e5dd7070Spatrick         }
2161e5dd7070Spatrick       } else {
2162a9ac8606Spatrick         // We permit 'continue' and 'break' in the condition of a for loop.
2163a9ac8606Spatrick         getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
2164a9ac8606Spatrick 
2165e5dd7070Spatrick         ExprResult SecondExpr = ParseExpression();
2166e5dd7070Spatrick         if (SecondExpr.isInvalid())
2167e5dd7070Spatrick           SecondPart = Sema::ConditionError();
2168e5dd7070Spatrick         else
2169*12c85518Srobert           SecondPart = Actions.ActOnCondition(
2170*12c85518Srobert               getCurScope(), ForLoc, SecondExpr.get(),
2171*12c85518Srobert               Sema::ConditionKind::Boolean, /*MissingOK=*/true);
2172e5dd7070Spatrick       }
2173e5dd7070Spatrick     }
2174e5dd7070Spatrick   }
2175e5dd7070Spatrick 
2176a9ac8606Spatrick   // Enter a break / continue scope, if we didn't already enter one while
2177a9ac8606Spatrick   // parsing the second part.
2178*12c85518Srobert   if (!getCurScope()->isContinueScope())
2179a9ac8606Spatrick     getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope);
2180a9ac8606Spatrick 
2181e5dd7070Spatrick   // Parse the third part of the for statement.
2182e5dd7070Spatrick   if (!ForEach && !ForRangeInfo.ParsedForRangeDecl()) {
2183e5dd7070Spatrick     if (Tok.isNot(tok::semi)) {
2184e5dd7070Spatrick       if (!SecondPart.isInvalid())
2185e5dd7070Spatrick         Diag(Tok, diag::err_expected_semi_for);
2186e5dd7070Spatrick       else
2187e5dd7070Spatrick         // Skip until semicolon or rparen, don't consume it.
2188e5dd7070Spatrick         SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
2189e5dd7070Spatrick     }
2190e5dd7070Spatrick 
2191e5dd7070Spatrick     if (Tok.is(tok::semi)) {
2192e5dd7070Spatrick       ConsumeToken();
2193e5dd7070Spatrick     }
2194e5dd7070Spatrick 
2195e5dd7070Spatrick     if (Tok.isNot(tok::r_paren)) {   // for (...;...;)
2196e5dd7070Spatrick       ExprResult Third = ParseExpression();
2197e5dd7070Spatrick       // FIXME: The C++11 standard doesn't actually say that this is a
2198e5dd7070Spatrick       // discarded-value expression, but it clearly should be.
2199e5dd7070Spatrick       ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.get());
2200e5dd7070Spatrick     }
2201e5dd7070Spatrick   }
2202e5dd7070Spatrick   // Match the ')'.
2203e5dd7070Spatrick   T.consumeClose();
2204e5dd7070Spatrick 
2205e5dd7070Spatrick   // C++ Coroutines [stmt.iter]:
2206e5dd7070Spatrick   //   'co_await' can only be used for a range-based for statement.
2207e5dd7070Spatrick   if (CoawaitLoc.isValid() && !ForRangeInfo.ParsedForRangeDecl()) {
2208e5dd7070Spatrick     Diag(CoawaitLoc, diag::err_for_co_await_not_range_for);
2209e5dd7070Spatrick     CoawaitLoc = SourceLocation();
2210e5dd7070Spatrick   }
2211e5dd7070Spatrick 
2212*12c85518Srobert   if (CoawaitLoc.isValid() && getLangOpts().CPlusPlus20)
2213*12c85518Srobert     Diag(CoawaitLoc, diag::warn_deprecated_for_co_await);
2214*12c85518Srobert 
2215e5dd7070Spatrick   // We need to perform most of the semantic analysis for a C++0x for-range
2216e5dd7070Spatrick   // statememt before parsing the body, in order to be able to deduce the type
2217e5dd7070Spatrick   // of an auto-typed loop variable.
2218e5dd7070Spatrick   StmtResult ForRangeStmt;
2219e5dd7070Spatrick   StmtResult ForEachStmt;
2220e5dd7070Spatrick 
2221e5dd7070Spatrick   if (ForRangeInfo.ParsedForRangeDecl()) {
2222e5dd7070Spatrick     ExprResult CorrectedRange =
2223e5dd7070Spatrick         Actions.CorrectDelayedTyposInExpr(ForRangeInfo.RangeExpr.get());
2224e5dd7070Spatrick     ForRangeStmt = Actions.ActOnCXXForRangeStmt(
2225e5dd7070Spatrick         getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(),
2226e5dd7070Spatrick         ForRangeInfo.LoopVar.get(), ForRangeInfo.ColonLoc, CorrectedRange.get(),
2227e5dd7070Spatrick         T.getCloseLocation(), Sema::BFRK_Build);
2228e5dd7070Spatrick 
2229e5dd7070Spatrick   // Similarly, we need to do the semantic analysis for a for-range
2230e5dd7070Spatrick   // statement immediately in order to close over temporaries correctly.
2231e5dd7070Spatrick   } else if (ForEach) {
2232e5dd7070Spatrick     ForEachStmt = Actions.ActOnObjCForCollectionStmt(ForLoc,
2233e5dd7070Spatrick                                                      FirstPart.get(),
2234e5dd7070Spatrick                                                      Collection.get(),
2235e5dd7070Spatrick                                                      T.getCloseLocation());
2236e5dd7070Spatrick   } else {
2237e5dd7070Spatrick     // In OpenMP loop region loop control variable must be captured and be
2238e5dd7070Spatrick     // private. Perform analysis of first part (if any).
2239e5dd7070Spatrick     if (getLangOpts().OpenMP && FirstPart.isUsable()) {
2240e5dd7070Spatrick       Actions.ActOnOpenMPLoopInitialization(ForLoc, FirstPart.get());
2241e5dd7070Spatrick     }
2242e5dd7070Spatrick   }
2243e5dd7070Spatrick 
2244e5dd7070Spatrick   // C99 6.8.5p5 - In C99, the body of the for statement is a scope, even if
2245e5dd7070Spatrick   // there is no compound stmt.  C90 does not have this clause.  We only do this
2246e5dd7070Spatrick   // if the body isn't a compound statement to avoid push/pop in common cases.
2247e5dd7070Spatrick   //
2248e5dd7070Spatrick   // C++ 6.5p2:
2249e5dd7070Spatrick   // The substatement in an iteration-statement implicitly defines a local scope
2250e5dd7070Spatrick   // which is entered and exited each time through the loop.
2251e5dd7070Spatrick   //
2252e5dd7070Spatrick   // See comments in ParseIfStatement for why we create a scope for
2253e5dd7070Spatrick   // for-init-statement/condition and a new scope for substatement in C++.
2254e5dd7070Spatrick   //
2255e5dd7070Spatrick   ParseScope InnerScope(this, Scope::DeclScope, C99orCXXorObjC,
2256e5dd7070Spatrick                         Tok.is(tok::l_brace));
2257e5dd7070Spatrick 
2258e5dd7070Spatrick   // The body of the for loop has the same local mangling number as the
2259e5dd7070Spatrick   // for-init-statement.
2260e5dd7070Spatrick   // It will only be incremented if the body contains other things that would
2261e5dd7070Spatrick   // normally increment the mangling number (like a compound statement).
2262e5dd7070Spatrick   if (C99orCXXorObjC)
2263e5dd7070Spatrick     getCurScope()->decrementMSManglingNumber();
2264e5dd7070Spatrick 
2265e5dd7070Spatrick   MisleadingIndentationChecker MIChecker(*this, MSK_for, ForLoc);
2266e5dd7070Spatrick 
2267e5dd7070Spatrick   // Read the body statement.
2268e5dd7070Spatrick   StmtResult Body(ParseStatement(TrailingElseLoc));
2269e5dd7070Spatrick 
2270e5dd7070Spatrick   if (Body.isUsable())
2271e5dd7070Spatrick     MIChecker.Check();
2272e5dd7070Spatrick 
2273e5dd7070Spatrick   // Pop the body scope if needed.
2274e5dd7070Spatrick   InnerScope.Exit();
2275e5dd7070Spatrick 
2276e5dd7070Spatrick   // Leave the for-scope.
2277e5dd7070Spatrick   ForScope.Exit();
2278e5dd7070Spatrick 
2279e5dd7070Spatrick   if (Body.isInvalid())
2280e5dd7070Spatrick     return StmtError();
2281e5dd7070Spatrick 
2282e5dd7070Spatrick   if (ForEach)
2283e5dd7070Spatrick    return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(),
2284e5dd7070Spatrick                                               Body.get());
2285e5dd7070Spatrick 
2286e5dd7070Spatrick   if (ForRangeInfo.ParsedForRangeDecl())
2287e5dd7070Spatrick     return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get());
2288e5dd7070Spatrick 
2289e5dd7070Spatrick   return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(),
2290e5dd7070Spatrick                               SecondPart, ThirdPart, T.getCloseLocation(),
2291e5dd7070Spatrick                               Body.get());
2292e5dd7070Spatrick }
2293e5dd7070Spatrick 
2294e5dd7070Spatrick /// ParseGotoStatement
2295e5dd7070Spatrick ///       jump-statement:
2296e5dd7070Spatrick ///         'goto' identifier ';'
2297e5dd7070Spatrick /// [GNU]   'goto' '*' expression ';'
2298e5dd7070Spatrick ///
2299e5dd7070Spatrick /// Note: this lets the caller parse the end ';'.
2300e5dd7070Spatrick ///
ParseGotoStatement()2301e5dd7070Spatrick StmtResult Parser::ParseGotoStatement() {
2302e5dd7070Spatrick   assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
2303e5dd7070Spatrick   SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
2304e5dd7070Spatrick 
2305e5dd7070Spatrick   StmtResult Res;
2306e5dd7070Spatrick   if (Tok.is(tok::identifier)) {
2307e5dd7070Spatrick     LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
2308e5dd7070Spatrick                                                 Tok.getLocation());
2309e5dd7070Spatrick     Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(), LD);
2310e5dd7070Spatrick     ConsumeToken();
2311e5dd7070Spatrick   } else if (Tok.is(tok::star)) {
2312e5dd7070Spatrick     // GNU indirect goto extension.
2313e5dd7070Spatrick     Diag(Tok, diag::ext_gnu_indirect_goto);
2314e5dd7070Spatrick     SourceLocation StarLoc = ConsumeToken();
2315e5dd7070Spatrick     ExprResult R(ParseExpression());
2316e5dd7070Spatrick     if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
2317e5dd7070Spatrick       SkipUntil(tok::semi, StopBeforeMatch);
2318e5dd7070Spatrick       return StmtError();
2319e5dd7070Spatrick     }
2320e5dd7070Spatrick     Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.get());
2321e5dd7070Spatrick   } else {
2322e5dd7070Spatrick     Diag(Tok, diag::err_expected) << tok::identifier;
2323e5dd7070Spatrick     return StmtError();
2324e5dd7070Spatrick   }
2325e5dd7070Spatrick 
2326e5dd7070Spatrick   return Res;
2327e5dd7070Spatrick }
2328e5dd7070Spatrick 
2329e5dd7070Spatrick /// ParseContinueStatement
2330e5dd7070Spatrick ///       jump-statement:
2331e5dd7070Spatrick ///         'continue' ';'
2332e5dd7070Spatrick ///
2333e5dd7070Spatrick /// Note: this lets the caller parse the end ';'.
2334e5dd7070Spatrick ///
ParseContinueStatement()2335e5dd7070Spatrick StmtResult Parser::ParseContinueStatement() {
2336e5dd7070Spatrick   SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
2337e5dd7070Spatrick   return Actions.ActOnContinueStmt(ContinueLoc, getCurScope());
2338e5dd7070Spatrick }
2339e5dd7070Spatrick 
2340e5dd7070Spatrick /// ParseBreakStatement
2341e5dd7070Spatrick ///       jump-statement:
2342e5dd7070Spatrick ///         'break' ';'
2343e5dd7070Spatrick ///
2344e5dd7070Spatrick /// Note: this lets the caller parse the end ';'.
2345e5dd7070Spatrick ///
ParseBreakStatement()2346e5dd7070Spatrick StmtResult Parser::ParseBreakStatement() {
2347e5dd7070Spatrick   SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
2348e5dd7070Spatrick   return Actions.ActOnBreakStmt(BreakLoc, getCurScope());
2349e5dd7070Spatrick }
2350e5dd7070Spatrick 
2351e5dd7070Spatrick /// ParseReturnStatement
2352e5dd7070Spatrick ///       jump-statement:
2353e5dd7070Spatrick ///         'return' expression[opt] ';'
2354e5dd7070Spatrick ///         'return' braced-init-list ';'
2355e5dd7070Spatrick ///         'co_return' expression[opt] ';'
2356e5dd7070Spatrick ///         'co_return' braced-init-list ';'
ParseReturnStatement()2357e5dd7070Spatrick StmtResult Parser::ParseReturnStatement() {
2358e5dd7070Spatrick   assert((Tok.is(tok::kw_return) || Tok.is(tok::kw_co_return)) &&
2359e5dd7070Spatrick          "Not a return stmt!");
2360e5dd7070Spatrick   bool IsCoreturn = Tok.is(tok::kw_co_return);
2361e5dd7070Spatrick   SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
2362e5dd7070Spatrick 
2363e5dd7070Spatrick   ExprResult R;
2364e5dd7070Spatrick   if (Tok.isNot(tok::semi)) {
2365e5dd7070Spatrick     if (!IsCoreturn)
2366e5dd7070Spatrick       PreferredType.enterReturn(Actions, Tok.getLocation());
2367e5dd7070Spatrick     // FIXME: Code completion for co_return.
2368e5dd7070Spatrick     if (Tok.is(tok::code_completion) && !IsCoreturn) {
2369a9ac8606Spatrick       cutOffParsing();
2370e5dd7070Spatrick       Actions.CodeCompleteExpression(getCurScope(),
2371e5dd7070Spatrick                                      PreferredType.get(Tok.getLocation()));
2372e5dd7070Spatrick       return StmtError();
2373e5dd7070Spatrick     }
2374e5dd7070Spatrick 
2375e5dd7070Spatrick     if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus) {
2376e5dd7070Spatrick       R = ParseInitializer();
2377e5dd7070Spatrick       if (R.isUsable())
2378e5dd7070Spatrick         Diag(R.get()->getBeginLoc(),
2379e5dd7070Spatrick              getLangOpts().CPlusPlus11
2380e5dd7070Spatrick                  ? diag::warn_cxx98_compat_generalized_initializer_lists
2381e5dd7070Spatrick                  : diag::ext_generalized_initializer_lists)
2382e5dd7070Spatrick             << R.get()->getSourceRange();
2383e5dd7070Spatrick     } else
2384e5dd7070Spatrick       R = ParseExpression();
2385e5dd7070Spatrick     if (R.isInvalid()) {
2386e5dd7070Spatrick       SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
2387e5dd7070Spatrick       return StmtError();
2388e5dd7070Spatrick     }
2389e5dd7070Spatrick   }
2390e5dd7070Spatrick   if (IsCoreturn)
2391e5dd7070Spatrick     return Actions.ActOnCoreturnStmt(getCurScope(), ReturnLoc, R.get());
2392e5dd7070Spatrick   return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope());
2393e5dd7070Spatrick }
2394e5dd7070Spatrick 
ParsePragmaLoopHint(StmtVector & Stmts,ParsedStmtContext StmtCtx,SourceLocation * TrailingElseLoc,ParsedAttributes & Attrs)2395e5dd7070Spatrick StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts,
2396e5dd7070Spatrick                                        ParsedStmtContext StmtCtx,
2397e5dd7070Spatrick                                        SourceLocation *TrailingElseLoc,
2398*12c85518Srobert                                        ParsedAttributes &Attrs) {
2399e5dd7070Spatrick   // Create temporary attribute list.
2400*12c85518Srobert   ParsedAttributes TempAttrs(AttrFactory);
2401e5dd7070Spatrick 
2402ec727ea7Spatrick   SourceLocation StartLoc = Tok.getLocation();
2403ec727ea7Spatrick 
2404e5dd7070Spatrick   // Get loop hints and consume annotated token.
2405e5dd7070Spatrick   while (Tok.is(tok::annot_pragma_loop_hint)) {
2406e5dd7070Spatrick     LoopHint Hint;
2407e5dd7070Spatrick     if (!HandlePragmaLoopHint(Hint))
2408e5dd7070Spatrick       continue;
2409e5dd7070Spatrick 
2410e5dd7070Spatrick     ArgsUnion ArgHints[] = {Hint.PragmaNameLoc, Hint.OptionLoc, Hint.StateLoc,
2411e5dd7070Spatrick                             ArgsUnion(Hint.ValueExpr)};
2412e5dd7070Spatrick     TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr,
2413e5dd7070Spatrick                      Hint.PragmaNameLoc->Loc, ArgHints, 4,
2414e5dd7070Spatrick                      ParsedAttr::AS_Pragma);
2415e5dd7070Spatrick   }
2416e5dd7070Spatrick 
2417e5dd7070Spatrick   // Get the next statement.
2418e5dd7070Spatrick   MaybeParseCXX11Attributes(Attrs);
2419e5dd7070Spatrick 
2420*12c85518Srobert   ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);
2421e5dd7070Spatrick   StmtResult S = ParseStatementOrDeclarationAfterAttributes(
2422*12c85518Srobert       Stmts, StmtCtx, TrailingElseLoc, Attrs, EmptyDeclSpecAttrs);
2423e5dd7070Spatrick 
2424e5dd7070Spatrick   Attrs.takeAllFrom(TempAttrs);
2425ec727ea7Spatrick 
2426ec727ea7Spatrick   // Start of attribute range may already be set for some invalid input.
2427ec727ea7Spatrick   // See PR46336.
2428ec727ea7Spatrick   if (Attrs.Range.getBegin().isInvalid())
2429ec727ea7Spatrick     Attrs.Range.setBegin(StartLoc);
2430ec727ea7Spatrick 
2431e5dd7070Spatrick   return S;
2432e5dd7070Spatrick }
2433e5dd7070Spatrick 
ParseFunctionStatementBody(Decl * Decl,ParseScope & BodyScope)2434e5dd7070Spatrick Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
2435e5dd7070Spatrick   assert(Tok.is(tok::l_brace));
2436e5dd7070Spatrick   SourceLocation LBraceLoc = Tok.getLocation();
2437e5dd7070Spatrick 
2438e5dd7070Spatrick   PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, LBraceLoc,
2439e5dd7070Spatrick                                       "parsing function body");
2440e5dd7070Spatrick 
2441e5dd7070Spatrick   // Save and reset current vtordisp stack if we have entered a C++ method body.
2442e5dd7070Spatrick   bool IsCXXMethod =
2443e5dd7070Spatrick       getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl);
2444e5dd7070Spatrick   Sema::PragmaStackSentinelRAII
2445e5dd7070Spatrick     PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
2446e5dd7070Spatrick 
2447e5dd7070Spatrick   // Do not enter a scope for the brace, as the arguments are in the same scope
2448e5dd7070Spatrick   // (the function body) as the body itself.  Instead, just read the statement
2449e5dd7070Spatrick   // list and put it into a CompoundStmt for safe keeping.
2450e5dd7070Spatrick   StmtResult FnBody(ParseCompoundStatementBody());
2451e5dd7070Spatrick 
2452e5dd7070Spatrick   // If the function body could not be parsed, make a bogus compoundstmt.
2453e5dd7070Spatrick   if (FnBody.isInvalid()) {
2454e5dd7070Spatrick     Sema::CompoundScopeRAII CompoundScope(Actions);
2455*12c85518Srobert     FnBody =
2456*12c85518Srobert         Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, std::nullopt, false);
2457e5dd7070Spatrick   }
2458e5dd7070Spatrick 
2459e5dd7070Spatrick   BodyScope.Exit();
2460e5dd7070Spatrick   return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
2461e5dd7070Spatrick }
2462e5dd7070Spatrick 
2463e5dd7070Spatrick /// ParseFunctionTryBlock - Parse a C++ function-try-block.
2464e5dd7070Spatrick ///
2465e5dd7070Spatrick ///       function-try-block:
2466e5dd7070Spatrick ///         'try' ctor-initializer[opt] compound-statement handler-seq
2467e5dd7070Spatrick ///
ParseFunctionTryBlock(Decl * Decl,ParseScope & BodyScope)2468e5dd7070Spatrick Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
2469e5dd7070Spatrick   assert(Tok.is(tok::kw_try) && "Expected 'try'");
2470e5dd7070Spatrick   SourceLocation TryLoc = ConsumeToken();
2471e5dd7070Spatrick 
2472e5dd7070Spatrick   PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, TryLoc,
2473e5dd7070Spatrick                                       "parsing function try block");
2474e5dd7070Spatrick 
2475e5dd7070Spatrick   // Constructor initializer list?
2476e5dd7070Spatrick   if (Tok.is(tok::colon))
2477e5dd7070Spatrick     ParseConstructorInitializer(Decl);
2478e5dd7070Spatrick   else
2479e5dd7070Spatrick     Actions.ActOnDefaultCtorInitializers(Decl);
2480e5dd7070Spatrick 
2481e5dd7070Spatrick   // Save and reset current vtordisp stack if we have entered a C++ method body.
2482e5dd7070Spatrick   bool IsCXXMethod =
2483e5dd7070Spatrick       getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl);
2484e5dd7070Spatrick   Sema::PragmaStackSentinelRAII
2485e5dd7070Spatrick     PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
2486e5dd7070Spatrick 
2487e5dd7070Spatrick   SourceLocation LBraceLoc = Tok.getLocation();
2488e5dd7070Spatrick   StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true));
2489e5dd7070Spatrick   // If we failed to parse the try-catch, we just give the function an empty
2490e5dd7070Spatrick   // compound statement as the body.
2491e5dd7070Spatrick   if (FnBody.isInvalid()) {
2492e5dd7070Spatrick     Sema::CompoundScopeRAII CompoundScope(Actions);
2493*12c85518Srobert     FnBody =
2494*12c85518Srobert         Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, std::nullopt, false);
2495e5dd7070Spatrick   }
2496e5dd7070Spatrick 
2497e5dd7070Spatrick   BodyScope.Exit();
2498e5dd7070Spatrick   return Actions.ActOnFinishFunctionBody(Decl, FnBody.get());
2499e5dd7070Spatrick }
2500e5dd7070Spatrick 
trySkippingFunctionBody()2501e5dd7070Spatrick bool Parser::trySkippingFunctionBody() {
2502e5dd7070Spatrick   assert(SkipFunctionBodies &&
2503e5dd7070Spatrick          "Should only be called when SkipFunctionBodies is enabled");
2504e5dd7070Spatrick   if (!PP.isCodeCompletionEnabled()) {
2505e5dd7070Spatrick     SkipFunctionBody();
2506e5dd7070Spatrick     return true;
2507e5dd7070Spatrick   }
2508e5dd7070Spatrick 
2509e5dd7070Spatrick   // We're in code-completion mode. Skip parsing for all function bodies unless
2510e5dd7070Spatrick   // the body contains the code-completion point.
2511e5dd7070Spatrick   TentativeParsingAction PA(*this);
2512e5dd7070Spatrick   bool IsTryCatch = Tok.is(tok::kw_try);
2513e5dd7070Spatrick   CachedTokens Toks;
2514e5dd7070Spatrick   bool ErrorInPrologue = ConsumeAndStoreFunctionPrologue(Toks);
2515e5dd7070Spatrick   if (llvm::any_of(Toks, [](const Token &Tok) {
2516e5dd7070Spatrick         return Tok.is(tok::code_completion);
2517e5dd7070Spatrick       })) {
2518e5dd7070Spatrick     PA.Revert();
2519e5dd7070Spatrick     return false;
2520e5dd7070Spatrick   }
2521e5dd7070Spatrick   if (ErrorInPrologue) {
2522e5dd7070Spatrick     PA.Commit();
2523e5dd7070Spatrick     SkipMalformedDecl();
2524e5dd7070Spatrick     return true;
2525e5dd7070Spatrick   }
2526e5dd7070Spatrick   if (!SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
2527e5dd7070Spatrick     PA.Revert();
2528e5dd7070Spatrick     return false;
2529e5dd7070Spatrick   }
2530e5dd7070Spatrick   while (IsTryCatch && Tok.is(tok::kw_catch)) {
2531e5dd7070Spatrick     if (!SkipUntil(tok::l_brace, StopAtCodeCompletion) ||
2532e5dd7070Spatrick         !SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
2533e5dd7070Spatrick       PA.Revert();
2534e5dd7070Spatrick       return false;
2535e5dd7070Spatrick     }
2536e5dd7070Spatrick   }
2537e5dd7070Spatrick   PA.Commit();
2538e5dd7070Spatrick   return true;
2539e5dd7070Spatrick }
2540e5dd7070Spatrick 
2541e5dd7070Spatrick /// ParseCXXTryBlock - Parse a C++ try-block.
2542e5dd7070Spatrick ///
2543e5dd7070Spatrick ///       try-block:
2544e5dd7070Spatrick ///         'try' compound-statement handler-seq
2545e5dd7070Spatrick ///
ParseCXXTryBlock()2546e5dd7070Spatrick StmtResult Parser::ParseCXXTryBlock() {
2547e5dd7070Spatrick   assert(Tok.is(tok::kw_try) && "Expected 'try'");
2548e5dd7070Spatrick 
2549e5dd7070Spatrick   SourceLocation TryLoc = ConsumeToken();
2550e5dd7070Spatrick   return ParseCXXTryBlockCommon(TryLoc);
2551e5dd7070Spatrick }
2552e5dd7070Spatrick 
2553e5dd7070Spatrick /// ParseCXXTryBlockCommon - Parse the common part of try-block and
2554e5dd7070Spatrick /// function-try-block.
2555e5dd7070Spatrick ///
2556e5dd7070Spatrick ///       try-block:
2557e5dd7070Spatrick ///         'try' compound-statement handler-seq
2558e5dd7070Spatrick ///
2559e5dd7070Spatrick ///       function-try-block:
2560e5dd7070Spatrick ///         'try' ctor-initializer[opt] compound-statement handler-seq
2561e5dd7070Spatrick ///
2562e5dd7070Spatrick ///       handler-seq:
2563e5dd7070Spatrick ///         handler handler-seq[opt]
2564e5dd7070Spatrick ///
2565e5dd7070Spatrick ///       [Borland] try-block:
2566e5dd7070Spatrick ///         'try' compound-statement seh-except-block
2567e5dd7070Spatrick ///         'try' compound-statement seh-finally-block
2568e5dd7070Spatrick ///
ParseCXXTryBlockCommon(SourceLocation TryLoc,bool FnTry)2569e5dd7070Spatrick StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
2570e5dd7070Spatrick   if (Tok.isNot(tok::l_brace))
2571e5dd7070Spatrick     return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
2572e5dd7070Spatrick 
2573e5dd7070Spatrick   StmtResult TryBlock(ParseCompoundStatement(
2574e5dd7070Spatrick       /*isStmtExpr=*/false, Scope::DeclScope | Scope::TryScope |
2575e5dd7070Spatrick                                 Scope::CompoundStmtScope |
2576e5dd7070Spatrick                                 (FnTry ? Scope::FnTryCatchScope : 0)));
2577e5dd7070Spatrick   if (TryBlock.isInvalid())
2578e5dd7070Spatrick     return TryBlock;
2579e5dd7070Spatrick 
2580e5dd7070Spatrick   // Borland allows SEH-handlers with 'try'
2581e5dd7070Spatrick 
2582e5dd7070Spatrick   if ((Tok.is(tok::identifier) &&
2583e5dd7070Spatrick        Tok.getIdentifierInfo() == getSEHExceptKeyword()) ||
2584e5dd7070Spatrick       Tok.is(tok::kw___finally)) {
2585e5dd7070Spatrick     // TODO: Factor into common return ParseSEHHandlerCommon(...)
2586e5dd7070Spatrick     StmtResult Handler;
2587e5dd7070Spatrick     if(Tok.getIdentifierInfo() == getSEHExceptKeyword()) {
2588e5dd7070Spatrick       SourceLocation Loc = ConsumeToken();
2589e5dd7070Spatrick       Handler = ParseSEHExceptBlock(Loc);
2590e5dd7070Spatrick     }
2591e5dd7070Spatrick     else {
2592e5dd7070Spatrick       SourceLocation Loc = ConsumeToken();
2593e5dd7070Spatrick       Handler = ParseSEHFinallyBlock(Loc);
2594e5dd7070Spatrick     }
2595e5dd7070Spatrick     if(Handler.isInvalid())
2596e5dd7070Spatrick       return Handler;
2597e5dd7070Spatrick 
2598e5dd7070Spatrick     return Actions.ActOnSEHTryBlock(true /* IsCXXTry */,
2599e5dd7070Spatrick                                     TryLoc,
2600e5dd7070Spatrick                                     TryBlock.get(),
2601e5dd7070Spatrick                                     Handler.get());
2602e5dd7070Spatrick   }
2603e5dd7070Spatrick   else {
2604e5dd7070Spatrick     StmtVector Handlers;
2605e5dd7070Spatrick 
2606e5dd7070Spatrick     // C++11 attributes can't appear here, despite this context seeming
2607e5dd7070Spatrick     // statement-like.
2608e5dd7070Spatrick     DiagnoseAndSkipCXX11Attributes();
2609e5dd7070Spatrick 
2610e5dd7070Spatrick     if (Tok.isNot(tok::kw_catch))
2611e5dd7070Spatrick       return StmtError(Diag(Tok, diag::err_expected_catch));
2612e5dd7070Spatrick     while (Tok.is(tok::kw_catch)) {
2613e5dd7070Spatrick       StmtResult Handler(ParseCXXCatchBlock(FnTry));
2614e5dd7070Spatrick       if (!Handler.isInvalid())
2615e5dd7070Spatrick         Handlers.push_back(Handler.get());
2616e5dd7070Spatrick     }
2617e5dd7070Spatrick     // Don't bother creating the full statement if we don't have any usable
2618e5dd7070Spatrick     // handlers.
2619e5dd7070Spatrick     if (Handlers.empty())
2620e5dd7070Spatrick       return StmtError();
2621e5dd7070Spatrick 
2622e5dd7070Spatrick     return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.get(), Handlers);
2623e5dd7070Spatrick   }
2624e5dd7070Spatrick }
2625e5dd7070Spatrick 
2626e5dd7070Spatrick /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
2627e5dd7070Spatrick ///
2628e5dd7070Spatrick ///   handler:
2629e5dd7070Spatrick ///     'catch' '(' exception-declaration ')' compound-statement
2630e5dd7070Spatrick ///
2631e5dd7070Spatrick ///   exception-declaration:
2632e5dd7070Spatrick ///     attribute-specifier-seq[opt] type-specifier-seq declarator
2633e5dd7070Spatrick ///     attribute-specifier-seq[opt] type-specifier-seq abstract-declarator[opt]
2634e5dd7070Spatrick ///     '...'
2635e5dd7070Spatrick ///
ParseCXXCatchBlock(bool FnCatch)2636e5dd7070Spatrick StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) {
2637e5dd7070Spatrick   assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
2638e5dd7070Spatrick 
2639e5dd7070Spatrick   SourceLocation CatchLoc = ConsumeToken();
2640e5dd7070Spatrick 
2641e5dd7070Spatrick   BalancedDelimiterTracker T(*this, tok::l_paren);
2642e5dd7070Spatrick   if (T.expectAndConsume())
2643e5dd7070Spatrick     return StmtError();
2644e5dd7070Spatrick 
2645e5dd7070Spatrick   // C++ 3.3.2p3:
2646e5dd7070Spatrick   // The name in a catch exception-declaration is local to the handler and
2647e5dd7070Spatrick   // shall not be redeclared in the outermost block of the handler.
2648e5dd7070Spatrick   ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope |
2649e5dd7070Spatrick                                   Scope::CatchScope |
2650e5dd7070Spatrick                                   (FnCatch ? Scope::FnTryCatchScope : 0));
2651e5dd7070Spatrick 
2652e5dd7070Spatrick   // exception-declaration is equivalent to '...' or a parameter-declaration
2653e5dd7070Spatrick   // without default arguments.
2654e5dd7070Spatrick   Decl *ExceptionDecl = nullptr;
2655e5dd7070Spatrick   if (Tok.isNot(tok::ellipsis)) {
2656*12c85518Srobert     ParsedAttributes Attributes(AttrFactory);
2657e5dd7070Spatrick     MaybeParseCXX11Attributes(Attributes);
2658e5dd7070Spatrick 
2659e5dd7070Spatrick     DeclSpec DS(AttrFactory);
2660e5dd7070Spatrick 
2661e5dd7070Spatrick     if (ParseCXXTypeSpecifierSeq(DS))
2662e5dd7070Spatrick       return StmtError();
2663e5dd7070Spatrick 
2664*12c85518Srobert     Declarator ExDecl(DS, Attributes, DeclaratorContext::CXXCatch);
2665e5dd7070Spatrick     ParseDeclarator(ExDecl);
2666e5dd7070Spatrick     ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl);
2667e5dd7070Spatrick   } else
2668e5dd7070Spatrick     ConsumeToken();
2669e5dd7070Spatrick 
2670e5dd7070Spatrick   T.consumeClose();
2671e5dd7070Spatrick   if (T.getCloseLocation().isInvalid())
2672e5dd7070Spatrick     return StmtError();
2673e5dd7070Spatrick 
2674e5dd7070Spatrick   if (Tok.isNot(tok::l_brace))
2675e5dd7070Spatrick     return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace);
2676e5dd7070Spatrick 
2677e5dd7070Spatrick   // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
2678e5dd7070Spatrick   StmtResult Block(ParseCompoundStatement());
2679e5dd7070Spatrick   if (Block.isInvalid())
2680e5dd7070Spatrick     return Block;
2681e5dd7070Spatrick 
2682e5dd7070Spatrick   return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.get());
2683e5dd7070Spatrick }
2684e5dd7070Spatrick 
ParseMicrosoftIfExistsStatement(StmtVector & Stmts)2685e5dd7070Spatrick void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) {
2686e5dd7070Spatrick   IfExistsCondition Result;
2687e5dd7070Spatrick   if (ParseMicrosoftIfExistsCondition(Result))
2688e5dd7070Spatrick     return;
2689e5dd7070Spatrick 
2690e5dd7070Spatrick   // Handle dependent statements by parsing the braces as a compound statement.
2691e5dd7070Spatrick   // This is not the same behavior as Visual C++, which don't treat this as a
2692e5dd7070Spatrick   // compound statement, but for Clang's type checking we can't have anything
2693e5dd7070Spatrick   // inside these braces escaping to the surrounding code.
2694e5dd7070Spatrick   if (Result.Behavior == IEB_Dependent) {
2695e5dd7070Spatrick     if (!Tok.is(tok::l_brace)) {
2696e5dd7070Spatrick       Diag(Tok, diag::err_expected) << tok::l_brace;
2697e5dd7070Spatrick       return;
2698e5dd7070Spatrick     }
2699e5dd7070Spatrick 
2700e5dd7070Spatrick     StmtResult Compound = ParseCompoundStatement();
2701e5dd7070Spatrick     if (Compound.isInvalid())
2702e5dd7070Spatrick       return;
2703e5dd7070Spatrick 
2704e5dd7070Spatrick     StmtResult DepResult = Actions.ActOnMSDependentExistsStmt(Result.KeywordLoc,
2705e5dd7070Spatrick                                                               Result.IsIfExists,
2706e5dd7070Spatrick                                                               Result.SS,
2707e5dd7070Spatrick                                                               Result.Name,
2708e5dd7070Spatrick                                                               Compound.get());
2709e5dd7070Spatrick     if (DepResult.isUsable())
2710e5dd7070Spatrick       Stmts.push_back(DepResult.get());
2711e5dd7070Spatrick     return;
2712e5dd7070Spatrick   }
2713e5dd7070Spatrick 
2714e5dd7070Spatrick   BalancedDelimiterTracker Braces(*this, tok::l_brace);
2715e5dd7070Spatrick   if (Braces.consumeOpen()) {
2716e5dd7070Spatrick     Diag(Tok, diag::err_expected) << tok::l_brace;
2717e5dd7070Spatrick     return;
2718e5dd7070Spatrick   }
2719e5dd7070Spatrick 
2720e5dd7070Spatrick   switch (Result.Behavior) {
2721e5dd7070Spatrick   case IEB_Parse:
2722e5dd7070Spatrick     // Parse the statements below.
2723e5dd7070Spatrick     break;
2724e5dd7070Spatrick 
2725e5dd7070Spatrick   case IEB_Dependent:
2726e5dd7070Spatrick     llvm_unreachable("Dependent case handled above");
2727e5dd7070Spatrick 
2728e5dd7070Spatrick   case IEB_Skip:
2729e5dd7070Spatrick     Braces.skipToEnd();
2730e5dd7070Spatrick     return;
2731e5dd7070Spatrick   }
2732e5dd7070Spatrick 
2733e5dd7070Spatrick   // Condition is true, parse the statements.
2734e5dd7070Spatrick   while (Tok.isNot(tok::r_brace)) {
2735e5dd7070Spatrick     StmtResult R =
2736e5dd7070Spatrick         ParseStatementOrDeclaration(Stmts, ParsedStmtContext::Compound);
2737e5dd7070Spatrick     if (R.isUsable())
2738e5dd7070Spatrick       Stmts.push_back(R.get());
2739e5dd7070Spatrick   }
2740e5dd7070Spatrick   Braces.consumeClose();
2741e5dd7070Spatrick }
2742