ParseStmt.cpp revision 6405646cb649e4b4c6768b92d1fc83c175722f62
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//                     The LLVM Compiler Infrastructure
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details.
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file implements the Statement and Block portions of the Parser
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// interface.
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Parse/Parser.h"
16d167ca0d26e43292b8b9e8d5300d92784ae0e27dChris Lattner#include "RAIIObjectsForParser.h"
175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Parse/DeclSpec.h"
185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Parse/Scope.h"
19ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner#include "clang/Basic/Diagnostic.h"
20ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner#include "clang/Basic/PrettyStackTrace.h"
21ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner#include "clang/Basic/SourceManager.h"
225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang;
235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// C99 6.8: Statements and Blocks.
265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       StatementOrDeclaration:
305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         statement
315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         declaration
325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       statement:
345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         labeled-statement
355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         compound-statement
365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         expression-statement
375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         selection-statement
385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         iteration-statement
395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         jump-statement
40dcdd55fb4d28de8c314d6c6c1a38aa6aba76d431Argyrios Kyrtzidis/// [C++]   declaration-statement
41a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// [C++]   try-block
42b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC]   objc-throw-statement
43b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC]   objc-try-catch-statement
44c385c90c68dfa376650e2facfbb444b2ec9bd110Fariborz Jahanian/// [OBC]   objc-synchronized-statement
455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   asm-statement
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   openmp-construct             [TODO]
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         identifier ':' statement
505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'case' constant-expression ':' statement
515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'default' ':' statement
525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       selection-statement:
545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         if-statement
555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         switch-statement
565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       iteration-statement:
585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         while-statement
595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         do-statement
605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         for-statement
615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       expression-statement:
635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         expression[opt] ';'
645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'goto' identifier ';'
675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'continue' ';'
685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'break' ';'
695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'return' expression[opt] ';'
705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   'goto' '*' expression ';'
715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
72b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC] objc-throw-statement:
73b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC]   '@' 'throw' expression ';'
741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// [OBC]   '@' 'throw' ';'
751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///
7661364dddc33383e62cfe3b841dbc0f471280d95bSebastian RedlParser::OwningStmtResult
7761364dddc33383e62cfe3b841dbc0f471280d95bSebastian RedlParser::ParseStatementOrDeclaration(bool OnlyStatement) {
785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const char *SemiError = 0;
7915faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Res(Actions);
800e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
81bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  CXX0XAttributeList Attr;
82bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
83bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Attr = ParseCXX0XAttributes();
84bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt
855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Cases in this switch statement should fall through if the parser expects
865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // the token to end in a semicolon (in which case SemiError should be set),
875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // or they directly 'return;' if not.
88397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  tok::TokenKind Kind  = Tok.getKind();
89397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  SourceLocation AtLoc;
90397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  switch (Kind) {
91397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  case tok::at: // May be a @try or @throw statement
92397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian    {
93397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian      AtLoc = ConsumeToken();  // consume @
9443bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl      return ParseObjCAtStatement(AtLoc);
95397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian    }
96397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian
97791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor  case tok::code_completion:
98791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor    Actions.CodeCompleteOrdinaryName(CurScope);
99791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor    ConsumeToken();
100791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor    return ParseStatementOrDeclaration(OnlyStatement);
101791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor
102b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis  case tok::identifier:
103b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis    if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
104b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis      // identifier ':' statement
105bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      return ParseLabeledStatement(Attr.AttrList);
106b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis    }
107b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis    // PASS THROUGH.
108b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis
109f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner  default: {
1105404a156be26de1c63ca9916187f970848bb4dbbArgyrios Kyrtzidis    if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
11197144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner      SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
112bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd,
113bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt                                             Attr);
11497144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner      return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
115f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    }
116f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner
117f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    if (Tok.is(tok::r_brace)) {
1185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      Diag(Tok, diag::err_expected_statement);
11961364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl      return StmtError();
1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
1211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
122bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    // FIXME: Use the attributes
123f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    // expression[opt] ';'
124f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    OwningExprResult Expr(ParseExpression());
125f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    if (Expr.isInvalid()) {
126f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner      // If the expression is invalid, skip ahead to the next semicolon.  Not
127f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner      // doing this opens us up to the possibility of infinite loops if
128f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner      // ParseExpression does not consume any tokens.
129f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner      SkipUntil(tok::semi);
130f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner      return StmtError();
131f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    }
132f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    // Otherwise, eat the semicolon.
133f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
1345ee56e95c3905d2e7bc403631b03865cdbdd8a42Anders Carlsson    return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr));
135f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner  }
13661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_case:                // C99 6.8.1: labeled-statement
138bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseCaseStatement(Attr.AttrList);
1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_default:             // C99 6.8.1: labeled-statement
140bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseDefaultStatement(Attr.AttrList);
14161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
1425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::l_brace:                // C99 6.8.2: compound-statement
143bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseCompoundStatement(Attr.AttrList);
1445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::semi:                   // C99 6.8.3p3: expression[opt] ';'
145a60528cdac7deee3991c2b48af4df4f315e49e9dSebastian Redl    return Actions.ActOnNullStmt(ConsumeToken());
14661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
1475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_if:                  // C99 6.8.4.1: if-statement
148bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseIfStatement(Attr.AttrList);
1495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_switch:              // C99 6.8.4.2: switch-statement
150bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseSwitchStatement(Attr.AttrList);
15161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_while:               // C99 6.8.5.1: while-statement
153bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseWhileStatement(Attr.AttrList);
1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_do:                  // C99 6.8.5.2: do-statement
155bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Res = ParseDoStatement(Attr.AttrList);
1566869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "do/while";
1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_for:                 // C99 6.8.5.3: for-statement
159bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseForStatement(Attr.AttrList);
1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_goto:                // C99 6.8.6.1: goto-statement
162bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Res = ParseGotoStatement(Attr.AttrList);
1636869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "goto";
1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_continue:            // C99 6.8.6.2: continue-statement
166bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Res = ParseContinueStatement(Attr.AttrList);
1676869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "continue";
1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_break:               // C99 6.8.6.3: break-statement
170bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Res = ParseBreakStatement(Attr.AttrList);
1716869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "break";
1725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_return:              // C99 6.8.6.4: return-statement
174bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Res = ParseReturnStatement(Attr.AttrList);
1756869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "return";
1765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
17761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
178a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  case tok::kw_asm: {
179bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    if (Attr.HasAttr)
180bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
181bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt        << Attr.Range;
182d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    bool msAsm = false;
183d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    Res = ParseAsmStatement(msAsm);
18461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    if (msAsm) return move(Res);
1856869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "asm";
1865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
18861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
189a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  case tok::kw_try:                 // C++ 15: try-block
190bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseCXXTryBlock(Attr.AttrList);
191a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  }
192a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // If we reached this code, the statement must end in a semicolon.
1944e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::semi)) {
1955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
1960e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  } else if (!Res.isInvalid()) {
1977b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner    // If the result was valid, then we do want to diagnose this.  Use
1987b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner    // ExpectAndConsume to emit the diagnostic, even though we know it won't
1997b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner    // succeed.
2007b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner    ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
201195044028b76133e2a1f245b094468fe07db7330Chris Lattner    // Skip until we see a } or ;, but don't eat it.
202195044028b76133e2a1f245b094468fe07db7330Chris Lattner    SkipUntil(tok::r_brace, true, true);
2035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
2041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  return move(Res);
2065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
2075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
208f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis/// ParseLabeledStatement - We have an identifier and a ':' after it.
2095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
2105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
2115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         identifier ':' statement
2125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   identifier ':' attributes[opt] statement
2135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
214bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
2154e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
2165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer         "Not an identifier!");
2175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
218d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner  Token IdentTok = Tok;  // Save the whole token.
2195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ConsumeToken();  // eat the identifier.
220f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis
221f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  assert(Tok.is(tok::colon) && "Not a label!");
22261364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
2235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // identifier ':' statement
224f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  SourceLocation ColonLoc = ConsumeToken();
2255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
226f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  // Read label attributes, if present.
227f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  if (Tok.is(tok::kw___attribute))
228bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Attr = addAttributeLists(Attr, ParseGNUAttributes());
2295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
23061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult SubStmt(ParseStatement());
2310e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
232f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  // Broken substmt shouldn't prevent the label from being added to the AST.
2330e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (SubStmt.isInvalid())
234f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis    SubStmt = Actions.ActOnNullStmt(ColonLoc);
2350e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
236de307473448fb3cebcb4c10090728300b53bca03Sebastian Redl  return Actions.ActOnLabelStmt(IdentTok.getLocation(),
237de307473448fb3cebcb4c10090728300b53bca03Sebastian Redl                                IdentTok.getIdentifierInfo(),
23876ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl                                ColonLoc, move(SubStmt));
239f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis}
2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCaseStatement
2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'case' constant-expression ':' statement
2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   'case' constant-expression '...' constant-expression ':' statement
2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
246bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
2474e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_case) && "Not a case stmt!");
248bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
2491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
25024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // It is very very common for code to contain many case statements recursively
25124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // nested, as in (but usually without indentation):
25224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //  case 1:
25324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //    case 2:
25424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //      case 3:
25524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //         case 4:
25624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //           case 5: etc.
25724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //
25824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // Parsing this naively works, but is both inefficient and can cause us to run
25924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // out of stack space in our recursive descent parser.  As a special case,
26026140c6399d4b14a224d44cf0102a1919d8dab04Chris Lattner  // flatten this recursion into an iterative loop.  This is complex and gross,
26124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // but all the grossness is constrained to ParseCaseStatement (and some
26224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // wierdness in the actions), so this is just local grossness :).
2631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
26424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // TopLevelCase - This is the highest level we have parsed.  'case 1' in the
26524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // example above.
26624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  OwningStmtResult TopLevelCase(Actions, true);
2671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
26824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
26924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // gets updated each time a new case is parsed, and whose body is unset so
27024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // far.  When parsing 'case 4', this is the 'case 3' node.
27124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  StmtTy *DeepestParsedCaseStmt = 0;
2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
27324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // While we have case statements, eat and stack them.
27424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  do {
27524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SourceLocation CaseLoc = ConsumeToken();  // eat the 'case'.
2761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2773e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor    if (Tok.is(tok::code_completion)) {
2783e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor      Actions.CodeCompleteCase(CurScope);
2793e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor      ConsumeToken();
2803e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor    }
2813e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor
2826fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner    /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
2836fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner    /// Disable this form of error recovery while we're parsing the case
2846fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner    /// expression.
2856fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner    ColonProtectionRAIIObject ColonProtection(*this);
2866fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner
28724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    OwningExprResult LHS(ParseConstantExpression());
28824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    if (LHS.isInvalid()) {
28924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      SkipUntil(tok::colon);
29024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      return StmtError();
29124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    }
2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
29324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // GNU case range extension.
29424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SourceLocation DotDotDotLoc;
29524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    OwningExprResult RHS(Actions);
29624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    if (Tok.is(tok::ellipsis)) {
29724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      Diag(Tok, diag::ext_gnu_case_range);
29824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      DotDotDotLoc = ConsumeToken();
2990e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
30024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      RHS = ParseConstantExpression();
30124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      if (RHS.isInvalid()) {
30224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner        SkipUntil(tok::colon);
30324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner        return StmtError();
30424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      }
30524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    }
3066fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner
3076fb09c8acc1336a9508cd6223d9fcf87cf31e476Chris Lattner    ColonProtection.restore();
3080e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
30924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    if (Tok.isNot(tok::colon)) {
31024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      Diag(Tok, diag::err_expected_colon_after) << "'case'";
3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::colon);
31261364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl      return StmtError();
3135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
3140e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
31524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SourceLocation ColonLoc = ConsumeToken();
3161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
31724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    OwningStmtResult Case =
31824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      Actions.ActOnCaseStmt(CaseLoc, move(LHS), DotDotDotLoc,
31924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner                            move(RHS), ColonLoc);
3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
32124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // If we had a sema error parsing this case, then just ignore it and
32224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // continue parsing the sub-stmt.
32324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    if (Case.isInvalid()) {
32424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      if (TopLevelCase.isInvalid())  // No parsed case stmts.
32524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner        return ParseStatement();
32624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      // Otherwise, just don't add it as a nested case.
32724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    } else {
32824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      // If this is the first case statement we parsed, it becomes TopLevelCase.
32924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      // Otherwise we link it into the current chain.
33024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      StmtTy *NextDeepest = Case.get();
33124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      if (TopLevelCase.isInvalid())
33224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner        TopLevelCase = move(Case);
33324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      else
33424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner        Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(Case));
33524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      DeepestParsedCaseStmt = NextDeepest;
33624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    }
3371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // Handle all case statements.
33924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  } while (Tok.is(tok::kw_case));
3401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!");
3421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // If we found a non-case statement, start by parsing it.
34424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  OwningStmtResult SubStmt(Actions);
3451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  if (Tok.isNot(tok::r_brace)) {
34724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SubStmt = ParseStatement();
34824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  } else {
34924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // Nicely diagnose the common error "switch (X) { case 4: }", which is
35024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // not valid.
35124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // FIXME: add insertion hint.
3525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::err_label_end_of_compound_statement);
35324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SubStmt = true;
3545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
3551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
35624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // Broken sub-stmt shouldn't prevent forming the case statement properly.
3570e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (SubStmt.isInvalid())
35824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SubStmt = Actions.ActOnNullStmt(SourceLocation());
3591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
36024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // Install the body into the most deeply-nested case.
36124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(SubStmt));
36261364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
36324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // Return the top level parsed statement tree.
36426140c6399d4b14a224d44cf0102a1919d8dab04Chris Lattner  return move(TopLevelCase);
3655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
3665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseDefaultStatement
3685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
3695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'default' ':' statement
3705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note that this does not parse the 'statement' at the end.
3715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
372bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
373bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  //FIXME: Use attributes?
3744e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_default) && "Not a default stmt!");
3755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
3765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3774e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::colon)) {
3781ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_colon_after) << "'default'";
3795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::colon);
38061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
3815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
38261364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
3835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ColonLoc = ConsumeToken();
38461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
3855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Diagnose the common error "switch (X) {... default: }", which is not valid.
3864e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::r_brace)) {
3875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::err_label_end_of_compound_statement);
38861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
3895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
3905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
39161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult SubStmt(ParseStatement());
3920e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (SubStmt.isInvalid())
39361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
39461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
395117054a99f4994e4ec8a1fc904b554e1f2dc9b29Sebastian Redl  return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
39676ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl                                  move(SubStmt), CurScope);
3975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
3985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCompoundStatement - Parse a "{}" block.
4015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       compound-statement: [C99 6.8.2]
4035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         { block-item-list[opt] }
4045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   { label-declarations block-item-list } [TODO]
4055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       block-item-list:
4075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         block-item
4085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         block-item-list block-item
4095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       block-item:
4115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         declaration
41245a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner/// [GNU]   '__extension__' declaration
4135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         statement
4145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   openmp-directive            [TODO]
4155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] label-declarations:
4175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   label-declaration
4185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   label-declarations label-declaration
4195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] label-declaration:
4215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   '__label__' identifier-list ';'
4225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP] openmp-directive:             [TODO]
4245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   barrier-directive
4255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   flush-directive
4265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
427bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
428bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt                                                        bool isStmtExpr) {
429bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  //FIXME: Use attributes?
4304e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
43161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
43231e057270232c1c37602579cb6461c2704175672Chris Lattner  // Enter a scope to hold everything within the compound stmt.  Compound
43331e057270232c1c37602579cb6461c2704175672Chris Lattner  // statements can always hold declarations.
4348935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope CompoundScope(this, Scope::DeclScope);
4355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the statements in the body.
43761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  return ParseCompoundStatementBody(isStmtExpr);
4385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
4395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
4421b273c403734d343d720acb28f04011807c8aa56Steve Naroff/// ActOnCompoundStmt action.  This expects the '{' to be the current token, and
4435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// consume the '}' at the end of the block.  It does not manipulate the scope
4445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// stack.
44561364dddc33383e62cfe3b841dbc0f471280d95bSebastian RedlParser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
4461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
447ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner                                Tok.getLocation(),
448ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner                                "in compound statement ('{}')");
4491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation LBraceLoc = ConsumeBrace();  // eat the '{'.
4515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension.  These are
45345a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner  // only allowed at the start of a compound stmt regardless of the language.
454a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl
455a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  typedef StmtVector StmtsTy;
456a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  StmtsTy Stmts(Actions);
4574e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
45815faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl    OwningStmtResult R(Actions);
4594e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.isNot(tok::kw___extension__)) {
46045a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      R = ParseStatementOrDeclaration(false);
46145a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner    } else {
46245a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // __extension__ can start declarations and it can also be a unary
46345a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // operator for expressions.  Consume multiple __extension__ markers here
46445a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // until we can determine which is which.
465adf077f46ba5cddcd801a647a5e9a3eb97060df4Eli Friedman      // FIXME: This loses extension expressions in the AST!
46645a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      SourceLocation ExtLoc = ConsumeToken();
4674e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner      while (Tok.is(tok::kw___extension__))
46845a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        ConsumeToken();
46939146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner
470bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      CXX0XAttributeList Attr;
471bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
472bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt        Attr = ParseCXX0XAttributes();
473bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt
47445a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // If this is the start of a declaration, parse it as such.
4755404a156be26de1c63ca9916187f970848bb4dbbArgyrios Kyrtzidis      if (isDeclarationStatement()) {
476bc6c848f3e0ec2dc44f6e3d59ef85e884cc9b7beEli Friedman        // __extension__ silences extension warnings in the subdeclaration.
47797144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner        // FIXME: Save the __extension__ on the decl as a node somehow?
478bc6c848f3e0ec2dc44f6e3d59ef85e884cc9b7beEli Friedman        ExtensionRAIIObject O(Diags);
479bc6c848f3e0ec2dc44f6e3d59ef85e884cc9b7beEli Friedman
48097144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner        SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
481bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt        DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
482bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt                                              Attr);
48397144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner        R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
48445a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      } else {
485adf077f46ba5cddcd801a647a5e9a3eb97060df4Eli Friedman        // Otherwise this was a unary __extension__ marker.
486adf077f46ba5cddcd801a647a5e9a3eb97060df4Eli Friedman        OwningExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
487043a0b50a2a7a29c78a1ffb774f6fca8baf464a0Chris Lattner
4880e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl        if (Res.isInvalid()) {
48945a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner          SkipUntil(tok::semi);
49045a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner          continue;
49145a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        }
492f512e82f56671b695a32d019103e62a302838b7eSebastian Redl
493bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt        // FIXME: Use attributes?
49439146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner        // Eat the semicolon at the end of stmt and convert the expr into a
49539146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner        // statement.
49645a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
4975ee56e95c3905d2e7bc403631b03865cdbdd8a42Anders Carlsson        R = Actions.ActOnExprStmt(Actions.MakeFullExpr(Res));
49845a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      }
49945a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner    }
50061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
5010e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (R.isUsable())
502effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl      Stmts.push_back(R.release());
5035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
50461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
5055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // We broke out of the while loop because we found a '}' or EOF.
5064e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::r_brace)) {
5075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::err_expected_rbrace);
50861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
5095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
51061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
5115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation RBraceLoc = ConsumeBrace();
512f512e82f56671b695a32d019103e62a302838b7eSebastian Redl  return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc, move_arg(Stmts),
513a60528cdac7deee3991c2b48af4df4f315e49e9dSebastian Redl                                   isStmtExpr);
5145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
5155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
51615ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// ParseParenExprOrCondition:
51715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// [C  ]     '(' expression ')'
518ff871fb8f9c5906a4dee78afd81f60c3837e16cbChris Lattner/// [C++]     '(' condition ')'       [not allowed if OnlyAllowCondition=true]
51915ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner///
52015ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// This function parses and performs error recovery on the specified condition
52115ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// or expression (depending on whether we're in C++ or C mode).  This function
52215ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// goes out of its way to recover well.  It returns true if there was a parser
52315ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// error (the right paren couldn't be found), which indicates that the caller
52415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// should try to recover harder.  It returns false if the condition is
52515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// successfully parsed.  Note that a successful parse can still have semantic
52615ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// errors in the condition.
52799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregorbool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult,
52899e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor                                       DeclPtrTy &DeclResult) {
52999e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  bool ParseError = false;
53099e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor
53115ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  SourceLocation LParenLoc = ConsumeParen();
53299e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (getLang().CPlusPlus)
53399e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor    ParseError = ParseCXXCondition(ExprResult, DeclResult);
53499e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  else {
53599e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor    ExprResult = ParseExpression();
53699e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor    DeclResult = DeclPtrTy();
53799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  }
5381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
53915ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  // If the parser was confused by the condition and we don't have a ')', try to
54015ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  // recover by skipping ahead to a semi and bailing out.  If condexp is
54115ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  // semantically invalid but we have well formed code, keep going.
54299e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (ExprResult.isInvalid() && !DeclResult.get() && Tok.isNot(tok::r_paren)) {
54315ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    SkipUntil(tok::semi);
54415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    // Skipping may have stopped if it found the containing ')'.  If so, we can
54515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    // continue parsing the if statement.
54615ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    if (Tok.isNot(tok::r_paren))
54715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner      return true;
54815ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  }
5491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
55015ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  // Otherwise the condition is valid or the rparen is present.
55199e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  MatchRHSPunctuation(tok::r_paren, LParenLoc);
55215ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  return false;
55315ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner}
55415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner
55515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner
5565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseIfStatement
5575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       if-statement: [C99 6.8.4.1]
5585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'if' '(' expression ')' statement
5595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'if' '(' expression ')' statement 'else' statement
56071b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'if' '(' condition ')' statement
56171b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'if' '(' condition ')' statement 'else' statement
5625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
563bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
564bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
5654e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_if) && "Not an if stmt!");
5665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
5675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
5684e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
5691ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "if";
5705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
57161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
5725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
57371b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis
574488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
575488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
5762215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.4p3 - In C99, the if statement is a block.  This is not
5772215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.
578488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
579488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
580488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
581488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
582488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
58314d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
58414d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
58514d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
58614d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
587488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
5888935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
5892215325a5696fb3b23551239b900559bb3018ee9Chris Lattner
5905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the condition.
59115faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult CondExp(Actions);
59299e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  DeclPtrTy CondVar;
59399e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (ParseParenExprOrCondition(CondExp, CondVar))
59415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    return StmtError();
59518914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner
5965ee56e95c3905d2e7bc403631b03865cdbdd8a42Anders Carlsson  FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp));
5971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5980ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
59938484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
60038484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
601488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
602488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p1:
603488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in a selection-statement (each substatement, in the else
604488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // form of the if statement) implicitly defines a local scope.
605488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
606488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // For C++ we create a scope for the condition and a new scope for
607488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // substatements because:
608488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // -When the 'then' scope exits, we want the condition declaration to still be
609488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    active for the 'else' scope too.
610488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // -Sema will detect name clashes by considering declarations of a
611488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    'ControlScope' as part of its direct subscope.
612488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // -If we wanted the condition and substatement to be in the same scope, we
613488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    would have to notify ParseStatement not to create a new scope. It's
614488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    simpler to let it create a new scope.
615488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
6161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParseScope InnerScope(this, Scope::DeclScope,
6178935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                        C99orCXX && Tok.isNot(tok::l_brace));
61871b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis
619b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // Read the 'then' stmt.
620b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  SourceLocation ThenStmtLoc = Tok.getLocation();
62161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult ThenStmt(ParseStatement());
6225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
623a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner  // Pop the 'if' scope if needed.
6248935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  InnerScope.Exit();
62561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
6265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // If it has an else, parse it.
6275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ElseLoc;
628b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  SourceLocation ElseStmtLoc;
62915faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult ElseStmt(Actions);
6300e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
6314e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::kw_else)) {
6325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ElseLoc = ConsumeToken();
63361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
6340ecea03077117c7ea54c88091a44c73cef67923cChris Lattner    // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
63538484403c8356fb41540ace6c74f28867f28febaChris Lattner    // there is no compound stmt.  C90 does not have this clause.  We only do
63638484403c8356fb41540ace6c74f28867f28febaChris Lattner    // this if the body isn't a compound statement to avoid push/pop in common
63738484403c8356fb41540ace6c74f28867f28febaChris Lattner    // cases.
638488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    //
639488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    // C++ 6.4p1:
640488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    // The substatement in a selection-statement (each substatement, in the else
641488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    // form of the if statement) implicitly defines a local scope.
642488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    //
64361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    ParseScope InnerScope(this, Scope::DeclScope,
6448935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                          C99orCXX && Tok.isNot(tok::l_brace));
6450e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
646caaf29a08761b14fbe42a29080c22dd6961056d1Douglas Gregor    bool WithinElse = CurScope->isWithinElse();
647caaf29a08761b14fbe42a29080c22dd6961056d1Douglas Gregor    CurScope->setWithinElse(true);
648b96728d90abc35a520798066d2a75ca36400a617Chris Lattner    ElseStmtLoc = Tok.getLocation();
6495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ElseStmt = ParseStatement();
650caaf29a08761b14fbe42a29080c22dd6961056d1Douglas Gregor    CurScope->setWithinElse(WithinElse);
651a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner
652a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner    // Pop the 'else' scope if needed.
6538935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    InnerScope.Exit();
6545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
65561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
6568935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  IfScope.Exit();
6571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
65818914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner  // If the condition was invalid, discard the if statement.  We could recover
65918914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner  // better by replacing it with a valid expr, but don't do that yet.
66099e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (CondExp.isInvalid() && !CondVar.get())
66118914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner    return StmtError();
6622215325a5696fb3b23551239b900559bb3018ee9Chris Lattner
663b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // If the then or else stmt is invalid and the other is valid (and present),
6641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // make turn the invalid one into a null stmt to avoid dropping the other
665b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // part.  If both are invalid, return error.
6660e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
6670e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      (ThenStmt.isInvalid() && ElseStmt.get() == 0) ||
6680e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      (ThenStmt.get() == 0  && ElseStmt.isInvalid())) {
669a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl    // Both invalid, or one is invalid and other is non-present: return error.
67061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
671b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  }
6720e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
673b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // Now if either are invalid, replace with a ';'.
6740e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (ThenStmt.isInvalid())
675b96728d90abc35a520798066d2a75ca36400a617Chris Lattner    ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
6760e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (ElseStmt.isInvalid())
677b96728d90abc35a520798066d2a75ca36400a617Chris Lattner    ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
6780e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
67999e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, move(ThenStmt),
68076ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl                             ElseLoc, move(ElseStmt));
6815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
6825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseSwitchStatement
6845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       switch-statement:
6855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'switch' '(' expression ')' statement
68671b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'switch' '(' condition ')' statement
687bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
688bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
6894e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
6905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
6915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6924e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
6931ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "switch";
6945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
6959a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
6965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
6972215325a5696fb3b23551239b900559bb3018ee9Chris Lattner
698488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
699488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
7002215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.4p3 - In C99, the switch statement is a block.  This is
7012215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // not the case for C90.  Start the switch scope.
702488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
703488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
704488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
705488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
706488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
70714d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
70814d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
70914d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
71014d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
711488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
71215ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  unsigned ScopeFlags = Scope::BreakScope;
71315ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  if (C99orCXX)
71415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
7158935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope SwitchScope(this, ScopeFlags);
7165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the condition.
71815faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult Cond(Actions);
71999e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  DeclPtrTy CondVar;
72099e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (ParseParenExprOrCondition(Cond, CondVar))
7219a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
7222342ef75797a2ad6c9d7a784cfff220fd1a66008Eli Friedman
7235ee56e95c3905d2e7bc403631b03865cdbdd8a42Anders Carlsson  FullExprArg FullCond(Actions.MakeFullExpr(Cond));
72499e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor
725be724bab2ba7ad47aebced25e7c8ec551eb72d28Douglas Gregor  OwningStmtResult Switch = Actions.ActOnStartOfSwitchStmt(FullCond, CondVar);
7260e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
7270ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
72838484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
72938484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
730488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
731488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p1:
732488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in a selection-statement (each substatement, in the else
733488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // form of the if statement) implicitly defines a local scope.
734488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
735488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // See comments in ParseIfStatement for why we create a scope for the
736488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition and a new scope for substatement in C++.
737488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
7381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParseScope InnerScope(this, Scope::DeclScope,
7398935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                        C99orCXX && Tok.isNot(tok::l_brace));
74061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
7415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
74261364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult Body(ParseStatement());
7435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7440ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
7458935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  InnerScope.Exit();
7469a920342707e384473b464528d2fd286e8c70353Sebastian Redl
7470e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (Body.isInvalid()) {
7481b273c403734d343d720acb28f04011807c8aa56Steve Naroff    Body = Actions.ActOnNullStmt(Tok.getLocation());
749c1fcb7762673be706b0a40477d5e93411e918f93Anders Carlsson    // FIXME: Remove the case statement list from the Switch statement.
750c1fcb7762673be706b0a40477d5e93411e918f93Anders Carlsson  }
7518935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor
7528935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  SwitchScope.Exit();
75361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
75499e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (Cond.isInvalid() && !CondVar.get())
75515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    return StmtError();
756de307473448fb3cebcb4c10090728300b53bca03Sebastian Redl
75776ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl  return Actions.ActOnFinishSwitchStmt(SwitchLoc, move(Switch), move(Body));
7585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
7595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseWhileStatement
7615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       while-statement: [C99 6.8.5.1]
7625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'while' '(' expression ')' statement
76371b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'while' '(' condition ')' statement
764bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
765bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
7664e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_while) && "Not a while stmt!");
7675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation WhileLoc = Tok.getLocation();
7685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ConsumeToken();  // eat the 'while'.
7699a920342707e384473b464528d2fd286e8c70353Sebastian Redl
7704e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
7711ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "while";
7725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
7739a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
7745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
7759a920342707e384473b464528d2fd286e8c70353Sebastian Redl
776488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
777488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
7782215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.5p5 - In C99, the while statement is a block.  This is not
7792215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.  Start the loop scope.
780488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
781488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
782488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
783488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
784488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
78514d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
78614d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
78714d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
78814d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
789488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
7908935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  unsigned ScopeFlags;
791488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  if (C99orCXX)
7928935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
7938935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                 Scope::DeclScope  | Scope::ControlScope;
7942215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  else
7958935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
7968935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope WhileScope(this, ScopeFlags);
7975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the condition.
79915faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult Cond(Actions);
80099e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  DeclPtrTy CondVar;
80199e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (ParseParenExprOrCondition(Cond, CondVar))
80215ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    return StmtError();
8030e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
8045ee56e95c3905d2e7bc403631b03865cdbdd8a42Anders Carlsson  FullExprArg FullCond(Actions.MakeFullExpr(Cond));
8051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
8060ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
80738484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
80838484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
809488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
810488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.5p2:
811488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in an iteration-statement implicitly defines a local scope
812488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // which is entered and exited each time through the loop.
813488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
814488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // See comments in ParseIfStatement for why we create a scope for the
815488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition and a new scope for substatement in C++.
816488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
8171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParseScope InnerScope(this, Scope::DeclScope,
8188935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                        C99orCXX && Tok.isNot(tok::l_brace));
8199a920342707e384473b464528d2fd286e8c70353Sebastian Redl
8205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
82161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult Body(ParseStatement());
8225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8230ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
8248935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  InnerScope.Exit();
8258935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  WhileScope.Exit();
8269a920342707e384473b464528d2fd286e8c70353Sebastian Redl
82799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if ((Cond.isInvalid() && !CondVar.get()) || Body.isInvalid())
8289a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
8299a920342707e384473b464528d2fd286e8c70353Sebastian Redl
83099e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, move(Body));
8315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
8325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseDoStatement
8345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       do-statement: [C99 6.8.5.2]
8355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'do' statement 'while' '(' expression ')' ';'
8365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
837bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
838bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
8394e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_do) && "Not a do stmt!");
8405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
8419a920342707e384473b464528d2fd286e8c70353Sebastian Redl
8422215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.5p5 - In C99, the do statement is a block.  This is not
8432215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.  Start the loop scope.
8448935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  unsigned ScopeFlags;
8452215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  if (getLang().C99)
8468935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
8472215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  else
8488935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
8499a920342707e384473b464528d2fd286e8c70353Sebastian Redl
8508935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope DoScope(this, ScopeFlags);
8515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8520ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
85338484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause. We only do this
85438484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
855143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  //
856143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  // C++ 6.5p2:
857143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  // The substatement in an iteration-statement implicitly defines a local scope
858143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  // which is entered and exited each time through the loop.
859143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  //
8608935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope InnerScope(this, Scope::DeclScope,
8611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                        (getLang().C99 || getLang().CPlusPlus) &&
8628935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                        Tok.isNot(tok::l_brace));
8639a920342707e384473b464528d2fd286e8c70353Sebastian Redl
8645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
86561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult Body(ParseStatement());
8665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8670ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
8688935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  InnerScope.Exit();
8690ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
8704e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::kw_while)) {
8710e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (!Body.isInvalid()) {
872195044028b76133e2a1f245b094468fe07db7330Chris Lattner      Diag(Tok, diag::err_expected_while);
87328eb7e992b9a266abb300da25b6d3c1557cec361Chris Lattner      Diag(DoLoc, diag::note_matching) << "do";
874195044028b76133e2a1f245b094468fe07db7330Chris Lattner      SkipUntil(tok::semi, false, true);
875195044028b76133e2a1f245b094468fe07db7330Chris Lattner    }
8769a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
8775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
8785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation WhileLoc = ConsumeToken();
8799a920342707e384473b464528d2fd286e8c70353Sebastian Redl
8804e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
8811ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "do/while";
882195044028b76133e2a1f245b094468fe07db7330Chris Lattner    SkipUntil(tok::semi, false, true);
8839a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
8845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
8859a920342707e384473b464528d2fd286e8c70353Sebastian Redl
886ff871fb8f9c5906a4dee78afd81f60c3837e16cbChris Lattner  // Parse the parenthesized condition.
88704895d301e1107a8f03673c43c939a115c3c1195Douglas Gregor  SourceLocation LPLoc = ConsumeParen();
88804895d301e1107a8f03673c43c939a115c3c1195Douglas Gregor  OwningExprResult Cond = ParseExpression();
88904895d301e1107a8f03673c43c939a115c3c1195Douglas Gregor  SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc);
8908935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  DoScope.Exit();
8910e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
8929a920342707e384473b464528d2fd286e8c70353Sebastian Redl  if (Cond.isInvalid() || Body.isInvalid())
8939a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
8940e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
895989135901c750af61ef012b6b0a0368be415bc46Chris Lattner  return Actions.ActOnDoStmt(DoLoc, move(Body), WhileLoc, LPLoc,
896989135901c750af61ef012b6b0a0368be415bc46Chris Lattner                             move(Cond), RPLoc);
8975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
8985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseForStatement
9005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       for-statement: [C99 6.8.5.3]
9015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
9025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
90371b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
90471b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]       statement
9053ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian/// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
9063ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian/// [OBJC2] 'for' '(' expr 'in' expr ')' statement
90771b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis///
90871b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] for-init-statement:
90971b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   expression-statement
91071b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   simple-declaration
91171b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis///
912bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
913bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
9144e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_for) && "Not a for stmt!");
9155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
9169a920342707e384473b464528d2fd286e8c70353Sebastian Redl
9174e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
9181ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "for";
9195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
9209a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
9215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
9229a920342707e384473b464528d2fd286e8c70353Sebastian Redl
9234d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner  bool C99orCXXorObjC = getLang().C99 || getLang().CPlusPlus || getLang().ObjC1;
924488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
9252215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.5p5 - In C99, the for statement is a block.  This is not
9262215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.  Start the loop scope.
927488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
928488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
929488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
930488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
931488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
93214d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
93314d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
93414d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
93514d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
936488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.5.3p1:
937488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // Names declared in the for-init-statement are in the same declarative-region
938488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // as those declared in the condition.
939488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
9408935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  unsigned ScopeFlags;
9414d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner  if (C99orCXXorObjC)
9428935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
9438935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                 Scope::DeclScope  | Scope::ControlScope;
9442215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  else
9458935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
9468935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor
9478935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope ForScope(this, ScopeFlags);
9485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
9495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation LParenLoc = ConsumeParen();
95015faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult Value(Actions);
9510e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
952bdd15f701fe98f77b1b8ddb3f4a5c0d83bb8fa9cFariborz Jahanian  bool ForEach = false;
953f05b1520d6f175acbfc3913489f4dfa842875ec4Sebastian Redl  OwningStmtResult FirstPart(Actions);
954f05b1520d6f175acbfc3913489f4dfa842875ec4Sebastian Redl  OwningExprResult SecondPart(Actions), ThirdPart(Actions);
95599e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  DeclPtrTy SecondVar;
95699e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor
957791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor  if (Tok.is(tok::code_completion)) {
958791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor    Actions.CodeCompleteOrdinaryName(CurScope);
959791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor    ConsumeToken();
960791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor  }
961791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor
9625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the first part of the for specifier.
9634e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::semi)) {  // for (;
9645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // no first part, eat the ';'.
9655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
966bbc70c019f7b7f9a256ee29dab5287ecc82c6553Argyrios Kyrtzidis  } else if (isSimpleDeclaration()) {  // for (int X = 4;
9675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Parse declaration, which eats the ';'.
9684d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner    if (!C99orCXXorObjC)   // Use of C99-style for loops in C90 mode?
9695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
9709a920342707e384473b464528d2fd286e8c70353Sebastian Redl
971bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    AttributeList *AttrList = 0;
972bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
973bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      AttrList = ParseCXX0XAttributes().AttrList;
974bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt
97597144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner    SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
976bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
977bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt                                               AttrList);
978cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner    FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
9791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
980cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner    if (Tok.is(tok::semi)) {  // for (int x = 4;
981cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner      ConsumeToken();
982cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner    } else if ((ForEach = isTokIdentifier_in())) {
983a7cf23a72b0846fc5aacf3f38bb8c8f9e76784cfFariborz Jahanian      Actions.ActOnForEachDeclStmt(DG);
9841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      // ObjC: for (id x in expr)
9853ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      ConsumeToken(); // consume 'in'
9860e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      SecondPart = ParseExpression();
987cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner    } else {
988cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner      Diag(Tok, diag::err_expected_semi_for);
989cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner      SkipUntil(tok::semi);
9903ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
9915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  } else {
9925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Value = ParseExpression();
9935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
9945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Turn the expression into a stmt.
9950e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (!Value.isInvalid())
9965ee56e95c3905d2e7bc403631b03865cdbdd8a42Anders Carlsson      FirstPart = Actions.ActOnExprStmt(Actions.MakeFullExpr(Value));
997effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
9984e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.is(tok::semi)) {
9995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      ConsumeToken();
1000682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner    } else if ((ForEach = isTokIdentifier_in())) {
10013ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      ConsumeToken(); // consume 'in'
10020e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      SecondPart = ParseExpression();
1003682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner    } else {
10040e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
10055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::semi);
10065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
10075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1008bdd15f701fe98f77b1b8ddb3f4a5c0d83bb8fa9cFariborz Jahanian  if (!ForEach) {
10090e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
10103ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    // Parse the second part of the for specifier.
10113ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    if (Tok.is(tok::semi)) {  // for (...;;
10123ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      // no second part.
10133ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    } else {
101499e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor      if (getLang().CPlusPlus)
101599e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor        ParseCXXCondition(SecondPart, SecondVar);
101699e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor      else
101799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor        SecondPart = ParseExpression();
10183ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
10190e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10203ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    if (Tok.is(tok::semi)) {
10213ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      ConsumeToken();
10223ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    } else {
102399e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor      if (!SecondPart.isInvalid() || SecondVar.get())
102499e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor        Diag(Tok, diag::err_expected_semi_for);
10253ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      SkipUntil(tok::semi);
10263ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
10279a920342707e384473b464528d2fd286e8c70353Sebastian Redl
10283ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    // Parse the third part of the for specifier.
10294dca69b3f8180bdfa0287399c89e0594080bae66Chris Lattner    if (Tok.isNot(tok::r_paren))    // for (...;...;)
1030f05b1520d6f175acbfc3913489f4dfa842875ec4Sebastian Redl      ThirdPart = ParseExpression();
10315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
10325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Match the ')'.
10335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
10340e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10350ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
103638484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
103738484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
1038488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
1039488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.5p2:
1040488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in an iteration-statement implicitly defines a local scope
1041488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // which is entered and exited each time through the loop.
1042488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
1043488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // See comments in ParseIfStatement for why we create a scope for
1044488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // for-init-statement/condition and a new scope for substatement in C++.
1045488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
10461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParseScope InnerScope(this, Scope::DeclScope,
10474d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner                        C99orCXXorObjC && Tok.isNot(tok::l_brace));
10480e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
105061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult Body(ParseStatement());
10510e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10520ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
10538935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  InnerScope.Exit();
10540ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
10555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Leave the for-scope.
10568935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ForScope.Exit();
10570e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10580e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (Body.isInvalid())
10599a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
1060effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
1061effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl  if (!ForEach)
106276ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl    return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart),
10635ee56e95c3905d2e7bc403631b03865cdbdd8a42Anders Carlsson                                Actions.MakeFullExpr(SecondPart), SecondVar,
10645ee56e95c3905d2e7bc403631b03865cdbdd8a42Anders Carlsson                                Actions.MakeFullExpr(ThirdPart), RParenLoc,
106599e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor                                move(Body));
10661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1067682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner  return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
1068682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner                                            move(FirstPart),
1069682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner                                            move(SecondPart),
1070682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner                                            RParenLoc, move(Body));
10715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
10725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
10735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseGotoStatement
10745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
10755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'goto' identifier ';'
10765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   'goto' '*' expression ';'
10775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
10785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
10795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
1080bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
1081bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
10824e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
10835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
10849a920342707e384473b464528d2fd286e8c70353Sebastian Redl
108515faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Res(Actions);
10864e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::identifier)) {
10871b273c403734d343d720acb28f04011807c8aa56Steve Naroff    Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
10885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                                Tok.getIdentifierInfo());
10895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
1090f01fdff97b245caac98100d232c760b4d0531411Eli Friedman  } else if (Tok.is(tok::star)) {
10915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // GNU indirect goto extension.
10925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::ext_gnu_indirect_goto);
10935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SourceLocation StarLoc = ConsumeToken();
10942f7ece7c77eb17e24e8f0f4e1b7fb01aa5111f96Sebastian Redl    OwningExprResult R(ParseExpression());
10950e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
10965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::semi, false, true);
10979a920342707e384473b464528d2fd286e8c70353Sebastian Redl      return StmtError();
10985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
109976ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl    Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, move(R));
110095cfb85ad1820117e0864712555f3aa4fdf4721aChris Lattner  } else {
110195cfb85ad1820117e0864712555f3aa4fdf4721aChris Lattner    Diag(Tok, diag::err_expected_ident);
11029a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
11035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
11040e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
11059a920342707e384473b464528d2fd286e8c70353Sebastian Redl  return move(Res);
11065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
11075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseContinueStatement
11095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
11105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'continue' ';'
11115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
11135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
1114bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
1115bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
11165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
11174cffe2fd5c23168bc08f0453c684cbd3f79471d3Sebastian Redl  return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
11185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
11195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseBreakStatement
11215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
11225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'break' ';'
11235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
11255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
1126bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
1127bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
11285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
11294cffe2fd5c23168bc08f0453c684cbd3f79471d3Sebastian Redl  return Actions.ActOnBreakStmt(BreakLoc, CurScope);
11305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
11315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseReturnStatement
11335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
11345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'return' expression[opt] ';'
1135bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
1136bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
11374e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_return) && "Not a return stmt!");
11385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
11399a920342707e384473b464528d2fd286e8c70353Sebastian Redl
114015faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult R(Actions);
11414e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::semi)) {
11425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    R = ParseExpression();
11430e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
11445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::semi, false, true);
11459a920342707e384473b464528d2fd286e8c70353Sebastian Redl      return StmtError();
11465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
11475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1148f53b4433abb7a3bc14c0329d3175cbc291280137Anders Carlsson  return Actions.ActOnReturnStmt(ReturnLoc, move(R));
11495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
11505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11515f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this
11525f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// routine is called to skip/ignore tokens that comprise the MS asm statement.
11539a920342707e384473b464528d2fd286e8c70353Sebastian RedlParser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
1154b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff  if (Tok.is(tok::l_brace)) {
1155b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    unsigned short savedBraceCount = BraceCount;
1156b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    do {
1157b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff      ConsumeAnyToken();
1158b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof));
11591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  } else {
1160b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    // From the MS website: If used without braces, the __asm keyword means
1161b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    // that the rest of the line is an assembly-language statement.
1162b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    SourceManager &SrcMgr = PP.getSourceManager();
116303d6bc6734eb79dc27628d9ea1126c299c80b4b6Steve Naroff    SourceLocation TokLoc = Tok.getLocation();
1164f7cf85b330bedd2877e1371fb0a83e99751ae162Chris Lattner    unsigned LineNo = SrcMgr.getInstantiationLineNumber(TokLoc);
1165362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff    do {
1166362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff      ConsumeAnyToken();
1167362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff      TokLoc = Tok.getLocation();
11681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) &&
11691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump             Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) &&
1170362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff             Tok.isNot(tok::eof));
1171b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff  }
117295059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  llvm::SmallVector<std::string, 4> Names;
117395059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  Token t;
117495059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  t.setKind(tok::string_literal);
117595059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  t.setLiteralData("\"FIXME: not done\"");
117695059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  t.clearFlag(Token::NeedsCleaning);
117795059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  t.setLength(17);
117895059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  OwningExprResult AsmString(Actions.ActOnStringLiteral(&t, 1));
117995059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  ExprVector Constraints(Actions);
118095059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  ExprVector Exprs(Actions);
118195059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  ExprVector Clobbers(Actions);
118295059b50136e8aa9bb02017fb9210d3708b06577Mike Stump  return Actions.ActOnAsmStmt(Tok.getLocation(), true, true, 0, 0, Names.data(),
118395059b50136e8aa9bb02017fb9210d3708b06577Mike Stump                              move_arg(Constraints), move_arg(Exprs),
118495059b50136e8aa9bb02017fb9210d3708b06577Mike Stump                              move(AsmString), move_arg(Clobbers),
118595059b50136e8aa9bb02017fb9210d3708b06577Mike Stump                              Tok.getLocation());
1186d62701bc5321049353017e9abf1963edd57646aaSteve Naroff}
1187d62701bc5321049353017e9abf1963edd57646aaSteve Naroff
11885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseAsmStatement - Parse a GNU extended asm statement.
11895f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///       asm-statement:
11905f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         gnu-asm-statement
11915f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         ms-asm-statement
11925f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///
11935f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [GNU] gnu-asm-statement:
11945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'asm' type-qualifier[opt] '(' asm-argument ')' ';'
11955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-argument:
11975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal
11985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal ':' asm-operands[opt]
11995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
12005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
12015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///                 ':' asm-clobbers
12025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
12035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-clobbers:
12045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal
12055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-clobbers ',' asm-string-literal
12065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
12075f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [MS]  ms-asm-statement:
12085f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         '__asm' assembly-instruction ';'[opt]
12095f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         '__asm' '{' assembly-instruction-list '}' ';'[opt]
12105f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///
12115f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [MS]  assembly-instruction-list:
12125f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         assembly-instruction ';'[opt]
12135f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         assembly-instruction-list ';' assembly-instruction ';'[opt]
12145f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///
12159a920342707e384473b464528d2fd286e8c70353Sebastian RedlParser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
12164e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
1217fe795956194141c91ae555985c9b930595bff43fChris Lattner  SourceLocation AsmLoc = ConsumeToken();
12189a920342707e384473b464528d2fd286e8c70353Sebastian Redl
12195f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff  if (getLang().Microsoft && Tok.isNot(tok::l_paren) && !isTypeQualifier()) {
1220d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    msAsm = true;
1221d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    return FuzzyParseMicrosoftAsmStatement();
1222d62701bc5321049353017e9abf1963edd57646aaSteve Naroff  }
12235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  DeclSpec DS;
12245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation Loc = Tok.getLocation();
1225bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  ParseTypeQualifierListOpt(DS, true, false);
12269a920342707e384473b464528d2fd286e8c70353Sebastian Redl
12275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // GNU asms accept, but warn, about type-qualifiers other than volatile.
12285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
12291ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
12305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
12311ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
12329a920342707e384473b464528d2fd286e8c70353Sebastian Redl
12335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Remember if this was a volatile asm.
123439c47b56f45437bbc49c9568b7308a400234a730Anders Carlsson  bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
12354e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
12361ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "asm";
12375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::r_paren);
12389a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
12395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
12405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  Loc = ConsumeParen();
12419a920342707e384473b464528d2fd286e8c70353Sebastian Redl
1242effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl  OwningExprResult AsmString(ParseAsmStringLiteral());
12430e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (AsmString.isInvalid())
12449a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
12450e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
1246b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson  llvm::SmallVector<std::string, 4> Names;
1247a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  ExprVector Constraints(Actions);
1248a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  ExprVector Exprs(Actions);
1249a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  ExprVector Clobbers(Actions);
1250dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson
1251dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  if (Tok.is(tok::r_paren)) {
125264cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner    // We have a simple asm expression like 'asm("foo")'.
125364cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner    SourceLocation RParenLoc = ConsumeParen();
125464cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner    return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
125564cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner                                /*NumOutputs*/ 0, /*NumInputs*/ 0, 0,
125664cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner                                move_arg(Constraints), move_arg(Exprs),
125764cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner                                move(AsmString), move_arg(Clobbers),
125864cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner                                RParenLoc);
125964cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  }
12609a920342707e384473b464528d2fd286e8c70353Sebastian Redl
126164cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  // Parse Outputs, if present.
12626405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner  bool AteExtraColon = false;
12636405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner  if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
12646405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner    // In C++ mode, parse "::" like ": :".
12656405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner    AteExtraColon = Tok.is(tok::coloncolon);
126664cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner    ConsumeToken();
126764cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner
12686405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner    if (!AteExtraColon &&
12696405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner        ParseAsmOperandsOpt(Names, Constraints, Exprs))
127064cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner      return StmtError();
127164cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  }
12726405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner
127364cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  unsigned NumOutputs = Names.size();
12749a920342707e384473b464528d2fd286e8c70353Sebastian Redl
127564cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  // Parse Inputs, if present.
12766405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner  if (AteExtraColon ||
12776405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner      Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
12786405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner    // In C++ mode, parse "::" like ": :".
12796405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner    if (AteExtraColon)
12806405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner      AteExtraColon = false;
12816405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner    else {
12826405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner      AteExtraColon = Tok.is(tok::coloncolon);
12836405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner      ConsumeToken();
12846405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner    }
12856405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner
12866405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner    if (!AteExtraColon &&
12876405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner        ParseAsmOperandsOpt(Names, Constraints, Exprs))
128864cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner      return StmtError();
128964cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  }
1290effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
129164cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  assert(Names.size() == Constraints.size() &&
129264cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner         Constraints.size() == Exprs.size() &&
129364cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner         "Input operand size mismatch!");
1294b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson
129564cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  unsigned NumInputs = Names.size() - NumOutputs;
1296effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
129764cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  // Parse the clobbers, if present.
12986405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner  if (AteExtraColon || Tok.is(tok::colon)) {
12996405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner    if (!AteExtraColon)
13006405646cb649e4b4c6768b92d1fc83c175722f62Chris Lattner      ConsumeToken();
1301effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
130264cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner    // Parse the asm-string list for clobbers.
130364cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner    while (1) {
130464cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner      OwningExprResult Clobber(ParseAsmStringLiteral());
13055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
130664cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner      if (Clobber.isInvalid())
130764cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner        break;
1308effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
130964cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner      Clobbers.push_back(Clobber.release());
1310effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
131164cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner      if (Tok.isNot(tok::comma)) break;
131264cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner      ConsumeToken();
13135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
1314dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  }
1315effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
131664cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc);
131764cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner  return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile,
1318beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad                              NumOutputs, NumInputs, Names.data(),
1319f512e82f56671b695a32d019103e62a302838b7eSebastian Redl                              move_arg(Constraints), move_arg(Exprs),
132076ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl                              move(AsmString), move_arg(Clobbers),
13213037ed0a27dba62e522304183718efc149e8b6d9Sebastian Redl                              RParenLoc);
13225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
13235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
13245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseAsmOperands - Parse the asm-operands production as used by
132564cb4757acbf10f0c702f17c4fe90f4b7aba3490Chris Lattner/// asm-statement, assuming the leading ':' token was eaten.
13265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
13275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-operands:
13285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-operand
13295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-operands ',' asm-operand
13305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
13315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-operand:
13325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal '(' expression ')'
13335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         '[' identifier ']' asm-string-literal '(' expression ')'
13345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
13355ffe14ca96bd662de7820f6875d3f04789a640c1Daniel Dunbar//
13365ffe14ca96bd662de7820f6875d3f04789a640c1Daniel Dunbar// FIXME: Avoid unnecessary std::string trashing.
13378bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlssonbool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
1338b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson                                 llvm::SmallVectorImpl<ExprTy*> &Constraints,
1339b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson                                 llvm::SmallVectorImpl<ExprTy*> &Exprs) {
13405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // 'asm-operands' isn't present?
13414e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
13428bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson    return false;
13431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  while (1) {
13455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Read the [id] if present.
13464e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.is(tok::l_square)) {
13475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SourceLocation Loc = ConsumeBracket();
13481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13494e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner      if (Tok.isNot(tok::identifier)) {
13505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        Diag(Tok, diag::err_expected_ident);
13515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        SkipUntil(tok::r_paren);
13528bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson        return true;
13535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      }
13541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1355b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson      IdentifierInfo *II = Tok.getIdentifierInfo();
135669efba74cf5488060accf34c011b33ce6c15ece0Chris Lattner      ConsumeToken();
1357b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson
135801eb9b9683535d8a65c704ad2c545903409e2d36Daniel Dunbar      Names.push_back(II->getName());
13595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      MatchRHSPunctuation(tok::r_square, Loc);
1360b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson    } else
1361b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson      Names.push_back(std::string());
13620e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
1363effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl    OwningExprResult Constraint(ParseAsmStringLiteral());
13640e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (Constraint.isInvalid()) {
1365b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson        SkipUntil(tok::r_paren);
13668bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson        return true;
1367b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson    }
1368effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl    Constraints.push_back(Constraint.release());
13695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
13704e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.isNot(tok::l_paren)) {
13711ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner      Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
13725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::r_paren);
13738bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson      return true;
13745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
1375effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
13765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Read the parenthesized expression.
137772056a237c536ee63285ab0850cb50f299281767Eli Friedman    SourceLocation OpenLoc = ConsumeParen();
137872056a237c536ee63285ab0850cb50f299281767Eli Friedman    OwningExprResult Res(ParseExpression());
137972056a237c536ee63285ab0850cb50f299281767Eli Friedman    MatchRHSPunctuation(tok::r_paren, OpenLoc);
13800e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (Res.isInvalid()) {
13815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::r_paren);
13828bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson      return true;
13835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
1384effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl    Exprs.push_back(Res.release());
13855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Eat the comma and continue parsing if it exists.
13868bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson    if (Tok.isNot(tok::comma)) return false;
13875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
13885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
13898bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson
13908bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson  return true;
13915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1392f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian
1393b28317a8e5e0e2953d1e5406d753d6c3c7f1e7d2Chris LattnerParser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
139440e9bc84a2ab49fc33c2b1a95c6674ab2b820e9eChris Lattner  assert(Tok.is(tok::l_brace));
139540e9bc84a2ab49fc33c2b1a95c6674ab2b820e9eChris Lattner  SourceLocation LBraceLoc = Tok.getLocation();
1396d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
139749f28ca787d8db7cac3c8898334f70ea55374c98Chris Lattner  PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions,
139849f28ca787d8db7cac3c8898334f70ea55374c98Chris Lattner                                        PP.getSourceManager(),
139949f28ca787d8db7cac3c8898334f70ea55374c98Chris Lattner                                        "parsing function body");
14001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1401f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // Do not enter a scope for the brace, as the arguments are in the same scope
1402f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // (the function body) as the body itself.  Instead, just read the statement
1403f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // list and put it into a CompoundStmt for safe keeping.
140461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult FnBody(ParseCompoundStatementBody());
140561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
1406f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // If the function body could not be parsed, make a bogus compoundstmt.
14070e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (FnBody.isInvalid())
14081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
140940e9bc84a2ab49fc33c2b1a95c6674ab2b820e9eChris Lattner                                       MultiStmtArg(Actions), false);
141061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
141176ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl  return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
1412cd5af4b5863c63b62cde96ad6d52fb1eec0e26bbSeo Sanghyeon}
1413a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1414d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// ParseFunctionTryBlock - Parse a C++ function-try-block.
1415d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1416d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///       function-try-block:
1417d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///         'try' ctor-initializer[opt] compound-statement handler-seq
1418d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1419d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian RedlParser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) {
1420d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  assert(Tok.is(tok::kw_try) && "Expected 'try'");
1421d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  SourceLocation TryLoc = ConsumeToken();
1422d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1423d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  PrettyStackTraceActionsDecl CrashInfo(Decl, TryLoc, Actions,
1424d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl                                        PP.getSourceManager(),
1425d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl                                        "parsing function try block");
1426d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1427d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  // Constructor initializer list?
1428d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  if (Tok.is(tok::colon))
1429d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl    ParseConstructorInitializer(Decl);
1430d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1431de1b60a9868f80f0872ed05d78df3b40a10ba5caSebastian Redl  SourceLocation LBraceLoc = Tok.getLocation();
1432d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  OwningStmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
1433d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  // If we failed to parse the try-catch, we just give the function an empty
1434d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  // compound statement as the body.
1435d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  if (FnBody.isInvalid())
1436de1b60a9868f80f0872ed05d78df3b40a10ba5caSebastian Redl    FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
1437d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl                                       MultiStmtArg(Actions), false);
1438d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1439d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
1440d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl}
1441d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1442a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// ParseCXXTryBlock - Parse a C++ try-block.
1443a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///
1444a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///       try-block:
1445a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         'try' compound-statement handler-seq
1446a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///
1447bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
1448bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Add attributes?
1449a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  assert(Tok.is(tok::kw_try) && "Expected 'try'");
1450a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1451a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  SourceLocation TryLoc = ConsumeToken();
1452d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  return ParseCXXTryBlockCommon(TryLoc);
1453d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl}
1454d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1455d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// ParseCXXTryBlockCommon - Parse the common part of try-block and
1456d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// function-try-block.
1457d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1458d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///       try-block:
1459d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///         'try' compound-statement handler-seq
1460d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1461d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///       function-try-block:
1462d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///         'try' ctor-initializer[opt] compound-statement handler-seq
1463d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1464d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///       handler-seq:
1465d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///         handler handler-seq[opt]
1466d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1467d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian RedlParser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
1468a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Tok.isNot(tok::l_brace))
1469a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError(Diag(Tok, diag::err_expected_lbrace));
1470bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
1471bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  OwningStmtResult TryBlock(ParseCompoundStatement(0));
1472a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (TryBlock.isInvalid())
1473a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return move(TryBlock);
1474a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1475a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  StmtVector Handlers(Actions);
1476bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
1477bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    CXX0XAttributeList Attr = ParseCXX0XAttributes();
1478bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
1479bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      << Attr.Range;
1480bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  }
1481a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Tok.isNot(tok::kw_catch))
1482a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError(Diag(Tok, diag::err_expected_catch));
1483a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  while (Tok.is(tok::kw_catch)) {
1484a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    OwningStmtResult Handler(ParseCXXCatchBlock());
1485a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    if (!Handler.isInvalid())
1486a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl      Handlers.push_back(Handler.release());
1487a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  }
1488a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // Don't bother creating the full statement if we don't have any usable
1489a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // handlers.
1490a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Handlers.empty())
1491a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError();
1492a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
149376ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl  return Actions.ActOnCXXTryBlock(TryLoc, move(TryBlock), move_arg(Handlers));
1494a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl}
1495a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1496a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
1497a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///
1498a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///       handler:
1499a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         'catch' '(' exception-declaration ')' compound-statement
1500a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///
1501a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///       exception-declaration:
1502a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         type-specifier-seq declarator
1503a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         type-specifier-seq abstract-declarator
1504a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         type-specifier-seq
1505a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         '...'
1506a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///
1507a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian RedlParser::OwningStmtResult Parser::ParseCXXCatchBlock() {
1508a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
1509a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1510a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  SourceLocation CatchLoc = ConsumeToken();
1511a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1512a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  SourceLocation LParenLoc = Tok.getLocation();
1513a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
1514a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError();
1515a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1516a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // C++ 3.3.2p3:
1517a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // The name in a catch exception-declaration is local to the handler and
1518a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // shall not be redeclared in the outermost block of the handler.
1519a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope);
1520a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1521a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // exception-declaration is equivalent to '...' or a parameter-declaration
1522a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // without default arguments.
1523b28317a8e5e0e2953d1e5406d753d6c3c7f1e7d2Chris Lattner  DeclPtrTy ExceptionDecl;
1524a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Tok.isNot(tok::ellipsis)) {
1525a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    DeclSpec DS;
15264b07b2968f87f3cd5a3d8c76145f1cbfd718d42dSebastian Redl    if (ParseCXXTypeSpecifierSeq(DS))
15274b07b2968f87f3cd5a3d8c76145f1cbfd718d42dSebastian Redl      return StmtError();
1528a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    Declarator ExDecl(DS, Declarator::CXXCatchContext);
1529a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    ParseDeclarator(ExDecl);
1530a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    ExceptionDecl = Actions.ActOnExceptionDeclarator(CurScope, ExDecl);
1531a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  } else
1532a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    ConsumeToken();
1533a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1534a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
1535a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError();
1536a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1537a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Tok.isNot(tok::l_brace))
1538a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError(Diag(Tok, diag::err_expected_lbrace));
1539a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1540bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
1541bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  OwningStmtResult Block(ParseCompoundStatement(0));
1542a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Block.isInvalid())
1543a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return move(Block);
1544a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
154576ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl  return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, move(Block));
1546a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl}
1547