Chromium Code Reviews| Index: src/parser.cc |
| diff --git a/src/parser.cc b/src/parser.cc |
| index 77c98b77e4c0cd6aadb003ec1965f82d879c30c8..b79dfb3f8fca9e82cf2bf9d93be66f08fb96c52c 100644 |
| --- a/src/parser.cc |
| +++ b/src/parser.cc |
| @@ -1819,13 +1819,23 @@ Statement* Parser::ParseSubStatement(ZoneList<const AstRawString*>* labels, |
| return ParseForStatement(labels, ok); |
| case Token::CONTINUE: |
| - return ParseContinueStatement(ok); |
| - |
| case Token::BREAK: |
| - return ParseBreakStatement(labels, ok); |
| - |
| case Token::RETURN: |
| - return ParseReturnStatement(ok); |
| + case Token::THROW: |
| + case Token::TRY: { |
| + // These statements must have their labels preserved in an enclosing |
| + // block |
| + if (labels == NULL) { |
| + return ParseWrappedStatement(labels, ok); |
| + } else { |
| + Block* result = |
| + factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition); |
| + Target target(&this->target_stack_, result); |
| + Statement* statement = ParseWrappedStatement(labels, CHECK_OK); |
| + if (result) result->AddStatement(statement, zone()); |
| + return result; |
| + } |
| + } |
| case Token::WITH: |
| return ParseWithStatement(labels, ok); |
| @@ -1833,23 +1843,6 @@ Statement* Parser::ParseSubStatement(ZoneList<const AstRawString*>* labels, |
| case Token::SWITCH: |
| return ParseSwitchStatement(labels, ok); |
| - case Token::THROW: |
| - return ParseThrowStatement(ok); |
| - |
| - case Token::TRY: { |
| - // NOTE: It is somewhat complicated to have labels on |
| - // try-statements. When breaking out of a try-finally statement, |
| - // one must take great care not to treat it as a |
| - // fall-through. It is much easier just to wrap the entire |
| - // try-statement in a statement block and put the labels there |
| - Block* result = |
| - factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition); |
| - Target target(&this->target_stack_, result); |
| - TryStatement* statement = ParseTryStatement(CHECK_OK); |
| - if (result) result->AddStatement(statement, zone()); |
| - return result; |
| - } |
| - |
| case Token::FUNCTION: { |
| // FunctionDeclaration is only allowed in the context of SourceElements |
| // (Ecma 262 5th Edition, clause 14): |
| @@ -1890,6 +1883,31 @@ Statement* Parser::ParseSubStatement(ZoneList<const AstRawString*>* labels, |
| } |
| } |
| +Statement* Parser::ParseWrappedStatement(ZoneList<const AstRawString*>* labels, |
|
rossberg
2015/04/15 19:56:34
In fact, I would just inline the switch instead of
conradw
2015/04/16 10:59:57
Inlining would mean duplicating the code, it has t
|
| + bool* ok) { |
| + switch (peek()) { |
| + case Token::CONTINUE: |
| + return ParseContinueStatement(ok); |
| + |
| + case Token::BREAK: |
| + return ParseBreakStatement(labels, ok); |
| + |
| + case Token::RETURN: |
| + return ParseReturnStatement(ok); |
| + |
| + case Token::THROW: |
| + return ParseThrowStatement(ok); |
| + |
| + case Token::TRY: |
| + return ParseTryStatement(ok); |
| + |
| + default: |
| + *ok = false; |
|
rossberg
2015/04/15 19:56:34
This case should be UNREACHABLE();
conradw
2015/04/16 10:59:57
Done.
|
| + ReportUnexpectedToken(scanner()->current_token()); |
| + return NULL; |
| + } |
| +} |
| + |
| VariableProxy* Parser::NewUnresolved(const AstRawString* name, |
| VariableMode mode) { |
| @@ -2845,13 +2863,19 @@ CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) { |
| int pos = position(); |
| ZoneList<Statement*>* statements = |
| new(zone()) ZoneList<Statement*>(5, zone()); |
| + Statement* stat = NULL; |
| while (peek() != Token::CASE && |
| peek() != Token::DEFAULT && |
| peek() != Token::RBRACE) { |
| - Statement* stat = ParseStatementListItem(CHECK_OK); |
| + stat = ParseStatementListItem(CHECK_OK); |
| statements->Add(stat, zone()); |
| } |
| - |
| + if (is_strong(language_mode()) && stat != NULL && |
| + !stat->IsJump()) { |
|
rossberg
2015/04/15 19:56:34
Nit: stray line break
conradw
2015/04/16 10:59:57
Done.
|
| + ReportMessageAt(scanner()->location(), "strong_switch_fallthrough"); |
| + *ok = false; |
| + return NULL; |
| + } |
| return factory()->NewCaseClause(label, statements, pos); |
| } |
| @@ -4468,7 +4492,6 @@ void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { |
| // ---------------------------------------------------------------------------- |
| // Parser support |
| - |
| bool Parser::TargetStackContainsLabel(const AstRawString* label) { |
| for (Target* t = target_stack_; t != NULL; t = t->previous()) { |
| if (ContainsLabel(t->statement()->labels(), label)) return true; |