blob: 052aa1a8eeca9cd25ebb8f7295c48bd469b23995 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Statement and Block portions of the Parser
11// interface.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Parse/Parser.h"
16#include "clang/Basic/Diagnostic.h"
17#include "clang/Parse/DeclSpec.h"
18#include "clang/Parse/Scope.h"
19using namespace clang;
20
21//===----------------------------------------------------------------------===//
22// C99 6.8: Statements and Blocks.
23//===----------------------------------------------------------------------===//
24
25/// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
26/// StatementOrDeclaration:
27/// statement
28/// declaration
29///
30/// statement:
31/// labeled-statement
32/// compound-statement
33/// expression-statement
34/// selection-statement
35/// iteration-statement
36/// jump-statement
Fariborz Jahanianb384d322007-10-04 20:19:06 +000037/// [OBC] objc-throw-statement
38/// [OBC] objc-try-catch-statement
Fariborz Jahanianc385c902008-01-29 18:21:32 +000039/// [OBC] objc-synchronized-statement
Reid Spencer5f016e22007-07-11 17:01:13 +000040/// [GNU] asm-statement
41/// [OMP] openmp-construct [TODO]
42///
43/// labeled-statement:
44/// identifier ':' statement
45/// 'case' constant-expression ':' statement
46/// 'default' ':' statement
47///
48/// selection-statement:
49/// if-statement
50/// switch-statement
51///
52/// iteration-statement:
53/// while-statement
54/// do-statement
55/// for-statement
56///
57/// expression-statement:
58/// expression[opt] ';'
59///
60/// jump-statement:
61/// 'goto' identifier ';'
62/// 'continue' ';'
63/// 'break' ';'
64/// 'return' expression[opt] ';'
65/// [GNU] 'goto' '*' expression ';'
66///
Fariborz Jahanianb384d322007-10-04 20:19:06 +000067/// [OBC] objc-throw-statement:
68/// [OBC] '@' 'throw' expression ';'
69/// [OBC] '@' 'throw' ';'
Reid Spencer5f016e22007-07-11 17:01:13 +000070///
71Parser::StmtResult Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
72 const char *SemiError = 0;
73 Parser::StmtResult Res;
74
75 // Cases in this switch statement should fall through if the parser expects
76 // the token to end in a semicolon (in which case SemiError should be set),
77 // or they directly 'return;' if not.
Fariborz Jahanian397fcc12007-09-19 19:14:32 +000078 tok::TokenKind Kind = Tok.getKind();
79 SourceLocation AtLoc;
80 switch (Kind) {
Reid Spencer5f016e22007-07-11 17:01:13 +000081 case tok::identifier: // C99 6.8.1: labeled-statement
82 // identifier ':' statement
83 // declaration (if !OnlyStatement)
84 // expression[opt] ';'
85 return ParseIdentifierStatement(OnlyStatement);
86
Fariborz Jahanian397fcc12007-09-19 19:14:32 +000087 case tok::at: // May be a @try or @throw statement
88 {
89 AtLoc = ConsumeToken(); // consume @
Steve Naroff64515f32008-02-05 21:27:35 +000090 return ParseObjCAtStatement(AtLoc);
Fariborz Jahanian397fcc12007-09-19 19:14:32 +000091 }
Fariborz Jahanian397fcc12007-09-19 19:14:32 +000092
Reid Spencer5f016e22007-07-11 17:01:13 +000093 default:
Fariborz Jahanianb384d322007-10-04 20:19:06 +000094 if (!OnlyStatement && isDeclarationSpecifier()) {
Steve Naroff1b273c42007-09-16 14:56:35 +000095 return Actions.ActOnDeclStmt(ParseDeclaration(Declarator::BlockContext));
Chris Lattner4e1d99a2007-10-09 17:41:39 +000096 } else if (Tok.is(tok::r_brace)) {
Reid Spencer5f016e22007-07-11 17:01:13 +000097 Diag(Tok, diag::err_expected_statement);
98 return true;
99 } else {
100 // expression[opt] ';'
Fariborz Jahanianb384d322007-10-04 20:19:06 +0000101 ExprResult Res = ParseExpression();
Reid Spencer5f016e22007-07-11 17:01:13 +0000102 if (Res.isInvalid) {
103 // If the expression is invalid, skip ahead to the next semicolon. Not
104 // doing this opens us up to the possibility of infinite loops if
105 // ParseExpression does not consume any tokens.
106 SkipUntil(tok::semi);
107 return true;
108 }
109 // Otherwise, eat the semicolon.
110 ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
Steve Naroff1b273c42007-09-16 14:56:35 +0000111 return Actions.ActOnExprStmt(Res.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000112 }
113
114 case tok::kw_case: // C99 6.8.1: labeled-statement
115 return ParseCaseStatement();
116 case tok::kw_default: // C99 6.8.1: labeled-statement
117 return ParseDefaultStatement();
118
119 case tok::l_brace: // C99 6.8.2: compound-statement
120 return ParseCompoundStatement();
121 case tok::semi: // C99 6.8.3p3: expression[opt] ';'
Steve Naroff1b273c42007-09-16 14:56:35 +0000122 return Actions.ActOnNullStmt(ConsumeToken());
Reid Spencer5f016e22007-07-11 17:01:13 +0000123
124 case tok::kw_if: // C99 6.8.4.1: if-statement
125 return ParseIfStatement();
126 case tok::kw_switch: // C99 6.8.4.2: switch-statement
127 return ParseSwitchStatement();
128
129 case tok::kw_while: // C99 6.8.5.1: while-statement
130 return ParseWhileStatement();
131 case tok::kw_do: // C99 6.8.5.2: do-statement
132 Res = ParseDoStatement();
133 SemiError = "do/while loop";
134 break;
135 case tok::kw_for: // C99 6.8.5.3: for-statement
136 return ParseForStatement();
137
138 case tok::kw_goto: // C99 6.8.6.1: goto-statement
139 Res = ParseGotoStatement();
140 SemiError = "goto statement";
141 break;
142 case tok::kw_continue: // C99 6.8.6.2: continue-statement
143 Res = ParseContinueStatement();
144 SemiError = "continue statement";
145 break;
146 case tok::kw_break: // C99 6.8.6.3: break-statement
147 Res = ParseBreakStatement();
148 SemiError = "break statement";
149 break;
150 case tok::kw_return: // C99 6.8.6.4: return-statement
151 Res = ParseReturnStatement();
152 SemiError = "return statement";
153 break;
154
155 case tok::kw_asm:
Steve Naroffd62701b2008-02-07 03:50:06 +0000156 bool msAsm = false;
157 Res = ParseAsmStatement(msAsm);
158 if (msAsm) return Res;
Reid Spencer5f016e22007-07-11 17:01:13 +0000159 SemiError = "asm statement";
160 break;
161 }
162
163 // If we reached this code, the statement must end in a semicolon.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000164 if (Tok.is(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000165 ConsumeToken();
166 } else {
167 Diag(Tok, diag::err_expected_semi_after, SemiError);
168 SkipUntil(tok::semi);
169 }
170 return Res;
171}
172
173/// ParseIdentifierStatement - Because we don't have two-token lookahead, we
174/// have a bit of a quandry here. Reading the identifier is necessary to see if
175/// there is a ':' after it. If there is, this is a label, regardless of what
176/// else the identifier can mean. If not, this is either part of a declaration
177/// (if the identifier is a type-name) or part of an expression.
178///
179/// labeled-statement:
180/// identifier ':' statement
181/// [GNU] identifier ':' attributes[opt] statement
182/// declaration (if !OnlyStatement)
183/// expression[opt] ';'
184///
185Parser::StmtResult Parser::ParseIdentifierStatement(bool OnlyStatement) {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000186 assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
Reid Spencer5f016e22007-07-11 17:01:13 +0000187 "Not an identifier!");
188
Chris Lattnerd2177732007-07-20 16:59:19 +0000189 Token IdentTok = Tok; // Save the whole token.
Reid Spencer5f016e22007-07-11 17:01:13 +0000190 ConsumeToken(); // eat the identifier.
191
192 // identifier ':' statement
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000193 if (Tok.is(tok::colon)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000194 SourceLocation ColonLoc = ConsumeToken();
195
196 // Read label attributes, if present.
197 DeclTy *AttrList = 0;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000198 if (Tok.is(tok::kw___attribute))
Reid Spencer5f016e22007-07-11 17:01:13 +0000199 // TODO: save these somewhere.
200 AttrList = ParseAttributes();
201
202 StmtResult SubStmt = ParseStatement();
203
204 // Broken substmt shouldn't prevent the label from being added to the AST.
205 if (SubStmt.isInvalid)
Steve Naroff1b273c42007-09-16 14:56:35 +0000206 SubStmt = Actions.ActOnNullStmt(ColonLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000207
Steve Naroff1b273c42007-09-16 14:56:35 +0000208 return Actions.ActOnLabelStmt(IdentTok.getLocation(),
Reid Spencer5f016e22007-07-11 17:01:13 +0000209 IdentTok.getIdentifierInfo(),
210 ColonLoc, SubStmt.Val);
211 }
212
213 // Check to see if this is a declaration.
214 void *TypeRep;
215 if (!OnlyStatement &&
216 (TypeRep = Actions.isTypeName(*IdentTok.getIdentifierInfo(), CurScope))) {
217 // Handle this. Warn/disable if in middle of block and !C99.
218 DeclSpec DS;
219
220 // Add the typedef name to the start of the decl-specs.
221 const char *PrevSpec = 0;
222 int isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typedef,
223 IdentTok.getLocation(), PrevSpec,
224 TypeRep);
225 assert(!isInvalid && "First declspec can't be invalid!");
Steve Narofff908a872007-10-30 02:23:23 +0000226 SourceLocation endProtoLoc;
Fariborz Jahaniandfbcce22007-10-11 18:08:47 +0000227 if (Tok.is(tok::less)) {
228 llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
Steve Narofff908a872007-10-30 02:23:23 +0000229 ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc);
Fariborz Jahaniandfbcce22007-10-11 18:08:47 +0000230 llvm::SmallVector<DeclTy *, 8> *ProtocolDecl =
231 new llvm::SmallVector<DeclTy *, 8>;
232 DS.setProtocolQualifiers(ProtocolDecl);
233 Actions.FindProtocolDeclaration(IdentTok.getLocation(),
234 &ProtocolRefs[0], ProtocolRefs.size(),
235 *ProtocolDecl);
236 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000237
238 // ParseDeclarationSpecifiers will continue from there.
239 ParseDeclarationSpecifiers(DS);
240
241 // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
242 // declaration-specifiers init-declarator-list[opt] ';'
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000243 if (Tok.is(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000244 // TODO: emit error on 'int;' or 'const enum foo;'.
245 // if (!DS.isMissingDeclaratorOk()) Diag(...);
246
247 ConsumeToken();
248 // FIXME: Return this as a type decl.
249 return 0;
250 }
251
252 // Parse all the declarators.
253 Declarator DeclaratorInfo(DS, Declarator::BlockContext);
254 ParseDeclarator(DeclaratorInfo);
255
256 DeclTy *Decl = ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
Steve Naroff1b273c42007-09-16 14:56:35 +0000257 return Decl ? Actions.ActOnDeclStmt(Decl) : 0;
Reid Spencer5f016e22007-07-11 17:01:13 +0000258 }
259
260 // Otherwise, this is an expression. Seed it with II and parse it.
261 ExprResult Res = ParseExpressionWithLeadingIdentifier(IdentTok);
262 if (Res.isInvalid) {
263 SkipUntil(tok::semi);
264 return true;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000265 } else if (Tok.isNot(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000266 Diag(Tok, diag::err_expected_semi_after, "expression");
267 SkipUntil(tok::semi);
268 return true;
269 } else {
270 ConsumeToken();
271 // Convert expr to a stmt.
Steve Naroff1b273c42007-09-16 14:56:35 +0000272 return Actions.ActOnExprStmt(Res.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000273 }
274}
275
276/// ParseCaseStatement
277/// labeled-statement:
278/// 'case' constant-expression ':' statement
279/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
280///
281/// Note that this does not parse the 'statement' at the end.
282///
283Parser::StmtResult Parser::ParseCaseStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000284 assert(Tok.is(tok::kw_case) && "Not a case stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000285 SourceLocation CaseLoc = ConsumeToken(); // eat the 'case'.
286
287 ExprResult LHS = ParseConstantExpression();
288 if (LHS.isInvalid) {
289 SkipUntil(tok::colon);
290 return true;
291 }
292
293 // GNU case range extension.
294 SourceLocation DotDotDotLoc;
295 ExprTy *RHSVal = 0;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000296 if (Tok.is(tok::ellipsis)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000297 Diag(Tok, diag::ext_gnu_case_range);
298 DotDotDotLoc = ConsumeToken();
299
300 ExprResult RHS = ParseConstantExpression();
301 if (RHS.isInvalid) {
302 SkipUntil(tok::colon);
303 return true;
304 }
305 RHSVal = RHS.Val;
306 }
307
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000308 if (Tok.isNot(tok::colon)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000309 Diag(Tok, diag::err_expected_colon_after, "'case'");
310 SkipUntil(tok::colon);
311 return true;
312 }
313
314 SourceLocation ColonLoc = ConsumeToken();
315
316 // Diagnose the common error "switch (X) { case 4: }", which is not valid.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000317 if (Tok.is(tok::r_brace)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000318 Diag(Tok, diag::err_label_end_of_compound_statement);
319 return true;
320 }
321
322 StmtResult SubStmt = ParseStatement();
323
324 // Broken substmt shouldn't prevent the case from being added to the AST.
325 if (SubStmt.isInvalid)
Steve Naroff1b273c42007-09-16 14:56:35 +0000326 SubStmt = Actions.ActOnNullStmt(ColonLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000327
Steve Naroff1b273c42007-09-16 14:56:35 +0000328 return Actions.ActOnCaseStmt(CaseLoc, LHS.Val, DotDotDotLoc, RHSVal, ColonLoc,
Reid Spencer5f016e22007-07-11 17:01:13 +0000329 SubStmt.Val);
330}
331
332/// ParseDefaultStatement
333/// labeled-statement:
334/// 'default' ':' statement
335/// Note that this does not parse the 'statement' at the end.
336///
337Parser::StmtResult Parser::ParseDefaultStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000338 assert(Tok.is(tok::kw_default) && "Not a default stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000339 SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
340
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000341 if (Tok.isNot(tok::colon)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000342 Diag(Tok, diag::err_expected_colon_after, "'default'");
343 SkipUntil(tok::colon);
344 return true;
345 }
346
347 SourceLocation ColonLoc = ConsumeToken();
348
349 // Diagnose the common error "switch (X) {... default: }", which is not valid.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000350 if (Tok.is(tok::r_brace)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000351 Diag(Tok, diag::err_label_end_of_compound_statement);
352 return true;
353 }
354
355 StmtResult SubStmt = ParseStatement();
356 if (SubStmt.isInvalid)
357 return true;
358
Steve Naroff1b273c42007-09-16 14:56:35 +0000359 return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt.Val, CurScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000360}
361
362
363/// ParseCompoundStatement - Parse a "{}" block.
364///
365/// compound-statement: [C99 6.8.2]
366/// { block-item-list[opt] }
367/// [GNU] { label-declarations block-item-list } [TODO]
368///
369/// block-item-list:
370/// block-item
371/// block-item-list block-item
372///
373/// block-item:
374/// declaration
Chris Lattner45a566c2007-08-27 01:01:57 +0000375/// [GNU] '__extension__' declaration
Reid Spencer5f016e22007-07-11 17:01:13 +0000376/// statement
377/// [OMP] openmp-directive [TODO]
378///
379/// [GNU] label-declarations:
380/// [GNU] label-declaration
381/// [GNU] label-declarations label-declaration
382///
383/// [GNU] label-declaration:
384/// [GNU] '__label__' identifier-list ';'
385///
386/// [OMP] openmp-directive: [TODO]
387/// [OMP] barrier-directive
388/// [OMP] flush-directive
389///
Chris Lattner98414c12007-08-31 21:49:55 +0000390Parser::StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000391 assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000392
Chris Lattner31e05722007-08-26 06:24:45 +0000393 // Enter a scope to hold everything within the compound stmt. Compound
394 // statements can always hold declarations.
395 EnterScope(Scope::DeclScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000396
397 // Parse the statements in the body.
Chris Lattner98414c12007-08-31 21:49:55 +0000398 StmtResult Body = ParseCompoundStatementBody(isStmtExpr);
Reid Spencer5f016e22007-07-11 17:01:13 +0000399
400 ExitScope();
401 return Body;
402}
403
404
405/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
Steve Naroff1b273c42007-09-16 14:56:35 +0000406/// ActOnCompoundStmt action. This expects the '{' to be the current token, and
Reid Spencer5f016e22007-07-11 17:01:13 +0000407/// consume the '}' at the end of the block. It does not manipulate the scope
408/// stack.
Chris Lattner98414c12007-08-31 21:49:55 +0000409Parser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000410 SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'.
411
412 // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
Chris Lattner45a566c2007-08-27 01:01:57 +0000413 // only allowed at the start of a compound stmt regardless of the language.
Reid Spencer5f016e22007-07-11 17:01:13 +0000414
415 llvm::SmallVector<StmtTy*, 32> Stmts;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000416 while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
Chris Lattner45a566c2007-08-27 01:01:57 +0000417 StmtResult R;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000418 if (Tok.isNot(tok::kw___extension__)) {
Chris Lattner45a566c2007-08-27 01:01:57 +0000419 R = ParseStatementOrDeclaration(false);
420 } else {
421 // __extension__ can start declarations and it can also be a unary
422 // operator for expressions. Consume multiple __extension__ markers here
423 // until we can determine which is which.
424 SourceLocation ExtLoc = ConsumeToken();
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000425 while (Tok.is(tok::kw___extension__))
Chris Lattner45a566c2007-08-27 01:01:57 +0000426 ConsumeToken();
427
428 // If this is the start of a declaration, parse it as such.
429 if (isDeclarationSpecifier()) {
430 // FIXME: Save the __extension__ on the decl as a node somehow.
431 // FIXME: disable extwarns.
Steve Naroff1b273c42007-09-16 14:56:35 +0000432 R = Actions.ActOnDeclStmt(ParseDeclaration(Declarator::BlockContext));
Chris Lattner45a566c2007-08-27 01:01:57 +0000433 } else {
434 // Otherwise this was a unary __extension__ marker. Parse the
435 // subexpression and add the __extension__ unary op.
436 // FIXME: disable extwarns.
437 ExprResult Res = ParseCastExpression(false);
438 if (Res.isInvalid) {
439 SkipUntil(tok::semi);
440 continue;
441 }
442
443 // Add the __extension__ node to the AST.
Steve Narofff69936d2007-09-16 03:34:24 +0000444 Res = Actions.ActOnUnaryOp(ExtLoc, tok::kw___extension__, Res.Val);
Chris Lattner45a566c2007-08-27 01:01:57 +0000445 if (Res.isInvalid)
446 continue;
447
448 // Eat the semicolon at the end of stmt and convert the expr into a stmt.
449 ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
Steve Naroff1b273c42007-09-16 14:56:35 +0000450 R = Actions.ActOnExprStmt(Res.Val);
Chris Lattner45a566c2007-08-27 01:01:57 +0000451 }
452 }
453
Reid Spencer5f016e22007-07-11 17:01:13 +0000454 if (!R.isInvalid && R.Val)
455 Stmts.push_back(R.Val);
456 }
457
458 // We broke out of the while loop because we found a '}' or EOF.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000459 if (Tok.isNot(tok::r_brace)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000460 Diag(Tok, diag::err_expected_rbrace);
Steve Naroffd1a7cf82008-01-31 18:29:10 +0000461 return true;
Reid Spencer5f016e22007-07-11 17:01:13 +0000462 }
463
464 SourceLocation RBraceLoc = ConsumeBrace();
Steve Naroff1b273c42007-09-16 14:56:35 +0000465 return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
Chris Lattner98414c12007-08-31 21:49:55 +0000466 &Stmts[0], Stmts.size(), isStmtExpr);
Reid Spencer5f016e22007-07-11 17:01:13 +0000467}
468
469/// ParseIfStatement
470/// if-statement: [C99 6.8.4.1]
471/// 'if' '(' expression ')' statement
472/// 'if' '(' expression ')' statement 'else' statement
473///
474Parser::StmtResult Parser::ParseIfStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000475 assert(Tok.is(tok::kw_if) && "Not an if stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000476 SourceLocation IfLoc = ConsumeToken(); // eat the 'if'.
477
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000478 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000479 Diag(Tok, diag::err_expected_lparen_after, "if");
480 SkipUntil(tok::semi);
481 return true;
482 }
483
Chris Lattner22153252007-08-26 23:08:06 +0000484 // C99 6.8.4p3 - In C99, the if statement is a block. This is not
485 // the case for C90.
486 if (getLang().C99)
487 EnterScope(Scope::DeclScope);
488
Reid Spencer5f016e22007-07-11 17:01:13 +0000489 // Parse the condition.
490 ExprResult CondExp = ParseSimpleParenExpression();
491 if (CondExp.isInvalid) {
492 SkipUntil(tok::semi);
Chris Lattner22153252007-08-26 23:08:06 +0000493 if (getLang().C99)
494 ExitScope();
Reid Spencer5f016e22007-07-11 17:01:13 +0000495 return true;
496 }
497
Chris Lattner0ecea032007-08-22 05:28:50 +0000498 // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000499 // there is no compound stmt. C90 does not have this clause. We only do this
500 // if the body isn't a compound statement to avoid push/pop in common cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000501 bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000502 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattnera36ce712007-08-22 05:16:28 +0000503
Chris Lattnerb96728d2007-10-29 05:08:52 +0000504 // Read the 'then' stmt.
505 SourceLocation ThenStmtLoc = Tok.getLocation();
506 StmtResult ThenStmt = ParseStatement();
Reid Spencer5f016e22007-07-11 17:01:13 +0000507
Chris Lattnera36ce712007-08-22 05:16:28 +0000508 // Pop the 'if' scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000509 if (NeedsInnerScope) ExitScope();
Reid Spencer5f016e22007-07-11 17:01:13 +0000510
511 // If it has an else, parse it.
512 SourceLocation ElseLoc;
Chris Lattnerb96728d2007-10-29 05:08:52 +0000513 SourceLocation ElseStmtLoc;
Reid Spencer5f016e22007-07-11 17:01:13 +0000514 StmtResult ElseStmt(false);
Chris Lattnerb96728d2007-10-29 05:08:52 +0000515
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000516 if (Tok.is(tok::kw_else)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000517 ElseLoc = ConsumeToken();
Chris Lattnera36ce712007-08-22 05:16:28 +0000518
Chris Lattner0ecea032007-08-22 05:28:50 +0000519 // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000520 // there is no compound stmt. C90 does not have this clause. We only do
521 // this if the body isn't a compound statement to avoid push/pop in common
522 // cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000523 NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000524 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattnera36ce712007-08-22 05:16:28 +0000525
Chris Lattnerb96728d2007-10-29 05:08:52 +0000526 ElseStmtLoc = Tok.getLocation();
Reid Spencer5f016e22007-07-11 17:01:13 +0000527 ElseStmt = ParseStatement();
Chris Lattnera36ce712007-08-22 05:16:28 +0000528
529 // Pop the 'else' scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000530 if (NeedsInnerScope) ExitScope();
Reid Spencer5f016e22007-07-11 17:01:13 +0000531 }
532
Chris Lattner22153252007-08-26 23:08:06 +0000533 if (getLang().C99)
534 ExitScope();
535
Chris Lattnerb96728d2007-10-29 05:08:52 +0000536 // If the then or else stmt is invalid and the other is valid (and present),
537 // make turn the invalid one into a null stmt to avoid dropping the other
538 // part. If both are invalid, return error.
539 if ((ThenStmt.isInvalid && ElseStmt.isInvalid) ||
540 (ThenStmt.isInvalid && ElseStmt.Val == 0) ||
541 (ThenStmt.Val == 0 && ElseStmt.isInvalid)) {
542 // Both invalid, or one is invalid and other is non-present: delete cond and
543 // return error.
544 Actions.DeleteExpr(CondExp.Val);
545 return true;
546 }
547
548 // Now if either are invalid, replace with a ';'.
549 if (ThenStmt.isInvalid)
550 ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
551 if (ElseStmt.isInvalid)
552 ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
553
Chris Lattnerb96728d2007-10-29 05:08:52 +0000554 return Actions.ActOnIfStmt(IfLoc, CondExp.Val, ThenStmt.Val,
Reid Spencer5f016e22007-07-11 17:01:13 +0000555 ElseLoc, ElseStmt.Val);
556}
557
558/// ParseSwitchStatement
559/// switch-statement:
560/// 'switch' '(' expression ')' statement
561Parser::StmtResult Parser::ParseSwitchStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000562 assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000563 SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'.
564
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000565 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000566 Diag(Tok, diag::err_expected_lparen_after, "switch");
567 SkipUntil(tok::semi);
568 return true;
569 }
Chris Lattner22153252007-08-26 23:08:06 +0000570
571 // C99 6.8.4p3 - In C99, the switch statement is a block. This is
572 // not the case for C90. Start the switch scope.
573 if (getLang().C99)
574 EnterScope(Scope::BreakScope|Scope::DeclScope);
575 else
576 EnterScope(Scope::BreakScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000577
578 // Parse the condition.
579 ExprResult Cond = ParseSimpleParenExpression();
580
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000581 if (Cond.isInvalid) {
582 ExitScope();
583 return true;
584 }
585
Steve Naroff1b273c42007-09-16 14:56:35 +0000586 StmtResult Switch = Actions.ActOnStartOfSwitchStmt(Cond.Val);
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000587
Chris Lattner0ecea032007-08-22 05:28:50 +0000588 // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000589 // there is no compound stmt. C90 does not have this clause. We only do this
590 // if the body isn't a compound statement to avoid push/pop in common cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000591 bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000592 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000593
Reid Spencer5f016e22007-07-11 17:01:13 +0000594 // Read the body statement.
595 StmtResult Body = ParseStatement();
596
Chris Lattner0ecea032007-08-22 05:28:50 +0000597 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000598 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000599
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000600 if (Body.isInvalid) {
Steve Naroff1b273c42007-09-16 14:56:35 +0000601 Body = Actions.ActOnNullStmt(Tok.getLocation());
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000602 // FIXME: Remove the case statement list from the Switch statement.
603 }
604
Reid Spencer5f016e22007-07-11 17:01:13 +0000605 ExitScope();
606
Steve Naroff1b273c42007-09-16 14:56:35 +0000607 return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.Val, Body.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000608}
609
610/// ParseWhileStatement
611/// while-statement: [C99 6.8.5.1]
612/// 'while' '(' expression ')' statement
613Parser::StmtResult Parser::ParseWhileStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000614 assert(Tok.is(tok::kw_while) && "Not a while stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000615 SourceLocation WhileLoc = Tok.getLocation();
616 ConsumeToken(); // eat the 'while'.
617
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000618 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000619 Diag(Tok, diag::err_expected_lparen_after, "while");
620 SkipUntil(tok::semi);
621 return true;
622 }
623
Chris Lattner22153252007-08-26 23:08:06 +0000624 // C99 6.8.5p5 - In C99, the while statement is a block. This is not
625 // the case for C90. Start the loop scope.
626 if (getLang().C99)
627 EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
628 else
629 EnterScope(Scope::BreakScope | Scope::ContinueScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000630
631 // Parse the condition.
632 ExprResult Cond = ParseSimpleParenExpression();
633
Chris Lattner0ecea032007-08-22 05:28:50 +0000634 // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000635 // there is no compound stmt. C90 does not have this clause. We only do this
636 // if the body isn't a compound statement to avoid push/pop in common cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000637 bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000638 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000639
Reid Spencer5f016e22007-07-11 17:01:13 +0000640 // Read the body statement.
641 StmtResult Body = ParseStatement();
642
Chris Lattner0ecea032007-08-22 05:28:50 +0000643 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000644 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000645
Reid Spencer5f016e22007-07-11 17:01:13 +0000646 ExitScope();
647
648 if (Cond.isInvalid || Body.isInvalid) return true;
649
Steve Naroff1b273c42007-09-16 14:56:35 +0000650 return Actions.ActOnWhileStmt(WhileLoc, Cond.Val, Body.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000651}
652
653/// ParseDoStatement
654/// do-statement: [C99 6.8.5.2]
655/// 'do' statement 'while' '(' expression ')' ';'
656/// Note: this lets the caller parse the end ';'.
657Parser::StmtResult Parser::ParseDoStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000658 assert(Tok.is(tok::kw_do) && "Not a do stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000659 SourceLocation DoLoc = ConsumeToken(); // eat the 'do'.
660
Chris Lattner22153252007-08-26 23:08:06 +0000661 // C99 6.8.5p5 - In C99, the do statement is a block. This is not
662 // the case for C90. Start the loop scope.
663 if (getLang().C99)
664 EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
665 else
666 EnterScope(Scope::BreakScope | Scope::ContinueScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000667
Chris Lattner0ecea032007-08-22 05:28:50 +0000668 // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000669 // there is no compound stmt. C90 does not have this clause. We only do this
670 // if the body isn't a compound statement to avoid push/pop in common cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000671 bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000672 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000673
Reid Spencer5f016e22007-07-11 17:01:13 +0000674 // Read the body statement.
675 StmtResult Body = ParseStatement();
676
Chris Lattner0ecea032007-08-22 05:28:50 +0000677 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000678 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000679
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000680 if (Tok.isNot(tok::kw_while)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000681 ExitScope();
682 Diag(Tok, diag::err_expected_while);
683 Diag(DoLoc, diag::err_matching, "do");
684 SkipUntil(tok::semi);
685 return true;
686 }
687 SourceLocation WhileLoc = ConsumeToken();
688
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000689 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000690 ExitScope();
691 Diag(Tok, diag::err_expected_lparen_after, "do/while");
692 SkipUntil(tok::semi);
693 return true;
694 }
695
696 // Parse the condition.
697 ExprResult Cond = ParseSimpleParenExpression();
698
699 ExitScope();
700
701 if (Cond.isInvalid || Body.isInvalid) return true;
702
Steve Naroff1b273c42007-09-16 14:56:35 +0000703 return Actions.ActOnDoStmt(DoLoc, Body.Val, WhileLoc, Cond.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000704}
705
706/// ParseForStatement
707/// for-statement: [C99 6.8.5.3]
708/// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
709/// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
Fariborz Jahanian3ba5a0f2008-01-03 17:55:25 +0000710/// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
711/// [OBJC2] 'for' '(' expr 'in' expr ')' statement
Reid Spencer5f016e22007-07-11 17:01:13 +0000712Parser::StmtResult Parser::ParseForStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000713 assert(Tok.is(tok::kw_for) && "Not a for stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000714 SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
715
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000716 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000717 Diag(Tok, diag::err_expected_lparen_after, "for");
718 SkipUntil(tok::semi);
719 return true;
720 }
721
Chris Lattner22153252007-08-26 23:08:06 +0000722 // C99 6.8.5p5 - In C99, the for statement is a block. This is not
723 // the case for C90. Start the loop scope.
724 if (getLang().C99)
725 EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
726 else
727 EnterScope(Scope::BreakScope | Scope::ContinueScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000728
729 SourceLocation LParenLoc = ConsumeParen();
730 ExprResult Value;
731
732 StmtTy *FirstPart = 0;
733 ExprTy *SecondPart = 0;
734 StmtTy *ThirdPart = 0;
Fariborz Jahanianbdd15f72008-01-04 23:23:46 +0000735 bool ForEach = false;
Reid Spencer5f016e22007-07-11 17:01:13 +0000736
737 // Parse the first part of the for specifier.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000738 if (Tok.is(tok::semi)) { // for (;
Reid Spencer5f016e22007-07-11 17:01:13 +0000739 // no first part, eat the ';'.
740 ConsumeToken();
741 } else if (isDeclarationSpecifier()) { // for (int X = 4;
742 // Parse declaration, which eats the ';'.
743 if (!getLang().C99) // Use of C99-style for loops in C90 mode?
744 Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
745 DeclTy *aBlockVarDecl = ParseDeclaration(Declarator::ForContext);
Steve Naroff1b273c42007-09-16 14:56:35 +0000746 StmtResult stmtResult = Actions.ActOnDeclStmt(aBlockVarDecl);
Reid Spencer5f016e22007-07-11 17:01:13 +0000747 FirstPart = stmtResult.isInvalid ? 0 : stmtResult.Val;
Fariborz Jahanianbdd15f72008-01-04 23:23:46 +0000748 if ((ForEach = isTokIdentifier_in())) {
Fariborz Jahanian3ba5a0f2008-01-03 17:55:25 +0000749 ConsumeToken(); // consume 'in'
750 Value = ParseExpression();
751 if (!Value.isInvalid)
752 SecondPart = Value.Val;
753 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000754 } else {
755 Value = ParseExpression();
756
757 // Turn the expression into a stmt.
758 if (!Value.isInvalid) {
Steve Naroff1b273c42007-09-16 14:56:35 +0000759 StmtResult R = Actions.ActOnExprStmt(Value.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000760 if (!R.isInvalid)
761 FirstPart = R.Val;
762 }
763
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000764 if (Tok.is(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000765 ConsumeToken();
Fariborz Jahanian3ba5a0f2008-01-03 17:55:25 +0000766 }
Fariborz Jahanianbdd15f72008-01-04 23:23:46 +0000767 else if ((ForEach = isTokIdentifier_in())) {
Fariborz Jahanian3ba5a0f2008-01-03 17:55:25 +0000768 ConsumeToken(); // consume 'in'
769 Value = ParseExpression();
770 if (!Value.isInvalid)
771 SecondPart = Value.Val;
772 }
773 else {
Reid Spencer5f016e22007-07-11 17:01:13 +0000774 if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
775 SkipUntil(tok::semi);
776 }
777 }
Fariborz Jahanianbdd15f72008-01-04 23:23:46 +0000778 if (!ForEach) {
Fariborz Jahanian3ba5a0f2008-01-03 17:55:25 +0000779 // Parse the second part of the for specifier.
780 if (Tok.is(tok::semi)) { // for (...;;
781 // no second part.
782 Value = ExprResult();
783 } else {
784 Value = ParseExpression();
785 if (!Value.isInvalid)
786 SecondPart = Value.Val;
787 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000788
Fariborz Jahanian3ba5a0f2008-01-03 17:55:25 +0000789 if (Tok.is(tok::semi)) {
790 ConsumeToken();
791 } else {
792 if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
793 SkipUntil(tok::semi);
794 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000795
Fariborz Jahanian3ba5a0f2008-01-03 17:55:25 +0000796 // Parse the third part of the for specifier.
797 if (Tok.is(tok::r_paren)) { // for (...;...;)
798 // no third part.
799 Value = ExprResult();
800 } else {
801 Value = ParseExpression();
802 if (!Value.isInvalid) {
803 // Turn the expression into a stmt.
804 StmtResult R = Actions.ActOnExprStmt(Value.Val);
805 if (!R.isInvalid)
806 ThirdPart = R.Val;
807 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000808 }
809 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000810 // Match the ')'.
811 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
812
Chris Lattner0ecea032007-08-22 05:28:50 +0000813 // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000814 // there is no compound stmt. C90 does not have this clause. We only do this
815 // if the body isn't a compound statement to avoid push/pop in common cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000816 bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000817 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000818
Reid Spencer5f016e22007-07-11 17:01:13 +0000819 // Read the body statement.
820 StmtResult Body = ParseStatement();
821
Chris Lattner0ecea032007-08-22 05:28:50 +0000822 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000823 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000824
Reid Spencer5f016e22007-07-11 17:01:13 +0000825 // Leave the for-scope.
826 ExitScope();
827
828 if (Body.isInvalid)
829 return Body;
830
Fariborz Jahanianbdd15f72008-01-04 23:23:46 +0000831 if (!ForEach)
832 return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart,
833 SecondPart, ThirdPart, RParenLoc, Body.Val);
834 else
Ted Kremeneka526c5c2008-01-07 19:49:32 +0000835 return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, FirstPart,
Fariborz Jahanianbdd15f72008-01-04 23:23:46 +0000836 SecondPart, RParenLoc, Body.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000837}
838
839/// ParseGotoStatement
840/// jump-statement:
841/// 'goto' identifier ';'
842/// [GNU] 'goto' '*' expression ';'
843///
844/// Note: this lets the caller parse the end ';'.
845///
846Parser::StmtResult Parser::ParseGotoStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000847 assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000848 SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
849
850 StmtResult Res;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000851 if (Tok.is(tok::identifier)) {
Steve Naroff1b273c42007-09-16 14:56:35 +0000852 Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
Reid Spencer5f016e22007-07-11 17:01:13 +0000853 Tok.getIdentifierInfo());
854 ConsumeToken();
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000855 } else if (Tok.is(tok::star) && !getLang().NoExtensions) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000856 // GNU indirect goto extension.
857 Diag(Tok, diag::ext_gnu_indirect_goto);
858 SourceLocation StarLoc = ConsumeToken();
859 ExprResult R = ParseExpression();
860 if (R.isInvalid) { // Skip to the semicolon, but don't consume it.
861 SkipUntil(tok::semi, false, true);
862 return true;
863 }
Steve Naroff1b273c42007-09-16 14:56:35 +0000864 Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.Val);
Chris Lattner95cfb852007-07-22 04:13:33 +0000865 } else {
866 Diag(Tok, diag::err_expected_ident);
867 return true;
Reid Spencer5f016e22007-07-11 17:01:13 +0000868 }
Chris Lattner95cfb852007-07-22 04:13:33 +0000869
Reid Spencer5f016e22007-07-11 17:01:13 +0000870 return Res;
871}
872
873/// ParseContinueStatement
874/// jump-statement:
875/// 'continue' ';'
876///
877/// Note: this lets the caller parse the end ';'.
878///
879Parser::StmtResult Parser::ParseContinueStatement() {
880 SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
Steve Naroff1b273c42007-09-16 14:56:35 +0000881 return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000882}
883
884/// ParseBreakStatement
885/// jump-statement:
886/// 'break' ';'
887///
888/// Note: this lets the caller parse the end ';'.
889///
890Parser::StmtResult Parser::ParseBreakStatement() {
891 SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
Steve Naroff1b273c42007-09-16 14:56:35 +0000892 return Actions.ActOnBreakStmt(BreakLoc, CurScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000893}
894
895/// ParseReturnStatement
896/// jump-statement:
897/// 'return' expression[opt] ';'
898Parser::StmtResult Parser::ParseReturnStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000899 assert(Tok.is(tok::kw_return) && "Not a return stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000900 SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
901
902 ExprResult R(0);
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000903 if (Tok.isNot(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000904 R = ParseExpression();
905 if (R.isInvalid) { // Skip to the semicolon, but don't consume it.
906 SkipUntil(tok::semi, false, true);
907 return true;
908 }
909 }
Steve Naroff1b273c42007-09-16 14:56:35 +0000910 return Actions.ActOnReturnStmt(ReturnLoc, R.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000911}
912
Steve Naroffd62701b2008-02-07 03:50:06 +0000913Parser::StmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
914 unsigned short savedBraceCount = BraceCount;
915 do {
916 ConsumeAnyToken();
917 } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof));
918 return false;
919}
920
Reid Spencer5f016e22007-07-11 17:01:13 +0000921/// ParseAsmStatement - Parse a GNU extended asm statement.
922/// [GNU] asm-statement:
923/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';'
924///
925/// [GNU] asm-argument:
926/// asm-string-literal
927/// asm-string-literal ':' asm-operands[opt]
928/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
929/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
930/// ':' asm-clobbers
931///
932/// [GNU] asm-clobbers:
933/// asm-string-literal
934/// asm-clobbers ',' asm-string-literal
935///
Steve Naroffd62701b2008-02-07 03:50:06 +0000936Parser::StmtResult Parser::ParseAsmStatement(bool &msAsm) {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000937 assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
Chris Lattnerfe795952007-10-29 04:04:16 +0000938 SourceLocation AsmLoc = ConsumeToken();
Reid Spencer5f016e22007-07-11 17:01:13 +0000939
Steve Naroffd62701b2008-02-07 03:50:06 +0000940 if (Tok.is(tok::l_brace)) {
941 msAsm = true;
942 return FuzzyParseMicrosoftAsmStatement();
943 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000944 DeclSpec DS;
945 SourceLocation Loc = Tok.getLocation();
946 ParseTypeQualifierListOpt(DS);
947
948 // GNU asms accept, but warn, about type-qualifiers other than volatile.
949 if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
950 Diag(Loc, diag::w_asm_qualifier_ignored, "const");
951 if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
952 Diag(Loc, diag::w_asm_qualifier_ignored, "restrict");
953
954 // Remember if this was a volatile asm.
Anders Carlsson39c47b52007-11-23 23:12:25 +0000955 bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
Anders Carlssondfab34a2008-02-05 23:03:50 +0000956 bool isSimple = false;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000957 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000958 Diag(Tok, diag::err_expected_lparen_after, "asm");
959 SkipUntil(tok::r_paren);
960 return true;
961 }
962 Loc = ConsumeParen();
963
Anders Carlsson6a0ef4b2007-11-20 19:21:03 +0000964 ExprResult AsmString = ParseAsmStringLiteral();
965 if (AsmString.isInvalid)
966 return true;
Anders Carlssonb235fc22007-11-22 01:36:19 +0000967
968 llvm::SmallVector<std::string, 4> Names;
969 llvm::SmallVector<ExprTy*, 4> Constraints;
970 llvm::SmallVector<ExprTy*, 4> Exprs;
Anders Carlssonb235fc22007-11-22 01:36:19 +0000971 llvm::SmallVector<ExprTy*, 4> Clobbers;
Reid Spencer5f016e22007-07-11 17:01:13 +0000972
Anders Carlssondfab34a2008-02-05 23:03:50 +0000973 unsigned NumInputs = 0, NumOutputs = 0;
974
975 SourceLocation RParenLoc;
976 if (Tok.is(tok::r_paren)) {
977 // We have a simple asm expression
978 isSimple = true;
979
980 RParenLoc = ConsumeParen();
981 } else {
982 // Parse Outputs, if present.
983 ParseAsmOperandsOpt(Names, Constraints, Exprs);
984
985 NumOutputs = Names.size();
986
987 // Parse Inputs, if present.
988 ParseAsmOperandsOpt(Names, Constraints, Exprs);
989 assert(Names.size() == Constraints.size() &&
990 Constraints.size() == Exprs.size()
991 && "Input operand size mismatch!");
992
993 NumInputs = Names.size() - NumOutputs;
994
995 // Parse the clobbers, if present.
996 if (Tok.is(tok::colon)) {
Anders Carlssoneecf8472007-11-21 23:27:34 +0000997 ConsumeToken();
Anders Carlssondfab34a2008-02-05 23:03:50 +0000998
999 // Parse the asm-string list for clobbers.
1000 while (1) {
1001 ExprResult Clobber = ParseAsmStringLiteral();
1002
1003 if (Clobber.isInvalid)
1004 break;
1005
1006 Clobbers.push_back(Clobber.Val);
1007
1008 if (Tok.isNot(tok::comma)) break;
1009 ConsumeToken();
1010 }
Reid Spencer5f016e22007-07-11 17:01:13 +00001011 }
Anders Carlssondfab34a2008-02-05 23:03:50 +00001012
1013 RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc);
Reid Spencer5f016e22007-07-11 17:01:13 +00001014 }
1015
Anders Carlssondfab34a2008-02-05 23:03:50 +00001016 return Actions.ActOnAsmStmt(AsmLoc, isSimple, isVolatile,
1017 NumOutputs, NumInputs,
Anders Carlssonb235fc22007-11-22 01:36:19 +00001018 &Names[0], &Constraints[0], &Exprs[0],
1019 AsmString.Val,
1020 Clobbers.size(), &Clobbers[0],
1021 RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +00001022}
1023
1024/// ParseAsmOperands - Parse the asm-operands production as used by
1025/// asm-statement. We also parse a leading ':' token. If the leading colon is
1026/// not present, we do not parse anything.
1027///
1028/// [GNU] asm-operands:
1029/// asm-operand
1030/// asm-operands ',' asm-operand
1031///
1032/// [GNU] asm-operand:
1033/// asm-string-literal '(' expression ')'
1034/// '[' identifier ']' asm-string-literal '(' expression ')'
1035///
Anders Carlssonb235fc22007-11-22 01:36:19 +00001036void Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
1037 llvm::SmallVectorImpl<ExprTy*> &Constraints,
1038 llvm::SmallVectorImpl<ExprTy*> &Exprs) {
Reid Spencer5f016e22007-07-11 17:01:13 +00001039 // Only do anything if this operand is present.
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001040 if (Tok.isNot(tok::colon)) return;
Reid Spencer5f016e22007-07-11 17:01:13 +00001041 ConsumeToken();
1042
1043 // 'asm-operands' isn't present?
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001044 if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
Reid Spencer5f016e22007-07-11 17:01:13 +00001045 return;
1046
Anders Carlssonb235fc22007-11-22 01:36:19 +00001047 while (1) {
Reid Spencer5f016e22007-07-11 17:01:13 +00001048 // Read the [id] if present.
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001049 if (Tok.is(tok::l_square)) {
Reid Spencer5f016e22007-07-11 17:01:13 +00001050 SourceLocation Loc = ConsumeBracket();
1051
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001052 if (Tok.isNot(tok::identifier)) {
Reid Spencer5f016e22007-07-11 17:01:13 +00001053 Diag(Tok, diag::err_expected_ident);
1054 SkipUntil(tok::r_paren);
1055 return;
1056 }
Chris Lattner69efba72007-10-29 04:06:22 +00001057
Anders Carlssonb235fc22007-11-22 01:36:19 +00001058 IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner69efba72007-10-29 04:06:22 +00001059 ConsumeToken();
Anders Carlssonb235fc22007-11-22 01:36:19 +00001060
1061 Names.push_back(std::string(II->getName(), II->getLength()));
Reid Spencer5f016e22007-07-11 17:01:13 +00001062 MatchRHSPunctuation(tok::r_square, Loc);
Anders Carlssonb235fc22007-11-22 01:36:19 +00001063 } else
1064 Names.push_back(std::string());
Reid Spencer5f016e22007-07-11 17:01:13 +00001065
Anders Carlssonb235fc22007-11-22 01:36:19 +00001066 ExprResult Constraint = ParseAsmStringLiteral();
1067 if (Constraint.isInvalid) {
1068 SkipUntil(tok::r_paren);
1069 return;
1070 }
1071 Constraints.push_back(Constraint.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +00001072
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001073 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +00001074 Diag(Tok, diag::err_expected_lparen_after, "asm operand");
1075 SkipUntil(tok::r_paren);
1076 return;
1077 }
1078
1079 // Read the parenthesized expression.
1080 ExprResult Res = ParseSimpleParenExpression();
1081 if (Res.isInvalid) {
1082 SkipUntil(tok::r_paren);
1083 return;
1084 }
Anders Carlssonb235fc22007-11-22 01:36:19 +00001085 Exprs.push_back(Res.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +00001086 // Eat the comma and continue parsing if it exists.
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001087 if (Tok.isNot(tok::comma)) return;
Reid Spencer5f016e22007-07-11 17:01:13 +00001088 ConsumeToken();
1089 }
1090}
Fariborz Jahanianf9ed3152007-11-08 19:01:26 +00001091
1092Parser::DeclTy *Parser::ParseFunctionStatementBody(DeclTy *Decl,
1093 SourceLocation L, SourceLocation R) {
1094 // Do not enter a scope for the brace, as the arguments are in the same scope
1095 // (the function body) as the body itself. Instead, just read the statement
1096 // list and put it into a CompoundStmt for safe keeping.
1097 StmtResult FnBody = ParseCompoundStatementBody();
1098
1099 // If the function body could not be parsed, make a bogus compoundstmt.
1100 if (FnBody.isInvalid)
1101 FnBody = Actions.ActOnCompoundStmt(L, R, 0, 0, false);
1102
1103 // Leave the function body scope.
1104 ExitScope();
1105
Steve Naroffd6d054d2007-11-11 23:20:51 +00001106 return Actions.ActOnFinishFunctionBody(Decl, FnBody.Val);
Seo Sanghyeoncd5af4b2007-12-01 08:06:07 +00001107}