blob: 063735196ee6a2a6147e401832f29e3ed6c9950b [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
Fariborz Jahanianb384d322007-10-04 20:19:06 +000037/// [OBC] objc-throw-statement
38/// [OBC] objc-try-catch-statement
Reid Spencer5f016e22007-07-11 17:01:13 +000039/// [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///
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 @
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);
Fariborz Jahanianb384d322007-10-04 20:19:06 +000094 ExprResult Res = ParseExpressionWithLeadingAt(AtLoc);
95 if (Res.isInvalid) {
96 // If the expression is invalid, skip ahead to the next semicolon. Not
97 // doing this opens us up to the possibility of infinite loops if
98 // ParseExpression does not consume any tokens.
99 SkipUntil(tok::semi);
100 return true;
101 }
102 // Otherwise, eat the semicolon.
103 ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
104 return Actions.ActOnExprStmt(Res.Val);
Fariborz Jahanian397fcc12007-09-19 19:14:32 +0000105 }
Fariborz Jahanian397fcc12007-09-19 19:14:32 +0000106
Reid Spencer5f016e22007-07-11 17:01:13 +0000107 default:
Fariborz Jahanianb384d322007-10-04 20:19:06 +0000108 if (!OnlyStatement && isDeclarationSpecifier()) {
Steve Naroff1b273c42007-09-16 14:56:35 +0000109 return Actions.ActOnDeclStmt(ParseDeclaration(Declarator::BlockContext));
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000110 } else if (Tok.is(tok::r_brace)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000111 Diag(Tok, diag::err_expected_statement);
112 return true;
113 } else {
114 // expression[opt] ';'
Fariborz Jahanianb384d322007-10-04 20:19:06 +0000115 ExprResult Res = ParseExpression();
Reid Spencer5f016e22007-07-11 17:01:13 +0000116 if (Res.isInvalid) {
117 // If the expression is invalid, skip ahead to the next semicolon. Not
118 // doing this opens us up to the possibility of infinite loops if
119 // ParseExpression does not consume any tokens.
120 SkipUntil(tok::semi);
121 return true;
122 }
123 // Otherwise, eat the semicolon.
124 ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
Steve Naroff1b273c42007-09-16 14:56:35 +0000125 return Actions.ActOnExprStmt(Res.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000126 }
127
128 case tok::kw_case: // C99 6.8.1: labeled-statement
129 return ParseCaseStatement();
130 case tok::kw_default: // C99 6.8.1: labeled-statement
131 return ParseDefaultStatement();
132
133 case tok::l_brace: // C99 6.8.2: compound-statement
134 return ParseCompoundStatement();
135 case tok::semi: // C99 6.8.3p3: expression[opt] ';'
Steve Naroff1b273c42007-09-16 14:56:35 +0000136 return Actions.ActOnNullStmt(ConsumeToken());
Reid Spencer5f016e22007-07-11 17:01:13 +0000137
138 case tok::kw_if: // C99 6.8.4.1: if-statement
139 return ParseIfStatement();
140 case tok::kw_switch: // C99 6.8.4.2: switch-statement
141 return ParseSwitchStatement();
142
143 case tok::kw_while: // C99 6.8.5.1: while-statement
144 return ParseWhileStatement();
145 case tok::kw_do: // C99 6.8.5.2: do-statement
146 Res = ParseDoStatement();
147 SemiError = "do/while loop";
148 break;
149 case tok::kw_for: // C99 6.8.5.3: for-statement
150 return ParseForStatement();
151
152 case tok::kw_goto: // C99 6.8.6.1: goto-statement
153 Res = ParseGotoStatement();
154 SemiError = "goto statement";
155 break;
156 case tok::kw_continue: // C99 6.8.6.2: continue-statement
157 Res = ParseContinueStatement();
158 SemiError = "continue statement";
159 break;
160 case tok::kw_break: // C99 6.8.6.3: break-statement
161 Res = ParseBreakStatement();
162 SemiError = "break statement";
163 break;
164 case tok::kw_return: // C99 6.8.6.4: return-statement
165 Res = ParseReturnStatement();
166 SemiError = "return statement";
167 break;
168
169 case tok::kw_asm:
170 Res = ParseAsmStatement();
171 SemiError = "asm statement";
172 break;
173 }
174
175 // If we reached this code, the statement must end in a semicolon.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000176 if (Tok.is(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000177 ConsumeToken();
178 } else {
179 Diag(Tok, diag::err_expected_semi_after, SemiError);
180 SkipUntil(tok::semi);
181 }
182 return Res;
183}
184
185/// ParseIdentifierStatement - Because we don't have two-token lookahead, we
186/// have a bit of a quandry here. Reading the identifier is necessary to see if
187/// there is a ':' after it. If there is, this is a label, regardless of what
188/// else the identifier can mean. If not, this is either part of a declaration
189/// (if the identifier is a type-name) or part of an expression.
190///
191/// labeled-statement:
192/// identifier ':' statement
193/// [GNU] identifier ':' attributes[opt] statement
194/// declaration (if !OnlyStatement)
195/// expression[opt] ';'
196///
197Parser::StmtResult Parser::ParseIdentifierStatement(bool OnlyStatement) {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000198 assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
Reid Spencer5f016e22007-07-11 17:01:13 +0000199 "Not an identifier!");
200
Chris Lattnerd2177732007-07-20 16:59:19 +0000201 Token IdentTok = Tok; // Save the whole token.
Reid Spencer5f016e22007-07-11 17:01:13 +0000202 ConsumeToken(); // eat the identifier.
203
204 // identifier ':' statement
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000205 if (Tok.is(tok::colon)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000206 SourceLocation ColonLoc = ConsumeToken();
207
208 // Read label attributes, if present.
209 DeclTy *AttrList = 0;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000210 if (Tok.is(tok::kw___attribute))
Reid Spencer5f016e22007-07-11 17:01:13 +0000211 // TODO: save these somewhere.
212 AttrList = ParseAttributes();
213
214 StmtResult SubStmt = ParseStatement();
215
216 // Broken substmt shouldn't prevent the label from being added to the AST.
217 if (SubStmt.isInvalid)
Steve Naroff1b273c42007-09-16 14:56:35 +0000218 SubStmt = Actions.ActOnNullStmt(ColonLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000219
Steve Naroff1b273c42007-09-16 14:56:35 +0000220 return Actions.ActOnLabelStmt(IdentTok.getLocation(),
Reid Spencer5f016e22007-07-11 17:01:13 +0000221 IdentTok.getIdentifierInfo(),
222 ColonLoc, SubStmt.Val);
223 }
224
225 // Check to see if this is a declaration.
226 void *TypeRep;
227 if (!OnlyStatement &&
228 (TypeRep = Actions.isTypeName(*IdentTok.getIdentifierInfo(), CurScope))) {
229 // Handle this. Warn/disable if in middle of block and !C99.
230 DeclSpec DS;
231
232 // Add the typedef name to the start of the decl-specs.
233 const char *PrevSpec = 0;
234 int isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typedef,
235 IdentTok.getLocation(), PrevSpec,
236 TypeRep);
237 assert(!isInvalid && "First declspec can't be invalid!");
Steve Narofff908a872007-10-30 02:23:23 +0000238 SourceLocation endProtoLoc;
Fariborz Jahaniandfbcce22007-10-11 18:08:47 +0000239 if (Tok.is(tok::less)) {
240 llvm::SmallVector<IdentifierInfo *, 8> ProtocolRefs;
Steve Narofff908a872007-10-30 02:23:23 +0000241 ParseObjCProtocolReferences(ProtocolRefs, endProtoLoc);
Fariborz Jahaniandfbcce22007-10-11 18:08:47 +0000242 llvm::SmallVector<DeclTy *, 8> *ProtocolDecl =
243 new llvm::SmallVector<DeclTy *, 8>;
244 DS.setProtocolQualifiers(ProtocolDecl);
245 Actions.FindProtocolDeclaration(IdentTok.getLocation(),
246 &ProtocolRefs[0], ProtocolRefs.size(),
247 *ProtocolDecl);
248 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000249
250 // ParseDeclarationSpecifiers will continue from there.
251 ParseDeclarationSpecifiers(DS);
252
253 // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"
254 // declaration-specifiers init-declarator-list[opt] ';'
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000255 if (Tok.is(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000256 // TODO: emit error on 'int;' or 'const enum foo;'.
257 // if (!DS.isMissingDeclaratorOk()) Diag(...);
258
259 ConsumeToken();
260 // FIXME: Return this as a type decl.
261 return 0;
262 }
263
264 // Parse all the declarators.
265 Declarator DeclaratorInfo(DS, Declarator::BlockContext);
266 ParseDeclarator(DeclaratorInfo);
267
268 DeclTy *Decl = ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo);
Steve Naroff1b273c42007-09-16 14:56:35 +0000269 return Decl ? Actions.ActOnDeclStmt(Decl) : 0;
Reid Spencer5f016e22007-07-11 17:01:13 +0000270 }
271
272 // Otherwise, this is an expression. Seed it with II and parse it.
273 ExprResult Res = ParseExpressionWithLeadingIdentifier(IdentTok);
274 if (Res.isInvalid) {
275 SkipUntil(tok::semi);
276 return true;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000277 } else if (Tok.isNot(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000278 Diag(Tok, diag::err_expected_semi_after, "expression");
279 SkipUntil(tok::semi);
280 return true;
281 } else {
282 ConsumeToken();
283 // Convert expr to a stmt.
Steve Naroff1b273c42007-09-16 14:56:35 +0000284 return Actions.ActOnExprStmt(Res.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000285 }
286}
287
288/// ParseCaseStatement
289/// labeled-statement:
290/// 'case' constant-expression ':' statement
291/// [GNU] 'case' constant-expression '...' constant-expression ':' statement
292///
293/// Note that this does not parse the 'statement' at the end.
294///
295Parser::StmtResult Parser::ParseCaseStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000296 assert(Tok.is(tok::kw_case) && "Not a case stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000297 SourceLocation CaseLoc = ConsumeToken(); // eat the 'case'.
298
299 ExprResult LHS = ParseConstantExpression();
300 if (LHS.isInvalid) {
301 SkipUntil(tok::colon);
302 return true;
303 }
304
305 // GNU case range extension.
306 SourceLocation DotDotDotLoc;
307 ExprTy *RHSVal = 0;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000308 if (Tok.is(tok::ellipsis)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000309 Diag(Tok, diag::ext_gnu_case_range);
310 DotDotDotLoc = ConsumeToken();
311
312 ExprResult RHS = ParseConstantExpression();
313 if (RHS.isInvalid) {
314 SkipUntil(tok::colon);
315 return true;
316 }
317 RHSVal = RHS.Val;
318 }
319
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000320 if (Tok.isNot(tok::colon)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000321 Diag(Tok, diag::err_expected_colon_after, "'case'");
322 SkipUntil(tok::colon);
323 return true;
324 }
325
326 SourceLocation ColonLoc = ConsumeToken();
327
328 // Diagnose the common error "switch (X) { case 4: }", which is not valid.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000329 if (Tok.is(tok::r_brace)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000330 Diag(Tok, diag::err_label_end_of_compound_statement);
331 return true;
332 }
333
334 StmtResult SubStmt = ParseStatement();
335
336 // Broken substmt shouldn't prevent the case from being added to the AST.
337 if (SubStmt.isInvalid)
Steve Naroff1b273c42007-09-16 14:56:35 +0000338 SubStmt = Actions.ActOnNullStmt(ColonLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000339
Steve Naroff1b273c42007-09-16 14:56:35 +0000340 return Actions.ActOnCaseStmt(CaseLoc, LHS.Val, DotDotDotLoc, RHSVal, ColonLoc,
Reid Spencer5f016e22007-07-11 17:01:13 +0000341 SubStmt.Val);
342}
343
344/// ParseDefaultStatement
345/// labeled-statement:
346/// 'default' ':' statement
347/// Note that this does not parse the 'statement' at the end.
348///
349Parser::StmtResult Parser::ParseDefaultStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000350 assert(Tok.is(tok::kw_default) && "Not a default stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000351 SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
352
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000353 if (Tok.isNot(tok::colon)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000354 Diag(Tok, diag::err_expected_colon_after, "'default'");
355 SkipUntil(tok::colon);
356 return true;
357 }
358
359 SourceLocation ColonLoc = ConsumeToken();
360
361 // Diagnose the common error "switch (X) {... default: }", which is not valid.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000362 if (Tok.is(tok::r_brace)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000363 Diag(Tok, diag::err_label_end_of_compound_statement);
364 return true;
365 }
366
367 StmtResult SubStmt = ParseStatement();
368 if (SubStmt.isInvalid)
369 return true;
370
Steve Naroff1b273c42007-09-16 14:56:35 +0000371 return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt.Val, CurScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000372}
373
374
375/// ParseCompoundStatement - Parse a "{}" block.
376///
377/// compound-statement: [C99 6.8.2]
378/// { block-item-list[opt] }
379/// [GNU] { label-declarations block-item-list } [TODO]
380///
381/// block-item-list:
382/// block-item
383/// block-item-list block-item
384///
385/// block-item:
386/// declaration
Chris Lattner45a566c2007-08-27 01:01:57 +0000387/// [GNU] '__extension__' declaration
Reid Spencer5f016e22007-07-11 17:01:13 +0000388/// statement
389/// [OMP] openmp-directive [TODO]
390///
391/// [GNU] label-declarations:
392/// [GNU] label-declaration
393/// [GNU] label-declarations label-declaration
394///
395/// [GNU] label-declaration:
396/// [GNU] '__label__' identifier-list ';'
397///
398/// [OMP] openmp-directive: [TODO]
399/// [OMP] barrier-directive
400/// [OMP] flush-directive
401///
Chris Lattner98414c12007-08-31 21:49:55 +0000402Parser::StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000403 assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000404
Chris Lattner31e05722007-08-26 06:24:45 +0000405 // Enter a scope to hold everything within the compound stmt. Compound
406 // statements can always hold declarations.
407 EnterScope(Scope::DeclScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000408
409 // Parse the statements in the body.
Chris Lattner98414c12007-08-31 21:49:55 +0000410 StmtResult Body = ParseCompoundStatementBody(isStmtExpr);
Reid Spencer5f016e22007-07-11 17:01:13 +0000411
412 ExitScope();
413 return Body;
414}
415
416
417/// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
Steve Naroff1b273c42007-09-16 14:56:35 +0000418/// ActOnCompoundStmt action. This expects the '{' to be the current token, and
Reid Spencer5f016e22007-07-11 17:01:13 +0000419/// consume the '}' at the end of the block. It does not manipulate the scope
420/// stack.
Chris Lattner98414c12007-08-31 21:49:55 +0000421Parser::StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000422 SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'.
423
424 // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
Chris Lattner45a566c2007-08-27 01:01:57 +0000425 // only allowed at the start of a compound stmt regardless of the language.
Reid Spencer5f016e22007-07-11 17:01:13 +0000426
427 llvm::SmallVector<StmtTy*, 32> Stmts;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000428 while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
Chris Lattner45a566c2007-08-27 01:01:57 +0000429 StmtResult R;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000430 if (Tok.isNot(tok::kw___extension__)) {
Chris Lattner45a566c2007-08-27 01:01:57 +0000431 R = ParseStatementOrDeclaration(false);
432 } else {
433 // __extension__ can start declarations and it can also be a unary
434 // operator for expressions. Consume multiple __extension__ markers here
435 // until we can determine which is which.
436 SourceLocation ExtLoc = ConsumeToken();
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000437 while (Tok.is(tok::kw___extension__))
Chris Lattner45a566c2007-08-27 01:01:57 +0000438 ConsumeToken();
439
440 // If this is the start of a declaration, parse it as such.
441 if (isDeclarationSpecifier()) {
442 // FIXME: Save the __extension__ on the decl as a node somehow.
443 // FIXME: disable extwarns.
Steve Naroff1b273c42007-09-16 14:56:35 +0000444 R = Actions.ActOnDeclStmt(ParseDeclaration(Declarator::BlockContext));
Chris Lattner45a566c2007-08-27 01:01:57 +0000445 } else {
446 // Otherwise this was a unary __extension__ marker. Parse the
447 // subexpression and add the __extension__ unary op.
448 // FIXME: disable extwarns.
449 ExprResult Res = ParseCastExpression(false);
450 if (Res.isInvalid) {
451 SkipUntil(tok::semi);
452 continue;
453 }
454
455 // Add the __extension__ node to the AST.
Steve Narofff69936d2007-09-16 03:34:24 +0000456 Res = Actions.ActOnUnaryOp(ExtLoc, tok::kw___extension__, Res.Val);
Chris Lattner45a566c2007-08-27 01:01:57 +0000457 if (Res.isInvalid)
458 continue;
459
460 // Eat the semicolon at the end of stmt and convert the expr into a stmt.
461 ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
Steve Naroff1b273c42007-09-16 14:56:35 +0000462 R = Actions.ActOnExprStmt(Res.Val);
Chris Lattner45a566c2007-08-27 01:01:57 +0000463 }
464 }
465
Reid Spencer5f016e22007-07-11 17:01:13 +0000466 if (!R.isInvalid && R.Val)
467 Stmts.push_back(R.Val);
468 }
469
470 // We broke out of the while loop because we found a '}' or EOF.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000471 if (Tok.isNot(tok::r_brace)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000472 Diag(Tok, diag::err_expected_rbrace);
473 return 0;
474 }
475
476 SourceLocation RBraceLoc = ConsumeBrace();
Steve Naroff1b273c42007-09-16 14:56:35 +0000477 return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc,
Chris Lattner98414c12007-08-31 21:49:55 +0000478 &Stmts[0], Stmts.size(), isStmtExpr);
Reid Spencer5f016e22007-07-11 17:01:13 +0000479}
480
481/// ParseIfStatement
482/// if-statement: [C99 6.8.4.1]
483/// 'if' '(' expression ')' statement
484/// 'if' '(' expression ')' statement 'else' statement
485///
486Parser::StmtResult Parser::ParseIfStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000487 assert(Tok.is(tok::kw_if) && "Not an if stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000488 SourceLocation IfLoc = ConsumeToken(); // eat the 'if'.
489
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000490 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000491 Diag(Tok, diag::err_expected_lparen_after, "if");
492 SkipUntil(tok::semi);
493 return true;
494 }
495
Chris Lattner22153252007-08-26 23:08:06 +0000496 // C99 6.8.4p3 - In C99, the if statement is a block. This is not
497 // the case for C90.
498 if (getLang().C99)
499 EnterScope(Scope::DeclScope);
500
Reid Spencer5f016e22007-07-11 17:01:13 +0000501 // Parse the condition.
502 ExprResult CondExp = ParseSimpleParenExpression();
503 if (CondExp.isInvalid) {
504 SkipUntil(tok::semi);
Chris Lattner22153252007-08-26 23:08:06 +0000505 if (getLang().C99)
506 ExitScope();
Reid Spencer5f016e22007-07-11 17:01:13 +0000507 return true;
508 }
509
Chris Lattner0ecea032007-08-22 05:28:50 +0000510 // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000511 // there is no compound stmt. C90 does not have this clause. We only do this
512 // if the body isn't a compound statement to avoid push/pop in common cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000513 bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000514 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattnera36ce712007-08-22 05:16:28 +0000515
Chris Lattnerb96728d2007-10-29 05:08:52 +0000516 // Read the 'then' stmt.
517 SourceLocation ThenStmtLoc = Tok.getLocation();
518 StmtResult ThenStmt = ParseStatement();
Reid Spencer5f016e22007-07-11 17:01:13 +0000519
Chris Lattnera36ce712007-08-22 05:16:28 +0000520 // Pop the 'if' scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000521 if (NeedsInnerScope) ExitScope();
Reid Spencer5f016e22007-07-11 17:01:13 +0000522
523 // If it has an else, parse it.
524 SourceLocation ElseLoc;
Chris Lattnerb96728d2007-10-29 05:08:52 +0000525 SourceLocation ElseStmtLoc;
Reid Spencer5f016e22007-07-11 17:01:13 +0000526 StmtResult ElseStmt(false);
Chris Lattnerb96728d2007-10-29 05:08:52 +0000527
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000528 if (Tok.is(tok::kw_else)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000529 ElseLoc = ConsumeToken();
Chris Lattnera36ce712007-08-22 05:16:28 +0000530
Chris Lattner0ecea032007-08-22 05:28:50 +0000531 // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000532 // there is no compound stmt. C90 does not have this clause. We only do
533 // this if the body isn't a compound statement to avoid push/pop in common
534 // cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000535 NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000536 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattnera36ce712007-08-22 05:16:28 +0000537
Chris Lattnerb96728d2007-10-29 05:08:52 +0000538 ElseStmtLoc = Tok.getLocation();
Reid Spencer5f016e22007-07-11 17:01:13 +0000539 ElseStmt = ParseStatement();
Chris Lattnera36ce712007-08-22 05:16:28 +0000540
541 // Pop the 'else' scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000542 if (NeedsInnerScope) ExitScope();
Reid Spencer5f016e22007-07-11 17:01:13 +0000543 }
544
Chris Lattner22153252007-08-26 23:08:06 +0000545 if (getLang().C99)
546 ExitScope();
547
Chris Lattnerb96728d2007-10-29 05:08:52 +0000548 // If the then or else stmt is invalid and the other is valid (and present),
549 // make turn the invalid one into a null stmt to avoid dropping the other
550 // part. If both are invalid, return error.
551 if ((ThenStmt.isInvalid && ElseStmt.isInvalid) ||
552 (ThenStmt.isInvalid && ElseStmt.Val == 0) ||
553 (ThenStmt.Val == 0 && ElseStmt.isInvalid)) {
554 // Both invalid, or one is invalid and other is non-present: delete cond and
555 // return error.
556 Actions.DeleteExpr(CondExp.Val);
557 return true;
558 }
559
560 // Now if either are invalid, replace with a ';'.
561 if (ThenStmt.isInvalid)
562 ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
563 if (ElseStmt.isInvalid)
564 ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
565
566
567
568 return Actions.ActOnIfStmt(IfLoc, CondExp.Val, ThenStmt.Val,
Reid Spencer5f016e22007-07-11 17:01:13 +0000569 ElseLoc, ElseStmt.Val);
570}
571
572/// ParseSwitchStatement
573/// switch-statement:
574/// 'switch' '(' expression ')' statement
575Parser::StmtResult Parser::ParseSwitchStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000576 assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000577 SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'.
578
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000579 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000580 Diag(Tok, diag::err_expected_lparen_after, "switch");
581 SkipUntil(tok::semi);
582 return true;
583 }
Chris Lattner22153252007-08-26 23:08:06 +0000584
585 // C99 6.8.4p3 - In C99, the switch statement is a block. This is
586 // not the case for C90. Start the switch scope.
587 if (getLang().C99)
588 EnterScope(Scope::BreakScope|Scope::DeclScope);
589 else
590 EnterScope(Scope::BreakScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000591
592 // Parse the condition.
593 ExprResult Cond = ParseSimpleParenExpression();
594
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000595 if (Cond.isInvalid) {
596 ExitScope();
597 return true;
598 }
599
Steve Naroff1b273c42007-09-16 14:56:35 +0000600 StmtResult Switch = Actions.ActOnStartOfSwitchStmt(Cond.Val);
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000601
Chris Lattner0ecea032007-08-22 05:28:50 +0000602 // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000603 // there is no compound stmt. C90 does not have this clause. We only do this
604 // if the body isn't a compound statement to avoid push/pop in common cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000605 bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000606 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000607
Reid Spencer5f016e22007-07-11 17:01:13 +0000608 // Read the body statement.
609 StmtResult Body = ParseStatement();
610
Chris Lattner0ecea032007-08-22 05:28:50 +0000611 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000612 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000613
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000614 if (Body.isInvalid) {
Steve Naroff1b273c42007-09-16 14:56:35 +0000615 Body = Actions.ActOnNullStmt(Tok.getLocation());
Anders Carlssonc1fcb772007-07-22 07:07:56 +0000616 // FIXME: Remove the case statement list from the Switch statement.
617 }
618
Reid Spencer5f016e22007-07-11 17:01:13 +0000619 ExitScope();
620
Steve Naroff1b273c42007-09-16 14:56:35 +0000621 return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.Val, Body.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000622}
623
624/// ParseWhileStatement
625/// while-statement: [C99 6.8.5.1]
626/// 'while' '(' expression ')' statement
627Parser::StmtResult Parser::ParseWhileStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000628 assert(Tok.is(tok::kw_while) && "Not a while stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000629 SourceLocation WhileLoc = Tok.getLocation();
630 ConsumeToken(); // eat the 'while'.
631
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000632 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000633 Diag(Tok, diag::err_expected_lparen_after, "while");
634 SkipUntil(tok::semi);
635 return true;
636 }
637
Chris Lattner22153252007-08-26 23:08:06 +0000638 // C99 6.8.5p5 - In C99, the while 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
645 // Parse the condition.
646 ExprResult Cond = ParseSimpleParenExpression();
647
Chris Lattner0ecea032007-08-22 05:28:50 +0000648 // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000649 // there is no compound stmt. C90 does not have this clause. We only do this
650 // if the body isn't a compound statement to avoid push/pop in common cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000651 bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000652 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000653
Reid Spencer5f016e22007-07-11 17:01:13 +0000654 // Read the body statement.
655 StmtResult Body = ParseStatement();
656
Chris Lattner0ecea032007-08-22 05:28:50 +0000657 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000658 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000659
Reid Spencer5f016e22007-07-11 17:01:13 +0000660 ExitScope();
661
662 if (Cond.isInvalid || Body.isInvalid) return true;
663
Steve Naroff1b273c42007-09-16 14:56:35 +0000664 return Actions.ActOnWhileStmt(WhileLoc, Cond.Val, Body.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000665}
666
667/// ParseDoStatement
668/// do-statement: [C99 6.8.5.2]
669/// 'do' statement 'while' '(' expression ')' ';'
670/// Note: this lets the caller parse the end ';'.
671Parser::StmtResult Parser::ParseDoStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000672 assert(Tok.is(tok::kw_do) && "Not a do stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000673 SourceLocation DoLoc = ConsumeToken(); // eat the 'do'.
674
Chris Lattner22153252007-08-26 23:08:06 +0000675 // C99 6.8.5p5 - In C99, the do statement is a block. This is not
676 // the case for C90. Start the loop scope.
677 if (getLang().C99)
678 EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
679 else
680 EnterScope(Scope::BreakScope | Scope::ContinueScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000681
Chris Lattner0ecea032007-08-22 05:28:50 +0000682 // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000683 // there is no compound stmt. C90 does not have this clause. We only do this
684 // if the body isn't a compound statement to avoid push/pop in common cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000685 bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000686 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000687
Reid Spencer5f016e22007-07-11 17:01:13 +0000688 // Read the body statement.
689 StmtResult Body = ParseStatement();
690
Chris Lattner0ecea032007-08-22 05:28:50 +0000691 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000692 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000693
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000694 if (Tok.isNot(tok::kw_while)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000695 ExitScope();
696 Diag(Tok, diag::err_expected_while);
697 Diag(DoLoc, diag::err_matching, "do");
698 SkipUntil(tok::semi);
699 return true;
700 }
701 SourceLocation WhileLoc = ConsumeToken();
702
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000703 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000704 ExitScope();
705 Diag(Tok, diag::err_expected_lparen_after, "do/while");
706 SkipUntil(tok::semi);
707 return true;
708 }
709
710 // Parse the condition.
711 ExprResult Cond = ParseSimpleParenExpression();
712
713 ExitScope();
714
715 if (Cond.isInvalid || Body.isInvalid) return true;
716
Steve Naroff1b273c42007-09-16 14:56:35 +0000717 return Actions.ActOnDoStmt(DoLoc, Body.Val, WhileLoc, Cond.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000718}
719
720/// ParseForStatement
721/// for-statement: [C99 6.8.5.3]
722/// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
723/// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
724Parser::StmtResult Parser::ParseForStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000725 assert(Tok.is(tok::kw_for) && "Not a for stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000726 SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
727
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000728 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000729 Diag(Tok, diag::err_expected_lparen_after, "for");
730 SkipUntil(tok::semi);
731 return true;
732 }
733
Chris Lattner22153252007-08-26 23:08:06 +0000734 // C99 6.8.5p5 - In C99, the for statement is a block. This is not
735 // the case for C90. Start the loop scope.
736 if (getLang().C99)
737 EnterScope(Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope);
738 else
739 EnterScope(Scope::BreakScope | Scope::ContinueScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000740
741 SourceLocation LParenLoc = ConsumeParen();
742 ExprResult Value;
743
744 StmtTy *FirstPart = 0;
745 ExprTy *SecondPart = 0;
746 StmtTy *ThirdPart = 0;
747
748 // Parse the first part of the for specifier.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000749 if (Tok.is(tok::semi)) { // for (;
Reid Spencer5f016e22007-07-11 17:01:13 +0000750 // no first part, eat the ';'.
751 ConsumeToken();
752 } else if (isDeclarationSpecifier()) { // for (int X = 4;
753 // Parse declaration, which eats the ';'.
754 if (!getLang().C99) // Use of C99-style for loops in C90 mode?
755 Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
756 DeclTy *aBlockVarDecl = ParseDeclaration(Declarator::ForContext);
Steve Naroff1b273c42007-09-16 14:56:35 +0000757 StmtResult stmtResult = Actions.ActOnDeclStmt(aBlockVarDecl);
Reid Spencer5f016e22007-07-11 17:01:13 +0000758 FirstPart = stmtResult.isInvalid ? 0 : stmtResult.Val;
759 } else {
760 Value = ParseExpression();
761
762 // Turn the expression into a stmt.
763 if (!Value.isInvalid) {
Steve Naroff1b273c42007-09-16 14:56:35 +0000764 StmtResult R = Actions.ActOnExprStmt(Value.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000765 if (!R.isInvalid)
766 FirstPart = R.Val;
767 }
768
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000769 if (Tok.is(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000770 ConsumeToken();
771 } else {
772 if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
773 SkipUntil(tok::semi);
774 }
775 }
776
777 // Parse the second part of the for specifier.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000778 if (Tok.is(tok::semi)) { // for (...;;
Reid Spencer5f016e22007-07-11 17:01:13 +0000779 // no second part.
780 Value = ExprResult();
781 } else {
782 Value = ParseExpression();
783 if (!Value.isInvalid)
784 SecondPart = Value.Val;
785 }
786
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000787 if (Tok.is(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000788 ConsumeToken();
789 } else {
790 if (!Value.isInvalid) Diag(Tok, diag::err_expected_semi_for);
791 SkipUntil(tok::semi);
792 }
793
794 // Parse the third part of the for specifier.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000795 if (Tok.is(tok::r_paren)) { // for (...;...;)
Reid Spencer5f016e22007-07-11 17:01:13 +0000796 // no third part.
797 Value = ExprResult();
798 } else {
799 Value = ParseExpression();
800 if (!Value.isInvalid) {
801 // Turn the expression into a stmt.
Steve Naroff1b273c42007-09-16 14:56:35 +0000802 StmtResult R = Actions.ActOnExprStmt(Value.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000803 if (!R.isInvalid)
804 ThirdPart = R.Val;
805 }
806 }
807
808 // Match the ')'.
809 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
810
Chris Lattner0ecea032007-08-22 05:28:50 +0000811 // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
Chris Lattner38484402007-08-22 05:33:11 +0000812 // there is no compound stmt. C90 does not have this clause. We only do this
813 // if the body isn't a compound statement to avoid push/pop in common cases.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000814 bool NeedsInnerScope = getLang().C99 && Tok.isNot(tok::l_brace);
Chris Lattner31e05722007-08-26 06:24:45 +0000815 if (NeedsInnerScope) EnterScope(Scope::DeclScope);
Chris Lattner0ecea032007-08-22 05:28:50 +0000816
Reid Spencer5f016e22007-07-11 17:01:13 +0000817 // Read the body statement.
818 StmtResult Body = ParseStatement();
819
Chris Lattner0ecea032007-08-22 05:28:50 +0000820 // Pop the body scope if needed.
Chris Lattner38484402007-08-22 05:33:11 +0000821 if (NeedsInnerScope) ExitScope();
Chris Lattner0ecea032007-08-22 05:28:50 +0000822
Reid Spencer5f016e22007-07-11 17:01:13 +0000823 // Leave the for-scope.
824 ExitScope();
825
826 if (Body.isInvalid)
827 return Body;
828
Steve Naroff1b273c42007-09-16 14:56:35 +0000829 return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart, SecondPart,
Reid Spencer5f016e22007-07-11 17:01:13 +0000830 ThirdPart, RParenLoc, Body.Val);
831}
832
833/// ParseGotoStatement
834/// jump-statement:
835/// 'goto' identifier ';'
836/// [GNU] 'goto' '*' expression ';'
837///
838/// Note: this lets the caller parse the end ';'.
839///
840Parser::StmtResult Parser::ParseGotoStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000841 assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000842 SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
843
844 StmtResult Res;
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000845 if (Tok.is(tok::identifier)) {
Steve Naroff1b273c42007-09-16 14:56:35 +0000846 Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
Reid Spencer5f016e22007-07-11 17:01:13 +0000847 Tok.getIdentifierInfo());
848 ConsumeToken();
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000849 } else if (Tok.is(tok::star) && !getLang().NoExtensions) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000850 // GNU indirect goto extension.
851 Diag(Tok, diag::ext_gnu_indirect_goto);
852 SourceLocation StarLoc = ConsumeToken();
853 ExprResult R = ParseExpression();
854 if (R.isInvalid) { // Skip to the semicolon, but don't consume it.
855 SkipUntil(tok::semi, false, true);
856 return true;
857 }
Steve Naroff1b273c42007-09-16 14:56:35 +0000858 Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.Val);
Chris Lattner95cfb852007-07-22 04:13:33 +0000859 } else {
860 Diag(Tok, diag::err_expected_ident);
861 return true;
Reid Spencer5f016e22007-07-11 17:01:13 +0000862 }
Chris Lattner95cfb852007-07-22 04:13:33 +0000863
Reid Spencer5f016e22007-07-11 17:01:13 +0000864 return Res;
865}
866
867/// ParseContinueStatement
868/// jump-statement:
869/// 'continue' ';'
870///
871/// Note: this lets the caller parse the end ';'.
872///
873Parser::StmtResult Parser::ParseContinueStatement() {
874 SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
Steve Naroff1b273c42007-09-16 14:56:35 +0000875 return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000876}
877
878/// ParseBreakStatement
879/// jump-statement:
880/// 'break' ';'
881///
882/// Note: this lets the caller parse the end ';'.
883///
884Parser::StmtResult Parser::ParseBreakStatement() {
885 SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
Steve Naroff1b273c42007-09-16 14:56:35 +0000886 return Actions.ActOnBreakStmt(BreakLoc, CurScope);
Reid Spencer5f016e22007-07-11 17:01:13 +0000887}
888
889/// ParseReturnStatement
890/// jump-statement:
891/// 'return' expression[opt] ';'
892Parser::StmtResult Parser::ParseReturnStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000893 assert(Tok.is(tok::kw_return) && "Not a return stmt!");
Reid Spencer5f016e22007-07-11 17:01:13 +0000894 SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
895
896 ExprResult R(0);
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000897 if (Tok.isNot(tok::semi)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000898 R = ParseExpression();
899 if (R.isInvalid) { // Skip to the semicolon, but don't consume it.
900 SkipUntil(tok::semi, false, true);
901 return true;
902 }
903 }
Steve Naroff1b273c42007-09-16 14:56:35 +0000904 return Actions.ActOnReturnStmt(ReturnLoc, R.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +0000905}
906
907/// ParseAsmStatement - Parse a GNU extended asm statement.
908/// [GNU] asm-statement:
909/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';'
910///
911/// [GNU] asm-argument:
912/// asm-string-literal
913/// asm-string-literal ':' asm-operands[opt]
914/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
915/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
916/// ':' asm-clobbers
917///
918/// [GNU] asm-clobbers:
919/// asm-string-literal
920/// asm-clobbers ',' asm-string-literal
921///
922Parser::StmtResult Parser::ParseAsmStatement() {
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000923 assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
Chris Lattnerfe795952007-10-29 04:04:16 +0000924 SourceLocation AsmLoc = ConsumeToken();
Reid Spencer5f016e22007-07-11 17:01:13 +0000925
926 DeclSpec DS;
927 SourceLocation Loc = Tok.getLocation();
928 ParseTypeQualifierListOpt(DS);
929
930 // GNU asms accept, but warn, about type-qualifiers other than volatile.
931 if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
932 Diag(Loc, diag::w_asm_qualifier_ignored, "const");
933 if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
934 Diag(Loc, diag::w_asm_qualifier_ignored, "restrict");
935
936 // Remember if this was a volatile asm.
Anders Carlsson39c47b52007-11-23 23:12:25 +0000937 bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
Reid Spencer5f016e22007-07-11 17:01:13 +0000938
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000939 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000940 Diag(Tok, diag::err_expected_lparen_after, "asm");
941 SkipUntil(tok::r_paren);
942 return true;
943 }
944 Loc = ConsumeParen();
945
Anders Carlsson6a0ef4b2007-11-20 19:21:03 +0000946 ExprResult AsmString = ParseAsmStringLiteral();
947 if (AsmString.isInvalid)
948 return true;
Anders Carlssonb235fc22007-11-22 01:36:19 +0000949
950 llvm::SmallVector<std::string, 4> Names;
951 llvm::SmallVector<ExprTy*, 4> Constraints;
952 llvm::SmallVector<ExprTy*, 4> Exprs;
953
954 // Parse Outputs, if present.
955 ParseAsmOperandsOpt(Names, Constraints, Exprs);
956
957 unsigned NumOutputs = Names.size();
Reid Spencer5f016e22007-07-11 17:01:13 +0000958
959 // Parse Inputs, if present.
Anders Carlssonb235fc22007-11-22 01:36:19 +0000960 ParseAsmOperandsOpt(Names, Constraints, Exprs);
961 assert(Names.size() == Constraints.size() &&
962 Constraints.size() == Exprs.size()
963 && "Input operand size mismatch!");
964
965 unsigned NumInputs = Names.size() - NumOutputs;
966
967 llvm::SmallVector<ExprTy*, 4> Clobbers;
Reid Spencer5f016e22007-07-11 17:01:13 +0000968
969 // Parse the clobbers, if present.
Chris Lattner4e1d99a2007-10-09 17:41:39 +0000970 if (Tok.is(tok::colon)) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000971 ConsumeToken();
972
Anders Carlssoneecf8472007-11-21 23:27:34 +0000973 // Parse the asm-string list for clobbers.
974 while (1) {
Anders Carlssonb235fc22007-11-22 01:36:19 +0000975 ExprResult Clobber = ParseAsmStringLiteral();
Reid Spencer5f016e22007-07-11 17:01:13 +0000976
Anders Carlssonb235fc22007-11-22 01:36:19 +0000977 if (Clobber.isInvalid)
978 break;
979
980 Clobbers.push_back(Clobber.Val);
981
Anders Carlssoneecf8472007-11-21 23:27:34 +0000982 if (Tok.isNot(tok::comma)) break;
983 ConsumeToken();
Reid Spencer5f016e22007-07-11 17:01:13 +0000984 }
985 }
986
Chris Lattnerfe795952007-10-29 04:04:16 +0000987 SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000988
Anders Carlsson39c47b52007-11-23 23:12:25 +0000989 return Actions.ActOnAsmStmt(AsmLoc, isVolatile, NumOutputs, NumInputs,
Anders Carlssonb235fc22007-11-22 01:36:19 +0000990 &Names[0], &Constraints[0], &Exprs[0],
991 AsmString.Val,
992 Clobbers.size(), &Clobbers[0],
993 RParenLoc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000994}
995
996/// ParseAsmOperands - Parse the asm-operands production as used by
997/// asm-statement. We also parse a leading ':' token. If the leading colon is
998/// not present, we do not parse anything.
999///
1000/// [GNU] asm-operands:
1001/// asm-operand
1002/// asm-operands ',' asm-operand
1003///
1004/// [GNU] asm-operand:
1005/// asm-string-literal '(' expression ')'
1006/// '[' identifier ']' asm-string-literal '(' expression ')'
1007///
Anders Carlssonb235fc22007-11-22 01:36:19 +00001008void Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
1009 llvm::SmallVectorImpl<ExprTy*> &Constraints,
1010 llvm::SmallVectorImpl<ExprTy*> &Exprs) {
Reid Spencer5f016e22007-07-11 17:01:13 +00001011 // Only do anything if this operand is present.
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001012 if (Tok.isNot(tok::colon)) return;
Reid Spencer5f016e22007-07-11 17:01:13 +00001013 ConsumeToken();
1014
1015 // 'asm-operands' isn't present?
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001016 if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
Reid Spencer5f016e22007-07-11 17:01:13 +00001017 return;
1018
Anders Carlssonb235fc22007-11-22 01:36:19 +00001019 while (1) {
Reid Spencer5f016e22007-07-11 17:01:13 +00001020 // Read the [id] if present.
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001021 if (Tok.is(tok::l_square)) {
Reid Spencer5f016e22007-07-11 17:01:13 +00001022 SourceLocation Loc = ConsumeBracket();
1023
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001024 if (Tok.isNot(tok::identifier)) {
Reid Spencer5f016e22007-07-11 17:01:13 +00001025 Diag(Tok, diag::err_expected_ident);
1026 SkipUntil(tok::r_paren);
1027 return;
1028 }
Chris Lattner69efba72007-10-29 04:06:22 +00001029
Anders Carlssonb235fc22007-11-22 01:36:19 +00001030 IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner69efba72007-10-29 04:06:22 +00001031 ConsumeToken();
Anders Carlssonb235fc22007-11-22 01:36:19 +00001032
1033 Names.push_back(std::string(II->getName(), II->getLength()));
Reid Spencer5f016e22007-07-11 17:01:13 +00001034 MatchRHSPunctuation(tok::r_square, Loc);
Anders Carlssonb235fc22007-11-22 01:36:19 +00001035 } else
1036 Names.push_back(std::string());
Reid Spencer5f016e22007-07-11 17:01:13 +00001037
Anders Carlssonb235fc22007-11-22 01:36:19 +00001038 ExprResult Constraint = ParseAsmStringLiteral();
1039 if (Constraint.isInvalid) {
1040 SkipUntil(tok::r_paren);
1041 return;
1042 }
1043 Constraints.push_back(Constraint.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +00001044
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001045 if (Tok.isNot(tok::l_paren)) {
Reid Spencer5f016e22007-07-11 17:01:13 +00001046 Diag(Tok, diag::err_expected_lparen_after, "asm operand");
1047 SkipUntil(tok::r_paren);
1048 return;
1049 }
1050
1051 // Read the parenthesized expression.
1052 ExprResult Res = ParseSimpleParenExpression();
1053 if (Res.isInvalid) {
1054 SkipUntil(tok::r_paren);
1055 return;
1056 }
Anders Carlssonb235fc22007-11-22 01:36:19 +00001057 Exprs.push_back(Res.Val);
Reid Spencer5f016e22007-07-11 17:01:13 +00001058 // Eat the comma and continue parsing if it exists.
Chris Lattner4e1d99a2007-10-09 17:41:39 +00001059 if (Tok.isNot(tok::comma)) return;
Reid Spencer5f016e22007-07-11 17:01:13 +00001060 ConsumeToken();
1061 }
1062}
Fariborz Jahanianf9ed3152007-11-08 19:01:26 +00001063
1064Parser::DeclTy *Parser::ParseFunctionStatementBody(DeclTy *Decl,
1065 SourceLocation L, SourceLocation R) {
1066 // Do not enter a scope for the brace, as the arguments are in the same scope
1067 // (the function body) as the body itself. Instead, just read the statement
1068 // list and put it into a CompoundStmt for safe keeping.
1069 StmtResult FnBody = ParseCompoundStatementBody();
1070
1071 // If the function body could not be parsed, make a bogus compoundstmt.
1072 if (FnBody.isInvalid)
1073 FnBody = Actions.ActOnCompoundStmt(L, R, 0, 0, false);
1074
1075 // Leave the function body scope.
1076 ExitScope();
1077
Steve Naroffd6d054d2007-11-11 23:20:51 +00001078 return Actions.ActOnFinishFunctionBody(Decl, FnBody.Val);
Seo Sanghyeoncd5af4b2007-12-01 08:06:07 +00001079}