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; |