ParseStmt.cpp revision 15faa7fdfb496489dec9470aa5eb699b29ecdacc
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"
1639146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner#include "ExtensionRAIIObject.h"
17a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl#include "AstGuard.h"
185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/Diagnostic.h"
19b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff#include "clang/Basic/SourceManager.h"
205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Parse/DeclSpec.h"
215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Parse/Scope.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
41b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC]   objc-throw-statement
42b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC]   objc-try-catch-statement
43c385c90c68dfa376650e2facfbb444b2ec9bd110Fariborz Jahanian/// [OBC]   objc-synchronized-statement
445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   asm-statement
455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   openmp-construct             [TODO]
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         identifier ':' statement
495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'case' constant-expression ':' statement
505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'default' ':' statement
515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       selection-statement:
535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         if-statement
545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         switch-statement
555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       iteration-statement:
575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         while-statement
585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         do-statement
595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         for-statement
605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       expression-statement:
625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         expression[opt] ';'
635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'goto' identifier ';'
665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'continue' ';'
675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'break' ';'
685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'return' expression[opt] ';'
695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   'goto' '*' expression ';'
705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
71b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC] objc-throw-statement:
72b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC]   '@' 'throw' expression ';'
73b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC]   '@' 'throw' ';'
745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const char *SemiError = 0;
7715faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Res(Actions);
780e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Cases in this switch statement should fall through if the parser expects
805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // the token to end in a semicolon (in which case SemiError should be set),
815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // or they directly 'return;' if not.
82397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  tok::TokenKind Kind  = Tok.getKind();
83397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  SourceLocation AtLoc;
84397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  switch (Kind) {
85397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  case tok::at: // May be a @try or @throw statement
86397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian    {
87397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian      AtLoc = ConsumeToken();  // consume @
8864515f31850024a263e8f55f81e9ea4b39925cfaSteve Naroff      return ParseObjCAtStatement(AtLoc);
89397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian    }
90397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian
91b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis  case tok::identifier:
92b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis    if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
93b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis      // identifier ':' statement
94b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis      return ParseLabeledStatement();
95b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis    }
96b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis    // PASS THROUGH.
97b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis
985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  default:
995404a156be26de1c63ca9916187f970848bb4dbbArgyrios Kyrtzidis    if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
10081c018d9482e7cc2addadc6202dcf162a01faefdChris Lattner      SourceLocation DeclStart = Tok.getLocation();
1010e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      DeclTy *Decl = ParseDeclaration(Declarator::BlockContext);
10281c018d9482e7cc2addadc6202dcf162a01faefdChris Lattner      // FIXME: Pass in the right location for the end of the declstmt.
1030e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      return Actions.ActOnDeclStmt(Decl, DeclStart, DeclStart);
1044e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    } else if (Tok.is(tok::r_brace)) {
1055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      Diag(Tok, diag::err_expected_statement);
1065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      return true;
1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    } else {
1085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      // expression[opt] ';'
10915faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl      OwningExprResult Expr(Actions, ParseExpression());
1100e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      if (Expr.isInvalid()) {
1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        // If the expression is invalid, skip ahead to the next semicolon.  Not
1125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        // doing this opens us up to the possibility of infinite loops if
1135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        // ParseExpression does not consume any tokens.
1145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        SkipUntil(tok::semi);
1155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        return true;
1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      }
1175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      // Otherwise, eat the semicolon.
1185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
1190e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      return Actions.ActOnExprStmt(Expr.move());
1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
1215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_case:                // C99 6.8.1: labeled-statement
1235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ParseCaseStatement();
1245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_default:             // C99 6.8.1: labeled-statement
1255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ParseDefaultStatement();
1265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::l_brace:                // C99 6.8.2: compound-statement
1285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ParseCompoundStatement();
1295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::semi:                   // C99 6.8.3p3: expression[opt] ';'
1301b273c403734d343d720acb28f04011807c8aa56Steve Naroff    return Actions.ActOnNullStmt(ConsumeToken());
1315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_if:                  // C99 6.8.4.1: if-statement
1335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ParseIfStatement();
1345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_switch:              // C99 6.8.4.2: switch-statement
1355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ParseSwitchStatement();
1365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_while:               // C99 6.8.5.1: while-statement
1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ParseWhileStatement();
1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_do:                  // C99 6.8.5.2: do-statement
1405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Res = ParseDoStatement();
1415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SemiError = "do/while loop";
1425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_for:                 // C99 6.8.5.3: for-statement
1445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return ParseForStatement();
1455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_goto:                // C99 6.8.6.1: goto-statement
1475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Res = ParseGotoStatement();
1485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SemiError = "goto statement";
1495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_continue:            // C99 6.8.6.2: continue-statement
1515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Res = ParseContinueStatement();
1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SemiError = "continue statement";
1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_break:               // C99 6.8.6.3: break-statement
1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Res = ParseBreakStatement();
1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SemiError = "break statement";
1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_return:              // C99 6.8.6.4: return-statement
1595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Res = ParseReturnStatement();
1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SemiError = "return statement";
1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_asm:
164d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    bool msAsm = false;
165d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    Res = ParseAsmStatement(msAsm);
1660e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (msAsm) return Res.move();
1675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SemiError = "asm statement";
1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // If we reached this code, the statement must end in a semicolon.
1724e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::semi)) {
1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
1740e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  } else if (!Res.isInvalid()) {
1751ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_semi_after) << SemiError;
176195044028b76133e2a1f245b094468fe07db7330Chris Lattner    // Skip until we see a } or ;, but don't eat it.
177195044028b76133e2a1f245b094468fe07db7330Chris Lattner    SkipUntil(tok::r_brace, true, true);
1785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1790e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Res.move();
1805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
182f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis/// ParseLabeledStatement - We have an identifier and a ':' after it.
1835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
1845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
1855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         identifier ':' statement
1865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   identifier ':' attributes[opt] statement
1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
188f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios KyrtzidisParser::StmtResult Parser::ParseLabeledStatement() {
1894e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
1905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer         "Not an identifier!");
1915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
192d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner  Token IdentTok = Tok;  // Save the whole token.
1935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ConsumeToken();  // eat the identifier.
194f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis
195f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  assert(Tok.is(tok::colon) && "Not a label!");
1965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // identifier ':' statement
198f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  SourceLocation ColonLoc = ConsumeToken();
1995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
200f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  // Read label attributes, if present.
201f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  DeclTy *AttrList = 0;
202f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  if (Tok.is(tok::kw___attribute))
203f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis    // TODO: save these somewhere.
204f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis    AttrList = ParseAttributes();
2055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
20615faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult SubStmt(Actions, ParseStatement());
2070e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
208f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  // Broken substmt shouldn't prevent the label from being added to the AST.
2090e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (SubStmt.isInvalid())
210f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis    SubStmt = Actions.ActOnNullStmt(ColonLoc);
2110e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
212f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  return Actions.ActOnLabelStmt(IdentTok.getLocation(),
213f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis                                IdentTok.getIdentifierInfo(),
2140e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                                ColonLoc, SubStmt.move());
215f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis}
2165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCaseStatement
2185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
2195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'case' constant-expression ':' statement
2205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   'case' constant-expression '...' constant-expression ':' statement
2215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
2225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note that this does not parse the 'statement' at the end.
2235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
2245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseCaseStatement() {
2254e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_case) && "Not a case stmt!");
2265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation CaseLoc = ConsumeToken();  // eat the 'case'.
2275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
22815faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult LHS(Actions, ParseConstantExpression());
2290e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (LHS.isInvalid()) {
2305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::colon);
2315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
2325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
2330e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
2345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // GNU case range extension.
2355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation DotDotDotLoc;
23615faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult RHS(Actions);
2374e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::ellipsis)) {
2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::ext_gnu_case_range);
2395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    DotDotDotLoc = ConsumeToken();
2400e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
2410e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    RHS = ParseConstantExpression();
2420e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (RHS.isInvalid()) {
2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::colon);
2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      return true;
2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
2465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
2470e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
2484e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::colon)) {
2491ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_colon_after) << "'case'";
2505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::colon);
2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
2535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ColonLoc = ConsumeToken();
2555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Diagnose the common error "switch (X) { case 4: }", which is not valid.
2574e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::r_brace)) {
2585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::err_label_end_of_compound_statement);
2595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
2605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
2615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
26215faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult SubStmt(Actions, ParseStatement());
2635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Broken substmt shouldn't prevent the case from being added to the AST.
2650e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (SubStmt.isInvalid())
2661b273c403734d343d720acb28f04011807c8aa56Steve Naroff    SubStmt = Actions.ActOnNullStmt(ColonLoc);
2675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2680e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Actions.ActOnCaseStmt(CaseLoc, LHS.move(), DotDotDotLoc,
2690e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                               RHS.move(), ColonLoc, SubStmt.move());
2705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
2715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseDefaultStatement
2735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
2745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'default' ':' statement
2755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note that this does not parse the 'statement' at the end.
2765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
2775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseDefaultStatement() {
2784e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_default) && "Not a default stmt!");
2795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
2805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2814e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::colon)) {
2821ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_colon_after) << "'default'";
2835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::colon);
2845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
2855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
2865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ColonLoc = ConsumeToken();
2885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Diagnose the common error "switch (X) {... default: }", which is not valid.
2904e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::r_brace)) {
2915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::err_label_end_of_compound_statement);
2925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
2935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
2945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
29515faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult SubStmt(Actions, ParseStatement());
2960e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (SubStmt.isInvalid())
2975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
2985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2990e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
3000e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                                  SubStmt.move(), CurScope);
3015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
3025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCompoundStatement - Parse a "{}" block.
3055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
3065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       compound-statement: [C99 6.8.2]
3075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         { block-item-list[opt] }
3085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   { label-declarations block-item-list } [TODO]
3095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
3105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       block-item-list:
3115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         block-item
3125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         block-item-list block-item
3135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
3145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       block-item:
3155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         declaration
31645a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner/// [GNU]   '__extension__' declaration
3175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         statement
3185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   openmp-directive            [TODO]
3195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
3205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] label-declarations:
3215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   label-declaration
3225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   label-declarations label-declaration
3235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
3245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] label-declaration:
3255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   '__label__' identifier-list ';'
3265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
3275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP] openmp-directive:             [TODO]
3285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   barrier-directive
3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   flush-directive
3305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
33198414c1b7d1944a57156d52e29bd41c005de09acChris LattnerParser::StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
3324e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
3335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
33431e057270232c1c37602579cb6461c2704175672Chris Lattner  // Enter a scope to hold everything within the compound stmt.  Compound
33531e057270232c1c37602579cb6461c2704175672Chris Lattner  // statements can always hold declarations.
33631e057270232c1c37602579cb6461c2704175672Chris Lattner  EnterScope(Scope::DeclScope);
3375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the statements in the body.
33915faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Body(Actions, ParseCompoundStatementBody(isStmtExpr));
3405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ExitScope();
3420e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Body.move();
3435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
3445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
3471b273c403734d343d720acb28f04011807c8aa56Steve Naroff/// ActOnCompoundStmt action.  This expects the '{' to be the current token, and
3485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// consume the '}' at the end of the block.  It does not manipulate the scope
3495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// stack.
35098414c1b7d1944a57156d52e29bd41c005de09acChris LattnerParser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
3515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation LBraceLoc = ConsumeBrace();  // eat the '{'.
3525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension.  These are
35445a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner  // only allowed at the start of a compound stmt regardless of the language.
355a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl
356a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  typedef StmtVector StmtsTy;
357a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  StmtsTy Stmts(Actions);
3584e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
35915faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl    OwningStmtResult R(Actions);
3604e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.isNot(tok::kw___extension__)) {
36145a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      R = ParseStatementOrDeclaration(false);
36245a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner    } else {
36345a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // __extension__ can start declarations and it can also be a unary
36445a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // operator for expressions.  Consume multiple __extension__ markers here
36545a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // until we can determine which is which.
36645a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      SourceLocation ExtLoc = ConsumeToken();
3674e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner      while (Tok.is(tok::kw___extension__))
36845a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        ConsumeToken();
36945a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner
370043a0b50a2a7a29c78a1ffb774f6fca8baf464a0Chris Lattner      // __extension__ silences extension warnings in the subexpression.
37139146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner      ExtensionRAIIObject O(Diags);  // Use RAII to do this.
37239146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner
37345a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // If this is the start of a declaration, parse it as such.
3745404a156be26de1c63ca9916187f970848bb4dbbArgyrios Kyrtzidis      if (isDeclarationStatement()) {
37545a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        // FIXME: Save the __extension__ on the decl as a node somehow.
37681c018d9482e7cc2addadc6202dcf162a01faefdChris Lattner        SourceLocation DeclStart = Tok.getLocation();
37781c018d9482e7cc2addadc6202dcf162a01faefdChris Lattner        DeclTy *Res = ParseDeclaration(Declarator::BlockContext);
37881c018d9482e7cc2addadc6202dcf162a01faefdChris Lattner        // FIXME: Pass in the right location for the end of the declstmt.
379691a38b740562119ea8b2e25c3e04599971e708fChris Lattner        R = Actions.ActOnDeclStmt(Res, DeclStart, DeclStart);
38045a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      } else {
38145a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        // Otherwise this was a unary __extension__ marker.  Parse the
38245a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        // subexpression and add the __extension__ unary op.
38315faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl        OwningExprResult Res(Actions, ParseCastExpression(false));
384043a0b50a2a7a29c78a1ffb774f6fca8baf464a0Chris Lattner
3850e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl        if (Res.isInvalid()) {
38645a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner          SkipUntil(tok::semi);
38745a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner          continue;
38845a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        }
38945a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner
39045a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        // Add the __extension__ node to the AST.
39174253736184c0717a0649922551bf9d8b6815651Douglas Gregor        Res = Actions.ActOnUnaryOp(CurScope, ExtLoc, tok::kw___extension__,
3920e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                                   Res.move());
3930e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl        if (Res.isInvalid())
39445a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner          continue;
39545a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner
39639146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner        // Eat the semicolon at the end of stmt and convert the expr into a
39739146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner        // statement.
39845a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
3990e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl        R = Actions.ActOnExprStmt(Res.move());
40045a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      }
40145a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner    }
40245a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner
4030e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (R.isUsable())
4040e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      Stmts.push_back(R.move());
4055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
4065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // We broke out of the while loop because we found a '}' or EOF.
4084e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::r_brace)) {
4095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::err_expected_rbrace);
410d1a7cf8c922ae97cd70d784553c5b7566b5c5e7bSteve Naroff    return true;
4115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
4125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation RBraceLoc = ConsumeBrace();
4141b273c403734d343d720acb28f04011807c8aa56Steve Naroff  return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
415a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl                                   Stmts.take(), Stmts.size(), isStmtExpr);
4165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
4175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseIfStatement
4195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       if-statement: [C99 6.8.4.1]
4205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'if' '(' expression ')' statement
4215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'if' '(' expression ')' statement 'else' statement
42271b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'if' '(' condition ')' statement
42371b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'if' '(' condition ')' statement 'else' statement
4245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseIfStatement() {
4264e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_if) && "Not an if stmt!");
4275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
4285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4294e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
4301ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "if";
4315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
4325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
4335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
43471b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis
435488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
436488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
4372215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.4p3 - In C99, the if statement is a block.  This is not
4382215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.
439488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
440488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
441488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
442488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
443488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
44414d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
44514d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
44614d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
44714d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
448488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
449488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  if (C99orCXX)
45071b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    EnterScope(Scope::DeclScope | Scope::ControlScope);
4512215325a5696fb3b23551239b900559bb3018ee9Chris Lattner
4525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the condition.
45315faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult CondExp(Actions);
45471b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis  if (getLang().CPlusPlus) {
45571b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    SourceLocation LParenLoc = ConsumeParen();
45671b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    CondExp = ParseCXXCondition();
45771b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    MatchRHSPunctuation(tok::r_paren, LParenLoc);
45871b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis  } else {
45971b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    CondExp = ParseSimpleParenExpression();
46071b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis  }
46171b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis
4620e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (CondExp.isInvalid()) {
4635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
464488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    if (C99orCXX)
4652215325a5696fb3b23551239b900559bb3018ee9Chris Lattner      ExitScope();
4665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
4675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
4685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4690ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
47038484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
47138484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
472488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
473488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p1:
474488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in a selection-statement (each substatement, in the else
475488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // form of the if statement) implicitly defines a local scope.
476488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
477488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // For C++ we create a scope for the condition and a new scope for
478488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // substatements because:
479488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // -When the 'then' scope exits, we want the condition declaration to still be
480488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    active for the 'else' scope too.
481488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // -Sema will detect name clashes by considering declarations of a
482488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    'ControlScope' as part of its direct subscope.
483488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // -If we wanted the condition and substatement to be in the same scope, we
484488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    would have to notify ParseStatement not to create a new scope. It's
485488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    simpler to let it create a new scope.
486488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
487488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool NeedsInnerScope = C99orCXX && Tok.isNot(tok::l_brace);
48831e057270232c1c37602579cb6461c2704175672Chris Lattner  if (NeedsInnerScope) EnterScope(Scope::DeclScope);
48971b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis
490b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // Read the 'then' stmt.
491b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  SourceLocation ThenStmtLoc = Tok.getLocation();
49215faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult ThenStmt(Actions, ParseStatement());
4935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
494a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner  // Pop the 'if' scope if needed.
49538484403c8356fb41540ace6c74f28867f28febaChris Lattner  if (NeedsInnerScope) ExitScope();
4965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // If it has an else, parse it.
4985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ElseLoc;
499b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  SourceLocation ElseStmtLoc;
50015faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult ElseStmt(Actions);
5010e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
5024e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::kw_else)) {
5035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ElseLoc = ConsumeToken();
504a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner
5050ecea03077117c7ea54c88091a44c73cef67923cChris Lattner    // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
50638484403c8356fb41540ace6c74f28867f28febaChris Lattner    // there is no compound stmt.  C90 does not have this clause.  We only do
50738484403c8356fb41540ace6c74f28867f28febaChris Lattner    // this if the body isn't a compound statement to avoid push/pop in common
50838484403c8356fb41540ace6c74f28867f28febaChris Lattner    // cases.
509488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    //
510488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    // C++ 6.4p1:
511488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    // The substatement in a selection-statement (each substatement, in the else
512488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    // form of the if statement) implicitly defines a local scope.
513488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    //
514488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    NeedsInnerScope = C99orCXX && Tok.isNot(tok::l_brace);
51531e057270232c1c37602579cb6461c2704175672Chris Lattner    if (NeedsInnerScope) EnterScope(Scope::DeclScope);
5160e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
517b96728d90abc35a520798066d2a75ca36400a617Chris Lattner    ElseStmtLoc = Tok.getLocation();
5185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ElseStmt = ParseStatement();
519a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner
520a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner    // Pop the 'else' scope if needed.
52138484403c8356fb41540ace6c74f28867f28febaChris Lattner    if (NeedsInnerScope) ExitScope();
5225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
5235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
524488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  if (C99orCXX)
5252215325a5696fb3b23551239b900559bb3018ee9Chris Lattner    ExitScope();
5262215325a5696fb3b23551239b900559bb3018ee9Chris Lattner
527b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // If the then or else stmt is invalid and the other is valid (and present),
528b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // make turn the invalid one into a null stmt to avoid dropping the other
529b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // part.  If both are invalid, return error.
5300e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
5310e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      (ThenStmt.isInvalid() && ElseStmt.get() == 0) ||
5320e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      (ThenStmt.get() == 0  && ElseStmt.isInvalid())) {
533a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl    // Both invalid, or one is invalid and other is non-present: return error.
534b96728d90abc35a520798066d2a75ca36400a617Chris Lattner    return true;
535b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  }
5360e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
537b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // Now if either are invalid, replace with a ';'.
5380e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (ThenStmt.isInvalid())
539b96728d90abc35a520798066d2a75ca36400a617Chris Lattner    ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
5400e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (ElseStmt.isInvalid())
541b96728d90abc35a520798066d2a75ca36400a617Chris Lattner    ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
5420e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
5430e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Actions.ActOnIfStmt(IfLoc, CondExp.move(), ThenStmt.move(),
5440e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                             ElseLoc, ElseStmt.move());
5455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
5465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
5475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseSwitchStatement
5485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       switch-statement:
5495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'switch' '(' expression ')' statement
55071b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'switch' '(' condition ')' statement
5515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseSwitchStatement() {
5524e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
5535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
5545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
5554e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
5561ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "switch";
5575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
5585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
5595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
5602215325a5696fb3b23551239b900559bb3018ee9Chris Lattner
561488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
562488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
5632215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.4p3 - In C99, the switch statement is a block.  This is
5642215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // not the case for C90.  Start the switch scope.
565488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
566488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
567488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
568488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
569488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
57014d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
57114d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
57214d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
57314d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
574488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
575488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  if (C99orCXX)
57671b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    EnterScope(Scope::BreakScope | Scope::DeclScope | Scope::ControlScope);
5772215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  else
5782215325a5696fb3b23551239b900559bb3018ee9Chris Lattner    EnterScope(Scope::BreakScope);
5795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
5805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the condition.
58115faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult Cond(Actions);
58271b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis  if (getLang().CPlusPlus) {
58371b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    SourceLocation LParenLoc = ConsumeParen();
58471b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    Cond = ParseCXXCondition();
58571b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    MatchRHSPunctuation(tok::r_paren, LParenLoc);
58671b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis  } else {
58771b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    Cond = ParseSimpleParenExpression();
58871b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis  }
5895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
5900e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (Cond.isInvalid()) {
591c1fcb7762673be706b0a40477d5e93411e918f93Anders Carlsson    ExitScope();
592c1fcb7762673be706b0a40477d5e93411e918f93Anders Carlsson    return true;
593c1fcb7762673be706b0a40477d5e93411e918f93Anders Carlsson  }
5940e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
59515faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Switch(Actions, Actions.ActOnStartOfSwitchStmt(Cond.move()));
5960e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
5970ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
59838484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
59938484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
600488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
601488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p1:
602488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in a selection-statement (each substatement, in the else
603488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // form of the if statement) implicitly defines a local scope.
604488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
605488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // See comments in ParseIfStatement for why we create a scope for the
606488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition and a new scope for substatement in C++.
607488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
608488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool NeedsInnerScope = C99orCXX && Tok.isNot(tok::l_brace);
60931e057270232c1c37602579cb6461c2704175672Chris Lattner  if (NeedsInnerScope) EnterScope(Scope::DeclScope);
6100ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
6115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
61215faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Body(Actions, ParseStatement());
6135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6140ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
61538484403c8356fb41540ace6c74f28867f28febaChris Lattner  if (NeedsInnerScope) ExitScope();
6160ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
6170e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (Body.isInvalid()) {
6181b273c403734d343d720acb28f04011807c8aa56Steve Naroff    Body = Actions.ActOnNullStmt(Tok.getLocation());
619c1fcb7762673be706b0a40477d5e93411e918f93Anders Carlsson    // FIXME: Remove the case statement list from the Switch statement.
620c1fcb7762673be706b0a40477d5e93411e918f93Anders Carlsson  }
6215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
622c1fcb7762673be706b0a40477d5e93411e918f93Anders Carlsson  ExitScope();
6235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6240e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.move(), Body.move());
6255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
6265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseWhileStatement
6285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       while-statement: [C99 6.8.5.1]
6295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'while' '(' expression ')' statement
63071b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'while' '(' condition ')' statement
6315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseWhileStatement() {
6324e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_while) && "Not a while stmt!");
6335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation WhileLoc = Tok.getLocation();
6345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ConsumeToken();  // eat the 'while'.
6355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6364e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
6371ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "while";
6385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
6395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
6405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
6415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
642488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
643488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
6442215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.5p5 - In C99, the while statement is a block.  This is not
6452215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.  Start the loop scope.
646488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
647488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
648488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
649488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
650488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
65114d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
65214d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
65314d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
65414d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
655488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
656488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  if (C99orCXX)
65771b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    EnterScope(Scope::BreakScope | Scope::ContinueScope |
65871b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis               Scope::DeclScope  | Scope::ControlScope);
6592215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  else
6602215325a5696fb3b23551239b900559bb3018ee9Chris Lattner    EnterScope(Scope::BreakScope | Scope::ContinueScope);
6615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the condition.
66315faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult Cond(Actions);
66471b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis  if (getLang().CPlusPlus) {
66571b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    SourceLocation LParenLoc = ConsumeParen();
66671b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    Cond = ParseCXXCondition();
66771b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    MatchRHSPunctuation(tok::r_paren, LParenLoc);
66871b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis  } else {
66971b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    Cond = ParseSimpleParenExpression();
67071b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis  }
6710e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
6720ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
67338484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
67438484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
675488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
676488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.5p2:
677488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in an iteration-statement implicitly defines a local scope
678488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // which is entered and exited each time through the loop.
679488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
680488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // See comments in ParseIfStatement for why we create a scope for the
681488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition and a new scope for substatement in C++.
682488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
683488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool NeedsInnerScope = C99orCXX && Tok.isNot(tok::l_brace);
68431e057270232c1c37602579cb6461c2704175672Chris Lattner  if (NeedsInnerScope) EnterScope(Scope::DeclScope);
6850ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
6865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
68715faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Body(Actions, ParseStatement());
6885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6890ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
69038484403c8356fb41540ace6c74f28867f28febaChris Lattner  if (NeedsInnerScope) ExitScope();
6910ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
6925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ExitScope();
6935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6940e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (Cond.isInvalid() || Body.isInvalid()) return true;
6955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6960e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Actions.ActOnWhileStmt(WhileLoc, Cond.move(), Body.move());
6975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
6985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseDoStatement
7005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       do-statement: [C99 6.8.5.2]
7015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'do' statement 'while' '(' expression ')' ';'
7025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
7035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseDoStatement() {
7044e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_do) && "Not a do stmt!");
7055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
7065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7072215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.5p5 - In C99, the do statement is a block.  This is not
7082215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.  Start the loop scope.
7092215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  if (getLang().C99)
7102215325a5696fb3b23551239b900559bb3018ee9Chris Lattner    EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
7112215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  else
7122215325a5696fb3b23551239b900559bb3018ee9Chris Lattner    EnterScope(Scope::BreakScope | Scope::ContinueScope);
7135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7140ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
71538484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause. We only do this
71638484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
717143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  //
718143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  // C++ 6.5p2:
719143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  // The substatement in an iteration-statement implicitly defines a local scope
720143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  // which is entered and exited each time through the loop.
721143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  //
722195044028b76133e2a1f245b094468fe07db7330Chris Lattner  bool NeedsInnerScope =
723195044028b76133e2a1f245b094468fe07db7330Chris Lattner    (getLang().C99 || getLang().CPlusPlus) && Tok.isNot(tok::l_brace);
72431e057270232c1c37602579cb6461c2704175672Chris Lattner  if (NeedsInnerScope) EnterScope(Scope::DeclScope);
7250ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
7265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
72715faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Body(Actions, ParseStatement());
7285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7290ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
73038484403c8356fb41540ace6c74f28867f28febaChris Lattner  if (NeedsInnerScope) ExitScope();
7310ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
7324e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::kw_while)) {
7335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ExitScope();
7340e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (!Body.isInvalid()) {
735195044028b76133e2a1f245b094468fe07db7330Chris Lattner      Diag(Tok, diag::err_expected_while);
73628eb7e992b9a266abb300da25b6d3c1557cec361Chris Lattner      Diag(DoLoc, diag::note_matching) << "do";
737195044028b76133e2a1f245b094468fe07db7330Chris Lattner      SkipUntil(tok::semi, false, true);
738195044028b76133e2a1f245b094468fe07db7330Chris Lattner    }
7395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
7405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
7415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation WhileLoc = ConsumeToken();
7425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7434e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
7445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ExitScope();
7451ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "do/while";
746195044028b76133e2a1f245b094468fe07db7330Chris Lattner    SkipUntil(tok::semi, false, true);
7475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
7485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
7495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the condition.
75115faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult Cond(Actions, ParseSimpleParenExpression());
7520e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
7535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ExitScope();
7540e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
7550e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (Cond.isInvalid() || Body.isInvalid()) return true;
7560e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
7570e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Actions.ActOnDoStmt(DoLoc, Body.move(), WhileLoc, Cond.move());
7585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
7595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseForStatement
7615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       for-statement: [C99 6.8.5.3]
7625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
7635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
76471b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
76571b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]       statement
7663ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian/// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
7673ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian/// [OBJC2] 'for' '(' expr 'in' expr ')' statement
76871b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis///
76971b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] for-init-statement:
77071b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   expression-statement
77171b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   simple-declaration
77271b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis///
7735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseForStatement() {
7744e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_for) && "Not a for stmt!");
7755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
7765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7774e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
7781ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "for";
7795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
7805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
7815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
7825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
783488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
784488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
7852215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.5p5 - In C99, the for statement is a block.  This is not
7862215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.  Start the loop scope.
787488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
788488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
789488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
790488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
791488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
79214d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
79314d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
79414d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
79514d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
796488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.5.3p1:
797488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // Names declared in the for-init-statement are in the same declarative-region
798488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // as those declared in the condition.
799488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
800488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  if (C99orCXX)
80171b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    EnterScope(Scope::BreakScope | Scope::ContinueScope |
80271b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis               Scope::DeclScope  | Scope::ControlScope);
8032215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  else
8042215325a5696fb3b23551239b900559bb3018ee9Chris Lattner    EnterScope(Scope::BreakScope | Scope::ContinueScope);
8055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation LParenLoc = ConsumeParen();
80715faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult Value(Actions);
8080e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
809bdd15f701fe98f77b1b8ddb3f4a5c0d83bb8fa9cFariborz Jahanian  bool ForEach = false;
81015faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult FirstPart(Actions), ThirdPart(Actions);
81115faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult SecondPart(Actions);
8120e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
8135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the first part of the for specifier.
8144e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::semi)) {  // for (;
8155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // no first part, eat the ';'.
8165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
817bbc70c019f7b7f9a256ee29dab5287ecc82c6553Argyrios Kyrtzidis  } else if (isSimpleDeclaration()) {  // for (int X = 4;
8185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Parse declaration, which eats the ';'.
819488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    if (!C99orCXX)   // Use of C99-style for loops in C90 mode?
8205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
82181c018d9482e7cc2addadc6202dcf162a01faefdChris Lattner
82281c018d9482e7cc2addadc6202dcf162a01faefdChris Lattner    SourceLocation DeclStart = Tok.getLocation();
82371b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis    DeclTy *aBlockVarDecl = ParseSimpleDeclaration(Declarator::ForContext);
82481c018d9482e7cc2addadc6202dcf162a01faefdChris Lattner    // FIXME: Pass in the right location for the end of the declstmt.
8250e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    FirstPart = Actions.ActOnDeclStmt(aBlockVarDecl, DeclStart,
8260e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                                          DeclStart);
827bdd15f701fe98f77b1b8ddb3f4a5c0d83bb8fa9cFariborz Jahanian    if ((ForEach = isTokIdentifier_in())) {
8283ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      ConsumeToken(); // consume 'in'
8290e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      SecondPart = ParseExpression();
8303ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
8315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  } else {
8325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Value = ParseExpression();
8335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Turn the expression into a stmt.
8350e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (!Value.isInvalid())
8360e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      FirstPart = Actions.ActOnExprStmt(Value.move());
8375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8384e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.is(tok::semi)) {
8395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      ConsumeToken();
8403ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
841bdd15f701fe98f77b1b8ddb3f4a5c0d83bb8fa9cFariborz Jahanian    else if ((ForEach = isTokIdentifier_in())) {
8423ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      ConsumeToken(); // consume 'in'
8430e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      SecondPart = ParseExpression();
8443ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
8453ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    else {
8460e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
8475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::semi);
8485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
8495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
850bdd15f701fe98f77b1b8ddb3f4a5c0d83bb8fa9cFariborz Jahanian  if (!ForEach) {
8510e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
8523ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    // Parse the second part of the for specifier.
8533ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    if (Tok.is(tok::semi)) {  // for (...;;
8543ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      // no second part.
8553ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    } else {
8560e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      SecondPart = getLang().CPlusPlus ? ParseCXXCondition()
8570e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                                       : ParseExpression();
8583ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
8590e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
8603ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    if (Tok.is(tok::semi)) {
8613ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      ConsumeToken();
8623ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    } else {
8630e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      if (!SecondPart.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
8643ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      SkipUntil(tok::semi);
8653ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
8665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8673ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    // Parse the third part of the for specifier.
8683ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    if (Tok.is(tok::r_paren)) {  // for (...;...;)
8693ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      // no third part.
8703ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    } else {
8713ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      Value = ParseExpression();
8720e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      if (!Value.isInvalid()) {
8733ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian        // Turn the expression into a stmt.
8740e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl        ThirdPart = Actions.ActOnExprStmt(Value.move());
8753ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      }
8765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
8775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
8785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Match the ')'.
8795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
8800e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
8810ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
88238484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
88338484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
884488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
885488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.5p2:
886488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in an iteration-statement implicitly defines a local scope
887488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // which is entered and exited each time through the loop.
888488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
889488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // See comments in ParseIfStatement for why we create a scope for
890488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // for-init-statement/condition and a new scope for substatement in C++.
891488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
892488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool NeedsInnerScope = C99orCXX && Tok.isNot(tok::l_brace);
89331e057270232c1c37602579cb6461c2704175672Chris Lattner  if (NeedsInnerScope) EnterScope(Scope::DeclScope);
8940e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
8955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
89615faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Body(Actions, ParseStatement());
8970e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
8980ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
89938484403c8356fb41540ace6c74f28867f28febaChris Lattner  if (NeedsInnerScope) ExitScope();
9000ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
9015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Leave the for-scope.
9025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ExitScope();
9030e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
9040e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (Body.isInvalid())
9050e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    return true;
9065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
907bdd15f701fe98f77b1b8ddb3f4a5c0d83bb8fa9cFariborz Jahanian  if (!ForEach)
9080e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.move(),
9090e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                                SecondPart.move(), ThirdPart.move(), RParenLoc,
9100e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                                Body.move());
911bdd15f701fe98f77b1b8ddb3f4a5c0d83bb8fa9cFariborz Jahanian  else
9120e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
9130e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                                              FirstPart.move(),
9140e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                                              SecondPart.move(),
9150e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                                              RParenLoc, Body.move());
9165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
9175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
9185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseGotoStatement
9195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
9205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'goto' identifier ';'
9215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   'goto' '*' expression ';'
9225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
9235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
9245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
9255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseGotoStatement() {
9264e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
9275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
9285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
92915faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Res(Actions);
9304e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::identifier)) {
9311b273c403734d343d720acb28f04011807c8aa56Steve Naroff    Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
9325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                                Tok.getIdentifierInfo());
9335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
9344e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  } else if (Tok.is(tok::star) && !getLang().NoExtensions) {
9355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // GNU indirect goto extension.
9365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::ext_gnu_indirect_goto);
9375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SourceLocation StarLoc = ConsumeToken();
93815faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl    OwningExprResult R(Actions, ParseExpression());
9390e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
9405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::semi, false, true);
9415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      return true;
9425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
9430e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.move());
94495cfb85ad1820117e0864712555f3aa4fdf4721aChris Lattner  } else {
94595cfb85ad1820117e0864712555f3aa4fdf4721aChris Lattner    Diag(Tok, diag::err_expected_ident);
94695cfb85ad1820117e0864712555f3aa4fdf4721aChris Lattner    return true;
9475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
9480e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
9490e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Res.move();
9505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
9515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
9525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseContinueStatement
9535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
9545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'continue' ';'
9555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
9565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
9575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
9585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseContinueStatement() {
9595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
9601b273c403734d343d720acb28f04011807c8aa56Steve Naroff  return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
9615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
9625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
9635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseBreakStatement
9645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
9655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'break' ';'
9665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
9675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
9685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
9695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseBreakStatement() {
9705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
9711b273c403734d343d720acb28f04011807c8aa56Steve Naroff  return Actions.ActOnBreakStmt(BreakLoc, CurScope);
9725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
9735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
9745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseReturnStatement
9755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
9765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'return' expression[opt] ';'
9775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid SpencerParser::StmtResult Parser::ParseReturnStatement() {
9784e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_return) && "Not a return stmt!");
9795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
9805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
98115faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult R(Actions);
9824e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::semi)) {
9835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    R = ParseExpression();
9840e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
9855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::semi, false, true);
9865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      return true;
9875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
9885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
9890e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Actions.ActOnReturnStmt(ReturnLoc, R.move());
9905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
9915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
9925f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this
9935f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// routine is called to skip/ignore tokens that comprise the MS asm statement.
994d62701bc5321049353017e9abf1963edd57646aaSteve NaroffParser::StmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
995b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff  if (Tok.is(tok::l_brace)) {
996b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    unsigned short savedBraceCount = BraceCount;
997b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    do {
998b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff      ConsumeAnyToken();
999b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof));
1000b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff  } else {
1001b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    // From the MS website: If used without braces, the __asm keyword means
1002b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    // that the rest of the line is an assembly-language statement.
1003b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    SourceManager &SrcMgr = PP.getSourceManager();
100403d6bc6734eb79dc27628d9ea1126c299c80b4b6Steve Naroff    SourceLocation TokLoc = Tok.getLocation();
1005362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff    unsigned lineNo = SrcMgr.getLogicalLineNumber(TokLoc);
1006362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff    do {
1007362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff      ConsumeAnyToken();
1008362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff      TokLoc = Tok.getLocation();
1009362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff    } while ((SrcMgr.getLogicalLineNumber(TokLoc) == lineNo) &&
1010362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff             Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) &&
1011362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff             Tok.isNot(tok::eof));
1012b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff  }
1013d77bc2834269593282e06806a74d14e244bc26a4Steve Naroff  return Actions.ActOnNullStmt(Tok.getLocation());
1014d62701bc5321049353017e9abf1963edd57646aaSteve Naroff}
1015d62701bc5321049353017e9abf1963edd57646aaSteve Naroff
10165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseAsmStatement - Parse a GNU extended asm statement.
10175f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///       asm-statement:
10185f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         gnu-asm-statement
10195f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         ms-asm-statement
10205f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///
10215f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [GNU] gnu-asm-statement:
10225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'asm' type-qualifier[opt] '(' asm-argument ')' ';'
10235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
10245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-argument:
10255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal
10265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal ':' asm-operands[opt]
10275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
10285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
10295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///                 ':' asm-clobbers
10305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
10315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-clobbers:
10325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal
10335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-clobbers ',' asm-string-literal
10345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
10355f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [MS]  ms-asm-statement:
10365f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         '__asm' assembly-instruction ';'[opt]
10375f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         '__asm' '{' assembly-instruction-list '}' ';'[opt]
10385f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///
10395f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [MS]  assembly-instruction-list:
10405f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         assembly-instruction ';'[opt]
10415f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         assembly-instruction-list ';' assembly-instruction ';'[opt]
10425f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///
1043d62701bc5321049353017e9abf1963edd57646aaSteve NaroffParser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
10444e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
1045fe795956194141c91ae555985c9b930595bff43fChris Lattner  SourceLocation AsmLoc = ConsumeToken();
10465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
10475f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff  if (getLang().Microsoft && Tok.isNot(tok::l_paren) && !isTypeQualifier()) {
1048d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    msAsm = true;
1049d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    return FuzzyParseMicrosoftAsmStatement();
1050d62701bc5321049353017e9abf1963edd57646aaSteve Naroff  }
10515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  DeclSpec DS;
10525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation Loc = Tok.getLocation();
10535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ParseTypeQualifierListOpt(DS);
10545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
10555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // GNU asms accept, but warn, about type-qualifiers other than volatile.
10565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
10571ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
10585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
10591ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
10605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
10615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Remember if this was a volatile asm.
106239c47b56f45437bbc49c9568b7308a400234a730Anders Carlsson  bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
1063dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  bool isSimple = false;
10644e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
10651ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "asm";
10665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::r_paren);
10675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return true;
10685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
10695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  Loc = ConsumeParen();
10705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
107115faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult AsmString(Actions, ParseAsmStringLiteral());
10720e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (AsmString.isInvalid())
10736a0ef4b83c91a6d6d5acb4ed5577c4659fe022a3Anders Carlsson    return true;
10740e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
1075b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson  llvm::SmallVector<std::string, 4> Names;
1076a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  ExprVector Constraints(Actions);
1077a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  ExprVector Exprs(Actions);
1078a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  ExprVector Clobbers(Actions);
1079dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson
1080dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  unsigned NumInputs = 0, NumOutputs = 0;
1081b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson
1082dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  SourceLocation RParenLoc;
1083dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  if (Tok.is(tok::r_paren)) {
1084dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    // We have a simple asm expression
1085dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    isSimple = true;
1086dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson
1087dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    RParenLoc = ConsumeParen();
1088dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  } else {
1089a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl    // Parse Outputs, if present.
10908bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson    if (ParseAsmOperandsOpt(Names, Constraints, Exprs))
10918bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson        return true;
1092b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson
1093dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    NumOutputs = Names.size();
10945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1095dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    // Parse Inputs, if present.
10968bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson    if (ParseAsmOperandsOpt(Names, Constraints, Exprs))
10978bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson        return true;
10988bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson
1099dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    assert(Names.size() == Constraints.size() &&
1100dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson           Constraints.size() == Exprs.size()
1101dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson           && "Input operand size mismatch!");
1102b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson
1103dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    NumInputs = Names.size() - NumOutputs;
11045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1105dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    // Parse the clobbers, if present.
1106dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    if (Tok.is(tok::colon)) {
1107dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson      ConsumeToken();
11085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1109dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson      // Parse the asm-string list for clobbers.
1110dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson      while (1) {
111115faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl        OwningExprResult Clobber(Actions, ParseAsmStringLiteral());
11125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11130e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl        if (Clobber.isInvalid())
1114dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson          break;
1115b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson
11160e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl        Clobbers.push_back(Clobber.move());
1117b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson
1118dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson        if (Tok.isNot(tok::comma)) break;
1119dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson        ConsumeToken();
1120dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson      }
11215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
11225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1123dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc);
1124dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  }
11255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1126dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  return Actions.ActOnAsmStmt(AsmLoc, isSimple, isVolatile,
1127dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson                              NumOutputs, NumInputs,
1128a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl                              &Names[0], Constraints.take(),
11290e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl                              Exprs.take(), AsmString.move(),
1130a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl                              Clobbers.size(), Clobbers.take(),
1131b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson                              RParenLoc);
11325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
11335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseAsmOperands - Parse the asm-operands production as used by
11355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-statement.  We also parse a leading ':' token.  If the leading colon is
11365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// not present, we do not parse anything.
11375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-operands:
11395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-operand
11405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-operands ',' asm-operand
11415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-operand:
11435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal '(' expression ')'
11445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         '[' identifier ']' asm-string-literal '(' expression ')'
11455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11468bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlssonbool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
1147b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson                                 llvm::SmallVectorImpl<ExprTy*> &Constraints,
1148b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson                                 llvm::SmallVectorImpl<ExprTy*> &Exprs) {
11495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Only do anything if this operand is present.
11508bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson  if (Tok.isNot(tok::colon)) return false;
11515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ConsumeToken();
11525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // 'asm-operands' isn't present?
11544e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
11558bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson    return false;
11565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1157b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson  while (1) {
11585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Read the [id] if present.
11594e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.is(tok::l_square)) {
11605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SourceLocation Loc = ConsumeBracket();
11615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11624e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner      if (Tok.isNot(tok::identifier)) {
11635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        Diag(Tok, diag::err_expected_ident);
11645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        SkipUntil(tok::r_paren);
11658bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson        return true;
11665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      }
116769efba74cf5488060accf34c011b33ce6c15ece0Chris Lattner
1168b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson      IdentifierInfo *II = Tok.getIdentifierInfo();
116969efba74cf5488060accf34c011b33ce6c15ece0Chris Lattner      ConsumeToken();
1170b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson
1171b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson      Names.push_back(std::string(II->getName(), II->getLength()));
11725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      MatchRHSPunctuation(tok::r_square, Loc);
1173b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson    } else
1174b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson      Names.push_back(std::string());
11750e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
117615faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl    OwningExprResult Constraint(Actions, ParseAsmStringLiteral());
11770e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (Constraint.isInvalid()) {
1178b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson        SkipUntil(tok::r_paren);
11798bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson        return true;
1180b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson    }
11810e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    Constraints.push_back(Constraint.move());
11825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11834e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.isNot(tok::l_paren)) {
11841ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner      Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
11855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::r_paren);
11868bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson      return true;
11875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
11885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Read the parenthesized expression.
119015faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl    OwningExprResult Res(Actions, ParseSimpleParenExpression());
11910e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (Res.isInvalid()) {
11925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::r_paren);
11938bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson      return true;
11945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
11950e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    Exprs.push_back(Res.move());
11965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Eat the comma and continue parsing if it exists.
11978bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson    if (Tok.isNot(tok::comma)) return false;
11985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
11995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
12008bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson
12018bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson  return true;
12025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1203f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian
1204f9ed3157c93495474003a5ec360039030fd42e9cFariborz JahanianParser::DeclTy *Parser::ParseFunctionStatementBody(DeclTy *Decl,
1205f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian                                           SourceLocation L, SourceLocation R) {
1206f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // Do not enter a scope for the brace, as the arguments are in the same scope
1207f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // (the function body) as the body itself.  Instead, just read the statement
1208f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // list and put it into a CompoundStmt for safe keeping.
120915faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult FnBody(Actions, ParseCompoundStatementBody());
1210f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian
1211f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // If the function body could not be parsed, make a bogus compoundstmt.
12120e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (FnBody.isInvalid())
1213f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian    FnBody = Actions.ActOnCompoundStmt(L, R, 0, 0, false);
1214f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian
1215f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // Leave the function body scope.
1216f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  ExitScope();
1217f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian
12180e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  return Actions.ActOnFinishFunctionBody(Decl, FnBody.move());
1219cd5af4b5863c63b62cde96ad6d52fb1eec0e26bbSeo Sanghyeon}
1220