blob: 9675307b2ce0f9608d8386e8ae868e3901bf248f [file] [log] [blame]
Chris Lattner0ccd51e2006-08-09 05:47:47 +00001//===--- Statement.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"
Chris Lattner53361ac2006-08-10 05:19:57 +000017#include "clang/Parse/Declarations.h"
Chris Lattner0ccd51e2006-08-09 05:47:47 +000018using namespace llvm;
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 [TODO]
41/// [OMP] openmp-construct [TODO]
42///
43/// labeled-statement:
44/// identifier ':' statement
45/// 'case' constant-expression ':' statement
46/// 'default' ':' statement
47///
Chris Lattner0ccd51e2006-08-09 05:47:47 +000048/// selection-statement:
49/// if-statement
50/// switch-statement
51///
52/// iteration-statement:
53/// while-statement
54/// do-statement
55/// for-statement
56///
Chris Lattner9075bd72006-08-10 04:59:57 +000057/// expression-statement:
58/// expression[opt] ';'
59///
Chris Lattner0ccd51e2006-08-09 05:47:47 +000060/// jump-statement:
61/// 'goto' identifier ';'
62/// 'continue' ';'
63/// 'break' ';'
64/// 'return' expression[opt] ';'
Chris Lattner503fadc2006-08-10 05:45:44 +000065/// [GNU] 'goto' '*' expression ';'
Chris Lattner0ccd51e2006-08-09 05:47:47 +000066///
67/// [OBC] objc-throw-statement: [TODO]
68/// [OBC] '@' 'throw' expression ';' [TODO]
69/// [OBC] '@' 'throw' ';' [TODO]
70///
Chris Lattnerc951dae2006-08-10 04:23:57 +000071void Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
Chris Lattner503fadc2006-08-10 05:45:44 +000072 const char *SemiError = 0;
73
Chris Lattnerd2685cf2006-08-10 05:59:48 +000074ParseNextStatement:
Chris Lattner503fadc2006-08-10 05:45:44 +000075 // 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.
Chris Lattner0ccd51e2006-08-09 05:47:47 +000078 switch (Tok.getKind()) {
Chris Lattnerf8afb622006-08-10 18:26:31 +000079 case tok::identifier: // C99 6.8.1: labeled-statement
80 // identifier ':' statement
81 // declaration (if !OnlyStatement)
82 // expression[opt] ';'
83 return ParseIdentifierStatement(OnlyStatement);
84
Chris Lattner0ccd51e2006-08-09 05:47:47 +000085 default:
Chris Lattnerf8afb622006-08-10 18:26:31 +000086 if (!OnlyStatement && isDeclarationSpecifier()) {
87 // TODO: warn/disable if declaration is in the middle of a block and !C99.
88 ParseDeclaration(Declarator::BlockContext);
89 return;
90 } else if (Tok.getKind() == tok::r_brace) {
91 Diag(Tok, diag::err_expected_statement);
92 } else {
93 // expression[opt] ';'
94 ParseExpression();
95 }
Chris Lattner503fadc2006-08-10 05:45:44 +000096 return;
Chris Lattner0ccd51e2006-08-09 05:47:47 +000097
Chris Lattnerd2685cf2006-08-10 05:59:48 +000098 case tok::kw_case: // C99 6.8.1: labeled-statement
99 ParseCaseStatement();
100 if (Tok.getKind() == tok::r_brace) {
101 Diag(Tok, diag::err_label_end_of_compound_statement);
102 return;
103 }
104 OnlyStatement = true;
105 goto ParseNextStatement;
106 case tok::kw_default: // C99 6.8.1: labeled-statement
107 ParseDefaultStatement();
108 if (Tok.getKind() == tok::r_brace) {
109 Diag(Tok, diag::err_label_end_of_compound_statement);
110 return;
111 }
112 OnlyStatement = true;
113 goto ParseNextStatement;
Chris Lattner9075bd72006-08-10 04:59:57 +0000114
115 case tok::l_brace: // C99 6.8.2: compound-statement
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000116 ParseCompoundStatement();
Chris Lattner503fadc2006-08-10 05:45:44 +0000117 return;
Chris Lattner9075bd72006-08-10 04:59:57 +0000118 case tok::semi: // C99 6.8.3: expression[opt] ';'
Chris Lattnerc951dae2006-08-10 04:23:57 +0000119 ConsumeToken();
Chris Lattner503fadc2006-08-10 05:45:44 +0000120 return;
121
Chris Lattner9075bd72006-08-10 04:59:57 +0000122 case tok::kw_if: // C99 6.8.4.1: if-statement
Chris Lattnerc951dae2006-08-10 04:23:57 +0000123 ParseIfStatement();
Chris Lattner503fadc2006-08-10 05:45:44 +0000124 return;
Chris Lattner9075bd72006-08-10 04:59:57 +0000125 case tok::kw_switch: // C99 6.8.4.2: switch-statement
126 ParseSwitchStatement();
Chris Lattner503fadc2006-08-10 05:45:44 +0000127 return;
128
Chris Lattner9075bd72006-08-10 04:59:57 +0000129 case tok::kw_while: // C99 6.8.5.1: while-statement
130 ParseWhileStatement();
Chris Lattner503fadc2006-08-10 05:45:44 +0000131 return;
Chris Lattner9075bd72006-08-10 04:59:57 +0000132 case tok::kw_do: // C99 6.8.5.2: do-statement
133 ParseDoStatement();
Chris Lattner503fadc2006-08-10 05:45:44 +0000134 SemiError = "do/while loop";
Chris Lattner9075bd72006-08-10 04:59:57 +0000135 break;
136 case tok::kw_for: // C99 6.8.5.3: for-statement
137 ParseForStatement();
Chris Lattner503fadc2006-08-10 05:45:44 +0000138 return;
139
140 case tok::kw_goto: // C99 6.8.6.1: goto-statement
141 ParseGotoStatement();
142 SemiError = "goto statement";
Chris Lattner9075bd72006-08-10 04:59:57 +0000143 break;
Chris Lattner503fadc2006-08-10 05:45:44 +0000144 case tok::kw_continue: // C99 6.8.6.2: continue-statement
145 ConsumeToken(); // eat the 'continue'.
146 SemiError = "continue statement";
147 break;
148 case tok::kw_break: // C99 6.8.6.3: break-statement
149 ConsumeToken(); // eat the 'break'.
150 SemiError = "break statement";
151 break;
152 case tok::kw_return: // C99 6.8.6.4: return-statement
153 ParseReturnStatement();
154 SemiError = "return statement";
155 break;
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000156 }
Chris Lattner503fadc2006-08-10 05:45:44 +0000157
158 // If we reached this code, the statement must end in a semicolon.
159 if (Tok.getKind() == tok::semi) {
160 ConsumeToken();
161 } else {
162 Diag(Tok, diag::err_expected_semi_after, SemiError);
163 SkipUntil(tok::semi);
164 }
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000165}
166
Chris Lattnerf8afb622006-08-10 18:26:31 +0000167/// ParseIdentifierStatement - Because we don't have two-token lookahead, we
168/// have a bit of a quandry here. Reading the identifier is necessary to see if
169/// there is a ':' after it. If there is, this is a label, regardless of what
170/// else the identifier can mean. If not, this is either part of a declaration
171/// (if the identifier is a type-name) or part of an expression.
Chris Lattner6dfd9782006-08-10 18:31:37 +0000172///
173/// labeled-statement:
174/// identifier ':' statement
175/// declaration (if !OnlyStatement)
176/// expression[opt] ';'
177///
Chris Lattnerf8afb622006-08-10 18:26:31 +0000178void Parser::ParseIdentifierStatement(bool OnlyStatement) {
Chris Lattner6dfd9782006-08-10 18:31:37 +0000179 IdentifierInfo *II = Tok.getIdentifierInfo();
180 assert(Tok.getKind() == tok::identifier && II && "Not an identifier!");
181
182 ConsumeToken(); // eat the identifier.
183
184 // identifier ':' statement
185 if (Tok.getKind() == tok::colon) {
186 ConsumeToken();
187 ParseStatement();
188 return;
189 }
190
191 // declaration
192 if (!OnlyStatement && 0/*Is typedef name!*/) {
193 // Handle this. Warn/disable if in middle of block and !C99.
Chris Lattner2f9980e2006-08-10 18:39:24 +0000194 DeclSpec DS;
195
196 // FIXME: Add the typedef name to the start of the decl-specs.
197 // ParseDeclarationSpecifiers will continue from there.
198 ParseDeclarationSpecifiers(DS);
199
200 // Parse all the declarators.
201 Declarator DeclaratorInfo(DS, Declarator::BlockContext);
202 ParseDeclarator(DeclaratorInfo);
203
204 ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
205 return;
Chris Lattner6dfd9782006-08-10 18:31:37 +0000206 }
207
Chris Lattner2f9980e2006-08-10 18:39:24 +0000208 // Otherwise, this is an expression. Seed it with II.
Chris Lattnerf8afb622006-08-10 18:26:31 +0000209
210 assert(0);
Chris Lattnerf8afb622006-08-10 18:26:31 +0000211}
212
Chris Lattnerd2685cf2006-08-10 05:59:48 +0000213/// ParseCaseStatement
214/// labeled-statement:
215/// 'case' constant-expression ':' statement
216///
217/// Note that this does not parse the 'statement' at the end.
218///
219void Parser::ParseCaseStatement() {
220 assert(Tok.getKind() == tok::kw_case && "Not a case stmt!");
221 ConsumeToken(); // eat the 'case'.
222
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000223 ParseAssignmentExpression(); // Expr without commas.
Chris Lattnerd2685cf2006-08-10 05:59:48 +0000224
225 if (Tok.getKind() == tok::colon) {
226 ConsumeToken();
227 } else {
228 Diag(Tok, diag::err_expected_colon_after, "'case'");
229 SkipUntil(tok::colon);
230 }
231}
232
233/// ParseDefaultStatement
234/// labeled-statement:
235/// 'default' ':' statement
236/// Note that this does not parse the 'statement' at the end.
237///
238void Parser::ParseDefaultStatement() {
239 assert(Tok.getKind() == tok::kw_default && "Not a default stmt!");
240 ConsumeToken(); // eat the 'default'.
241
242 if (Tok.getKind() == tok::colon) {
243 ConsumeToken();
244 } else {
245 Diag(Tok, diag::err_expected_colon_after, "'default'");
246 SkipUntil(tok::colon);
247 }
248}
249
250
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000251/// ParseCompoundStatement - Parse a "{}" block.
252///
253/// compound-statement: [C99 6.8.2]
254/// { block-item-list[opt] }
255/// [GNU] { label-declarations block-item-list } [TODO]
256///
257/// block-item-list:
258/// block-item
259/// block-item-list block-item
260///
261/// block-item:
262/// declaration
263/// [GNU] '__extension__' declaration [TODO]
264/// statement
265/// [OMP] openmp-directive [TODO]
266///
267/// [GNU] label-declarations:
268/// [GNU] label-declaration
269/// [GNU] label-declarations label-declaration
270///
271/// [GNU] label-declaration:
272/// [GNU] '__label__' identifier-list ';'
273///
274/// [OMP] openmp-directive: [TODO]
275/// [OMP] barrier-directive
276/// [OMP] flush-directive
277void Parser::ParseCompoundStatement() {
278 assert(Tok.getKind() == tok::l_brace && "Not a compount stmt!");
279 ConsumeBrace(); // eat the '{'.
280
281 while (Tok.getKind() != tok::r_brace && Tok.getKind() != tok::eof)
Chris Lattnerc951dae2006-08-10 04:23:57 +0000282 ParseStatementOrDeclaration(false);
Chris Lattner0ccd51e2006-08-09 05:47:47 +0000283
284 // We broke out of the while loop because we found a '}' or EOF.
285 if (Tok.getKind() == tok::r_brace)
286 ConsumeBrace();
287 else
288 Diag(Tok, diag::err_expected_rbrace);
289}
Chris Lattnerc951dae2006-08-10 04:23:57 +0000290
291/// ParseIfStatement
292/// if-statement: [C99 6.8.4.1]
293/// 'if' '(' expression ')' statement
294/// 'if' '(' expression ')' statement 'else' statement
295void Parser::ParseIfStatement() {
296 assert(Tok.getKind() == tok::kw_if && "Not an if stmt!");
297 ConsumeToken(); // eat the 'if'.
298
299 if (Tok.getKind() != tok::l_paren) {
Chris Lattner9075bd72006-08-10 04:59:57 +0000300 Diag(Tok, diag::err_expected_lparen_after, "if");
Chris Lattnerc951dae2006-08-10 04:23:57 +0000301 SkipUntil(tok::semi);
302 return;
303 }
304
305 // Parse the condition.
Chris Lattner4add4e62006-08-11 01:33:00 +0000306 ParenParseOption ParenExprType = SimpleExpr;
307 ParseParenExpression(ParenExprType);
Chris Lattnerc951dae2006-08-10 04:23:57 +0000308
309 // Read the if condition.
310 ParseStatement();
311
312 // If it has an else, parse it.
313 if (Tok.getKind() == tok::kw_else) {
314 ConsumeToken();
315 ParseStatement();
316 }
Chris Lattnerc951dae2006-08-10 04:23:57 +0000317}
318
Chris Lattner9075bd72006-08-10 04:59:57 +0000319/// ParseSwitchStatement
320/// switch-statement:
321/// 'switch' '(' expression ')' statement
322void Parser::ParseSwitchStatement() {
323 assert(Tok.getKind() == tok::kw_switch && "Not a switch stmt!");
324 ConsumeToken(); // eat the 'switch'.
325
326 if (Tok.getKind() != tok::l_paren) {
327 Diag(Tok, diag::err_expected_lparen_after, "switch");
328 SkipUntil(tok::semi);
329 return;
330 }
331
332 // Parse the condition.
Chris Lattner4add4e62006-08-11 01:33:00 +0000333 ParenParseOption ParenExprType = SimpleExpr;
334 ParseParenExpression(ParenExprType);
Chris Lattner9075bd72006-08-10 04:59:57 +0000335
336 // Read the body statement.
337 ParseStatement();
338}
339
340/// ParseWhileStatement
341/// while-statement: [C99 6.8.5.1]
342/// 'while' '(' expression ')' statement
343void Parser::ParseWhileStatement() {
344 assert(Tok.getKind() == tok::kw_while && "Not a while stmt!");
345 ConsumeToken(); // eat the 'while'.
346
347 if (Tok.getKind() != tok::l_paren) {
348 Diag(Tok, diag::err_expected_lparen_after, "while");
349 SkipUntil(tok::semi);
350 return;
351 }
352
353 // Parse the condition.
Chris Lattner4add4e62006-08-11 01:33:00 +0000354 ParenParseOption ParenExprType = SimpleExpr;
355 ParseParenExpression(ParenExprType);
Chris Lattner9075bd72006-08-10 04:59:57 +0000356
357 // Read the body statement.
358 ParseStatement();
359}
360
361/// ParseDoStatement
362/// do-statement: [C99 6.8.5.2]
363/// 'do' statement 'while' '(' expression ')' ';'
Chris Lattner503fadc2006-08-10 05:45:44 +0000364/// Note: this lets the caller parse the end ';'.
Chris Lattner9075bd72006-08-10 04:59:57 +0000365void Parser::ParseDoStatement() {
366 assert(Tok.getKind() == tok::kw_do && "Not a do stmt!");
367 SourceLocation DoLoc = Tok.getLocation();
368 ConsumeToken(); // eat the 'do'.
369
370 // Read the body statement.
371 ParseStatement();
372
373 if (Tok.getKind() != tok::kw_while) {
374 Diag(Tok, diag::err_expected_while);
Chris Lattnerc2dd85a2006-08-10 22:57:16 +0000375 Diag(DoLoc, diag::err_matching, "do");
Chris Lattner9075bd72006-08-10 04:59:57 +0000376 SkipUntil(tok::semi);
377 return;
378 }
379 ConsumeToken();
380
381 if (Tok.getKind() != tok::l_paren) {
382 Diag(Tok, diag::err_expected_lparen_after, "do/while");
383 SkipUntil(tok::semi);
384 return;
385 }
386
387 // Parse the condition.
Chris Lattner4add4e62006-08-11 01:33:00 +0000388 ParenParseOption ParenExprType = SimpleExpr;
389 ParseParenExpression(ParenExprType);
Chris Lattner9075bd72006-08-10 04:59:57 +0000390}
391
392/// ParseForStatement
393/// for-statement: [C99 6.8.5.3]
394/// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
395/// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
396void Parser::ParseForStatement() {
397 assert(Tok.getKind() == tok::kw_for && "Not a for stmt!");
398 SourceLocation ForLoc = Tok.getLocation();
399 ConsumeToken(); // eat the 'for'.
400
401 if (Tok.getKind() != tok::l_paren) {
402 Diag(Tok, diag::err_expected_lparen_after, "for");
403 SkipUntil(tok::semi);
404 return;
405 }
406
407 SourceLocation LParenLoc = Tok.getLocation();
408 ConsumeParen();
409
410 // Parse the first part of the for specifier.
411 if (Tok.getKind() == tok::semi) { // for (;
Chris Lattner53361ac2006-08-10 05:19:57 +0000412 // no first part, eat the ';'.
413 ConsumeToken();
Chris Lattner9075bd72006-08-10 04:59:57 +0000414 } else if (isDeclarationSpecifier()) { // for (int X = 4;
Chris Lattner53361ac2006-08-10 05:19:57 +0000415 // Parse declaration, which eats the ';'.
Chris Lattnerab1803652006-08-10 05:22:36 +0000416 if (!getLang().C99) // Use of C99-style for loops in C90 mode?
417 Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
Chris Lattner53361ac2006-08-10 05:19:57 +0000418 ParseDeclaration(Declarator::ForContext);
Chris Lattner9075bd72006-08-10 04:59:57 +0000419 } else {
420 ParseExpression();
Chris Lattner9075bd72006-08-10 04:59:57 +0000421
Chris Lattner53361ac2006-08-10 05:19:57 +0000422 if (Tok.getKind() == tok::semi) {
423 ConsumeToken();
424 } else {
425 Diag(Tok, diag::err_expected_semi_for);
Chris Lattner53361ac2006-08-10 05:19:57 +0000426 SkipUntil(tok::semi);
427 }
Chris Lattner9075bd72006-08-10 04:59:57 +0000428 }
429
430 // Parse the second part of the for specifier.
431 if (Tok.getKind() == tok::semi) { // for (...;;
432 // no second part.
433 } else {
434 ParseExpression();
435 }
436
437 if (Tok.getKind() == tok::semi) {
438 ConsumeToken();
439 } else {
440 Diag(Tok, diag::err_expected_semi_for);
Chris Lattner9075bd72006-08-10 04:59:57 +0000441 SkipUntil(tok::semi);
442 }
443
444 // Parse the third part of the for specifier.
445 if (Tok.getKind() == tok::r_paren) { // for (...;...;)
446 // no third part.
447 } else {
448 ParseExpression();
449 }
450
Chris Lattner4564bc12006-08-10 23:14:52 +0000451 // Match the ')'.
452 MatchRHSPunctuation(tok::r_paren, LParenLoc, "(", diag::err_expected_rparen);
Chris Lattner9075bd72006-08-10 04:59:57 +0000453
454 // Read the body statement.
455 ParseStatement();
456}
Chris Lattnerc951dae2006-08-10 04:23:57 +0000457
Chris Lattner503fadc2006-08-10 05:45:44 +0000458/// ParseGotoStatement
459/// jump-statement:
460/// 'goto' identifier ';'
461/// [GNU] 'goto' '*' expression ';'
462///
463/// Note: this lets the caller parse the end ';'.
464///
465void Parser::ParseGotoStatement() {
466 assert(Tok.getKind() == tok::kw_goto && "Not a goto stmt!");
467 ConsumeToken(); // eat the 'goto'.
468
469 if (Tok.getKind() == tok::identifier) {
470 ConsumeToken();
471 } else if (Tok.getKind() == tok::star && !getLang().NoExtensions) {
472 // GNU indirect goto extension.
473 Diag(Tok, diag::ext_gnu_indirect_goto);
474 ConsumeToken();
475 ParseExpression();
476 }
477}
478
479/// ParseReturnStatement
480/// jump-statement:
481/// 'return' expression[opt] ';'
482void Parser::ParseReturnStatement() {
483 assert(Tok.getKind() == tok::kw_return && "Not a return stmt!");
484 ConsumeToken(); // eat the 'return'.
485
486 if (Tok.getKind() != tok::semi)
487 ParseExpression();
488}