Index: runtime/vm/parser.cc |
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc |
index a0a0aecc68d15cfec0205f58a8ce901fdbfbeee9..8f1115eda658f365854fcc55bf620245516ad67d 100644 |
--- a/runtime/vm/parser.cc |
+++ b/runtime/vm/parser.cc |
@@ -6465,7 +6465,8 @@ SequenceNode* Parser::CloseAsyncGeneratorTryBlock(SequenceNode *body) { |
context_var, |
catch_clause, |
finally_clause, |
- try_index); |
+ try_index, |
+ finally_clause); |
current_block_->statements->Add(try_catch_node); |
return CloseBlock(); |
} |
@@ -6581,7 +6582,8 @@ SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) { |
context_var, |
catch_clause, |
NULL, // No finally clause. |
- try_index); |
+ try_index, |
+ NULL); // No rethrow-finally clause. |
current_block_->statements->Add(try_catch_node); |
return CloseBlock(); |
} |
@@ -8936,7 +8938,8 @@ AstNode* Parser::ParseAwaitForStatement(String* label_name) { |
context_var, |
catch_clause, |
finally_clause, |
- try_index); |
+ try_index, |
+ finally_clause); |
ASSERT(current_block_ == loop_block); |
loop_block->statements->Add(try_catch_node); |
@@ -9762,6 +9765,7 @@ AstNode* Parser::ParseTryStatement(String* label_name) { |
// of an existing outer try. Generate a finally clause to this purpose if it |
// is not declared. |
SequenceNode* finally_clause = NULL; |
+ SequenceNode* rethrow_clause = NULL; |
const bool parse = CurrentToken() == Token::kFINALLY; |
if (parse || (is_async && (try_stack_ != NULL))) { |
if (parse) { |
@@ -9795,6 +9799,21 @@ AstNode* Parser::ParseTryStatement(String* label_name) { |
stack_trace_var, |
is_async ? saved_exception_var : exception_var, |
is_async ? saved_stack_trace_var : stack_trace_var); |
+ if (finally_clause != NULL) { |
+ // Re-parse to create a duplicate of finally clause to avoid unintended |
+ // sharing of try-indices if the finally-block contains a try-catch. |
+ // The flow graph builder emits two copies of the finally-block if the |
+ // try-block has a normal exit: one for the exception- and one for the |
+ // non-exception case (see EffectGraphVisitor::VisitTryCatchNode) |
+ tokens_iterator_.SetCurrentPosition(finally_pos); |
+ rethrow_clause = EnsureFinallyClause( |
+ parse, |
+ is_async, |
+ exception_var, |
+ stack_trace_var, |
+ is_async ? saved_exception_var : exception_var, |
+ is_async ? saved_stack_trace_var : stack_trace_var); |
+ } |
} |
CatchClauseNode* catch_clause = new(Z) CatchClauseNode( |
@@ -9814,7 +9833,8 @@ AstNode* Parser::ParseTryStatement(String* label_name) { |
// on the try/catch, close the block that's embedding the try statement |
// and attach the label to it. |
AstNode* try_catch_node = new(Z) TryCatchNode( |
- try_pos, try_block, context_var, catch_clause, finally_clause, try_index); |
+ try_pos, try_block, context_var, catch_clause, finally_clause, try_index, |
+ rethrow_clause); |
if (try_label != NULL) { |
current_block_->statements->Add(try_catch_node); |