 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
79.3% |
388 / 489 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
98.8% |
483 / 489 |
| |
|
Line Coverage: |
87.6% |
522 / 596 |
| |
 |
|
 |
1 : //===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // 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 "RAIIObjectsForParser.h"
17 : #include "clang/Parse/DeclSpec.h"
18 : #include "clang/Parse/Scope.h"
19 : #include "clang/Basic/Diagnostic.h"
20 : #include "clang/Basic/PrettyStackTrace.h"
21 : #include "clang/Basic/SourceManager.h"
22 : using namespace clang;
23 :
24 : //===----------------------------------------------------------------------===//
25 : // C99 6.8: Statements and Blocks.
26 : //===----------------------------------------------------------------------===//
27 :
28 : /// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
29 : /// StatementOrDeclaration:
30 : /// statement
31 : /// declaration
32 : ///
33 : /// statement:
34 : /// labeled-statement
35 : /// compound-statement
36 : /// expression-statement
37 : /// selection-statement
38 : /// iteration-statement
39 : /// jump-statement
40 : /// [C++] declaration-statement
41 : /// [C++] try-block
42 : /// [OBC] objc-throw-statement
43 : /// [OBC] objc-try-catch-statement
44 : /// [OBC] objc-synchronized-statement
45 : /// [GNU] asm-statement
46 : /// [OMP] openmp-construct [TODO]
47 : ///
48 : /// labeled-statement:
49 : /// identifier ':' statement
50 : /// 'case' constant-expression ':' statement
51 : /// 'default' ':' statement
52 : ///
53 : /// selection-statement:
54 : /// if-statement
55 : /// switch-statement
56 : ///
57 : /// iteration-statement:
58 : /// while-statement
59 : /// do-statement
60 : /// for-statement
61 : ///
62 : /// expression-statement:
63 : /// expression[opt] ';'
64 : ///
65 : /// jump-statement:
66 : /// 'goto' identifier ';'
67 : /// 'continue' ';'
68 : /// 'break' ';'
69 : /// 'return' expression[opt] ';'
70 : /// [GNU] 'goto' '*' expression ';'
71 : ///
72 : /// [OBC] objc-throw-statement:
73 : /// [OBC] '@' 'throw' expression ';'
74 : /// [OBC] '@' 'throw' ';'
75 : ///
76 : Parser::OwningStmtResult
77 25500: Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
78 25500: const char *SemiError = 0;
79 25500: OwningStmtResult Res(Actions);
80 :
81 25500: CXX0XAttributeList Attr;
779: branch 1 taken
24721: branch 2 taken
15: branch 4 taken
764: branch 5 taken
15: branch 6 taken
25485: branch 7 taken
82 25500: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
83 15: Attr = ParseCXX0XAttributes();
84 :
85 : // Cases in this switch statement should fall through if the parser expects
86 : // the token to end in a semicolon (in which case SemiError should be set),
87 : // or they directly 'return;' if not.
88 25500: tok::TokenKind Kind = Tok.getKind();
89 25500: SourceLocation AtLoc;
118: branch 0 taken
5: branch 1 taken
8476: branch 2 taken
7877: branch 3 taken
258: branch 4 taken
53: branch 5 taken
1135: branch 6 taken
264: branch 7 taken
1559: branch 8 taken
139: branch 9 taken
173: branch 10 taken
74: branch 11 taken
284: branch 12 taken
158: branch 13 taken
32: branch 14 taken
265: branch 15 taken
4502: branch 16 taken
108: branch 17 taken
20: branch 18 taken
90 25500: switch (Kind) {
91 : case tok::at: // May be a @try or @throw statement
92 : {
93 118: AtLoc = ConsumeToken(); // consume @
94 118: return ParseObjCAtStatement(AtLoc);
95 : }
96 :
97 : case tok::code_completion:
98 5: Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Statement);
99 5: ConsumeToken();
100 5: return ParseStatementOrDeclaration(OnlyStatement);
101 :
102 : case tok::identifier:
151: branch 2 taken
8325: branch 3 taken
103 8476: if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
104 : // identifier ':' statement
105 151: return ParseLabeledStatement(Attr.AttrList);
106 : }
107 : // PASS THROUGH.
108 :
109 : default: {
11236: branch 1 taken
4966: branch 2 taken
10488: branch 3 taken
748: branch 4 taken
7091: branch 6 taken
8363: branch 7 taken
7091: branch 8 taken
9111: branch 9 taken
110 16202: if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
111 7091: SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
112 : DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd,
113 7091: Attr);
114 7091: return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
115 : }
116 :
0: branch 1 not taken
9111: branch 2 taken
117 9111: if (Tok.is(tok::r_brace)) {
118 0: Diag(Tok, diag::err_expected_statement);
119 0: return StmtError();
120 : }
121 :
122 : // FIXME: Use the attributes
123 : // expression[opt] ';'
124 9111: OwningExprResult Expr(ParseExpression());
637: branch 1 taken
8474: branch 2 taken
125 9111: if (Expr.isInvalid()) {
126 : // If the expression is invalid, skip ahead to the next semicolon. Not
127 : // doing this opens us up to the possibility of infinite loops if
128 : // ParseExpression does not consume any tokens.
129 637: SkipUntil(tok::semi);
130 637: return StmtError();
131 : }
132 : // Otherwise, eat the semicolon.
133 8474: ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
134 8474: return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr));
135 : }
136 :
137 : case tok::kw_case: // C99 6.8.1: labeled-statement
138 258: return ParseCaseStatement(Attr.AttrList);
139 : case tok::kw_default: // C99 6.8.1: labeled-statement
140 53: return ParseDefaultStatement(Attr.AttrList);
141 :
142 : case tok::l_brace: // C99 6.8.2: compound-statement
143 1135: return ParseCompoundStatement(Attr.AttrList);
144 : case tok::semi: // C99 6.8.3p3: expression[opt] ';'
145 264: return Actions.ActOnNullStmt(ConsumeToken());
146 :
147 : case tok::kw_if: // C99 6.8.4.1: if-statement
148 1559: return ParseIfStatement(Attr.AttrList);
149 : case tok::kw_switch: // C99 6.8.4.2: switch-statement
150 139: return ParseSwitchStatement(Attr.AttrList);
151 :
152 : case tok::kw_while: // C99 6.8.5.1: while-statement
153 173: return ParseWhileStatement(Attr.AttrList);
154 : case tok::kw_do: // C99 6.8.5.2: do-statement
155 74: Res = ParseDoStatement(Attr.AttrList);
156 74: SemiError = "do/while";
157 74: break;
158 : case tok::kw_for: // C99 6.8.5.3: for-statement
159 284: return ParseForStatement(Attr.AttrList);
160 :
161 : case tok::kw_goto: // C99 6.8.6.1: goto-statement
162 158: Res = ParseGotoStatement(Attr.AttrList);
163 158: SemiError = "goto";
164 158: break;
165 : case tok::kw_continue: // C99 6.8.6.2: continue-statement
166 32: Res = ParseContinueStatement(Attr.AttrList);
167 32: SemiError = "continue";
168 32: break;
169 : case tok::kw_break: // C99 6.8.6.3: break-statement
170 265: Res = ParseBreakStatement(Attr.AttrList);
171 265: SemiError = "break";
172 265: break;
173 : case tok::kw_return: // C99 6.8.6.4: return-statement
174 4502: Res = ParseReturnStatement(Attr.AttrList);
175 4502: SemiError = "return";
176 4502: break;
177 :
178 : case tok::kw_asm: {
0: branch 0 not taken
108: branch 1 taken
179 108: if (Attr.HasAttr)
180 : Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
181 0: << Attr.Range;
182 108: bool msAsm = false;
183 108: Res = ParseAsmStatement(msAsm);
5: branch 0 taken
103: branch 1 taken
184 108: if (msAsm) return move(Res);
185 103: SemiError = "asm";
186 103: break;
187 : }
188 :
189 : case tok::kw_try: // C++ 15: try-block
190 20: return ParseCXXTryBlock(Attr.AttrList);
191 : }
192 :
193 : // If we reached this code, the statement must end in a semicolon.
5129: branch 1 taken
5: branch 2 taken
194 5134: if (Tok.is(tok::semi)) {
195 5129: ConsumeToken();
1: branch 1 taken
4: branch 2 taken
196 5: } else if (!Res.isInvalid()) {
197 : // If the result was valid, then we do want to diagnose this. Use
198 : // ExpectAndConsume to emit the diagnostic, even though we know it won't
199 : // succeed.
200 1: ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
201 : // Skip until we see a } or ;, but don't eat it.
202 1: SkipUntil(tok::r_brace, true, true);
203 : }
204 :
205 5134: return move(Res);
206 : }
207 :
208 : /// ParseLabeledStatement - We have an identifier and a ':' after it.
209 : ///
210 : /// labeled-statement:
211 : /// identifier ':' statement
212 : /// [GNU] identifier ':' attributes[opt] statement
213 : ///
214 151: Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
215 : assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
151: branch 1 taken
0: branch 2 not taken
151: branch 4 taken
0: branch 5 not taken
216 151: "Not an identifier!");
217 :
218 151: Token IdentTok = Tok; // Save the whole token.
219 151: ConsumeToken(); // eat the identifier.
220 :
151: branch 1 taken
0: branch 2 not taken
221 151: assert(Tok.is(tok::colon) && "Not a label!");
222 :
223 : // identifier ':' statement
224 151: SourceLocation ColonLoc = ConsumeToken();
225 :
226 : // Read label attributes, if present.
0: branch 1 not taken
151: branch 2 taken
227 151: if (Tok.is(tok::kw___attribute))
228 0: Attr = addAttributeLists(Attr, ParseGNUAttributes());
229 :
230 151: OwningStmtResult SubStmt(ParseStatement());
231 :
232 : // Broken substmt shouldn't prevent the label from being added to the AST.
4: branch 1 taken
147: branch 2 taken
233 151: if (SubStmt.isInvalid())
234 4: SubStmt = Actions.ActOnNullStmt(ColonLoc);
235 :
236 : return Actions.ActOnLabelStmt(IdentTok.getLocation(),
237 : IdentTok.getIdentifierInfo(),
238 151: ColonLoc, move(SubStmt));
239 : }
240 :
241 : /// ParseCaseStatement
242 : /// labeled-statement:
243 : /// 'case' constant-expression ':' statement
244 : /// [GNU] 'case' constant-expression '...' constant-expression ':' statement
245 : ///
246 258: Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
258: branch 1 taken
0: branch 2 not taken
247 258: assert(Tok.is(tok::kw_case) && "Not a case stmt!");
248 : // FIXME: Use attributes?
249 :
250 : // It is very very common for code to contain many case statements recursively
251 : // nested, as in (but usually without indentation):
252 : // case 1:
253 : // case 2:
254 : // case 3:
255 : // case 4:
256 : // case 5: etc.
257 : //
258 : // Parsing this naively works, but is both inefficient and can cause us to run
259 : // out of stack space in our recursive descent parser. As a special case,
260 : // flatten this recursion into an iterative loop. This is complex and gross,
261 : // but all the grossness is constrained to ParseCaseStatement (and some
262 : // wierdness in the actions), so this is just local grossness :).
263 :
264 : // TopLevelCase - This is the highest level we have parsed. 'case 1' in the
265 : // example above.
266 258: OwningStmtResult TopLevelCase(Actions, true);
267 :
268 : // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
269 : // gets updated each time a new case is parsed, and whose body is unset so
270 : // far. When parsing 'case 4', this is the 'case 3' node.
271 258: StmtTy *DeepestParsedCaseStmt = 0;
272 :
273 : // While we have case statements, eat and stack them.
47: branch 1 taken
247: branch 2 taken
274 294: do {
275 305: SourceLocation CaseLoc = ConsumeToken(); // eat the 'case'.
276 :
5: branch 1 taken
300: branch 2 taken
277 305: if (Tok.is(tok::code_completion)) {
278 5: Actions.CodeCompleteCase(CurScope);
279 5: ConsumeToken();
280 : }
281 :
282 : /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
283 : /// Disable this form of error recovery while we're parsing the case
284 : /// expression.
285 305: ColonProtectionRAIIObject ColonProtection(*this);
286 :
287 305: OwningExprResult LHS(ParseConstantExpression());
5: branch 1 taken
300: branch 2 taken
288 305: if (LHS.isInvalid()) {
289 5: SkipUntil(tok::colon);
290 5: return StmtError();
291 : }
292 :
293 : // GNU case range extension.
294 300: SourceLocation DotDotDotLoc;
295 300: OwningExprResult RHS(Actions);
44: branch 1 taken
256: branch 2 taken
296 300: if (Tok.is(tok::ellipsis)) {
297 44: Diag(Tok, diag::ext_gnu_case_range);
298 44: DotDotDotLoc = ConsumeToken();
299 :
300 44: RHS = ParseConstantExpression();
0: branch 1 not taken
44: branch 2 taken
301 44: if (RHS.isInvalid()) {
302 0: SkipUntil(tok::colon);
303 0: return StmtError();
304 : }
305 : }
306 :
307 300: ColonProtection.restore();
308 :
0: branch 1 not taken
300: branch 2 taken
309 300: if (Tok.isNot(tok::colon)) {
310 0: Diag(Tok, diag::err_expected_colon_after) << "'case'";
311 0: SkipUntil(tok::colon);
312 0: return StmtError();
313 : }
314 :
315 300: SourceLocation ColonLoc = ConsumeToken();
316 :
317 : OwningStmtResult Case =
318 : Actions.ActOnCaseStmt(CaseLoc, move(LHS), DotDotDotLoc,
319 300: move(RHS), ColonLoc);
320 :
321 : // If we had a sema error parsing this case, then just ignore it and
322 : // continue parsing the sub-stmt.
6: branch 1 taken
294: branch 2 taken
323 300: if (Case.isInvalid()) {
6: branch 1 taken
0: branch 2 not taken
324 6: if (TopLevelCase.isInvalid()) // No parsed case stmts.
325 6: return ParseStatement();
326 : // Otherwise, just don't add it as a nested case.
327 : } else {
328 : // If this is the first case statement we parsed, it becomes TopLevelCase.
329 : // Otherwise we link it into the current chain.
330 294: StmtTy *NextDeepest = Case.get();
247: branch 1 taken
47: branch 2 taken
331 294: if (TopLevelCase.isInvalid())
332 247: TopLevelCase = move(Case);
333 : else
334 47: Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(Case));
335 294: DeepestParsedCaseStmt = NextDeepest;
294: branch 1 taken
6: branch 2 taken
294: branch 4 taken
6: branch 5 taken
294: branch 7 taken
11: branch 8 taken
294: branch 10 taken
11: branch 11 taken
336 300: }
337 :
338 : // Handle all case statements.
339 : } while (Tok.is(tok::kw_case));
340 :
247: branch 1 taken
0: branch 2 not taken
341 247: assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!");
342 :
343 : // If we found a non-case statement, start by parsing it.
344 247: OwningStmtResult SubStmt(Actions);
345 :
247: branch 1 taken
0: branch 2 not taken
346 247: if (Tok.isNot(tok::r_brace)) {
347 247: SubStmt = ParseStatement();
348 : } else {
349 : // Nicely diagnose the common error "switch (X) { case 4: }", which is
350 : // not valid.
351 : // FIXME: add insertion hint.
352 0: Diag(Tok, diag::err_label_end_of_compound_statement);
353 0: SubStmt = true;
354 : }
355 :
356 : // Broken sub-stmt shouldn't prevent forming the case statement properly.
0: branch 1 not taken
247: branch 2 taken
357 247: if (SubStmt.isInvalid())
358 0: SubStmt = Actions.ActOnNullStmt(SourceLocation());
359 :
360 : // Install the body into the most deeply-nested case.
361 247: Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(SubStmt));
362 :
363 : // Return the top level parsed statement tree.
364 247: return move(TopLevelCase);
365 : }
366 :
367 : /// ParseDefaultStatement
368 : /// labeled-statement:
369 : /// 'default' ':' statement
370 : /// Note that this does not parse the 'statement' at the end.
371 : ///
372 53: Parser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
373 : //FIXME: Use attributes?
53: branch 1 taken
0: branch 2 not taken
374 53: assert(Tok.is(tok::kw_default) && "Not a default stmt!");
375 53: SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'.
376 :
0: branch 1 not taken
53: branch 2 taken
377 53: if (Tok.isNot(tok::colon)) {
378 0: Diag(Tok, diag::err_expected_colon_after) << "'default'";
379 0: SkipUntil(tok::colon);
380 0: return StmtError();
381 : }
382 :
383 53: SourceLocation ColonLoc = ConsumeToken();
384 :
385 : // Diagnose the common error "switch (X) {... default: }", which is not valid.
0: branch 1 not taken
53: branch 2 taken
386 53: if (Tok.is(tok::r_brace)) {
387 0: Diag(Tok, diag::err_label_end_of_compound_statement);
388 0: return StmtError();
389 : }
390 :
391 53: OwningStmtResult SubStmt(ParseStatement());
0: branch 1 not taken
53: branch 2 taken
392 53: if (SubStmt.isInvalid())
393 0: return StmtError();
394 :
395 : return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
396 53: move(SubStmt), CurScope);
397 : }
398 :
399 :
400 : /// ParseCompoundStatement - Parse a "{}" block.
401 : ///
402 : /// compound-statement: [C99 6.8.2]
403 : /// { block-item-list[opt] }
404 : /// [GNU] { label-declarations block-item-list } [TODO]
405 : ///
406 : /// block-item-list:
407 : /// block-item
408 : /// block-item-list block-item
409 : ///
410 : /// block-item:
411 : /// declaration
412 : /// [GNU] '__extension__' declaration
413 : /// statement
414 : /// [OMP] openmp-directive [TODO]
415 : ///
416 : /// [GNU] label-declarations:
417 : /// [GNU] label-declaration
418 : /// [GNU] label-declarations label-declaration
419 : ///
420 : /// [GNU] label-declaration:
421 : /// [GNU] '__label__' identifier-list ';'
422 : ///
423 : /// [OMP] openmp-directive: [TODO]
424 : /// [OMP] barrier-directive
425 : /// [OMP] flush-directive
426 : ///
427 : Parser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
428 1265: bool isStmtExpr) {
429 : //FIXME: Use attributes?
1265: branch 1 taken
0: branch 2 not taken
430 1265: assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
431 :
432 : // Enter a scope to hold everything within the compound stmt. Compound
433 : // statements can always hold declarations.
434 1265: ParseScope CompoundScope(this, Scope::DeclScope);
435 :
436 : // Parse the statements in the body.
437 1265: return ParseCompoundStatementBody(isStmtExpr);
438 : }
439 :
440 :
441 : /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
442 : /// ActOnCompoundStmt action. This expects the '{' to be the current token, and
443 : /// consume the '}' at the end of the block. It does not manipulate the scope
444 : /// stack.
445 10872: Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
446 : PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
447 : Tok.getLocation(),
448 10872: "in compound statement ('{}')");
449 :
450 10872: SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'.
451 :
452 : // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are
453 : // only allowed at the start of a compound stmt regardless of the language.
454 :
455 : typedef StmtVector StmtsTy;
456 10872: StmtsTy Stmts(Actions);
22612: branch 1 taken
2: branch 2 taken
22674: branch 4 taken
10812: branch 5 taken
22614: branch 7 taken
60: branch 8 taken
22614: branch 9 taken
10872: branch 10 taken
457 66972: while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
458 22614: OwningStmtResult R(Actions);
22605: branch 1 taken
9: branch 2 taken
459 22614: if (Tok.isNot(tok::kw___extension__)) {
460 22605: R = ParseStatementOrDeclaration(false);
461 : } else {
462 : // __extension__ can start declarations and it can also be a unary
463 : // operator for expressions. Consume multiple __extension__ markers here
464 : // until we can determine which is which.
465 : // FIXME: This loses extension expressions in the AST!
466 9: SourceLocation ExtLoc = ConsumeToken();
0: branch 1 not taken
9: branch 2 taken
467 18: while (Tok.is(tok::kw___extension__))
468 0: ConsumeToken();
469 :
470 9: CXX0XAttributeList Attr;
0: branch 1 not taken
9: branch 2 taken
0: branch 4 not taken
0: branch 5 not taken
0: branch 6 not taken
9: branch 7 taken
471 9: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
472 0: Attr = ParseCXX0XAttributes();
473 :
474 : // If this is the start of a declaration, parse it as such.
3: branch 1 taken
6: branch 2 taken
475 9: if (isDeclarationStatement()) {
476 : // __extension__ silences extension warnings in the subdeclaration.
477 : // FIXME: Save the __extension__ on the decl as a node somehow?
478 3: ExtensionRAIIObject O(Diags);
479 :
480 3: SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
481 : DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
482 3: Attr);
483 3: R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
484 : } else {
485 : // Otherwise this was a unary __extension__ marker.
486 6: OwningExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
487 :
2: branch 1 taken
4: branch 2 taken
488 6: if (Res.isInvalid()) {
489 2: SkipUntil(tok::semi);
490 2: continue;
491 : }
492 :
493 : // FIXME: Use attributes?
494 : // Eat the semicolon at the end of stmt and convert the expr into a
495 : // statement.
496 4: ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
4: branch 7 taken
2: branch 8 taken
497 4: R = Actions.ActOnExprStmt(Actions.MakeFullExpr(Res));
498 : }
499 : }
500 :
21471: branch 1 taken
1141: branch 2 taken
501 22612: if (R.isUsable())
502 21471: Stmts.push_back(R.release());
503 : }
504 :
505 : // We broke out of the while loop because we found a '}' or EOF.
60: branch 1 taken
10812: branch 2 taken
506 10872: if (Tok.isNot(tok::r_brace)) {
507 60: Diag(Tok, diag::err_expected_rbrace);
508 60: return StmtError();
509 : }
510 :
511 10812: SourceLocation RBraceLoc = ConsumeBrace();
512 : return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc, move_arg(Stmts),
513 10812: isStmtExpr);
514 : }
515 :
516 : /// ParseParenExprOrCondition:
517 : /// [C ] '(' expression ')'
518 : /// [C++] '(' condition ')' [not allowed if OnlyAllowCondition=true]
519 : ///
520 : /// This function parses and performs error recovery on the specified condition
521 : /// or expression (depending on whether we're in C++ or C mode). This function
522 : /// goes out of its way to recover well. It returns true if there was a parser
523 : /// error (the right paren couldn't be found), which indicates that the caller
524 : /// should try to recover harder. It returns false if the condition is
525 : /// successfully parsed. Note that a successful parse can still have semantic
526 : /// errors in the condition.
527 : bool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult,
528 1871: DeclPtrTy &DeclResult) {
529 1871: bool ParseError = false;
530 :
531 1871: SourceLocation LParenLoc = ConsumeParen();
292: branch 1 taken
1579: branch 2 taken
532 1871: if (getLang().CPlusPlus)
533 292: ParseError = ParseCXXCondition(ExprResult, DeclResult);
534 : else {
535 1579: ExprResult = ParseExpression();
536 1579: DeclResult = DeclPtrTy();
537 : }
538 :
539 : // If the parser was confused by the condition and we don't have a ')', try to
540 : // recover by skipping ahead to a semi and bailing out. If condexp is
541 : // semantically invalid but we have well formed code, keep going.
63: branch 1 taken
1808: branch 2 taken
17: branch 4 taken
46: branch 5 taken
4: branch 7 taken
13: branch 8 taken
4: branch 9 taken
1867: branch 10 taken
542 1871: if (ExprResult.isInvalid() && !DeclResult.get() && Tok.isNot(tok::r_paren)) {
543 4: SkipUntil(tok::semi);
544 : // Skipping may have stopped if it found the containing ')'. If so, we can
545 : // continue parsing the if statement.
2: branch 1 taken
2: branch 2 taken
546 4: if (Tok.isNot(tok::r_paren))
547 2: return true;
548 : }
549 :
550 : // Otherwise the condition is valid or the rparen is present.
551 1869: MatchRHSPunctuation(tok::r_paren, LParenLoc);
552 1869: return false;
553 : }
554 :
555 :
556 : /// ParseIfStatement
557 : /// if-statement: [C99 6.8.4.1]
558 : /// 'if' '(' expression ')' statement
559 : /// 'if' '(' expression ')' statement 'else' statement
560 : /// [C++] 'if' '(' condition ')' statement
561 : /// [C++] 'if' '(' condition ')' statement 'else' statement
562 : ///
563 1559: Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
564 : // FIXME: Use attributes?
1559: branch 1 taken
0: branch 2 not taken
565 1559: assert(Tok.is(tok::kw_if) && "Not an if stmt!");
566 1559: SourceLocation IfLoc = ConsumeToken(); // eat the 'if'.
567 :
0: branch 1 not taken
1559: branch 2 taken
568 1559: if (Tok.isNot(tok::l_paren)) {
569 0: Diag(Tok, diag::err_expected_lparen_after) << "if";
570 0: SkipUntil(tok::semi);
571 0: return StmtError();
572 : }
573 :
219: branch 1 taken
1340: branch 2 taken
217: branch 4 taken
2: branch 5 taken
574 1559: bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
575 :
576 : // C99 6.8.4p3 - In C99, the if statement is a block. This is not
577 : // the case for C90.
578 : //
579 : // C++ 6.4p3:
580 : // A name introduced by a declaration in a condition is in scope from its
581 : // point of declaration until the end of the substatements controlled by the
582 : // condition.
583 : // C++ 3.3.2p4:
584 : // Names declared in the for-init-statement, and in the condition of if,
585 : // while, for, and switch statements are local to the if, while, for, or
586 : // switch statement (including the controlled statement).
587 : //
588 1559: ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
589 :
590 : // Parse the condition.
591 1559: OwningExprResult CondExp(Actions);
592 1559: DeclPtrTy CondVar;
0: branch 1 not taken
1559: branch 2 taken
593 1559: if (ParseParenExprOrCondition(CondExp, CondVar))
594 0: return StmtError();
595 :
596 1559: FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp));
597 :
598 : // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
599 : // there is no compound stmt. C90 does not have this clause. We only do this
600 : // if the body isn't a compound statement to avoid push/pop in common cases.
601 : //
602 : // C++ 6.4p1:
603 : // The substatement in a selection-statement (each substatement, in the else
604 : // form of the if statement) implicitly defines a local scope.
605 : //
606 : // For C++ we create a scope for the condition and a new scope for
607 : // substatements because:
608 : // -When the 'then' scope exits, we want the condition declaration to still be
609 : // active for the 'else' scope too.
610 : // -Sema will detect name clashes by considering declarations of a
611 : // 'ControlScope' as part of its direct subscope.
612 : // -If we wanted the condition and substatement to be in the same scope, we
613 : // would have to notify ParseStatement not to create a new scope. It's
614 : // simpler to let it create a new scope.
615 : //
616 : ParseScope InnerScope(this, Scope::DeclScope,
1557: branch 0 taken
2: branch 1 taken
1054: branch 3 taken
503: branch 4 taken
617 1559: C99orCXX && Tok.isNot(tok::l_brace));
618 :
619 : // Read the 'then' stmt.
620 1559: SourceLocation ThenStmtLoc = Tok.getLocation();
621 1559: OwningStmtResult ThenStmt(ParseStatement());
622 :
623 : // Pop the 'if' scope if needed.
624 1559: InnerScope.Exit();
625 :
626 : // If it has an else, parse it.
627 1559: SourceLocation ElseLoc;
628 1559: SourceLocation ElseStmtLoc;
629 1559: OwningStmtResult ElseStmt(Actions);
630 :
206: branch 1 taken
1353: branch 2 taken
631 1559: if (Tok.is(tok::kw_else)) {
632 206: ElseLoc = ConsumeToken();
633 :
634 : // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
635 : // there is no compound stmt. C90 does not have this clause. We only do
636 : // this if the body isn't a compound statement to avoid push/pop in common
637 : // cases.
638 : //
639 : // C++ 6.4p1:
640 : // The substatement in a selection-statement (each substatement, in the else
641 : // form of the if statement) implicitly defines a local scope.
642 : //
643 : ParseScope InnerScope(this, Scope::DeclScope,
206: branch 0 taken
0: branch 1 not taken
158: branch 3 taken
48: branch 4 taken
644 206: C99orCXX && Tok.isNot(tok::l_brace));
645 :
646 206: bool WithinElse = CurScope->isWithinElse();
647 206: CurScope->setWithinElse(true);
648 206: ElseStmtLoc = Tok.getLocation();
649 206: ElseStmt = ParseStatement();
650 206: CurScope->setWithinElse(WithinElse);
651 :
652 : // Pop the 'else' scope if needed.
653 206: InnerScope.Exit();
654 : }
655 :
656 1559: IfScope.Exit();
657 :
658 : // If the condition was invalid, discard the if statement. We could recover
659 : // better by replacing it with a valid expr, but don't do that yet.
32: branch 1 taken
1527: branch 2 taken
9: branch 4 taken
23: branch 5 taken
9: branch 6 taken
1550: branch 7 taken
660 1559: if (CondExp.isInvalid() && !CondVar.get())
661 9: return StmtError();
662 :
663 : // If the then or else stmt is invalid and the other is valid (and present),
664 : // make turn the invalid one into a null stmt to avoid dropping the other
665 : // part. If both are invalid, return error.
9: branch 1 taken
1541: branch 2 taken
6: branch 4 taken
3: branch 5 taken
6: branch 7 taken
1541: branch 8 taken
3: branch 10 taken
3: branch 11 taken
9: branch 13 taken
1535: branch 14 taken
0: branch 16 not taken
9: branch 17 taken
6: branch 18 taken
1544: branch 19 taken
666 1550: if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
667 : (ThenStmt.isInvalid() && ElseStmt.get() == 0) ||
668 : (ThenStmt.get() == 0 && ElseStmt.isInvalid())) {
669 : // Both invalid, or one is invalid and other is non-present: return error.
670 6: return StmtError();
671 : }
672 :
673 : // Now if either are invalid, replace with a ';'.
3: branch 1 taken
1541: branch 2 taken
674 1544: if (ThenStmt.isInvalid())
675 3: ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
4: branch 1 taken
1540: branch 2 taken
676 1544: if (ElseStmt.isInvalid())
677 4: ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
678 :
679 : return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, move(ThenStmt),
680 1544: ElseLoc, move(ElseStmt));
681 : }
682 :
683 : /// ParseSwitchStatement
684 : /// switch-statement:
685 : /// 'switch' '(' expression ')' statement
686 : /// [C++] 'switch' '(' condition ')' statement
687 139: Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
688 : // FIXME: Use attributes?
139: branch 1 taken
0: branch 2 not taken
689 139: assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
690 139: SourceLocation SwitchLoc = ConsumeToken(); // eat the 'switch'.
691 :
0: branch 1 not taken
139: branch 2 taken
692 139: if (Tok.isNot(tok::l_paren)) {
693 0: Diag(Tok, diag::err_expected_lparen_after) << "switch";
694 0: SkipUntil(tok::semi);
695 0: return StmtError();
696 : }
697 :
34: branch 1 taken
105: branch 2 taken
34: branch 4 taken
0: branch 5 not taken
698 139: bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
699 :
700 : // C99 6.8.4p3 - In C99, the switch statement is a block. This is
701 : // not the case for C90. Start the switch scope.
702 : //
703 : // C++ 6.4p3:
704 : // A name introduced by a declaration in a condition is in scope from its
705 : // point of declaration until the end of the substatements controlled by the
706 : // condition.
707 : // C++ 3.3.2p4:
708 : // Names declared in the for-init-statement, and in the condition of if,
709 : // while, for, and switch statements are local to the if, while, for, or
710 : // switch statement (including the controlled statement).
711 : //
712 139: unsigned ScopeFlags = Scope::BreakScope;
139: branch 0 taken
0: branch 1 not taken
713 139: if (C99orCXX)
714 139: ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
715 139: ParseScope SwitchScope(this, ScopeFlags);
716 :
717 : // Parse the condition.
718 139: OwningExprResult Cond(Actions);
719 139: DeclPtrTy CondVar;
2: branch 1 taken
137: branch 2 taken
720 139: if (ParseParenExprOrCondition(Cond, CondVar))
721 2: return StmtError();
722 :
723 137: FullExprArg FullCond(Actions.MakeFullExpr(Cond));
724 :
725 137: OwningStmtResult Switch = Actions.ActOnStartOfSwitchStmt(FullCond, CondVar);
726 :
727 : // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
728 : // there is no compound stmt. C90 does not have this clause. We only do this
729 : // if the body isn't a compound statement to avoid push/pop in common cases.
730 : //
731 : // C++ 6.4p1:
732 : // The substatement in a selection-statement (each substatement, in the else
733 : // form of the if statement) implicitly defines a local scope.
734 : //
735 : // See comments in ParseIfStatement for why we create a scope for the
736 : // condition and a new scope for substatement in C++.
737 : //
738 : ParseScope InnerScope(this, Scope::DeclScope,
137: branch 0 taken
0: branch 1 not taken
4: branch 3 taken
133: branch 4 taken
739 137: C99orCXX && Tok.isNot(tok::l_brace));
740 :
741 : // Read the body statement.
742 137: OwningStmtResult Body(ParseStatement());
743 :
744 : // Pop the scopes.
745 137: InnerScope.Exit();
746 137: SwitchScope.Exit();
747 :
10: branch 1 taken
127: branch 2 taken
3: branch 4 taken
7: branch 5 taken
3: branch 6 taken
134: branch 7 taken
748 137: if (Cond.isInvalid() && !CondVar.get()) {
749 3: Actions.ActOnSwitchBodyError(SwitchLoc, move(Switch), move(Body));
750 3: return StmtError();
751 : }
752 :
6: branch 1 taken
128: branch 2 taken
753 134: if (Body.isInvalid())
754 : // FIXME: Remove the case statement list from the Switch statement.
755 6: Body = Actions.ActOnNullStmt(Tok.getLocation());
756 :
757 134: return Actions.ActOnFinishSwitchStmt(SwitchLoc, move(Switch), move(Body));
758 : }
759 :
760 : /// ParseWhileStatement
761 : /// while-statement: [C99 6.8.5.1]
762 : /// 'while' '(' expression ')' statement
763 : /// [C++] 'while' '(' condition ')' statement
764 173: Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
765 : // FIXME: Use attributes?
173: branch 1 taken
0: branch 2 not taken
766 173: assert(Tok.is(tok::kw_while) && "Not a while stmt!");
767 173: SourceLocation WhileLoc = Tok.getLocation();
768 173: ConsumeToken(); // eat the 'while'.
769 :
0: branch 1 not taken
173: branch 2 taken
770 173: if (Tok.isNot(tok::l_paren)) {
771 0: Diag(Tok, diag::err_expected_lparen_after) << "while";
772 0: SkipUntil(tok::semi);
773 0: return StmtError();
774 : }
775 :
41: branch 1 taken
132: branch 2 taken
41: branch 4 taken
0: branch 5 not taken
776 173: bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
777 :
778 : // C99 6.8.5p5 - In C99, the while statement is a block. This is not
779 : // the case for C90. Start the loop scope.
780 : //
781 : // C++ 6.4p3:
782 : // A name introduced by a declaration in a condition is in scope from its
783 : // point of declaration until the end of the substatements controlled by the
784 : // condition.
785 : // C++ 3.3.2p4:
786 : // Names declared in the for-init-statement, and in the condition of if,
787 : // while, for, and switch statements are local to the if, while, for, or
788 : // switch statement (including the controlled statement).
789 : //
790 : unsigned ScopeFlags;
173: branch 0 taken
0: branch 1 not taken
791 173: if (C99orCXX)
792 : ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
793 173: Scope::DeclScope | Scope::ControlScope;
794 : else
795 0: ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
796 173: ParseScope WhileScope(this, ScopeFlags);
797 :
798 : // Parse the condition.
799 173: OwningExprResult Cond(Actions);
800 173: DeclPtrTy CondVar;
0: branch 1 not taken
173: branch 2 taken
801 173: if (ParseParenExprOrCondition(Cond, CondVar))
802 0: return StmtError();
803 :
804 173: FullExprArg FullCond(Actions.MakeFullExpr(Cond));
805 :
806 : // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
807 : // there is no compound stmt. C90 does not have this clause. We only do this
808 : // if the body isn't a compound statement to avoid push/pop in common cases.
809 : //
810 : // C++ 6.5p2:
811 : // The substatement in an iteration-statement implicitly defines a local scope
812 : // which is entered and exited each time through the loop.
813 : //
814 : // See comments in ParseIfStatement for why we create a scope for the
815 : // condition and a new scope for substatement in C++.
816 : //
817 : ParseScope InnerScope(this, Scope::DeclScope,
173: branch 0 taken
0: branch 1 not taken
32: branch 3 taken
141: branch 4 taken
818 173: C99orCXX && Tok.isNot(tok::l_brace));
819 :
820 : // Read the body statement.
821 173: OwningStmtResult Body(ParseStatement());
822 :
823 : // Pop the body scope if needed.
824 173: InnerScope.Exit();
825 173: WhileScope.Exit();
826 :
19: branch 1 taken
154: branch 2 taken
16: branch 4 taken
3: branch 5 taken
0: branch 7 not taken
170: branch 8 taken
3: branch 9 taken
170: branch 10 taken
827 173: if ((Cond.isInvalid() && !CondVar.get()) || Body.isInvalid())
828 3: return StmtError();
829 :
830 170: return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, move(Body));
831 : }
832 :
833 : /// ParseDoStatement
834 : /// do-statement: [C99 6.8.5.2]
835 : /// 'do' statement 'while' '(' expression ')' ';'
836 : /// Note: this lets the caller parse the end ';'.
837 74: Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
838 : // FIXME: Use attributes?
74: branch 1 taken
0: branch 2 not taken
839 74: assert(Tok.is(tok::kw_do) && "Not a do stmt!");
840 74: SourceLocation DoLoc = ConsumeToken(); // eat the 'do'.
841 :
842 : // C99 6.8.5p5 - In C99, the do statement is a block. This is not
843 : // the case for C90. Start the loop scope.
844 : unsigned ScopeFlags;
59: branch 1 taken
15: branch 2 taken
845 74: if (getLang().C99)
846 59: ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
847 : else
848 15: ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
849 :
850 74: ParseScope DoScope(this, ScopeFlags);
851 :
852 : // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
853 : // there is no compound stmt. C90 does not have this clause. We only do this
854 : // if the body isn't a compound statement to avoid push/pop in common cases.
855 : //
856 : // C++ 6.5p2:
857 : // The substatement in an iteration-statement implicitly defines a local scope
858 : // which is entered and exited each time through the loop.
859 : //
860 : ParseScope InnerScope(this, Scope::DeclScope,
861 : (getLang().C99 || getLang().CPlusPlus) &&
15: branch 1 taken
59: branch 2 taken
15: branch 4 taken
0: branch 5 not taken
10: branch 7 taken
64: branch 8 taken
862 74: Tok.isNot(tok::l_brace));
863 :
864 : // Read the body statement.
865 74: OwningStmtResult Body(ParseStatement());
866 :
867 : // Pop the body scope if needed.
868 74: InnerScope.Exit();
869 :
1: branch 1 taken
73: branch 2 taken
870 74: if (Tok.isNot(tok::kw_while)) {
0: branch 1 not taken
1: branch 2 taken
871 1: if (!Body.isInvalid()) {
872 0: Diag(Tok, diag::err_expected_while);
873 0: Diag(DoLoc, diag::note_matching) << "do";
874 0: SkipUntil(tok::semi, false, true);
875 : }
876 1: return StmtError();
877 : }
878 73: SourceLocation WhileLoc = ConsumeToken();
879 :
0: branch 1 not taken
73: branch 2 taken
880 73: if (Tok.isNot(tok::l_paren)) {
881 0: Diag(Tok, diag::err_expected_lparen_after) << "do/while";
882 0: SkipUntil(tok::semi, false, true);
883 0: return StmtError();
884 : }
885 :
886 : // Parse the parenthesized condition.
887 73: SourceLocation LPLoc = ConsumeParen();
888 73: OwningExprResult Cond = ParseExpression();
889 73: SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc);
890 73: DoScope.Exit();
891 :
73: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
73: branch 5 taken
0: branch 6 not taken
73: branch 7 taken
892 73: if (Cond.isInvalid() || Body.isInvalid())
893 0: return StmtError();
894 :
895 : return Actions.ActOnDoStmt(DoLoc, move(Body), WhileLoc, LPLoc,
896 73: move(Cond), RPLoc);
897 : }
898 :
899 : /// ParseForStatement
900 : /// for-statement: [C99 6.8.5.3]
901 : /// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
902 : /// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
903 : /// [C++] 'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
904 : /// [C++] statement
905 : /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
906 : /// [OBJC2] 'for' '(' expr 'in' expr ')' statement
907 : ///
908 : /// [C++] for-init-statement:
909 : /// [C++] expression-statement
910 : /// [C++] simple-declaration
911 : ///
912 284: Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
913 : // FIXME: Use attributes?
284: branch 1 taken
0: branch 2 not taken
914 284: assert(Tok.is(tok::kw_for) && "Not a for stmt!");
915 284: SourceLocation ForLoc = ConsumeToken(); // eat the 'for'.
916 :
0: branch 1 not taken
284: branch 2 taken
917 284: if (Tok.isNot(tok::l_paren)) {
918 0: Diag(Tok, diag::err_expected_lparen_after) << "for";
919 0: SkipUntil(tok::semi);
920 0: return StmtError();
921 : }
922 :
83: branch 1 taken
201: branch 2 taken
5: branch 4 taken
78: branch 5 taken
5: branch 7 taken
0: branch 8 not taken
923 284: bool C99orCXXorObjC = getLang().C99 || getLang().CPlusPlus || getLang().ObjC1;
924 :
925 : // C99 6.8.5p5 - In C99, the for statement is a block. This is not
926 : // the case for C90. Start the loop scope.
927 : //
928 : // C++ 6.4p3:
929 : // A name introduced by a declaration in a condition is in scope from its
930 : // point of declaration until the end of the substatements controlled by the
931 : // condition.
932 : // C++ 3.3.2p4:
933 : // Names declared in the for-init-statement, and in the condition of if,
934 : // while, for, and switch statements are local to the if, while, for, or
935 : // switch statement (including the controlled statement).
936 : // C++ 6.5.3p1:
937 : // Names declared in the for-init-statement are in the same declarative-region
938 : // as those declared in the condition.
939 : //
940 : unsigned ScopeFlags;
284: branch 0 taken
0: branch 1 not taken
941 284: if (C99orCXXorObjC)
942 : ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
943 284: Scope::DeclScope | Scope::ControlScope;
944 : else
945 0: ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
946 :
947 284: ParseScope ForScope(this, ScopeFlags);
948 :
949 284: SourceLocation LParenLoc = ConsumeParen();
950 284: OwningExprResult Value(Actions);
951 :
952 284: bool ForEach = false;
953 284: OwningStmtResult FirstPart(Actions);
954 284: OwningExprResult SecondPart(Actions), ThirdPart(Actions);
955 284: DeclPtrTy SecondVar;
956 :
0: branch 1 not taken
284: branch 2 taken
957 284: if (Tok.is(tok::code_completion)) {
958 : Actions.CodeCompleteOrdinaryName(CurScope,
959 : C99orCXXorObjC? Action::CCC_ForInit
0: branch 0 not taken
0: branch 1 not taken
960 0: : Action::CCC_Expression);
961 0: ConsumeToken();
962 : }
963 :
964 : // Parse the first part of the for specifier.
58: branch 1 taken
226: branch 2 taken
965 284: if (Tok.is(tok::semi)) { // for (;
966 : // no first part, eat the ';'.
967 58: ConsumeToken();
131: branch 1 taken
95: branch 2 taken
968 226: } else if (isSimpleDeclaration()) { // for (int X = 4;
969 : // Parse declaration, which eats the ';'.
0: branch 0 not taken
131: branch 1 taken
970 131: if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode?
971 0: Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
972 :
973 131: AttributeList *AttrList = 0;
22: branch 1 taken
109: branch 2 taken
0: branch 4 not taken
22: branch 5 taken
0: branch 6 not taken
131: branch 7 taken
974 131: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
975 0: AttrList = ParseCXX0XAttributes().AttrList;
976 :
977 131: SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
978 : DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
979 131: AttrList);
980 131: FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
981 :
99: branch 1 taken
32: branch 2 taken
982 131: if (Tok.is(tok::semi)) { // for (int x = 4;
983 99: ConsumeToken();
32: branch 1 taken
0: branch 2 not taken
984 32: } else if ((ForEach = isTokIdentifier_in())) {
985 32: Actions.ActOnForEachDeclStmt(DG);
986 : // ObjC: for (id x in expr)
987 32: ConsumeToken(); // consume 'in'
988 32: SecondPart = ParseExpression();
989 : } else {
990 0: Diag(Tok, diag::err_expected_semi_for);
991 0: SkipUntil(tok::semi);
992 : }
993 : } else {
994 95: Value = ParseExpression();
995 :
996 : // Turn the expression into a stmt.
95: branch 1 taken
0: branch 2 not taken
997 95: if (!Value.isInvalid())
998 95: FirstPart = Actions.ActOnExprStmt(Actions.MakeFullExpr(Value));
999 :
71: branch 1 taken
24: branch 2 taken
1000 95: if (Tok.is(tok::semi)) {
1001 71: ConsumeToken();
24: branch 1 taken
0: branch 2 not taken
1002 24: } else if ((ForEach = isTokIdentifier_in())) {
1003 24: ConsumeToken(); // consume 'in'
1004 24: SecondPart = ParseExpression();
1005 : } else {
0: branch 1 not taken
0: branch 2 not taken
1006 0: if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
1007 0: SkipUntil(tok::semi);
1008 : }
1009 : }
228: branch 0 taken
56: branch 1 taken
1010 284: if (!ForEach) {
228: branch 1 taken
0: branch 2 not taken
1011 228: assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
1012 : // Parse the second part of the for specifier.
192: branch 1 taken
36: branch 2 taken
1013 228: if (Tok.is(tok::semi)) { // for (...;;
1014 : // no second part.
1015 : } else {
73: branch 1 taken
119: branch 2 taken
1016 192: if (getLang().CPlusPlus)
1017 73: ParseCXXCondition(SecondPart, SecondVar);
1018 : else
1019 119: SecondPart = ParseExpression();
1020 : }
1021 :
227: branch 1 taken
1: branch 2 taken
1022 228: if (Tok.is(tok::semi)) {
1023 227: ConsumeToken();
1024 : } else {
1: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
1: branch 5 taken
0: branch 6 not taken
1: branch 7 taken
1025 1: if (!SecondPart.isInvalid() || SecondVar.get())
1026 0: Diag(Tok, diag::err_expected_semi_for);
1027 1: SkipUntil(tok::semi);
1028 : }
1029 :
1030 : // Parse the third part of the for specifier.
164: branch 1 taken
64: branch 2 taken
1031 228: if (Tok.isNot(tok::r_paren)) // for (...;...;)
1032 164: ThirdPart = ParseExpression();
1033 : }
1034 : // Match the ')'.
1035 284: SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
1036 :
1037 : // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
1038 : // there is no compound stmt. C90 does not have this clause. We only do this
1039 : // if the body isn't a compound statement to avoid push/pop in common cases.
1040 : //
1041 : // C++ 6.5p2:
1042 : // The substatement in an iteration-statement implicitly defines a local scope
1043 : // which is entered and exited each time through the loop.
1044 : //
1045 : // See comments in ParseIfStatement for why we create a scope for
1046 : // for-init-statement/condition and a new scope for substatement in C++.
1047 : //
1048 : ParseScope InnerScope(this, Scope::DeclScope,
284: branch 0 taken
0: branch 1 not taken
147: branch 3 taken
137: branch 4 taken
1049 284: C99orCXXorObjC && Tok.isNot(tok::l_brace));
1050 :
1051 : // Read the body statement.
1052 284: OwningStmtResult Body(ParseStatement());
1053 :
1054 : // Pop the body scope if needed.
1055 284: InnerScope.Exit();
1056 :
1057 : // Leave the for-scope.
1058 284: ForScope.Exit();
1059 :
0: branch 1 not taken
284: branch 2 taken
1060 284: if (Body.isInvalid())
1061 0: return StmtError();
1062 :
228: branch 0 taken
56: branch 1 taken
1063 284: if (!ForEach)
1064 : return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart),
1065 : Actions.MakeFullExpr(SecondPart), SecondVar,
1066 : Actions.MakeFullExpr(ThirdPart), RParenLoc,
1067 228: move(Body));
1068 :
1069 : return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
1070 : move(FirstPart),
1071 : move(SecondPart),
1072 56: RParenLoc, move(Body));
1073 : }
1074 :
1075 : /// ParseGotoStatement
1076 : /// jump-statement:
1077 : /// 'goto' identifier ';'
1078 : /// [GNU] 'goto' '*' expression ';'
1079 : ///
1080 : /// Note: this lets the caller parse the end ';'.
1081 : ///
1082 158: Parser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
1083 : // FIXME: Use attributes?
158: branch 1 taken
0: branch 2 not taken
1084 158: assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
1085 158: SourceLocation GotoLoc = ConsumeToken(); // eat the 'goto'.
1086 :
1087 158: OwningStmtResult Res(Actions);
123: branch 1 taken
35: branch 2 taken
1088 158: if (Tok.is(tok::identifier)) {
1089 : Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
1090 123: Tok.getIdentifierInfo());
1091 123: ConsumeToken();
34: branch 1 taken
1: branch 2 taken
1092 35: } else if (Tok.is(tok::star)) {
1093 : // GNU indirect goto extension.
1094 34: Diag(Tok, diag::ext_gnu_indirect_goto);
1095 34: SourceLocation StarLoc = ConsumeToken();
1096 34: OwningExprResult R(ParseExpression());
0: branch 1 not taken
34: branch 2 taken
1097 34: if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
1098 0: SkipUntil(tok::semi, false, true);
1099 0: return StmtError();
1100 : }
34: branch 10 taken
0: branch 11 not taken
1101 34: Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, move(R));
1102 : } else {
1103 1: Diag(Tok, diag::err_expected_ident);
1104 1: return StmtError();
1105 : }
1106 :
1107 157: return move(Res);
1108 : }
1109 :
1110 : /// ParseContinueStatement
1111 : /// jump-statement:
1112 : /// 'continue' ';'
1113 : ///
1114 : /// Note: this lets the caller parse the end ';'.
1115 : ///
1116 32: Parser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
1117 : // FIXME: Use attributes?
1118 32: SourceLocation ContinueLoc = ConsumeToken(); // eat the 'continue'.
1119 32: return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
1120 : }
1121 :
1122 : /// ParseBreakStatement
1123 : /// jump-statement:
1124 : /// 'break' ';'
1125 : ///
1126 : /// Note: this lets the caller parse the end ';'.
1127 : ///
1128 265: Parser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
1129 : // FIXME: Use attributes?
1130 265: SourceLocation BreakLoc = ConsumeToken(); // eat the 'break'.
1131 265: return Actions.ActOnBreakStmt(BreakLoc, CurScope);
1132 : }
1133 :
1134 : /// ParseReturnStatement
1135 : /// jump-statement:
1136 : /// 'return' expression[opt] ';'
1137 4502: Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
1138 : // FIXME: Use attributes?
4502: branch 1 taken
0: branch 2 not taken
1139 4502: assert(Tok.is(tok::kw_return) && "Not a return stmt!");
1140 4502: SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'.
1141 :
1142 4502: OwningExprResult R(Actions);
4198: branch 1 taken
304: branch 2 taken
1143 4502: if (Tok.isNot(tok::semi)) {
1144 4198: R = ParseExpression();
79: branch 1 taken
4119: branch 2 taken
1145 4198: if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
1146 79: SkipUntil(tok::semi, false, true);
1147 79: return StmtError();
1148 : }
1149 : }
1150 4423: return Actions.ActOnReturnStmt(ReturnLoc, move(R));
1151 : }
1152 :
1153 : /// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this
1154 : /// routine is called to skip/ignore tokens that comprise the MS asm statement.
1155 5: Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
1: branch 1 taken
4: branch 2 taken
1156 5: if (Tok.is(tok::l_brace)) {
1157 1: unsigned short savedBraceCount = BraceCount;
18: branch 0 taken
1: branch 1 taken
18: branch 3 taken
0: branch 4 not taken
18: branch 5 taken
1: branch 6 taken
1158 19: do {
1159 19: ConsumeAnyToken();
1160 : } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof));
1161 : } else {
1162 : // From the MS website: If used without braces, the __asm keyword means
1163 : // that the rest of the line is an assembly-language statement.
1164 4: SourceManager &SrcMgr = PP.getSourceManager();
1165 4: SourceLocation TokLoc = Tok.getLocation();
1166 4: unsigned LineNo = SrcMgr.getInstantiationLineNumber(TokLoc);
14: branch 1 taken
0: branch 2 not taken
10: branch 4 taken
4: branch 5 taken
10: branch 7 taken
0: branch 8 not taken
10: branch 10 taken
0: branch 11 not taken
10: branch 12 taken
4: branch 13 taken
1167 14: do {
1168 14: ConsumeAnyToken();
1169 14: TokLoc = Tok.getLocation();
1170 : } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) &&
1171 : Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) &&
1172 : Tok.isNot(tok::eof));
1173 : }
1174 5: Token t;
1175 5: t.setKind(tok::string_literal);
1176 5: t.setLiteralData("\"FIXME: not done\"");
1177 5: t.clearFlag(Token::NeedsCleaning);
1178 5: t.setLength(17);
1179 5: OwningExprResult AsmString(Actions.ActOnStringLiteral(&t, 1));
1180 5: ExprVector Constraints(Actions);
1181 5: ExprVector Exprs(Actions);
1182 5: ExprVector Clobbers(Actions);
1183 : return Actions.ActOnAsmStmt(Tok.getLocation(), true, true, 0, 0, 0,
1184 : move_arg(Constraints), move_arg(Exprs),
1185 : move(AsmString), move_arg(Clobbers),
1186 5: Tok.getLocation(), true);
1187 : }
1188 :
1189 : /// ParseAsmStatement - Parse a GNU extended asm statement.
1190 : /// asm-statement:
1191 : /// gnu-asm-statement
1192 : /// ms-asm-statement
1193 : ///
1194 : /// [GNU] gnu-asm-statement:
1195 : /// 'asm' type-qualifier[opt] '(' asm-argument ')' ';'
1196 : ///
1197 : /// [GNU] asm-argument:
1198 : /// asm-string-literal
1199 : /// asm-string-literal ':' asm-operands[opt]
1200 : /// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
1201 : /// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
1202 : /// ':' asm-clobbers
1203 : ///
1204 : /// [GNU] asm-clobbers:
1205 : /// asm-string-literal
1206 : /// asm-clobbers ',' asm-string-literal
1207 : ///
1208 : /// [MS] ms-asm-statement:
1209 : /// '__asm' assembly-instruction ';'[opt]
1210 : /// '__asm' '{' assembly-instruction-list '}' ';'[opt]
1211 : ///
1212 : /// [MS] assembly-instruction-list:
1213 : /// assembly-instruction ';'[opt]
1214 : /// assembly-instruction-list ';' assembly-instruction ';'[opt]
1215 : ///
1216 108: Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
108: branch 1 taken
0: branch 2 not taken
1217 108: assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
1218 108: SourceLocation AsmLoc = ConsumeToken();
1219 :
5: branch 1 taken
103: branch 2 taken
5: branch 4 taken
0: branch 5 not taken
5: branch 7 taken
0: branch 8 not taken
5: branch 9 taken
103: branch 10 taken
1220 113: if (getLang().Microsoft && Tok.isNot(tok::l_paren) && !isTypeQualifier()) {
1221 5: msAsm = true;
1222 5: return FuzzyParseMicrosoftAsmStatement();
1223 : }
1224 103: DeclSpec DS;
1225 103: SourceLocation Loc = Tok.getLocation();
1226 103: ParseTypeQualifierListOpt(DS, true, false);
1227 :
1228 : // GNU asms accept, but warn, about type-qualifiers other than volatile.
0: branch 1 not taken
103: branch 2 taken
1229 103: if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
1230 0: Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
0: branch 1 not taken
103: branch 2 taken
1231 103: if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
1232 0: Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
1233 :
1234 : // Remember if this was a volatile asm.
1235 103: bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
0: branch 1 not taken
103: branch 2 taken
1236 103: if (Tok.isNot(tok::l_paren)) {
1237 0: Diag(Tok, diag::err_expected_lparen_after) << "asm";
1238 0: SkipUntil(tok::r_paren);
1239 0: return StmtError();
1240 : }
1241 103: Loc = ConsumeParen();
1242 :
1243 103: OwningExprResult AsmString(ParseAsmStringLiteral());
0: branch 1 not taken
103: branch 2 taken
1244 103: if (AsmString.isInvalid())
1245 0: return StmtError();
1246 :
1247 103: llvm::SmallVector<IdentifierInfo *, 4> Names;
1248 103: ExprVector Constraints(Actions);
1249 103: ExprVector Exprs(Actions);
1250 103: ExprVector Clobbers(Actions);
1251 :
22: branch 1 taken
81: branch 2 taken
1252 103: if (Tok.is(tok::r_paren)) {
1253 : // We have a simple asm expression like 'asm("foo")'.
1254 22: SourceLocation RParenLoc = ConsumeParen();
1255 : return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
1256 : /*NumOutputs*/ 0, /*NumInputs*/ 0, 0,
1257 : move_arg(Constraints), move_arg(Exprs),
1258 : move(AsmString), move_arg(Clobbers),
1259 22: RParenLoc);
1260 : }
1261 :
1262 : // Parse Outputs, if present.
1263 81: bool AteExtraColon = false;
1: branch 1 taken
80: branch 2 taken
1: branch 4 taken
0: branch 5 not taken
81: branch 6 taken
0: branch 7 not taken
1264 81: if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
1265 : // In C++ mode, parse "::" like ": :".
1266 81: AteExtraColon = Tok.is(tok::coloncolon);
1267 81: ConsumeToken();
1268 :
80: branch 0 taken
1: branch 1 taken
1: branch 3 taken
79: branch 4 taken
1: branch 5 taken
80: branch 6 taken
1269 81: if (!AteExtraColon &&
1270 : ParseAsmOperandsOpt(Names, Constraints, Exprs))
1271 1: return StmtError();
1272 : }
1273 :
1274 80: unsigned NumOutputs = Names.size();
1275 :
1276 : // Parse Inputs, if present.
79: branch 0 taken
1: branch 1 taken
17: branch 3 taken
62: branch 4 taken
1: branch 6 taken
16: branch 7 taken
64: branch 8 taken
16: branch 9 taken
1277 80: if (AteExtraColon ||
1278 : Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
1279 : // In C++ mode, parse "::" like ": :".
1: branch 0 taken
63: branch 1 taken
1280 64: if (AteExtraColon)
1281 1: AteExtraColon = false;
1282 : else {
1283 63: AteExtraColon = Tok.is(tok::coloncolon);
1284 63: ConsumeToken();
1285 : }
1286 :
63: branch 0 taken
1: branch 1 taken
1: branch 3 taken
62: branch 4 taken
1: branch 5 taken
63: branch 6 taken
1287 64: if (!AteExtraColon &&
1288 : ParseAsmOperandsOpt(Names, Constraints, Exprs))
1289 1: return StmtError();
1290 : }
1291 :
1292 : assert(Names.size() == Constraints.size() &&
1293 : Constraints.size() == Exprs.size() &&
79: branch 2 taken
0: branch 3 not taken
79: branch 6 taken
0: branch 7 not taken
1294 79: "Input operand size mismatch!");
1295 :
1296 79: unsigned NumInputs = Names.size() - NumOutputs;
1297 :
1298 : // Parse the clobbers, if present.
78: branch 0 taken
1: branch 1 taken
21: branch 3 taken
57: branch 4 taken
22: branch 5 taken
57: branch 6 taken
1299 157: if (AteExtraColon || Tok.is(tok::colon)) {
21: branch 0 taken
1: branch 1 taken
1300 22: if (!AteExtraColon)
1301 21: ConsumeToken();
1302 :
1303 : // Parse the asm-string list for clobbers.
34: branch 1 taken
22: branch 2 taken
1304 56: while (1) {
1305 56: OwningExprResult Clobber(ParseAsmStringLiteral());
1306 :
1: branch 1 taken
55: branch 2 taken
1307 56: if (Clobber.isInvalid())
1308 22: break;
1309 :
1310 55: Clobbers.push_back(Clobber.release());
1311 :
21: branch 1 taken
34: branch 2 taken
1312 55: if (Tok.isNot(tok::comma)) break;
1313 34: ConsumeToken();
1314 : }
1315 : }
1316 :
1317 79: SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc);
1318 : return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile,
1319 : NumOutputs, NumInputs, Names.data(),
1320 : move_arg(Constraints), move_arg(Exprs),
1321 : move(AsmString), move_arg(Clobbers),
1322 79: RParenLoc);
1323 : }
1324 :
1325 : /// ParseAsmOperands - Parse the asm-operands production as used by
1326 : /// asm-statement, assuming the leading ':' token was eaten.
1327 : ///
1328 : /// [GNU] asm-operands:
1329 : /// asm-operand
1330 : /// asm-operands ',' asm-operand
1331 : ///
1332 : /// [GNU] asm-operand:
1333 : /// asm-string-literal '(' expression ')'
1334 : /// '[' identifier ']' asm-string-literal '(' expression ')'
1335 : ///
1336 : //
1337 : // FIXME: Avoid unnecessary std::string trashing.
1338 : bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
1339 : llvm::SmallVectorImpl<ExprTy *> &Constraints,
1340 143: llvm::SmallVectorImpl<ExprTy *> &Exprs) {
1341 : // 'asm-operands' isn't present?
76: branch 1 taken
67: branch 2 taken
68: branch 4 taken
8: branch 5 taken
68: branch 6 taken
75: branch 7 taken
1342 143: if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
1343 68: return false;
1344 :
13: branch 1 taken
75: branch 2 taken
13: branch 4 taken
75: branch 5 taken
1345 88: while (1) {
1346 : // Read the [id] if present.
10: branch 1 taken
78: branch 2 taken
1347 88: if (Tok.is(tok::l_square)) {
1348 10: SourceLocation Loc = ConsumeBracket();
1349 :
0: branch 1 not taken
10: branch 2 taken
1350 10: if (Tok.isNot(tok::identifier)) {
1351 0: Diag(Tok, diag::err_expected_ident);
1352 0: SkipUntil(tok::r_paren);
1353 0: return true;
1354 : }
1355 :
1356 10: IdentifierInfo *II = Tok.getIdentifierInfo();
1357 10: ConsumeToken();
1358 :
1359 10: Names.push_back(II);
1360 10: MatchRHSPunctuation(tok::r_square, Loc);
1361 : } else
1362 78: Names.push_back(0);
1363 :
1364 88: OwningExprResult Constraint(ParseAsmStringLiteral());
0: branch 1 not taken
88: branch 2 taken
1365 88: if (Constraint.isInvalid()) {
1366 0: SkipUntil(tok::r_paren);
1367 75: return true;
1368 : }
1369 88: Constraints.push_back(Constraint.release());
1370 :
0: branch 1 not taken
88: branch 2 taken
1371 88: if (Tok.isNot(tok::l_paren)) {
1372 0: Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
1373 0: SkipUntil(tok::r_paren);
1374 0: return true;
1375 : }
1376 :
1377 : // Read the parenthesized expression.
1378 88: SourceLocation OpenLoc = ConsumeParen();
1379 88: OwningExprResult Res(ParseExpression());
1380 88: MatchRHSPunctuation(tok::r_paren, OpenLoc);
2: branch 1 taken
86: branch 2 taken
1381 88: if (Res.isInvalid()) {
1382 2: SkipUntil(tok::r_paren);
1383 2: return true;
1384 : }
1385 86: Exprs.push_back(Res.release());
1386 : // Eat the comma and continue parsing if it exists.
73: branch 1 taken
13: branch 2 taken
1387 86: if (Tok.isNot(tok::comma)) return false;
1388 13: ConsumeToken();
1389 : }
1390 :
1391 : return true;
1392 : }
1393 :
1394 8250: Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
0: branch 1 not taken
8250: branch 2 taken
1395 8250: assert(Tok.is(tok::l_brace));
1396 8250: SourceLocation LBraceLoc = Tok.getLocation();
1397 :
1398 : PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions,
1399 : PP.getSourceManager(),
1400 8250: "parsing function body");
1401 :
1402 : // Do not enter a scope for the brace, as the arguments are in the same scope
1403 : // (the function body) as the body itself. Instead, just read the statement
1404 : // list and put it into a CompoundStmt for safe keeping.
1405 8250: OwningStmtResult FnBody(ParseCompoundStatementBody());
1406 :
1407 : // If the function body could not be parsed, make a bogus compoundstmt.
46: branch 1 taken
8204: branch 2 taken
1408 8250: if (FnBody.isInvalid())
1409 : FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
1410 46: MultiStmtArg(Actions), false);
1411 :
1412 8250: return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
1413 : }
1414 :
1415 : /// ParseFunctionTryBlock - Parse a C++ function-try-block.
1416 : ///
1417 : /// function-try-block:
1418 : /// 'try' ctor-initializer[opt] compound-statement handler-seq
1419 : ///
1420 8: Parser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) {
8: branch 1 taken
0: branch 2 not taken
1421 8: assert(Tok.is(tok::kw_try) && "Expected 'try'");
1422 8: SourceLocation TryLoc = ConsumeToken();
1423 :
1424 : PrettyStackTraceActionsDecl CrashInfo(Decl, TryLoc, Actions,
1425 : PP.getSourceManager(),
1426 8: "parsing function try block");
1427 :
1428 : // Constructor initializer list?
2: branch 1 taken
6: branch 2 taken
1429 8: if (Tok.is(tok::colon))
1430 2: ParseConstructorInitializer(Decl);
1431 :
1432 8: SourceLocation LBraceLoc = Tok.getLocation();
1433 8: OwningStmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
1434 : // If we failed to parse the try-catch, we just give the function an empty
1435 : // compound statement as the body.
0: branch 1 not taken
8: branch 2 taken
1436 8: if (FnBody.isInvalid())
1437 : FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
1438 0: MultiStmtArg(Actions), false);
1439 :
1440 8: return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
1441 : }
1442 :
1443 : /// ParseCXXTryBlock - Parse a C++ try-block.
1444 : ///
1445 : /// try-block:
1446 : /// 'try' compound-statement handler-seq
1447 : ///
1448 20: Parser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
1449 : // FIXME: Add attributes?
20: branch 1 taken
0: branch 2 not taken
1450 20: assert(Tok.is(tok::kw_try) && "Expected 'try'");
1451 :
1452 20: SourceLocation TryLoc = ConsumeToken();
1453 20: return ParseCXXTryBlockCommon(TryLoc);
1454 : }
1455 :
1456 : /// ParseCXXTryBlockCommon - Parse the common part of try-block and
1457 : /// function-try-block.
1458 : ///
1459 : /// try-block:
1460 : /// 'try' compound-statement handler-seq
1461 : ///
1462 : /// function-try-block:
1463 : /// 'try' ctor-initializer[opt] compound-statement handler-seq
1464 : ///
1465 : /// handler-seq:
1466 : /// handler handler-seq[opt]
1467 : ///
1468 28: Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
1: branch 1 taken
27: branch 2 taken
1469 28: if (Tok.isNot(tok::l_brace))
1470 1: return StmtError(Diag(Tok, diag::err_expected_lbrace));
1471 : // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
1472 27: OwningStmtResult TryBlock(ParseCompoundStatement(0));
0: branch 1 not taken
27: branch 2 taken
1473 27: if (TryBlock.isInvalid())
1474 0: return move(TryBlock);
1475 :
1476 27: StmtVector Handlers(Actions);
4: branch 1 taken
23: branch 2 taken
1: branch 4 taken
3: branch 5 taken
1: branch 6 taken
26: branch 7 taken
1477 27: if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
1478 1: CXX0XAttributeList Attr = ParseCXX0XAttributes();
1479 : Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
1480 1: << Attr.Range;
1481 : }
0: branch 1 not taken
27: branch 2 taken
1482 27: if (Tok.isNot(tok::kw_catch))
1483 0: return StmtError(Diag(Tok, diag::err_expected_catch));
41: branch 2 taken
27: branch 3 taken
1484 68: while (Tok.is(tok::kw_catch)) {
1485 41: OwningStmtResult Handler(ParseCXXCatchBlock());
38: branch 1 taken
3: branch 2 taken
1486 41: if (!Handler.isInvalid())
1487 38: Handlers.push_back(Handler.release());
1488 : }
1489 : // Don't bother creating the full statement if we don't have any usable
1490 : // handlers.
3: branch 1 taken
24: branch 2 taken
1491 27: if (Handlers.empty())
1492 3: return StmtError();
1493 :
1494 24: return Actions.ActOnCXXTryBlock(TryLoc, move(TryBlock), move_arg(Handlers));
1495 : }
1496 :
1497 : /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
1498 : ///
1499 : /// handler:
1500 : /// 'catch' '(' exception-declaration ')' compound-statement
1501 : ///
1502 : /// exception-declaration:
1503 : /// type-specifier-seq declarator
1504 : /// type-specifier-seq abstract-declarator
1505 : /// type-specifier-seq
1506 : /// '...'
1507 : ///
1508 41: Parser::OwningStmtResult Parser::ParseCXXCatchBlock() {
41: branch 1 taken
0: branch 2 not taken
1509 41: assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
1510 :
1511 41: SourceLocation CatchLoc = ConsumeToken();
1512 :
1513 41: SourceLocation LParenLoc = Tok.getLocation();
2: branch 1 taken
39: branch 2 taken
1514 41: if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
1515 2: return StmtError();
1516 :
1517 : // C++ 3.3.2p3:
1518 : // The name in a catch exception-declaration is local to the handler and
1519 : // shall not be redeclared in the outermost block of the handler.
1520 39: ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope);
1521 :
1522 : // exception-declaration is equivalent to '...' or a parameter-declaration
1523 : // without default arguments.
1524 39: DeclPtrTy ExceptionDecl;
24: branch 1 taken
15: branch 2 taken
1525 39: if (Tok.isNot(tok::ellipsis)) {
1526 24: DeclSpec DS;
0: branch 1 not taken
24: branch 2 taken
1527 24: if (ParseCXXTypeSpecifierSeq(DS))
1528 0: return StmtError();
1529 24: Declarator ExDecl(DS, Declarator::CXXCatchContext);
1530 24: ParseDeclarator(ExDecl);
24: branch 3 taken
0: branch 4 not taken
1531 24: ExceptionDecl = Actions.ActOnExceptionDeclarator(CurScope, ExDecl);
1532 : } else
1533 15: ConsumeToken();
1534 :
0: branch 2 not taken
39: branch 3 taken
1535 39: if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
1536 0: return StmtError();
1537 :
1: branch 1 taken
38: branch 2 taken
1538 39: if (Tok.isNot(tok::l_brace))
1539 1: return StmtError(Diag(Tok, diag::err_expected_lbrace));
1540 :
1541 : // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
1542 38: OwningStmtResult Block(ParseCompoundStatement(0));
0: branch 1 not taken
38: branch 2 taken
1543 38: if (Block.isInvalid())
1544 0: return move(Block);
1545 :
1546 38: return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, move(Block));
1547 : }
Generated: 2010-02-10 01:31 by zcov