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