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