Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 77c98b77e4c0cd6aadb003ec1965f82d879c30c8..597951c09325e4adbdf04bfc6797cc73ac914b73 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 ParseStatementAsUnlabelled(labels, ok); |
+ } else { |
+ Block* result = |
+ factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition); |
+ Target target(&this->target_stack_, result); |
+ Statement* statement = ParseStatementAsUnlabelled(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,30 @@ Statement* Parser::ParseSubStatement(ZoneList<const AstRawString*>* labels, |
} |
} |
+Statement* Parser::ParseStatementAsUnlabelled( |
+ ZoneList<const AstRawString*>* labels, 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: |
+ UNREACHABLE(); |
+ return NULL; |
+ } |
+} |
+ |
VariableProxy* Parser::NewUnresolved(const AstRawString* name, |
VariableMode mode) { |
@@ -2845,13 +2862,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() && |
+ peek() != Token::RBRACE) { |
+ ReportMessageAt(scanner()->location(), "strong_switch_fallthrough"); |
+ *ok = false; |
+ return NULL; |
+ } |
return factory()->NewCaseClause(label, statements, pos); |
} |
@@ -4468,7 +4491,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; |