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