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