blob: d37973b0139ed18a2bc1ab16511bbfbc54e45948 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
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
37/// [OBC] objc-throw-statement [TODO]
38/// [OBC] objc-try-catch-statement [TODO]
39/// [OBC] objc-synchronized-statement [TODO]
40/// [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///
67/// [OBC] objc-throw-statement: [TODO]
68/// [OBC] '@' 'throw' expression ';' [TODO]
69/// [OBC] '@' 'throw' ';' [TODO]
70///
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 @
90 if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_try)
91 return ParseObjCTryStmt(AtLoc);
92 else if (Tok.getIdentifierInfo()->getObjCKeywordID() == tok::objc_throw)
93 return ParseObjCThrowStmt(AtLoc);
94 }
95 // Fall thru.
96
Reid Spencer5f016e22007-07-11 17:01:13 +000097 default:
Fariborz Jahanian397fcc12007-09-19 19:14:32 +000098 if (Kind != tok::at && !OnlyStatement && isDeclarationSpecifier()) {
Steve Naroff1b273c42007-09-16 14:56:35 +000099 return Actions.ActOnDeclStmt(ParseDeclaration(Declarator::BlockContext));
Reid Spencer5f016e22007-07-11 17:01:13 +0000100 } else if (Tok.getKind() == tok::r_brace) {
101 Diag(Tok, diag::err_expected_statement);
102 return true;
103 } else {
104 // expression[opt] ';'
Fariborz Jahanian397fcc12007-09-19 19:14:32 +0000105 ExprResult Res = (Kind == tok::at) ? ParseExpressionWithLeadingAt(AtLoc)
106 : ParseExpression();
Reid Spencer5f016e22007-07-11 17:01:13 +0000107 if (Res.isInvalid) {
108 // If the expression is invalid, skip ahead to the next semicolon. Not
109 // doing this opens us up to the possibility of infinite loops if
110 // ParseExpression does not consume any tokens.
111 SkipUntil(tok::semi);
112 return true;
113 }
114 // Otherwise, eat the semicolon.
115 ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
Steve Naroff1b273c42007-09-16 14:56:35 +0000116 return Actions.ActOnExprStmt(Res.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000117 }
118
119 case tok::kw_case: // C99 6.8.1: labeled-statement
120 return ParseCaseStatement();
121 case tok::kw_default: // C99 6.8.1: labeled-statement
122 return ParseDefaultStatement();
123
124 case tok::l_brace: // C99 6.8.2: compound-statement
125 return ParseCompoundStatement();
126 case tok::semi: // C99 6.8.3p3: expression[opt] ';'
Steve Naroff1b273c42007-09-16 14:56:35 +0000127 return Actions.ActOnNullStmt(ConsumeToken());
Reid Spencer5f016e22007-07-11 17:01:13 +0000128
129 case tok::kw_if: // C99 6.8.4.1: if-statement
130 return ParseIfStatement();
131 case tok::kw_switch: // C99 6.8.4.2: switch-statement
132 return ParseSwitchStatement();
133
134 case tok::kw_while: // C99 6.8.5.1: while-statement
135 return ParseWhileStatement();
136 case tok::kw_do: // C99 6.8.5.2: do-statement
137 Res = ParseDoStatement();
138 SemiError = "do/while loop";
139 break;
140 case tok::kw_for: // C99 6.8.5.3: for-statement
141 return ParseForStatement();
142
143 case tok::kw_goto: // C99 6.8.6.1: goto-statement
144 Res = ParseGotoStatement();
145 SemiError = "goto statement";
146 break;
147 case tok::kw_continue: // C99 6.8.6.2: continue-statement
148 Res = ParseContinueStatement();
149 SemiError = "continue statement";
150 break;
151 case tok::kw_break: // C99 6.8.6.3: break-statement
152 Res = ParseBreakStatement();
153 SemiError = "break statement";
154 break;
155 case tok::kw_return: // C99 6.8.6.4: return-statement
156 Res = ParseReturnStatement();
157 SemiError = "return statement";
158 break;
159
160 case tok::kw_asm:
161 Res = ParseAsmStatement();
162 SemiError = "asm statement";
163 break;
164 }
165
166 // If we reached this code, the statement must end in a semicolon.
167 if (Tok.getKind() == tok::semi) {
168 ConsumeToken();
169 } else {
170 Diag(Tok, diag::err_expected_semi_after, SemiError);
171 SkipUntil(tok::semi);
172 }
173 return Res;
174}
175
176/// ParseIdentifierStatement - Because we don't have two-token lookahead, we
177/// have a bit of a quandry here. Reading the identifier is necessary to see if
178/// there is a ':' after it. If there is, this is a label, regardless of what
179/// else the identifier can mean. If not, this is either part of a declaration
180/// (if the identifier is a type-name) or part of an expression.
181///
182/// labeled-statement:
183/// identifier ':' statement
184/// [GNU] identifier ':' attributes[opt] statement
185/// declaration (if !OnlyStatement)
186/// expression[opt] ';'
187///
188Parser::StmtResult Parser::ParseIdentifierStatement(bool OnlyStatement) {
189 assert(Tok.getKind() == tok::identifier && Tok.getIdentifierInfo() &&
190 "Not an identifier!");
191
Chris Lattnerd2177732007-07-20 16:59:19 +0000192 Token IdentTok = Tok; // Save the whole token.
Reid Spencer5f016e22007-07-11 17:01:13 +0000193 ConsumeToken(); // eat the identifier.
194
195 // identifier ':' statement
196 if (Tok.getKind() == tok::colon) {
197 SourceLocation ColonLoc = ConsumeToken();
198
199 // Read label attributes, if present.
200 DeclTy *AttrList = 0;
201 if (Tok.getKind() == tok::kw___attribute)
202 // TODO: save these somewhere.
203 AttrList = ParseAttributes();
204
205 StmtResult SubStmt = ParseStatement();
206
207 // Broken substmt shouldn't prevent the label from being added to the AST.
208 if (SubStmt.isInvalid)
Steve Naroff1b273c42007-09-16 14:56:35 +0000209 SubStmt = Actions.ActOnNullStmt(ColonLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000210
Steve Naroff1b273c42007-09-16 14:56:35 +0000211 return Actions.ActOnLabelStmt(IdentTok.getLocation(),
Reid Spencer5f016e22007-07-11 17:01:13 +0000212 IdentTok.getIdentifierInfo(),
213 ColonLoc, SubStmt.Val);
214 }
215
216 // Check to see if this is a declaration.
217 void *TypeRep;
218 if (!OnlyStatement &&
219 (TypeRep = Actions.isTypeName(*IdentTok.getIdentifierInfo(), CurScope))) {
220 // Handle this. Warn/disable if in middle of block and !C99.
221 DeclSpec DS;
222
223 // Add the typedef name to the start of the decl-specs.
224 const char *PrevSpec = 0;
225 int isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typedef,
226 IdentTok.getLocation(), PrevSpec,
227 TypeRep);
228 assert(!isInvalid && "First declspec can't be invalid!");
229
230 // ParseDeclarationSpecifiers will continue from there.
231 ParseDeclarationSpecifiers(DS);
232
233 // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
234 // declaration-specifiers init-declarator-list[opt] ';'
235 if (Tok.getKind() == tok::semi) {
236 // TODO: emit error on 'int;' or 'const enum foo;'.
237 // if (!DS.isMissingDeclaratorOk()) Diag(...);
238
239 ConsumeToken();
240 // FIXME: Return this as a type decl.
241 return 0;
242 }
243
244 // Parse all the declarators.
245 Declarator DeclaratorInfo(DS, Declarator::BlockContext);
246 ParseDeclarator(DeclaratorInfo);
247
248 DeclTy *Decl = ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
Steve Naroff1b273c42007-09-16 14:56:35 +0000249 return Decl ? Actions.ActOnDeclStmt(Decl) : 0;
Reid Spencer5f016e22007-07-11 17:01:13 +0000250 }
251
252 // Otherwise, this is an expression. Seed it with II and parse it.
253 ExprResult Res = ParseExpressionWithLeadingIdentifier(IdentTok);
254 if (Res.isInvalid) {
255 SkipUntil(tok::semi);
256 return true;
257 } else if (Tok.getKind() != tok::semi) {
258 Diag(Tok, diag::err_expected_semi_after, "expression");
259 SkipUntil(tok::semi);
260 return true;
261 } else {
262 ConsumeToken();
263 // Convert expr to a stmt.
Steve Naroff1b273c42007-09-16 14:56:35 +0000264 return Actions.ActOnExprStmt(Res.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000265 }
266}
267
268/// ParseCaseStatement
269/// labeled-statement:
270/// 'case' constant-expression ':' statement
271/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
272///
273/// Note that this does not parse the 'statement' at the end.
274///
275Parser::StmtResult Parser::ParseCaseStatement() {
276 assert(Tok.getKind() == tok::kw_case && "Not a case stmt!");
277 SourceLocation CaseLoc = ConsumeToken(); // eat the 'case'.
278
279 ExprResult LHS = ParseConstantExpression();
280 if (LHS.isInvalid) {
281 SkipUntil(tok::colon);
282 return true;
283 }
284
285 // GNU case range extension.
286 SourceLocation DotDotDotLoc;
287 ExprTy *RHSVal = 0;
288 if (Tok.getKind() == tok::ellipsis) {
289 Diag(Tok, diag::ext_gnu_case_range);
290 DotDotDotLoc = ConsumeToken();
291
292 ExprResult RHS = ParseConstantExpression();
293 if (RHS.isInvalid) {
294 SkipUntil(tok::colon);
295 return true;
296 }
297 RHSVal = RHS.Val;
298 }
299
300 if (Tok.getKind() != tok::colon) {
301 Diag(Tok, diag::err_expected_colon_after, "'case'");
302 SkipUntil(tok::colon);
303 return true;
304 }
305
306 SourceLocation ColonLoc = ConsumeToken();
307
308 // Diagnose the common error "switch (X) { case 4: }", which is not valid.
309 if (Tok.getKind() == tok::r_brace) {
310 Diag(Tok, diag::err_label_end_of_compound_statement);
311 return true;
312 }
313
314 StmtResult SubStmt = ParseStatement();
315
316 // Broken substmt shouldn't prevent the case from being added to the AST.
317 if (SubStmt.isInvalid)
Steve Naroff1b273c42007-09-16 14:56:35 +0000318 SubStmt = Actions.ActOnNullStmt(ColonLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000319
Steve Naroff1b273c42007-09-16 14:56:35 +0000320 return Actions.ActOnCaseStmt(CaseLoc, LHS.Val, DotDotDotLoc, RHSVal, ColonLoc,
Reid Spencer5f016e22007-07-11 17:01:13 +0000321 SubStmt.Val);
322}
323
324/// ParseDefaultStatement
325/// labeled-statement:
326/// 'default' ':' statement
327/// Note that this does not parse the 'statement' at the end.
328///
329Parser::StmtResult Parser::ParseDefaultStatement() {
330 assert(Tok.getKind() == tok::kw_default && "Not a default stmt!");
331 SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
332
333 if (Tok.getKind() != tok::colon) {
334 Diag(Tok, diag::err_expected_colon_after, "'default'");
335 SkipUntil(tok::colon);
336 return true;
337 }
338
339 SourceLocation ColonLoc = ConsumeToken();
340
341 // Diagnose the common error "switch (X) {... default: }", which is not valid.
342 if (Tok.getKind() == tok::r_brace) {
343 Diag(Tok, diag::err_label_end_of_compound_statement);
344 return true;
345 }
346
347 StmtResult SubStmt = ParseStatement();
348 if (SubStmt.isInvalid)
349 return true;
350
Steve Naroff1b273c42007-09-16 14:56:35 +0000351 return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt.Val, CurScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000352}
353
354
355/// ParseCompoundStatement - Parse a "{}" block.
356///
357/// compound-statement: [C99 6.8.2]
358/// { block-item-list[opt] }
359/// [GNU] { label-declarations block-item-list } [TODO]
360///
361/// block-item-list:
362/// block-item
363/// block-item-list block-item
364///
365/// block-item:
366/// declaration
Chris Lattner45a566c2007-08-27 01:01:57 +0000367/// [GNU] '__extension__' declaration
Reid Spencer5f016e22007-07-11 17:01:13 +0000368/// statement
369/// [OMP] openmp-directive [TODO]
370///
371/// [GNU] label-declarations:
372/// [GNU] label-declaration
373/// [GNU] label-declarations label-declaration
374///
375/// [GNU] label-declaration:
376/// [GNU] '__label__' identifier-list ';'
377///
378/// [OMP] openmp-directive: [TODO]
379/// [OMP] barrier-directive
380/// [OMP] flush-directive
381///
Chris Lattner98414c12007-08-31 21:49:55 +0000382Parser::StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000383 assert(Tok.getKind() == tok::l_brace && "Not a compount stmt!");
384
Chris Lattner31e05722007-08-26 06:24:45 +0000385 // Enter a scope to hold everything within the compound stmt. Compound
386 // statements can always hold declarations.
387 EnterScope(Scope::DeclScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000388
389 // Parse the statements in the body.
Chris Lattner98414c12007-08-31 21:49:55 +0000390 StmtResult Body = ParseCompoundStatementBody(isStmtExpr);
Reid Spencer5f016e22007-07-11 17:01:13 +0000391
392 ExitScope();
393 return Body;
394}
395
396
397/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
Steve Naroff1b273c42007-09-16 14:56:35 +0000398/// ActOnCompoundStmt action. This expects the '{' to be the current token, and
Reid Spencer5f016e22007-07-11 17:01:13 +0000399/// consume the '}' at the end of the block. It does not manipulate the scope
400/// stack.
Chris Lattner98414c12007-08-31 21:49:55 +0000401Parser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000402 SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'.
403
404 // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
Chris Lattner45a566c2007-08-27 01:01:57 +0000405 // only allowed at the start of a compound stmt regardless of the language.
Reid Spencer5f016e22007-07-11 17:01:13 +0000406
407 llvm::SmallVector<StmtTy*, 32> Stmts;
408 while (Tok.getKind() != tok::r_brace && Tok.getKind() != tok::eof) {
Chris Lattner45a566c2007-08-27 01:01:57 +0000409 StmtResult R;
410 if (Tok.getKind() != tok::kw___extension__) {
411 R = ParseStatementOrDeclaration(false);
412 } else {
413 // __extension__ can start declarations and it can also be a unary
414 // operator for expressions. Consume multiple __extension__ markers here
415 // until we can determine which is which.
416 SourceLocation ExtLoc = ConsumeToken();
417 while (Tok.getKind() == tok::kw___extension__)
418 ConsumeToken();
419
420 // If this is the start of a declaration, parse it as such.
421 if (isDeclarationSpecifier()) {
422 // FIXME: Save the __extension__ on the decl as a node somehow.
423 // FIXME: disable extwarns.
Steve Naroff1b273c42007-09-16 14:56:35 +0000424 R = Actions.ActOnDeclStmt(ParseDeclaration(Declarator::BlockContext));
Chris Lattner45a566c2007-08-27 01:01:57 +0000425 } else {
426 // Otherwise this was a unary __extension__ marker. Parse the
427 // subexpression and add the __extension__ unary op.
428 // FIXME: disable extwarns.
429 ExprResult Res = ParseCastExpression(false);
430 if (Res.isInvalid) {
431 SkipUntil(tok::semi);
432 continue;
433 }
434
435 // Add the __extension__ node to the AST.
Steve Narofff69936d2007-09-16 03:34:24 +0000436 Res = Actions.ActOnUnaryOp(ExtLoc, tok::kw___extension__, Res.Val);
Chris Lattner45a566c2007-08-27 01:01:57 +0000437 if (Res.isInvalid)
438 continue;
439
440 // Eat the semicolon at the end of stmt and convert the expr into a stmt.
441 ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
Steve Naroff1b273c42007-09-16 14:56:35 +0000442 R = Actions.ActOnExprStmt(Res.Val);
Chris Lattner45a566c2007-08-27 01:01:57 +0000443 }
444 }
445
Reid Spencer5f016e22007-07-11 17:01:13 +0000446 if (!R.isInvalid && R.Val)
447 Stmts.push_back(R.Val);
448 }
449
450 // We broke out of the while loop because we found a '}' or EOF.
451 if (Tok.getKind() != tok::r_brace) {
452 Diag(Tok, diag::err_expected_rbrace);
453 return 0;
454 }
455
456 SourceLocation RBraceLoc = ConsumeBrace();
Steve Naroff1b273c42007-09-16 14:56:35 +0000457 return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
Chris Lattner98414c12007-08-31 21:49:55 +0000458 &Stmts[0], Stmts.size(), isStmtExpr);
Reid Spencer5f016e22007-07-11 17:01:13 +0000459}
460
461/// ParseIfStatement
462/// if-statement: [C99 6.8.4.1]
463/// 'if' '(' expression ')' statement
464/// 'if' '(' expression ')' statement 'else' statement
465///
466Parser::StmtResult Parser::ParseIfStatement() {
467 assert(Tok.getKind() == tok::kw_if && "Not an if stmt!");
468 SourceLocation IfLoc = ConsumeToken(); // eat the 'if'.
469
470 if (Tok.getKind() != tok::l_paren) {
471 Diag(Tok, diag::err_expected_lparen_after, "if");
472 SkipUntil(tok::semi);
473 return true;
474 }
475
Chris Lattner22153252007-08-26 23:08:06 +0000476 // C99 6.8.4p3 - In C99, the if statement is a block. This is not
477 // the case for C90.
478 if (getLang().C99)
479 EnterScope(Scope::DeclScope);
480
Reid Spencer5f016e22007-07-11 17:01:13 +0000481 // Parse the condition.
482 ExprResult CondExp = ParseSimpleParenExpression();
483 if (CondExp.isInvalid) {
484 SkipUntil(tok::semi);
Chris Lattner22153252007-08-26 23:08:06 +0000485 if (getLang().C99)
486 ExitScope();
Reid Spencer5f016e22007-07-11 17:01:13 +0000487 return true;
488 }
489
Chris Lattner0ecea032007-08-22 05:28:50 +0000490 // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000491 // there is no compound stmt. C90 does not have this clause. We only do this
492 // if the body isn't a compound statement to avoid push/pop in common cases.
493 bool NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace;
Chris Lattner31e05722007-08-26 06:24:45 +0000494 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattnera36ce712007-08-22 05:16:28 +0000495
Reid Spencer5f016e22007-07-11 17:01:13 +0000496 // Read the if condition.
497 StmtResult CondStmt = ParseStatement();
498
499 // Broken substmt shouldn't prevent the label from being added to the AST.
500 if (CondStmt.isInvalid)
Steve Naroff1b273c42007-09-16 14:56:35 +0000501 CondStmt = Actions.ActOnNullStmt(Tok.getLocation());
Reid Spencer5f016e22007-07-11 17:01:13 +0000502
Chris Lattnera36ce712007-08-22 05:16:28 +0000503 // Pop the 'if' scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000504 if (NeedsInnerScope) ExitScope();
Reid Spencer5f016e22007-07-11 17:01:13 +0000505
506 // If it has an else, parse it.
507 SourceLocation ElseLoc;
508 StmtResult ElseStmt(false);
509 if (Tok.getKind() == tok::kw_else) {
510 ElseLoc = ConsumeToken();
Chris Lattnera36ce712007-08-22 05:16:28 +0000511
Chris Lattner0ecea032007-08-22 05:28:50 +0000512 // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000513 // there is no compound stmt. C90 does not have this clause. We only do
514 // this if the body isn't a compound statement to avoid push/pop in common
515 // cases.
516 NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace;
Chris Lattner31e05722007-08-26 06:24:45 +0000517 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattnera36ce712007-08-22 05:16:28 +0000518
Reid Spencer5f016e22007-07-11 17:01:13 +0000519 ElseStmt = ParseStatement();
Chris Lattnera36ce712007-08-22 05:16:28 +0000520
521 // Pop the 'else' scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000522 if (NeedsInnerScope) ExitScope();
Reid Spencer5f016e22007-07-11 17:01:13 +0000523
524 if (ElseStmt.isInvalid)
Steve Naroff1b273c42007-09-16 14:56:35 +0000525 ElseStmt = Actions.ActOnNullStmt(ElseLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000526 }
527
Chris Lattner22153252007-08-26 23:08:06 +0000528 if (getLang().C99)
529 ExitScope();
530
Steve Naroff1b273c42007-09-16 14:56:35 +0000531 return Actions.ActOnIfStmt(IfLoc, CondExp.Val, CondStmt.Val,
Reid Spencer5f016e22007-07-11 17:01:13 +0000532 ElseLoc, ElseStmt.Val);
533}
534
535/// ParseSwitchStatement
536/// switch-statement:
537/// 'switch' '(' expression ')' statement
538Parser::StmtResult Parser::ParseSwitchStatement() {
539 assert(Tok.getKind() == tok::kw_switch && "Not a switch stmt!");
540 SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'.
541
542 if (Tok.getKind() != tok::l_paren) {
543 Diag(Tok, diag::err_expected_lparen_after, "switch");
544 SkipUntil(tok::semi);
545 return true;
546 }
Chris Lattner22153252007-08-26 23:08:06 +0000547
548 // C99 6.8.4p3 - In C99, the switch statement is a block. This is
549 // not the case for C90. Start the switch scope.
550 if (getLang().C99)
551 EnterScope(Scope::BreakScope|Scope::DeclScope);
552 else
553 EnterScope(Scope::BreakScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000554
555 // Parse the condition.
556 ExprResult Cond = ParseSimpleParenExpression();
557
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000558 if (Cond.isInvalid) {
559 ExitScope();
560 return true;
561 }
562
Steve Naroff1b273c42007-09-16 14:56:35 +0000563 StmtResult Switch = Actions.ActOnStartOfSwitchStmt(Cond.Val);
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000564
Chris Lattner0ecea032007-08-22 05:28:50 +0000565 // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000566 // there is no compound stmt. C90 does not have this clause. We only do this
567 // if the body isn't a compound statement to avoid push/pop in common cases.
568 bool NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace;
Chris Lattner31e05722007-08-26 06:24:45 +0000569 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000570
Reid Spencer5f016e22007-07-11 17:01:13 +0000571 // Read the body statement.
572 StmtResult Body = ParseStatement();
573
Chris Lattner0ecea032007-08-22 05:28:50 +0000574 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000575 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000576
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000577 if (Body.isInvalid) {
Steve Naroff1b273c42007-09-16 14:56:35 +0000578 Body = Actions.ActOnNullStmt(Tok.getLocation());
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000579 // FIXME: Remove the case statement list from the Switch statement.
580 }
581
Reid Spencer5f016e22007-07-11 17:01:13 +0000582 ExitScope();
583
Steve Naroff1b273c42007-09-16 14:56:35 +0000584 return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.Val, Body.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000585}
586
587/// ParseWhileStatement
588/// while-statement: [C99 6.8.5.1]
589/// 'while' '(' expression ')' statement
590Parser::StmtResult Parser::ParseWhileStatement() {
591 assert(Tok.getKind() == tok::kw_while && "Not a while stmt!");
592 SourceLocation WhileLoc = Tok.getLocation();
593 ConsumeToken(); // eat the 'while'.
594
595 if (Tok.getKind() != tok::l_paren) {
596 Diag(Tok, diag::err_expected_lparen_after, "while");
597 SkipUntil(tok::semi);
598 return true;
599 }
600
Chris Lattner22153252007-08-26 23:08:06 +0000601 // C99 6.8.5p5 - In C99, the while statement is a block. This is not
602 // the case for C90. Start the loop scope.
603 if (getLang().C99)
604 EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
605 else
606 EnterScope(Scope::BreakScope | Scope::ContinueScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000607
608 // Parse the condition.
609 ExprResult Cond = ParseSimpleParenExpression();
610
Chris Lattner0ecea032007-08-22 05:28:50 +0000611 // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000612 // there is no compound stmt. C90 does not have this clause. We only do this
613 // if the body isn't a compound statement to avoid push/pop in common cases.
614 bool NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace;
Chris Lattner31e05722007-08-26 06:24:45 +0000615 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000616
Reid Spencer5f016e22007-07-11 17:01:13 +0000617 // Read the body statement.
618 StmtResult Body = ParseStatement();
619
Chris Lattner0ecea032007-08-22 05:28:50 +0000620 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000621 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000622
Reid Spencer5f016e22007-07-11 17:01:13 +0000623 ExitScope();
624
625 if (Cond.isInvalid || Body.isInvalid) return true;
626
Steve Naroff1b273c42007-09-16 14:56:35 +0000627 return Actions.ActOnWhileStmt(WhileLoc, Cond.Val, Body.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000628}
629
630/// ParseDoStatement
631/// do-statement: [C99 6.8.5.2]
632/// 'do' statement 'while' '(' expression ')' ';'
633/// Note: this lets the caller parse the end ';'.
634Parser::StmtResult Parser::ParseDoStatement() {
635 assert(Tok.getKind() == tok::kw_do && "Not a do stmt!");
636 SourceLocation DoLoc = ConsumeToken(); // eat the 'do'.
637
Chris Lattner22153252007-08-26 23:08:06 +0000638 // C99 6.8.5p5 - In C99, the do statement is a block. This is not
639 // the case for C90. Start the loop scope.
640 if (getLang().C99)
641 EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
642 else
643 EnterScope(Scope::BreakScope | Scope::ContinueScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000644
Chris Lattner0ecea032007-08-22 05:28:50 +0000645 // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000646 // there is no compound stmt. C90 does not have this clause. We only do this
647 // if the body isn't a compound statement to avoid push/pop in common cases.
648 bool NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace;
Chris Lattner31e05722007-08-26 06:24:45 +0000649 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000650
Reid Spencer5f016e22007-07-11 17:01:13 +0000651 // Read the body statement.
652 StmtResult Body = ParseStatement();
653
Chris Lattner0ecea032007-08-22 05:28:50 +0000654 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000655 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000656
Reid Spencer5f016e22007-07-11 17:01:13 +0000657 if (Tok.getKind() != tok::kw_while) {
658 ExitScope();
659 Diag(Tok, diag::err_expected_while);
660 Diag(DoLoc, diag::err_matching, "do");
661 SkipUntil(tok::semi);
662 return true;
663 }
664 SourceLocation WhileLoc = ConsumeToken();
665
666 if (Tok.getKind() != tok::l_paren) {
667 ExitScope();
668 Diag(Tok, diag::err_expected_lparen_after, "do/while");
669 SkipUntil(tok::semi);
670 return true;
671 }
672
673 // Parse the condition.
674 ExprResult Cond = ParseSimpleParenExpression();
675
676 ExitScope();
677
678 if (Cond.isInvalid || Body.isInvalid) return true;
679
Steve Naroff1b273c42007-09-16 14:56:35 +0000680 return Actions.ActOnDoStmt(DoLoc, Body.Val, WhileLoc, Cond.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000681}
682
683/// ParseForStatement
684/// for-statement: [C99 6.8.5.3]
685/// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
686/// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
687Parser::StmtResult Parser::ParseForStatement() {
688 assert(Tok.getKind() == tok::kw_for && "Not a for stmt!");
689 SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
690
691 if (Tok.getKind() != tok::l_paren) {
692 Diag(Tok, diag::err_expected_lparen_after, "for");
693 SkipUntil(tok::semi);
694 return true;
695 }
696
Chris Lattner22153252007-08-26 23:08:06 +0000697 // C99 6.8.5p5 - In C99, the for statement is a block. This is not
698 // the case for C90. Start the loop scope.
699 if (getLang().C99)
700 EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
701 else
702 EnterScope(Scope::BreakScope | Scope::ContinueScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000703
704 SourceLocation LParenLoc = ConsumeParen();
705 ExprResult Value;
706
707 StmtTy *FirstPart = 0;
708 ExprTy *SecondPart = 0;
709 StmtTy *ThirdPart = 0;
710
711 // Parse the first part of the for specifier.
712 if (Tok.getKind() == tok::semi) { // for (;
713 // no first part, eat the ';'.
714 ConsumeToken();
715 } else if (isDeclarationSpecifier()) { // for (int X = 4;
716 // Parse declaration, which eats the ';'.
717 if (!getLang().C99) // Use of C99-style for loops in C90 mode?
718 Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
719 DeclTy *aBlockVarDecl = ParseDeclaration(Declarator::ForContext);
Steve Naroff1b273c42007-09-16 14:56:35 +0000720 StmtResult stmtResult = Actions.ActOnDeclStmt(aBlockVarDecl);
Reid Spencer5f016e22007-07-11 17:01:13 +0000721 FirstPart = stmtResult.isInvalid ? 0 : stmtResult.Val;
722 } else {
723 Value = ParseExpression();
724
725 // Turn the expression into a stmt.
726 if (!Value.isInvalid) {
Steve Naroff1b273c42007-09-16 14:56:35 +0000727 StmtResult R = Actions.ActOnExprStmt(Value.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000728 if (!R.isInvalid)
729 FirstPart = R.Val;
730 }
731
732 if (Tok.getKind() == tok::semi) {
733 ConsumeToken();
734 } else {
735 if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
736 SkipUntil(tok::semi);
737 }
738 }
739
740 // Parse the second part of the for specifier.
741 if (Tok.getKind() == tok::semi) { // for (...;;
742 // no second part.
743 Value = ExprResult();
744 } else {
745 Value = ParseExpression();
746 if (!Value.isInvalid)
747 SecondPart = Value.Val;
748 }
749
750 if (Tok.getKind() == tok::semi) {
751 ConsumeToken();
752 } else {
753 if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
754 SkipUntil(tok::semi);
755 }
756
757 // Parse the third part of the for specifier.
758 if (Tok.getKind() == tok::r_paren) { // for (...;...;)
759 // no third part.
760 Value = ExprResult();
761 } else {
762 Value = ParseExpression();
763 if (!Value.isInvalid) {
764 // Turn the expression into a stmt.
Steve Naroff1b273c42007-09-16 14:56:35 +0000765 StmtResult R = Actions.ActOnExprStmt(Value.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000766 if (!R.isInvalid)
767 ThirdPart = R.Val;
768 }
769 }
770
771 // Match the ')'.
772 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
773
Chris Lattner0ecea032007-08-22 05:28:50 +0000774 // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000775 // there is no compound stmt. C90 does not have this clause. We only do this
776 // if the body isn't a compound statement to avoid push/pop in common cases.
777 bool NeedsInnerScope = getLang().C99 && Tok.getKind() != tok::l_brace;
Chris Lattner31e05722007-08-26 06:24:45 +0000778 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000779
Reid Spencer5f016e22007-07-11 17:01:13 +0000780 // Read the body statement.
781 StmtResult Body = ParseStatement();
782
Chris Lattner0ecea032007-08-22 05:28:50 +0000783 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000784 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000785
Reid Spencer5f016e22007-07-11 17:01:13 +0000786 // Leave the for-scope.
787 ExitScope();
788
789 if (Body.isInvalid)
790 return Body;
791
Steve Naroff1b273c42007-09-16 14:56:35 +0000792 return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart, SecondPart,
Reid Spencer5f016e22007-07-11 17:01:13 +0000793 ThirdPart, RParenLoc, Body.Val);
794}
795
796/// ParseGotoStatement
797/// jump-statement:
798/// 'goto' identifier ';'
799/// [GNU] 'goto' '*' expression ';'
800///
801/// Note: this lets the caller parse the end ';'.
802///
803Parser::StmtResult Parser::ParseGotoStatement() {
804 assert(Tok.getKind() == tok::kw_goto && "Not a goto stmt!");
805 SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
806
807 StmtResult Res;
808 if (Tok.getKind() == tok::identifier) {
Steve Naroff1b273c42007-09-16 14:56:35 +0000809 Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
Reid Spencer5f016e22007-07-11 17:01:13 +0000810 Tok.getIdentifierInfo());
811 ConsumeToken();
812 } else if (Tok.getKind() == tok::star && !getLang().NoExtensions) {
813 // GNU indirect goto extension.
814 Diag(Tok, diag::ext_gnu_indirect_goto);
815 SourceLocation StarLoc = ConsumeToken();
816 ExprResult R = ParseExpression();
817 if (R.isInvalid) { // Skip to the semicolon, but don't consume it.
818 SkipUntil(tok::semi, false, true);
819 return true;
820 }
Steve Naroff1b273c42007-09-16 14:56:35 +0000821 Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.Val);
Chris Lattner95cfb852007-07-22 04:13:33 +0000822 } else {
823 Diag(Tok, diag::err_expected_ident);
824 return true;
Reid Spencer5f016e22007-07-11 17:01:13 +0000825 }
Chris Lattner95cfb852007-07-22 04:13:33 +0000826
Reid Spencer5f016e22007-07-11 17:01:13 +0000827 return Res;
828}
829
830/// ParseContinueStatement
831/// jump-statement:
832/// 'continue' ';'
833///
834/// Note: this lets the caller parse the end ';'.
835///
836Parser::StmtResult Parser::ParseContinueStatement() {
837 SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
Steve Naroff1b273c42007-09-16 14:56:35 +0000838 return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000839}
840
841/// ParseBreakStatement
842/// jump-statement:
843/// 'break' ';'
844///
845/// Note: this lets the caller parse the end ';'.
846///
847Parser::StmtResult Parser::ParseBreakStatement() {
848 SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
Steve Naroff1b273c42007-09-16 14:56:35 +0000849 return Actions.ActOnBreakStmt(BreakLoc, CurScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000850}
851
852/// ParseReturnStatement
853/// jump-statement:
854/// 'return' expression[opt] ';'
855Parser::StmtResult Parser::ParseReturnStatement() {
856 assert(Tok.getKind() == tok::kw_return && "Not a return stmt!");
857 SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
858
859 ExprResult R(0);
860 if (Tok.getKind() != tok::semi) {
861 R = ParseExpression();
862 if (R.isInvalid) { // Skip to the semicolon, but don't consume it.
863 SkipUntil(tok::semi, false, true);
864 return true;
865 }
866 }
Steve Naroff1b273c42007-09-16 14:56:35 +0000867 return Actions.ActOnReturnStmt(ReturnLoc, R.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000868}
869
870/// ParseAsmStatement - Parse a GNU extended asm statement.
871/// [GNU] asm-statement:
872/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';'
873///
874/// [GNU] asm-argument:
875/// asm-string-literal
876/// asm-string-literal ':' asm-operands[opt]
877/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
878/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
879/// ':' asm-clobbers
880///
881/// [GNU] asm-clobbers:
882/// asm-string-literal
883/// asm-clobbers ',' asm-string-literal
884///
885Parser::StmtResult Parser::ParseAsmStatement() {
886 assert(Tok.getKind() == tok::kw_asm && "Not an asm stmt");
887 ConsumeToken();
888
889 DeclSpec DS;
890 SourceLocation Loc = Tok.getLocation();
891 ParseTypeQualifierListOpt(DS);
892
893 // GNU asms accept, but warn, about type-qualifiers other than volatile.
894 if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
895 Diag(Loc, diag::w_asm_qualifier_ignored, "const");
896 if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
897 Diag(Loc, diag::w_asm_qualifier_ignored, "restrict");
898
899 // Remember if this was a volatile asm.
900 //bool isVolatile = DS.TypeQualifiers & DeclSpec::TQ_volatile;
901
902 if (Tok.getKind() != tok::l_paren) {
903 Diag(Tok, diag::err_expected_lparen_after, "asm");
904 SkipUntil(tok::r_paren);
905 return true;
906 }
907 Loc = ConsumeParen();
908
909 ParseAsmStringLiteral();
910
911 // Parse Outputs, if present.
912 ParseAsmOperandsOpt();
913
914 // Parse Inputs, if present.
915 ParseAsmOperandsOpt();
916
917 // Parse the clobbers, if present.
918 if (Tok.getKind() == tok::colon) {
919 ConsumeToken();
920
921 if (isTokenStringLiteral()) {
922 // Parse the asm-string list for clobbers.
923 while (1) {
924 ParseAsmStringLiteral();
925
926 if (Tok.getKind() != tok::comma) break;
927 ConsumeToken();
928 }
929 }
930 }
931
932 MatchRHSPunctuation(tok::r_paren, Loc);
933
934 // FIXME: Implement action for asm parsing.
935 return false;
936}
937
938/// ParseAsmOperands - Parse the asm-operands production as used by
939/// asm-statement. We also parse a leading ':' token. If the leading colon is
940/// not present, we do not parse anything.
941///
942/// [GNU] asm-operands:
943/// asm-operand
944/// asm-operands ',' asm-operand
945///
946/// [GNU] asm-operand:
947/// asm-string-literal '(' expression ')'
948/// '[' identifier ']' asm-string-literal '(' expression ')'
949///
950void Parser::ParseAsmOperandsOpt() {
951 // Only do anything if this operand is present.
952 if (Tok.getKind() != tok::colon) return;
953 ConsumeToken();
954
955 // 'asm-operands' isn't present?
956 if (!isTokenStringLiteral() && Tok.getKind() != tok::l_square)
957 return;
958
959 while (1) {
960 // Read the [id] if present.
961 if (Tok.getKind() == tok::l_square) {
962 SourceLocation Loc = ConsumeBracket();
963
964 if (Tok.getKind() != tok::identifier) {
965 Diag(Tok, diag::err_expected_ident);
966 SkipUntil(tok::r_paren);
967 return;
968 }
969 MatchRHSPunctuation(tok::r_square, Loc);
970 }
971
972 ParseAsmStringLiteral();
973
974 if (Tok.getKind() != tok::l_paren) {
975 Diag(Tok, diag::err_expected_lparen_after, "asm operand");
976 SkipUntil(tok::r_paren);
977 return;
978 }
979
980 // Read the parenthesized expression.
981 ExprResult Res = ParseSimpleParenExpression();
982 if (Res.isInvalid) {
983 SkipUntil(tok::r_paren);
984 return;
985 }
986
987 // Eat the comma and continue parsing if it exists.
988 if (Tok.getKind() != tok::comma) return;
989 ConsumeToken();
990 }
991}