ParseStmt.cpp revision be724bab2ba7ad47aebced25e7c8ec551eb72d28
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"
175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Parse/DeclSpec.h"
185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Parse/Scope.h"
19ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner#include "clang/Basic/Diagnostic.h"
20ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner#include "clang/Basic/PrettyStackTrace.h"
21ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner#include "clang/Basic/SourceManager.h"
225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang;
235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// C99 6.8: Statements and Blocks.
265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       StatementOrDeclaration:
305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         statement
315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         declaration
325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       statement:
345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         labeled-statement
355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         compound-statement
365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         expression-statement
375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         selection-statement
385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         iteration-statement
395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         jump-statement
40dcdd55fb4d28de8c314d6c6c1a38aa6aba76d431Argyrios Kyrtzidis/// [C++]   declaration-statement
41a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// [C++]   try-block
42b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC]   objc-throw-statement
43b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC]   objc-try-catch-statement
44c385c90c68dfa376650e2facfbb444b2ec9bd110Fariborz Jahanian/// [OBC]   objc-synchronized-statement
455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   asm-statement
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   openmp-construct             [TODO]
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         identifier ':' statement
505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'case' constant-expression ':' statement
515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'default' ':' statement
525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       selection-statement:
545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         if-statement
555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         switch-statement
565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       iteration-statement:
585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         while-statement
595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         do-statement
605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         for-statement
615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       expression-statement:
635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         expression[opt] ';'
645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'goto' identifier ';'
675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'continue' ';'
685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'break' ';'
695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'return' expression[opt] ';'
705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   'goto' '*' expression ';'
715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
72b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC] objc-throw-statement:
73b384d329e0b727d4f2effa28fbb9aba2ac420e7bFariborz Jahanian/// [OBC]   '@' 'throw' expression ';'
741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// [OBC]   '@' 'throw' ';'
751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump///
7661364dddc33383e62cfe3b841dbc0f471280d95bSebastian RedlParser::OwningStmtResult
7761364dddc33383e62cfe3b841dbc0f471280d95bSebastian RedlParser::ParseStatementOrDeclaration(bool OnlyStatement) {
785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const char *SemiError = 0;
7915faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Res(Actions);
800e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
81bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  CXX0XAttributeList Attr;
82bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
83bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Attr = ParseCXX0XAttributes();
84bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt
855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Cases in this switch statement should fall through if the parser expects
865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // the token to end in a semicolon (in which case SemiError should be set),
875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // or they directly 'return;' if not.
88397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  tok::TokenKind Kind  = Tok.getKind();
89397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  SourceLocation AtLoc;
90397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  switch (Kind) {
91397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian  case tok::at: // May be a @try or @throw statement
92397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian    {
93397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian      AtLoc = ConsumeToken();  // consume @
9443bc2a0973ffe404fabba6f8280cd6bad2c69fcbSebastian Redl      return ParseObjCAtStatement(AtLoc);
95397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian    }
96397fcc117e5631db53879fbfcca66966088f3f07Fariborz Jahanian
97791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor  case tok::code_completion:
98791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor    Actions.CodeCompleteOrdinaryName(CurScope);
99791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor    ConsumeToken();
100791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor    return ParseStatementOrDeclaration(OnlyStatement);
101791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor
102b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis  case tok::identifier:
103b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis    if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
104b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis      // identifier ':' statement
105bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      return ParseLabeledStatement(Attr.AttrList);
106b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis    }
107b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis    // PASS THROUGH.
108b9f930d7bdb911be8420e044876221bf8a39f45fArgyrios Kyrtzidis
109f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner  default: {
1105404a156be26de1c63ca9916187f970848bb4dbbArgyrios Kyrtzidis    if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
11197144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner      SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
112bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd,
113bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt                                             Attr);
11497144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner      return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
115f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    }
116f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner
117f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    if (Tok.is(tok::r_brace)) {
1185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      Diag(Tok, diag::err_expected_statement);
11961364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl      return StmtError();
1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
1211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
122bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    // FIXME: Use the attributes
123f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    // expression[opt] ';'
124f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    OwningExprResult Expr(ParseExpression());
125f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    if (Expr.isInvalid()) {
126f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner      // If the expression is invalid, skip ahead to the next semicolon.  Not
127f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner      // doing this opens us up to the possibility of infinite loops if
128f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner      // ParseExpression does not consume any tokens.
129f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner      SkipUntil(tok::semi);
130f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner      return StmtError();
131f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    }
132f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    // Otherwise, eat the semicolon.
133f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner    ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
1346b1d283fe879fb11d7ce7a69feecf66e77b0eaf3Anders Carlsson    return Actions.ActOnExprStmt(Actions.FullExpr(Expr));
135f919bfe282b8a94d956290dc9812b456fa2b447eChris Lattner  }
13661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_case:                // C99 6.8.1: labeled-statement
138bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseCaseStatement(Attr.AttrList);
1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_default:             // C99 6.8.1: labeled-statement
140bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseDefaultStatement(Attr.AttrList);
14161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
1425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::l_brace:                // C99 6.8.2: compound-statement
143bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseCompoundStatement(Attr.AttrList);
1445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::semi:                   // C99 6.8.3p3: expression[opt] ';'
145a60528cdac7deee3991c2b48af4df4f315e49e9dSebastian Redl    return Actions.ActOnNullStmt(ConsumeToken());
14661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
1475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_if:                  // C99 6.8.4.1: if-statement
148bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseIfStatement(Attr.AttrList);
1495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_switch:              // C99 6.8.4.2: switch-statement
150bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseSwitchStatement(Attr.AttrList);
15161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_while:               // C99 6.8.5.1: while-statement
153bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseWhileStatement(Attr.AttrList);
1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_do:                  // C99 6.8.5.2: do-statement
155bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Res = ParseDoStatement(Attr.AttrList);
1566869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "do/while";
1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_for:                 // C99 6.8.5.3: for-statement
159bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseForStatement(Attr.AttrList);
1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_goto:                // C99 6.8.6.1: goto-statement
162bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Res = ParseGotoStatement(Attr.AttrList);
1636869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "goto";
1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_continue:            // C99 6.8.6.2: continue-statement
166bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Res = ParseContinueStatement(Attr.AttrList);
1676869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "continue";
1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_break:               // C99 6.8.6.3: break-statement
170bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Res = ParseBreakStatement(Attr.AttrList);
1716869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "break";
1725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  case tok::kw_return:              // C99 6.8.6.4: return-statement
174bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Res = ParseReturnStatement(Attr.AttrList);
1756869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "return";
1765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
17761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
178a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  case tok::kw_asm: {
179bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    if (Attr.HasAttr)
180bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
181bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt        << Attr.Range;
182d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    bool msAsm = false;
183d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    Res = ParseAsmStatement(msAsm);
18461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    if (msAsm) return move(Res);
1856869d8ea1bb7d191b5b290f5a55ee74f2174829aChris Lattner    SemiError = "asm";
1865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    break;
1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
18861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
189a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  case tok::kw_try:                 // C++ 15: try-block
190bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    return ParseCXXTryBlock(Attr.AttrList);
191a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  }
192a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // If we reached this code, the statement must end in a semicolon.
1944e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::semi)) {
1955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
1960e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  } else if (!Res.isInvalid()) {
1977b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner    // If the result was valid, then we do want to diagnose this.  Use
1987b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner    // ExpectAndConsume to emit the diagnostic, even though we know it won't
1997b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner    // succeed.
2007b3684afffa2d5eda3dd6930f01faaa673686c16Chris Lattner    ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
201195044028b76133e2a1f245b094468fe07db7330Chris Lattner    // Skip until we see a } or ;, but don't eat it.
202195044028b76133e2a1f245b094468fe07db7330Chris Lattner    SkipUntil(tok::r_brace, true, true);
2035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
2041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
20561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  return move(Res);
2065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
2075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
208f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis/// ParseLabeledStatement - We have an identifier and a ':' after it.
2095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
2105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
2115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         identifier ':' statement
2125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   identifier ':' attributes[opt] statement
2135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
214bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
2154e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
2165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer         "Not an identifier!");
2175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
218d217773f106856a11879ec79dc468efefaf2ee75Chris Lattner  Token IdentTok = Tok;  // Save the whole token.
2195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ConsumeToken();  // eat the identifier.
220f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis
221f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  assert(Tok.is(tok::colon) && "Not a label!");
22261364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
2235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // identifier ':' statement
224f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  SourceLocation ColonLoc = ConsumeToken();
2255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
226f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  // Read label attributes, if present.
227f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  if (Tok.is(tok::kw___attribute))
228bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Attr = addAttributeLists(Attr, ParseGNUAttributes());
2295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
23061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult SubStmt(ParseStatement());
2310e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
232f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis  // Broken substmt shouldn't prevent the label from being added to the AST.
2330e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (SubStmt.isInvalid())
234f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis    SubStmt = Actions.ActOnNullStmt(ColonLoc);
2350e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
236de307473448fb3cebcb4c10090728300b53bca03Sebastian Redl  return Actions.ActOnLabelStmt(IdentTok.getLocation(),
237de307473448fb3cebcb4c10090728300b53bca03Sebastian Redl                                IdentTok.getIdentifierInfo(),
23876ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl                                ColonLoc, move(SubStmt));
239f7da726f09a6b7c5b9f5308e9690cb015398e671Argyrios Kyrtzidis}
2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCaseStatement
2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'case' constant-expression ':' statement
2445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   'case' constant-expression '...' constant-expression ':' statement
2455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
246bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
2474e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_case) && "Not a case stmt!");
248bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
2491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
25024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // It is very very common for code to contain many case statements recursively
25124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // nested, as in (but usually without indentation):
25224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //  case 1:
25324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //    case 2:
25424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //      case 3:
25524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //         case 4:
25624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //           case 5: etc.
25724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  //
25824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // Parsing this naively works, but is both inefficient and can cause us to run
25924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // out of stack space in our recursive descent parser.  As a special case,
26026140c6399d4b14a224d44cf0102a1919d8dab04Chris Lattner  // flatten this recursion into an iterative loop.  This is complex and gross,
26124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // but all the grossness is constrained to ParseCaseStatement (and some
26224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // wierdness in the actions), so this is just local grossness :).
2631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
26424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // TopLevelCase - This is the highest level we have parsed.  'case 1' in the
26524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // example above.
26624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  OwningStmtResult TopLevelCase(Actions, true);
2671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
26824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
26924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // gets updated each time a new case is parsed, and whose body is unset so
27024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // far.  When parsing 'case 4', this is the 'case 3' node.
27124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  StmtTy *DeepestParsedCaseStmt = 0;
2721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
27324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // While we have case statements, eat and stack them.
27424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  do {
27524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SourceLocation CaseLoc = ConsumeToken();  // eat the 'case'.
2761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
2773e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor    if (Tok.is(tok::code_completion)) {
2783e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor      Actions.CodeCompleteCase(CurScope);
2793e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor      ConsumeToken();
2803e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor    }
2813e1005f085006dfb3545f0c54ac5e22483137c7dDouglas Gregor
28224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    OwningExprResult LHS(ParseConstantExpression());
28324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    if (LHS.isInvalid()) {
28424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      SkipUntil(tok::colon);
28524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      return StmtError();
28624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    }
2875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
28824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // GNU case range extension.
28924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SourceLocation DotDotDotLoc;
29024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    OwningExprResult RHS(Actions);
29124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    if (Tok.is(tok::ellipsis)) {
29224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      Diag(Tok, diag::ext_gnu_case_range);
29324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      DotDotDotLoc = ConsumeToken();
2940e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
29524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      RHS = ParseConstantExpression();
29624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      if (RHS.isInvalid()) {
29724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner        SkipUntil(tok::colon);
29824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner        return StmtError();
29924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      }
30024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    }
3010e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
30224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    if (Tok.isNot(tok::colon)) {
30324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      Diag(Tok, diag::err_expected_colon_after) << "'case'";
3045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::colon);
30561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl      return StmtError();
3065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
3070e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
30824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SourceLocation ColonLoc = ConsumeToken();
3091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
31024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    OwningStmtResult Case =
31124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      Actions.ActOnCaseStmt(CaseLoc, move(LHS), DotDotDotLoc,
31224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner                            move(RHS), ColonLoc);
3131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
31424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // If we had a sema error parsing this case, then just ignore it and
31524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // continue parsing the sub-stmt.
31624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    if (Case.isInvalid()) {
31724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      if (TopLevelCase.isInvalid())  // No parsed case stmts.
31824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner        return ParseStatement();
31924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      // Otherwise, just don't add it as a nested case.
32024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    } else {
32124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      // If this is the first case statement we parsed, it becomes TopLevelCase.
32224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      // Otherwise we link it into the current chain.
32324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      StmtTy *NextDeepest = Case.get();
32424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      if (TopLevelCase.isInvalid())
32524e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner        TopLevelCase = move(Case);
32624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      else
32724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner        Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(Case));
32824e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner      DeepestParsedCaseStmt = NextDeepest;
32924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    }
3301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // Handle all case statements.
33224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  } while (Tok.is(tok::kw_case));
3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!");
3351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // If we found a non-case statement, start by parsing it.
33724e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  OwningStmtResult SubStmt(Actions);
3381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
33924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  if (Tok.isNot(tok::r_brace)) {
34024e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SubStmt = ParseStatement();
34124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  } else {
34224e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // Nicely diagnose the common error "switch (X) { case 4: }", which is
34324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // not valid.
34424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    // FIXME: add insertion hint.
3455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::err_label_end_of_compound_statement);
34624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SubStmt = true;
3475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
3481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
34924e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // Broken sub-stmt shouldn't prevent forming the case statement properly.
3500e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (SubStmt.isInvalid())
35124e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner    SubStmt = Actions.ActOnNullStmt(SourceLocation());
3521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
35324e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // Install the body into the most deeply-nested case.
35424e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(SubStmt));
35561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
35624e1e707b4c362f18e371e2bbf054a8345b57bfaChris Lattner  // Return the top level parsed statement tree.
35726140c6399d4b14a224d44cf0102a1919d8dab04Chris Lattner  return move(TopLevelCase);
3585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
3595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseDefaultStatement
3615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       labeled-statement:
3625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'default' ':' statement
3635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note that this does not parse the 'statement' at the end.
3645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
365bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
366bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  //FIXME: Use attributes?
3674e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_default) && "Not a default stmt!");
3685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
3695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3704e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::colon)) {
3711ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_colon_after) << "'default'";
3725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::colon);
37361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
3745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
37561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
3765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ColonLoc = ConsumeToken();
37761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
3785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Diagnose the common error "switch (X) {... default: }", which is not valid.
3794e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::r_brace)) {
3805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::err_label_end_of_compound_statement);
38161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
3825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
3835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
38461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult SubStmt(ParseStatement());
3850e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (SubStmt.isInvalid())
38661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
38761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
388117054a99f4994e4ec8a1fc904b554e1f2dc9b29Sebastian Redl  return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
38976ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl                                  move(SubStmt), CurScope);
3905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
3915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
3935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCompoundStatement - Parse a "{}" block.
3945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
3955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       compound-statement: [C99 6.8.2]
3965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         { block-item-list[opt] }
3975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   { label-declarations block-item-list } [TODO]
3985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
3995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       block-item-list:
4005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         block-item
4015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         block-item-list block-item
4025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       block-item:
4045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         declaration
40545a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner/// [GNU]   '__extension__' declaration
4065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         statement
4075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   openmp-directive            [TODO]
4085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] label-declarations:
4105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   label-declaration
4115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   label-declarations label-declaration
4125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] label-declaration:
4145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   '__label__' identifier-list ';'
4155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
4165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP] openmp-directive:             [TODO]
4175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   barrier-directive
4185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [OMP]   flush-directive
4195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
420bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
421bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt                                                        bool isStmtExpr) {
422bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  //FIXME: Use attributes?
4234e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
42461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
42531e057270232c1c37602579cb6461c2704175672Chris Lattner  // Enter a scope to hold everything within the compound stmt.  Compound
42631e057270232c1c37602579cb6461c2704175672Chris Lattner  // statements can always hold declarations.
4278935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope CompoundScope(this, Scope::DeclScope);
4285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the statements in the body.
43061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  return ParseCompoundStatementBody(isStmtExpr);
4315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
4325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
4351b273c403734d343d720acb28f04011807c8aa56Steve Naroff/// ActOnCompoundStmt action.  This expects the '{' to be the current token, and
4365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// consume the '}' at the end of the block.  It does not manipulate the scope
4375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// stack.
43861364dddc33383e62cfe3b841dbc0f471280d95bSebastian RedlParser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
4391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
440ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner                                Tok.getLocation(),
441ae50fa0a9e7217b043ed4ffe175af4b26dc90f34Chris Lattner                                "in compound statement ('{}')");
4421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
4435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation LBraceLoc = ConsumeBrace();  // eat the '{'.
4445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension.  These are
44645a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner  // only allowed at the start of a compound stmt regardless of the language.
447a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl
448a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  typedef StmtVector StmtsTy;
449a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  StmtsTy Stmts(Actions);
4504e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
45115faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl    OwningStmtResult R(Actions);
4524e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.isNot(tok::kw___extension__)) {
45345a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      R = ParseStatementOrDeclaration(false);
45445a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner    } else {
45545a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // __extension__ can start declarations and it can also be a unary
45645a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // operator for expressions.  Consume multiple __extension__ markers here
45745a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // until we can determine which is which.
458adf077f46ba5cddcd801a647a5e9a3eb97060df4Eli Friedman      // FIXME: This loses extension expressions in the AST!
45945a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      SourceLocation ExtLoc = ConsumeToken();
4604e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner      while (Tok.is(tok::kw___extension__))
46145a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        ConsumeToken();
46239146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner
463bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      CXX0XAttributeList Attr;
464bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
465bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt        Attr = ParseCXX0XAttributes();
466bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt
46745a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      // If this is the start of a declaration, parse it as such.
4685404a156be26de1c63ca9916187f970848bb4dbbArgyrios Kyrtzidis      if (isDeclarationStatement()) {
469bc6c848f3e0ec2dc44f6e3d59ef85e884cc9b7beEli Friedman        // __extension__ silences extension warnings in the subdeclaration.
47097144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner        // FIXME: Save the __extension__ on the decl as a node somehow?
471bc6c848f3e0ec2dc44f6e3d59ef85e884cc9b7beEli Friedman        ExtensionRAIIObject O(Diags);
472bc6c848f3e0ec2dc44f6e3d59ef85e884cc9b7beEli Friedman
47397144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner        SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
474bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt        DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
475bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt                                              Attr);
47697144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner        R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
47745a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      } else {
478adf077f46ba5cddcd801a647a5e9a3eb97060df4Eli Friedman        // Otherwise this was a unary __extension__ marker.
479adf077f46ba5cddcd801a647a5e9a3eb97060df4Eli Friedman        OwningExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
480043a0b50a2a7a29c78a1ffb774f6fca8baf464a0Chris Lattner
4810e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl        if (Res.isInvalid()) {
48245a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner          SkipUntil(tok::semi);
48345a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner          continue;
48445a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        }
485f512e82f56671b695a32d019103e62a302838b7eSebastian Redl
486bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt        // FIXME: Use attributes?
48739146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner        // Eat the semicolon at the end of stmt and convert the expr into a
48839146d6497ad5e7ca8ef639221e7b3e15d07c888Chris Lattner        // statement.
48945a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner        ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
4906b1d283fe879fb11d7ce7a69feecf66e77b0eaf3Anders Carlsson        R = Actions.ActOnExprStmt(Actions.FullExpr(Res));
49145a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner      }
49245a566cfcbec0efd50bc737991bdfcc70e986811Chris Lattner    }
49361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
4940e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (R.isUsable())
495effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl      Stmts.push_back(R.release());
4965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
49761364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
4985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // We broke out of the while loop because we found a '}' or EOF.
4994e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::r_brace)) {
5005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::err_expected_rbrace);
50161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
5025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
50361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
5045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation RBraceLoc = ConsumeBrace();
505f512e82f56671b695a32d019103e62a302838b7eSebastian Redl  return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc, move_arg(Stmts),
506a60528cdac7deee3991c2b48af4df4f315e49e9dSebastian Redl                                   isStmtExpr);
5075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
5085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
50915ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// ParseParenExprOrCondition:
51015ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// [C  ]     '(' expression ')'
511ff871fb8f9c5906a4dee78afd81f60c3837e16cbChris Lattner/// [C++]     '(' condition ')'       [not allowed if OnlyAllowCondition=true]
51215ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner///
51315ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// This function parses and performs error recovery on the specified condition
51415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// or expression (depending on whether we're in C++ or C mode).  This function
51515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// goes out of its way to recover well.  It returns true if there was a parser
51615ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// error (the right paren couldn't be found), which indicates that the caller
51715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// should try to recover harder.  It returns false if the condition is
51815ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// successfully parsed.  Note that a successful parse can still have semantic
51915ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner/// errors in the condition.
52099e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregorbool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult,
52199e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor                                       DeclPtrTy &DeclResult) {
52299e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  bool ParseError = false;
52399e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor
52415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  SourceLocation LParenLoc = ConsumeParen();
52599e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (getLang().CPlusPlus)
52699e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor    ParseError = ParseCXXCondition(ExprResult, DeclResult);
52799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  else {
52899e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor    ExprResult = ParseExpression();
52999e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor    DeclResult = DeclPtrTy();
53099e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  }
5311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
53215ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  // If the parser was confused by the condition and we don't have a ')', try to
53315ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  // recover by skipping ahead to a semi and bailing out.  If condexp is
53415ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  // semantically invalid but we have well formed code, keep going.
53599e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (ExprResult.isInvalid() && !DeclResult.get() && Tok.isNot(tok::r_paren)) {
53615ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    SkipUntil(tok::semi);
53715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    // Skipping may have stopped if it found the containing ')'.  If so, we can
53815ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    // continue parsing the if statement.
53915ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    if (Tok.isNot(tok::r_paren))
54015ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner      return true;
54115ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  }
5421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
54315ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  // Otherwise the condition is valid or the rparen is present.
54499e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  MatchRHSPunctuation(tok::r_paren, LParenLoc);
54515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  return false;
54615ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner}
54715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner
54815ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner
5495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseIfStatement
5505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       if-statement: [C99 6.8.4.1]
5515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'if' '(' expression ')' statement
5525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'if' '(' expression ')' statement 'else' statement
55371b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'if' '(' condition ')' statement
55471b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'if' '(' condition ')' statement 'else' statement
5555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
556bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
557bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
5584e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_if) && "Not an if stmt!");
5595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
5605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
5614e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
5621ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "if";
5635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
56461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
5655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
56671b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis
567488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
568488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
5692215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.4p3 - In C99, the if statement is a block.  This is not
5702215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.
571488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
572488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
573488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
574488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
575488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
57614d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
57714d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
57814d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
57914d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
580488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
5818935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
5822215325a5696fb3b23551239b900559bb3018ee9Chris Lattner
5835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the condition.
58415faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult CondExp(Actions);
58599e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  DeclPtrTy CondVar;
58699e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (ParseParenExprOrCondition(CondExp, CondVar))
58715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    return StmtError();
58818914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner
589c4ee170b0c71f61fb1dec273d15fb11c29449a88Anders Carlsson  FullExprArg FullCondExp(Actions.FullExpr(CondExp));
5901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
5910ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
59238484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
59338484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
594488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
595488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p1:
596488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in a selection-statement (each substatement, in the else
597488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // form of the if statement) implicitly defines a local scope.
598488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
599488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // For C++ we create a scope for the condition and a new scope for
600488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // substatements because:
601488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // -When the 'then' scope exits, we want the condition declaration to still be
602488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    active for the 'else' scope too.
603488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // -Sema will detect name clashes by considering declarations of a
604488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    'ControlScope' as part of its direct subscope.
605488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // -If we wanted the condition and substatement to be in the same scope, we
606488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    would have to notify ParseStatement not to create a new scope. It's
607488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //    simpler to let it create a new scope.
608488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
6091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParseScope InnerScope(this, Scope::DeclScope,
6108935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                        C99orCXX && Tok.isNot(tok::l_brace));
61171b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis
612b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // Read the 'then' stmt.
613b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  SourceLocation ThenStmtLoc = Tok.getLocation();
61461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult ThenStmt(ParseStatement());
6155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
616a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner  // Pop the 'if' scope if needed.
6178935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  InnerScope.Exit();
61861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
6195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // If it has an else, parse it.
6205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ElseLoc;
621b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  SourceLocation ElseStmtLoc;
62215faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult ElseStmt(Actions);
6230e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
6244e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::kw_else)) {
6255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ElseLoc = ConsumeToken();
62661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
6270ecea03077117c7ea54c88091a44c73cef67923cChris Lattner    // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
62838484403c8356fb41540ace6c74f28867f28febaChris Lattner    // there is no compound stmt.  C90 does not have this clause.  We only do
62938484403c8356fb41540ace6c74f28867f28febaChris Lattner    // this if the body isn't a compound statement to avoid push/pop in common
63038484403c8356fb41540ace6c74f28867f28febaChris Lattner    // cases.
631488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    //
632488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    // C++ 6.4p1:
633488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    // The substatement in a selection-statement (each substatement, in the else
634488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    // form of the if statement) implicitly defines a local scope.
635488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis    //
63661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    ParseScope InnerScope(this, Scope::DeclScope,
6378935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                          C99orCXX && Tok.isNot(tok::l_brace));
6380e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
639caaf29a08761b14fbe42a29080c22dd6961056d1Douglas Gregor    bool WithinElse = CurScope->isWithinElse();
640caaf29a08761b14fbe42a29080c22dd6961056d1Douglas Gregor    CurScope->setWithinElse(true);
641b96728d90abc35a520798066d2a75ca36400a617Chris Lattner    ElseStmtLoc = Tok.getLocation();
6425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ElseStmt = ParseStatement();
643caaf29a08761b14fbe42a29080c22dd6961056d1Douglas Gregor    CurScope->setWithinElse(WithinElse);
644a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner
645a36ce713cff561b88f1cba5aad3f384c0fb0a249Chris Lattner    // Pop the 'else' scope if needed.
6468935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    InnerScope.Exit();
6475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
64861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
6498935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  IfScope.Exit();
6501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
65118914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner  // If the condition was invalid, discard the if statement.  We could recover
65218914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner  // better by replacing it with a valid expr, but don't do that yet.
65399e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (CondExp.isInvalid() && !CondVar.get())
65418914bcb22774137ba720e5fcb377150bf2f6de3Chris Lattner    return StmtError();
6552215325a5696fb3b23551239b900559bb3018ee9Chris Lattner
656b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // If the then or else stmt is invalid and the other is valid (and present),
6571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // make turn the invalid one into a null stmt to avoid dropping the other
658b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // part.  If both are invalid, return error.
6590e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
6600e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      (ThenStmt.isInvalid() && ElseStmt.get() == 0) ||
6610e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      (ThenStmt.get() == 0  && ElseStmt.isInvalid())) {
662a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl    // Both invalid, or one is invalid and other is non-present: return error.
66361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl    return StmtError();
664b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  }
6650e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
666b96728d90abc35a520798066d2a75ca36400a617Chris Lattner  // Now if either are invalid, replace with a ';'.
6670e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (ThenStmt.isInvalid())
668b96728d90abc35a520798066d2a75ca36400a617Chris Lattner    ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
6690e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (ElseStmt.isInvalid())
670b96728d90abc35a520798066d2a75ca36400a617Chris Lattner    ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
6710e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
67299e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, move(ThenStmt),
67376ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl                             ElseLoc, move(ElseStmt));
6745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
6755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseSwitchStatement
6775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       switch-statement:
6785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'switch' '(' expression ')' statement
67971b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'switch' '(' condition ')' statement
680bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
681bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
6824e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
6835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
6845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6854e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
6861ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "switch";
6875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
6889a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
6895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
6902215325a5696fb3b23551239b900559bb3018ee9Chris Lattner
691488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
692488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
6932215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.4p3 - In C99, the switch statement is a block.  This is
6942215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // not the case for C90.  Start the switch scope.
695488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
696488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
697488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
698488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
699488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
70014d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
70114d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
70214d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
70314d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
704488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
70515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  unsigned ScopeFlags = Scope::BreakScope;
70615ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner  if (C99orCXX)
70715ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
7088935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope SwitchScope(this, ScopeFlags);
7095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the condition.
71115faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult Cond(Actions);
71299e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  DeclPtrTy CondVar;
71399e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (ParseParenExprOrCondition(Cond, CondVar))
7149a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
7152342ef75797a2ad6c9d7a784cfff220fd1a66008Eli Friedman
71699e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  FullExprArg FullCond(Actions.FullExpr(Cond));
71799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor
718be724bab2ba7ad47aebced25e7c8ec551eb72d28Douglas Gregor  OwningStmtResult Switch = Actions.ActOnStartOfSwitchStmt(FullCond, CondVar);
7190e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
7200ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
72138484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
72238484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
723488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
724488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p1:
725488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in a selection-statement (each substatement, in the else
726488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // form of the if statement) implicitly defines a local scope.
727488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
728488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // See comments in ParseIfStatement for why we create a scope for the
729488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition and a new scope for substatement in C++.
730488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
7311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParseScope InnerScope(this, Scope::DeclScope,
7328935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                        C99orCXX && Tok.isNot(tok::l_brace));
73361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
7345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
73561364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult Body(ParseStatement());
7365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7370ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
7388935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  InnerScope.Exit();
7399a920342707e384473b464528d2fd286e8c70353Sebastian Redl
7400e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (Body.isInvalid()) {
7411b273c403734d343d720acb28f04011807c8aa56Steve Naroff    Body = Actions.ActOnNullStmt(Tok.getLocation());
742c1fcb7762673be706b0a40477d5e93411e918f93Anders Carlsson    // FIXME: Remove the case statement list from the Switch statement.
743c1fcb7762673be706b0a40477d5e93411e918f93Anders Carlsson  }
7448935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor
7458935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  SwitchScope.Exit();
74661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
74799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (Cond.isInvalid() && !CondVar.get())
74815ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    return StmtError();
749de307473448fb3cebcb4c10090728300b53bca03Sebastian Redl
75076ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl  return Actions.ActOnFinishSwitchStmt(SwitchLoc, move(Switch), move(Body));
7515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
7525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseWhileStatement
7545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       while-statement: [C99 6.8.5.1]
7555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'while' '(' expression ')' statement
75671b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'while' '(' condition ')' statement
757bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
758bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
7594e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_while) && "Not a while stmt!");
7605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation WhileLoc = Tok.getLocation();
7615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ConsumeToken();  // eat the 'while'.
7629a920342707e384473b464528d2fd286e8c70353Sebastian Redl
7634e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
7641ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "while";
7655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
7669a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
7675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
7689a920342707e384473b464528d2fd286e8c70353Sebastian Redl
769488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
770488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
7712215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.5p5 - In C99, the while statement is a block.  This is not
7722215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.  Start the loop scope.
773488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
774488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
775488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
776488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
777488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
77814d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
77914d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
78014d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
78114d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
782488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
7838935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  unsigned ScopeFlags;
784488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  if (C99orCXX)
7858935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
7868935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                 Scope::DeclScope  | Scope::ControlScope;
7872215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  else
7888935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
7898935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope WhileScope(this, ScopeFlags);
7905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
7915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the condition.
79215faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult Cond(Actions);
79399e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  DeclPtrTy CondVar;
79499e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if (ParseParenExprOrCondition(Cond, CondVar))
79515ff1110c96a26c9315142d407c1f29d86a5ad1fChris Lattner    return StmtError();
7960e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
797c4ee170b0c71f61fb1dec273d15fb11c29449a88Anders Carlsson  FullExprArg FullCond(Actions.FullExpr(Cond));
7981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
7990ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
80038484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
80138484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
802488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
803488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.5p2:
804488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in an iteration-statement implicitly defines a local scope
805488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // which is entered and exited each time through the loop.
806488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
807488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // See comments in ParseIfStatement for why we create a scope for the
808488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition and a new scope for substatement in C++.
809488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
8101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParseScope InnerScope(this, Scope::DeclScope,
8118935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                        C99orCXX && Tok.isNot(tok::l_brace));
8129a920342707e384473b464528d2fd286e8c70353Sebastian Redl
8135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
81461364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult Body(ParseStatement());
8155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8160ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
8178935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  InnerScope.Exit();
8188935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  WhileScope.Exit();
8199a920342707e384473b464528d2fd286e8c70353Sebastian Redl
82099e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  if ((Cond.isInvalid() && !CondVar.get()) || Body.isInvalid())
8219a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
8229a920342707e384473b464528d2fd286e8c70353Sebastian Redl
82399e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, move(Body));
8245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
8255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseDoStatement
8275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       do-statement: [C99 6.8.5.2]
8285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'do' statement 'while' '(' expression ')' ';'
8295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
830bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
831bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
8324e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_do) && "Not a do stmt!");
8335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
8349a920342707e384473b464528d2fd286e8c70353Sebastian Redl
8352215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.5p5 - In C99, the do statement is a block.  This is not
8362215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.  Start the loop scope.
8378935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  unsigned ScopeFlags;
8382215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  if (getLang().C99)
8398935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
8402215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  else
8418935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
8429a920342707e384473b464528d2fd286e8c70353Sebastian Redl
8438935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope DoScope(this, ScopeFlags);
8445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8450ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
84638484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause. We only do this
84738484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
848143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  //
849143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  // C++ 6.5p2:
850143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  // The substatement in an iteration-statement implicitly defines a local scope
851143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  // which is entered and exited each time through the loop.
852143db71d8d87bc015fb496f71ef83b268813835aArgyrios Kyrtzidis  //
8538935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope InnerScope(this, Scope::DeclScope,
8541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                        (getLang().C99 || getLang().CPlusPlus) &&
8558935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                        Tok.isNot(tok::l_brace));
8569a920342707e384473b464528d2fd286e8c70353Sebastian Redl
8575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
85861364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult Body(ParseStatement());
8595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8600ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
8618935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  InnerScope.Exit();
8620ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
8634e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::kw_while)) {
8640e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (!Body.isInvalid()) {
865195044028b76133e2a1f245b094468fe07db7330Chris Lattner      Diag(Tok, diag::err_expected_while);
86628eb7e992b9a266abb300da25b6d3c1557cec361Chris Lattner      Diag(DoLoc, diag::note_matching) << "do";
867195044028b76133e2a1f245b094468fe07db7330Chris Lattner      SkipUntil(tok::semi, false, true);
868195044028b76133e2a1f245b094468fe07db7330Chris Lattner    }
8699a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
8705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
8715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation WhileLoc = ConsumeToken();
8729a920342707e384473b464528d2fd286e8c70353Sebastian Redl
8734e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
8741ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "do/while";
875195044028b76133e2a1f245b094468fe07db7330Chris Lattner    SkipUntil(tok::semi, false, true);
8769a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
8775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
8789a920342707e384473b464528d2fd286e8c70353Sebastian Redl
879ff871fb8f9c5906a4dee78afd81f60c3837e16cbChris Lattner  // Parse the parenthesized condition.
88004895d301e1107a8f03673c43c939a115c3c1195Douglas Gregor  SourceLocation LPLoc = ConsumeParen();
88104895d301e1107a8f03673c43c939a115c3c1195Douglas Gregor  OwningExprResult Cond = ParseExpression();
88204895d301e1107a8f03673c43c939a115c3c1195Douglas Gregor  SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc);
8838935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  DoScope.Exit();
8840e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
8859a920342707e384473b464528d2fd286e8c70353Sebastian Redl  if (Cond.isInvalid() || Body.isInvalid())
8869a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
8870e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
888989135901c750af61ef012b6b0a0368be415bc46Chris Lattner  return Actions.ActOnDoStmt(DoLoc, move(Body), WhileLoc, LPLoc,
889989135901c750af61ef012b6b0a0368be415bc46Chris Lattner                             move(Cond), RPLoc);
8905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
8915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
8925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseForStatement
8935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       for-statement: [C99 6.8.5.3]
8945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
8955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
89671b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
89771b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]       statement
8983ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian/// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
8993ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian/// [OBJC2] 'for' '(' expr 'in' expr ')' statement
90071b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis///
90171b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++] for-init-statement:
90271b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   expression-statement
90371b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis/// [C++]   simple-declaration
90471b914b999d9c4b6df11068fc5a3291ac4770492Argyrios Kyrtzidis///
905bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
906bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
9074e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_for) && "Not a for stmt!");
9085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
9099a920342707e384473b464528d2fd286e8c70353Sebastian Redl
9104e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
9111ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "for";
9125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::semi);
9139a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
9145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
9159a920342707e384473b464528d2fd286e8c70353Sebastian Redl
9164d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner  bool C99orCXXorObjC = getLang().C99 || getLang().CPlusPlus || getLang().ObjC1;
917488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis
9182215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // C99 6.8.5p5 - In C99, the for statement is a block.  This is not
9192215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  // the case for C90.  Start the loop scope.
920488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
921488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.4p3:
922488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // A name introduced by a declaration in a condition is in scope from its
923488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // point of declaration until the end of the substatements controlled by the
924488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // condition.
92514d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // C++ 3.3.2p4:
92614d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // Names declared in the for-init-statement, and in the condition of if,
92714d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // while, for, and switch statements are local to the if, while, for, or
92814d08c0c776302e2df12239d276072f43c894f0eArgyrios Kyrtzidis  // switch statement (including the controlled statement).
929488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.5.3p1:
930488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // Names declared in the for-init-statement are in the same declarative-region
931488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // as those declared in the condition.
932488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
9338935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  unsigned ScopeFlags;
9344d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner  if (C99orCXXorObjC)
9358935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
9368935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor                 Scope::DeclScope  | Scope::ControlScope;
9372215325a5696fb3b23551239b900559bb3018ee9Chris Lattner  else
9388935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor    ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
9398935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor
9408935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ParseScope ForScope(this, ScopeFlags);
9415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
9425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation LParenLoc = ConsumeParen();
94315faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult Value(Actions);
9440e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
945bdd15f701fe98f77b1b8ddb3f4a5c0d83bb8fa9cFariborz Jahanian  bool ForEach = false;
946f05b1520d6f175acbfc3913489f4dfa842875ec4Sebastian Redl  OwningStmtResult FirstPart(Actions);
947f05b1520d6f175acbfc3913489f4dfa842875ec4Sebastian Redl  OwningExprResult SecondPart(Actions), ThirdPart(Actions);
94899e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor  DeclPtrTy SecondVar;
94999e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor
950791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor  if (Tok.is(tok::code_completion)) {
951791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor    Actions.CodeCompleteOrdinaryName(CurScope);
952791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor    ConsumeToken();
953791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor  }
954791215b7a24666912c0b71175d2ca5ba082f666eDouglas Gregor
9555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Parse the first part of the for specifier.
9564e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::semi)) {  // for (;
9575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // no first part, eat the ';'.
9585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
959bbc70c019f7b7f9a256ee29dab5287ecc82c6553Argyrios Kyrtzidis  } else if (isSimpleDeclaration()) {  // for (int X = 4;
9605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Parse declaration, which eats the ';'.
9614d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner    if (!C99orCXXorObjC)   // Use of C99-style for loops in C90 mode?
9625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
9639a920342707e384473b464528d2fd286e8c70353Sebastian Redl
964bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    AttributeList *AttrList = 0;
965bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
966bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      AttrList = ParseCXX0XAttributes().AttrList;
967bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt
96897144fc41a9419bf6d74fc9450e8ef3f6e11f7e0Chris Lattner    SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
969bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
970bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt                                               AttrList);
971cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner    FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
9721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
973cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner    if (Tok.is(tok::semi)) {  // for (int x = 4;
974cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner      ConsumeToken();
975cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner    } else if ((ForEach = isTokIdentifier_in())) {
976a7cf23a72b0846fc5aacf3f38bb8c8f9e76784cfFariborz Jahanian      Actions.ActOnForEachDeclStmt(DG);
9771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      // ObjC: for (id x in expr)
9783ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      ConsumeToken(); // consume 'in'
9790e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      SecondPart = ParseExpression();
980cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner    } else {
981cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner      Diag(Tok, diag::err_expected_semi_for);
982cd1477562e7cf03279850885583d615e1f631dd4Chris Lattner      SkipUntil(tok::semi);
9833ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
9845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  } else {
9855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Value = ParseExpression();
9865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
9875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Turn the expression into a stmt.
9880e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (!Value.isInvalid())
9896b1d283fe879fb11d7ce7a69feecf66e77b0eaf3Anders Carlsson      FirstPart = Actions.ActOnExprStmt(Actions.FullExpr(Value));
990effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
9914e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.is(tok::semi)) {
9925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      ConsumeToken();
993682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner    } else if ((ForEach = isTokIdentifier_in())) {
9943ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      ConsumeToken(); // consume 'in'
9950e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      SecondPart = ParseExpression();
996682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner    } else {
9970e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl      if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
9985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::semi);
9995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
10005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1001bdd15f701fe98f77b1b8ddb3f4a5c0d83bb8fa9cFariborz Jahanian  if (!ForEach) {
10020e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
10033ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    // Parse the second part of the for specifier.
10043ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    if (Tok.is(tok::semi)) {  // for (...;;
10053ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      // no second part.
10063ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    } else {
100799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor      if (getLang().CPlusPlus)
100899e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor        ParseCXXCondition(SecondPart, SecondVar);
100999e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor      else
101099e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor        SecondPart = ParseExpression();
10113ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
10120e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10133ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    if (Tok.is(tok::semi)) {
10143ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      ConsumeToken();
10153ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    } else {
101699e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor      if (!SecondPart.isInvalid() || SecondVar.get())
101799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor        Diag(Tok, diag::err_expected_semi_for);
10183ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian      SkipUntil(tok::semi);
10193ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    }
10209a920342707e384473b464528d2fd286e8c70353Sebastian Redl
10213ba5a0f90a03d5e13d02cbee9abd2a1ba01b18bcFariborz Jahanian    // Parse the third part of the for specifier.
10224dca69b3f8180bdfa0287399c89e0594080bae66Chris Lattner    if (Tok.isNot(tok::r_paren))    // for (...;...;)
1023f05b1520d6f175acbfc3913489f4dfa842875ec4Sebastian Redl      ThirdPart = ParseExpression();
10245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
10255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Match the ')'.
10265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
10270e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10280ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
102938484403c8356fb41540ace6c74f28867f28febaChris Lattner  // there is no compound stmt.  C90 does not have this clause.  We only do this
103038484403c8356fb41540ace6c74f28867f28febaChris Lattner  // if the body isn't a compound statement to avoid push/pop in common cases.
1031488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
1032488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // C++ 6.5p2:
1033488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // The substatement in an iteration-statement implicitly defines a local scope
1034488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // which is entered and exited each time through the loop.
1035488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
1036488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // See comments in ParseIfStatement for why we create a scope for
1037488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  // for-init-statement/condition and a new scope for substatement in C++.
1038488d37e8c0bffe5c11e8fe508e43e445e83bfbddArgyrios Kyrtzidis  //
10391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ParseScope InnerScope(this, Scope::DeclScope,
10404d00f2a5a9b670cd0d67d640a42dbf7b9f342c59Chris Lattner                        C99orCXXorObjC && Tok.isNot(tok::l_brace));
10410e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Read the body statement.
104361364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult Body(ParseStatement());
10440e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10450ecea03077117c7ea54c88091a44c73cef67923cChris Lattner  // Pop the body scope if needed.
10468935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  InnerScope.Exit();
10470ecea03077117c7ea54c88091a44c73cef67923cChris Lattner
10485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Leave the for-scope.
10498935b8b49053122ddd3ab4cd59af0fe5eb9c23cfDouglas Gregor  ForScope.Exit();
10500e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10510e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (Body.isInvalid())
10529a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
1053effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
1054effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl  if (!ForEach)
105576ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl    return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart),
105699e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor                                Actions.FullExpr(SecondPart), SecondVar,
105799e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor                                Actions.FullExpr(ThirdPart), RParenLoc,
105899e9b4d172f6877e6ba5ebe75bb8238721f5e01cDouglas Gregor                                move(Body));
10591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1060682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner  return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
1061682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner                                            move(FirstPart),
1062682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner                                            move(SecondPart),
1063682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner                                            RParenLoc, move(Body));
10645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
10655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
10665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseGotoStatement
10675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
10685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'goto' identifier ';'
10695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU]   'goto' '*' expression ';'
10705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
10715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
10725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
1073bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
1074bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
10754e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
10765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
10779a920342707e384473b464528d2fd286e8c70353Sebastian Redl
107815faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningStmtResult Res(Actions);
10794e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.is(tok::identifier)) {
10801b273c403734d343d720acb28f04011807c8aa56Steve Naroff    Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
10815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer                                Tok.getIdentifierInfo());
10825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
1083f01fdff97b245caac98100d232c760b4d0531411Eli Friedman  } else if (Tok.is(tok::star)) {
10845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // GNU indirect goto extension.
10855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    Diag(Tok, diag::ext_gnu_indirect_goto);
10865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SourceLocation StarLoc = ConsumeToken();
10872f7ece7c77eb17e24e8f0f4e1b7fb01aa5111f96Sebastian Redl    OwningExprResult R(ParseExpression());
10880e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
10895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::semi, false, true);
10909a920342707e384473b464528d2fd286e8c70353Sebastian Redl      return StmtError();
10915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
109276ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl    Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, move(R));
109395cfb85ad1820117e0864712555f3aa4fdf4721aChris Lattner  } else {
109495cfb85ad1820117e0864712555f3aa4fdf4721aChris Lattner    Diag(Tok, diag::err_expected_ident);
10959a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
10965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
10970e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
10989a920342707e384473b464528d2fd286e8c70353Sebastian Redl  return move(Res);
10995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
11005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseContinueStatement
11025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
11035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'continue' ';'
11045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
11065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
1107bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
1108bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
11095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
11104cffe2fd5c23168bc08f0453c684cbd3f79471d3Sebastian Redl  return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
11115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
11125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseBreakStatement
11145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
11155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'break' ';'
11165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// Note: this lets the caller parse the end ';'.
11185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
1119bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
1120bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
11215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
11224cffe2fd5c23168bc08f0453c684cbd3f79471d3Sebastian Redl  return Actions.ActOnBreakStmt(BreakLoc, CurScope);
11235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
11245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseReturnStatement
11265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///       jump-statement:
11275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'return' expression[opt] ';'
1128bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
1129bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Use attributes?
11304e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_return) && "Not a return stmt!");
11315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
11329a920342707e384473b464528d2fd286e8c70353Sebastian Redl
113315faa7fdfb496489dec9470aa5eb699b29ecdaccSebastian Redl  OwningExprResult R(Actions);
11344e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::semi)) {
11355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    R = ParseExpression();
11360e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
11375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::semi, false, true);
11389a920342707e384473b464528d2fd286e8c70353Sebastian Redl      return StmtError();
11395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
11405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1141f53b4433abb7a3bc14c0329d3175cbc291280137Anders Carlsson  return Actions.ActOnReturnStmt(ReturnLoc, move(R));
11425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
11435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
11445f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this
11455f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// routine is called to skip/ignore tokens that comprise the MS asm statement.
11469a920342707e384473b464528d2fd286e8c70353Sebastian RedlParser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
1147b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff  if (Tok.is(tok::l_brace)) {
1148b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    unsigned short savedBraceCount = BraceCount;
1149b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    do {
1150b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff      ConsumeAnyToken();
1151b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof));
11521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  } else {
1153b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    // From the MS website: If used without braces, the __asm keyword means
1154b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    // that the rest of the line is an assembly-language statement.
1155b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff    SourceManager &SrcMgr = PP.getSourceManager();
115603d6bc6734eb79dc27628d9ea1126c299c80b4b6Steve Naroff    SourceLocation TokLoc = Tok.getLocation();
1157f7cf85b330bedd2877e1371fb0a83e99751ae162Chris Lattner    unsigned LineNo = SrcMgr.getInstantiationLineNumber(TokLoc);
1158362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff    do {
1159362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff      ConsumeAnyToken();
1160362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff      TokLoc = Tok.getLocation();
11611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) &&
11621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump             Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) &&
1163362809751711f7dc4ab01653ec7964a2e95f999bSteve Naroff             Tok.isNot(tok::eof));
1164b746ce84fb5c3fd2c5659f84dc6f2a883b499dc2Steve Naroff  }
1165a60528cdac7deee3991c2b48af4df4f315e49e9dSebastian Redl  return Actions.ActOnNullStmt(Tok.getLocation());
1166d62701bc5321049353017e9abf1963edd57646aaSteve Naroff}
1167d62701bc5321049353017e9abf1963edd57646aaSteve Naroff
11685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseAsmStatement - Parse a GNU extended asm statement.
11695f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///       asm-statement:
11705f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         gnu-asm-statement
11715f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         ms-asm-statement
11725f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///
11735f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [GNU] gnu-asm-statement:
11745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         'asm' type-qualifier[opt] '(' asm-argument ')' ';'
11755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-argument:
11775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal
11785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal ':' asm-operands[opt]
11795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
11805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
11815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///                 ':' asm-clobbers
11825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-clobbers:
11845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal
11855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-clobbers ',' asm-string-literal
11865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
11875f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [MS]  ms-asm-statement:
11885f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         '__asm' assembly-instruction ';'[opt]
11895f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         '__asm' '{' assembly-instruction-list '}' ';'[opt]
11905f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///
11915f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff/// [MS]  assembly-instruction-list:
11925f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         assembly-instruction ';'[opt]
11935f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///         assembly-instruction-list ';' assembly-instruction ';'[opt]
11945f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff///
11959a920342707e384473b464528d2fd286e8c70353Sebastian RedlParser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
11964e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
1197fe795956194141c91ae555985c9b930595bff43fChris Lattner  SourceLocation AsmLoc = ConsumeToken();
11989a920342707e384473b464528d2fd286e8c70353Sebastian Redl
11995f8aa696619e32bf307232841fedb704ba733b4dSteve Naroff  if (getLang().Microsoft && Tok.isNot(tok::l_paren) && !isTypeQualifier()) {
1200d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    msAsm = true;
1201d62701bc5321049353017e9abf1963edd57646aaSteve Naroff    return FuzzyParseMicrosoftAsmStatement();
1202d62701bc5321049353017e9abf1963edd57646aaSteve Naroff  }
12035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  DeclSpec DS;
12045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  SourceLocation Loc = Tok.getLocation();
1205bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  ParseTypeQualifierListOpt(DS, true, false);
12069a920342707e384473b464528d2fd286e8c70353Sebastian Redl
12075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // GNU asms accept, but warn, about type-qualifiers other than volatile.
12085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
12091ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
12105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
12111ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
12129a920342707e384473b464528d2fd286e8c70353Sebastian Redl
12135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Remember if this was a volatile asm.
121439c47b56f45437bbc49c9568b7308a400234a730Anders Carlsson  bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
1215dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  bool isSimple = false;
12164e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (Tok.isNot(tok::l_paren)) {
12171ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner    Diag(Tok, diag::err_expected_lparen_after) << "asm";
12185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    SkipUntil(tok::r_paren);
12199a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
12205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
12215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  Loc = ConsumeParen();
12229a920342707e384473b464528d2fd286e8c70353Sebastian Redl
1223effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl  OwningExprResult AsmString(ParseAsmStringLiteral());
12240e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (AsmString.isInvalid())
12259a920342707e384473b464528d2fd286e8c70353Sebastian Redl    return StmtError();
12260e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
1227b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson  llvm::SmallVector<std::string, 4> Names;
1228a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  ExprVector Constraints(Actions);
1229a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  ExprVector Exprs(Actions);
1230a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl  ExprVector Clobbers(Actions);
1231dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson
1232dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  unsigned NumInputs = 0, NumOutputs = 0;
12339a920342707e384473b464528d2fd286e8c70353Sebastian Redl
1234dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  SourceLocation RParenLoc;
1235dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  if (Tok.is(tok::r_paren)) {
1236dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    // We have a simple asm expression
1237dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    isSimple = true;
12389a920342707e384473b464528d2fd286e8c70353Sebastian Redl
1239dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    RParenLoc = ConsumeParen();
1240dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  } else {
1241a55e52c0802cae3b7c366a05c461d3d15074c1a3Sebastian Redl    // Parse Outputs, if present.
12428bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson    if (ParseAsmOperandsOpt(Names, Constraints, Exprs))
12439a920342707e384473b464528d2fd286e8c70353Sebastian Redl        return StmtError();
12449a920342707e384473b464528d2fd286e8c70353Sebastian Redl
1245dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    NumOutputs = Names.size();
12469a920342707e384473b464528d2fd286e8c70353Sebastian Redl
1247dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    // Parse Inputs, if present.
12488bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson    if (ParseAsmOperandsOpt(Names, Constraints, Exprs))
12499a920342707e384473b464528d2fd286e8c70353Sebastian Redl        return StmtError();
1250effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
1251dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    assert(Names.size() == Constraints.size() &&
12521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump           Constraints.size() == Exprs.size()
1253dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson           && "Input operand size mismatch!");
1254b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson
1255dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    NumInputs = Names.size() - NumOutputs;
1256effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
1257dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    // Parse the clobbers, if present.
1258dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    if (Tok.is(tok::colon)) {
1259dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson      ConsumeToken();
1260effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
1261dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson      // Parse the asm-string list for clobbers.
1262dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson      while (1) {
1263effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl        OwningExprResult Clobber(ParseAsmStringLiteral());
12645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
12650e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl        if (Clobber.isInvalid())
1266dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson          break;
1267effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
1268effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl        Clobbers.push_back(Clobber.release());
1269effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
1270dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson        if (Tok.isNot(tok::comma)) break;
1271dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson        ConsumeToken();
1272dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson      }
12735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
1274effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
1275dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson    RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc);
1276dfab34a696d1dba8622248c31aaf605906cb6109Anders Carlsson  }
1277effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
12783037ed0a27dba62e522304183718efc149e8b6d9Sebastian Redl  return Actions.ActOnAsmStmt(AsmLoc, isSimple, isVolatile,
1279beaaccd8e2a8748f77b66e2b330fb9136937e14cJay Foad                              NumOutputs, NumInputs, Names.data(),
1280f512e82f56671b695a32d019103e62a302838b7eSebastian Redl                              move_arg(Constraints), move_arg(Exprs),
128176ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl                              move(AsmString), move_arg(Clobbers),
12823037ed0a27dba62e522304183718efc149e8b6d9Sebastian Redl                              RParenLoc);
12835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
12845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
12855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// ParseAsmOperands - Parse the asm-operands production as used by
12865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// asm-statement.  We also parse a leading ':' token.  If the leading colon is
12875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// not present, we do not parse anything.
12885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
12895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-operands:
12905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-operand
12915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-operands ',' asm-operand
12925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
12935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// [GNU] asm-operand:
12945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         asm-string-literal '(' expression ')'
12955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///         '[' identifier ']' asm-string-literal '(' expression ')'
12965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
12975ffe14ca96bd662de7820f6875d3f04789a640c1Daniel Dunbar//
12985ffe14ca96bd662de7820f6875d3f04789a640c1Daniel Dunbar// FIXME: Avoid unnecessary std::string trashing.
12998bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlssonbool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
1300b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson                                 llvm::SmallVectorImpl<ExprTy*> &Constraints,
1301b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson                                 llvm::SmallVectorImpl<ExprTy*> &Exprs) {
13025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Only do anything if this operand is present.
13038bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson  if (Tok.isNot(tok::colon)) return false;
13045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ConsumeToken();
13051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // 'asm-operands' isn't present?
13074e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner  if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
13088bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson    return false;
13091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  while (1) {
13115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Read the [id] if present.
13124e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.is(tok::l_square)) {
13135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SourceLocation Loc = ConsumeBracket();
13141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
13154e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner      if (Tok.isNot(tok::identifier)) {
13165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        Diag(Tok, diag::err_expected_ident);
13175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer        SkipUntil(tok::r_paren);
13188bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson        return true;
13195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      }
13201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1321b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson      IdentifierInfo *II = Tok.getIdentifierInfo();
132269efba74cf5488060accf34c011b33ce6c15ece0Chris Lattner      ConsumeToken();
1323b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson
132401eb9b9683535d8a65c704ad2c545903409e2d36Daniel Dunbar      Names.push_back(II->getName());
13255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      MatchRHSPunctuation(tok::r_square, Loc);
1326b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson    } else
1327b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson      Names.push_back(std::string());
13280e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl
1329effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl    OwningExprResult Constraint(ParseAsmStringLiteral());
13300e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (Constraint.isInvalid()) {
1331b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson        SkipUntil(tok::r_paren);
13328bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson        return true;
1333b235fc2cf37621c7fc6511bb2b8788c95f9fb9fcAnders Carlsson    }
1334effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl    Constraints.push_back(Constraint.release());
13355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
13364e1d99a8a4d2958f0858f4baac68066af2c5cf17Chris Lattner    if (Tok.isNot(tok::l_paren)) {
13371ab3b96de160e4fbffec2a776e284a48a3bb543dChris Lattner      Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
13385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::r_paren);
13398bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson      return true;
13405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
1341effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl
13425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Read the parenthesized expression.
134372056a237c536ee63285ab0850cb50f299281767Eli Friedman    SourceLocation OpenLoc = ConsumeParen();
134472056a237c536ee63285ab0850cb50f299281767Eli Friedman    OwningExprResult Res(ParseExpression());
134572056a237c536ee63285ab0850cb50f299281767Eli Friedman    MatchRHSPunctuation(tok::r_paren, OpenLoc);
13460e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl    if (Res.isInvalid()) {
13475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer      SkipUntil(tok::r_paren);
13488bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson      return true;
13495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    }
1350effa8d1c97b00a3f53e972b0e61d9aade5ea1c57Sebastian Redl    Exprs.push_back(Res.release());
13515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Eat the comma and continue parsing if it exists.
13528bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson    if (Tok.isNot(tok::comma)) return false;
13535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    ConsumeToken();
13545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
13558bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson
13568bd36fcb4427519f41197d88b9121e2bbe9e3fc3Anders Carlsson  return true;
13575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1358f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian
1359b28317a8e5e0e2953d1e5406d753d6c3c7f1e7d2Chris LattnerParser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
136040e9bc84a2ab49fc33c2b1a95c6674ab2b820e9eChris Lattner  assert(Tok.is(tok::l_brace));
136140e9bc84a2ab49fc33c2b1a95c6674ab2b820e9eChris Lattner  SourceLocation LBraceLoc = Tok.getLocation();
1362d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
136349f28ca787d8db7cac3c8898334f70ea55374c98Chris Lattner  PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions,
136449f28ca787d8db7cac3c8898334f70ea55374c98Chris Lattner                                        PP.getSourceManager(),
136549f28ca787d8db7cac3c8898334f70ea55374c98Chris Lattner                                        "parsing function body");
13661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
1367f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // Do not enter a scope for the brace, as the arguments are in the same scope
1368f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // (the function body) as the body itself.  Instead, just read the statement
1369f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // list and put it into a CompoundStmt for safe keeping.
137061364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl  OwningStmtResult FnBody(ParseCompoundStatementBody());
137161364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
1372f9ed3157c93495474003a5ec360039030fd42e9cFariborz Jahanian  // If the function body could not be parsed, make a bogus compoundstmt.
13730e9eabca263e8922bec0e2b38c8670eba9a39a1fSebastian Redl  if (FnBody.isInvalid())
13741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
137540e9bc84a2ab49fc33c2b1a95c6674ab2b820e9eChris Lattner                                       MultiStmtArg(Actions), false);
137661364dddc33383e62cfe3b841dbc0f471280d95bSebastian Redl
137776ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl  return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
1378cd5af4b5863c63b62cde96ad6d52fb1eec0e26bbSeo Sanghyeon}
1379a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1380d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// ParseFunctionTryBlock - Parse a C++ function-try-block.
1381d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1382d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///       function-try-block:
1383d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///         'try' ctor-initializer[opt] compound-statement handler-seq
1384d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1385d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian RedlParser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) {
1386d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  assert(Tok.is(tok::kw_try) && "Expected 'try'");
1387d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  SourceLocation TryLoc = ConsumeToken();
1388d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1389d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  PrettyStackTraceActionsDecl CrashInfo(Decl, TryLoc, Actions,
1390d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl                                        PP.getSourceManager(),
1391d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl                                        "parsing function try block");
1392d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1393d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  // Constructor initializer list?
1394d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  if (Tok.is(tok::colon))
1395d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl    ParseConstructorInitializer(Decl);
1396d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1397de1b60a9868f80f0872ed05d78df3b40a10ba5caSebastian Redl  SourceLocation LBraceLoc = Tok.getLocation();
1398d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  OwningStmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
1399d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  // If we failed to parse the try-catch, we just give the function an empty
1400d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  // compound statement as the body.
1401d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  if (FnBody.isInvalid())
1402de1b60a9868f80f0872ed05d78df3b40a10ba5caSebastian Redl    FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
1403d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl                                       MultiStmtArg(Actions), false);
1404d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1405d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
1406d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl}
1407d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1408a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// ParseCXXTryBlock - Parse a C++ try-block.
1409a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///
1410a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///       try-block:
1411a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         'try' compound-statement handler-seq
1412a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///
1413bbd37c62e34db3f5a95c899723484a76c71d7757Sean HuntParser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
1414bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Add attributes?
1415a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  assert(Tok.is(tok::kw_try) && "Expected 'try'");
1416a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1417a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  SourceLocation TryLoc = ConsumeToken();
1418d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl  return ParseCXXTryBlockCommon(TryLoc);
1419d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl}
1420d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl
1421d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// ParseCXXTryBlockCommon - Parse the common part of try-block and
1422d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl/// function-try-block.
1423d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1424d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///       try-block:
1425d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///         'try' compound-statement handler-seq
1426d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1427d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///       function-try-block:
1428d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///         'try' ctor-initializer[opt] compound-statement handler-seq
1429d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1430d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///       handler-seq:
1431d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///         handler handler-seq[opt]
1432d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl///
1433d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian RedlParser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
1434a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Tok.isNot(tok::l_brace))
1435a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError(Diag(Tok, diag::err_expected_lbrace));
1436bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
1437bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  OwningStmtResult TryBlock(ParseCompoundStatement(0));
1438a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (TryBlock.isInvalid())
1439a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return move(TryBlock);
1440a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1441a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  StmtVector Handlers(Actions);
1442bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
1443bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    CXX0XAttributeList Attr = ParseCXX0XAttributes();
1444bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt    Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
1445bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt      << Attr.Range;
1446bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  }
1447a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Tok.isNot(tok::kw_catch))
1448a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError(Diag(Tok, diag::err_expected_catch));
1449a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  while (Tok.is(tok::kw_catch)) {
1450a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    OwningStmtResult Handler(ParseCXXCatchBlock());
1451a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    if (!Handler.isInvalid())
1452a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl      Handlers.push_back(Handler.release());
1453a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  }
1454a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // Don't bother creating the full statement if we don't have any usable
1455a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // handlers.
1456a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Handlers.empty())
1457a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError();
1458a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
145976ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl  return Actions.ActOnCXXTryBlock(TryLoc, move(TryBlock), move_arg(Handlers));
1460a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl}
1461a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1462a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl/// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
1463a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///
1464a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///       handler:
1465a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         'catch' '(' exception-declaration ')' compound-statement
1466a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///
1467a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///       exception-declaration:
1468a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         type-specifier-seq declarator
1469a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         type-specifier-seq abstract-declarator
1470a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         type-specifier-seq
1471a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///         '...'
1472a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl///
1473a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian RedlParser::OwningStmtResult Parser::ParseCXXCatchBlock() {
1474a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
1475a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1476a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  SourceLocation CatchLoc = ConsumeToken();
1477a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1478a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  SourceLocation LParenLoc = Tok.getLocation();
1479a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
1480a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError();
1481a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1482a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // C++ 3.3.2p3:
1483a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // The name in a catch exception-declaration is local to the handler and
1484a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // shall not be redeclared in the outermost block of the handler.
1485a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope);
1486a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1487a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // exception-declaration is equivalent to '...' or a parameter-declaration
1488a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  // without default arguments.
1489b28317a8e5e0e2953d1e5406d753d6c3c7f1e7d2Chris Lattner  DeclPtrTy ExceptionDecl;
1490a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Tok.isNot(tok::ellipsis)) {
1491a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    DeclSpec DS;
14924b07b2968f87f3cd5a3d8c76145f1cbfd718d42dSebastian Redl    if (ParseCXXTypeSpecifierSeq(DS))
14934b07b2968f87f3cd5a3d8c76145f1cbfd718d42dSebastian Redl      return StmtError();
1494a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    Declarator ExDecl(DS, Declarator::CXXCatchContext);
1495a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    ParseDeclarator(ExDecl);
1496a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    ExceptionDecl = Actions.ActOnExceptionDeclarator(CurScope, ExDecl);
1497a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  } else
1498a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    ConsumeToken();
1499a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1500a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
1501a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError();
1502a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1503a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Tok.isNot(tok::l_brace))
1504a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return StmtError(Diag(Tok, diag::err_expected_lbrace));
1505a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
1506bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
1507bbd37c62e34db3f5a95c899723484a76c71d7757Sean Hunt  OwningStmtResult Block(ParseCompoundStatement(0));
1508a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl  if (Block.isInvalid())
1509a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl    return move(Block);
1510a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl
151176ad2e85575722e8a38a2bd4648ab4304d9fcd24Sebastian Redl  return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, move(Block));
1512a0fd8652f3302d0f39ed9849b521ee5b76597b0aSebastian Redl}
1513