Index: runtime/vm/parser.cc |
=================================================================== |
--- runtime/vm/parser.cc (revision 26486) |
+++ runtime/vm/parser.cc (working copy) |
@@ -255,7 +255,8 @@ |
current_class_(Class::Handle(isolate_)), |
library_(Library::Handle(isolate_, library.raw())), |
try_blocks_list_(NULL), |
- last_used_try_index_(CatchClauseNode::kInvalidTryIndex) { |
+ last_used_try_index_(CatchClauseNode::kInvalidTryIndex), |
+ unregister_pending_function_(false) { |
ASSERT(tokens_iterator_.IsValid()); |
ASSERT(!library.IsNull()); |
} |
@@ -284,7 +285,8 @@ |
isolate_, |
parsed_function->function().origin()).library())), |
try_blocks_list_(NULL), |
- last_used_try_index_(CatchClauseNode::kInvalidTryIndex) { |
+ last_used_try_index_(CatchClauseNode::kInvalidTryIndex), |
+ unregister_pending_function_(false) { |
ASSERT(tokens_iterator_.IsValid()); |
ASSERT(!current_function().IsNull()); |
if (FLAG_enable_type_checks) { |
@@ -293,6 +295,19 @@ |
} |
+Parser::~Parser() { |
+ if (unregister_pending_function_) { |
+ const GrowableObjectArray& pending_functions = |
+ GrowableObjectArray::Handle( |
+ isolate()->object_store()->pending_functions()); |
+ ASSERT(pending_functions.Length() > 0); |
+ ASSERT(pending_functions.At(pending_functions.Length()-1) == |
+ current_function().raw()); |
+ pending_functions.RemoveLast(); |
+ } |
+} |
+ |
+ |
void Parser::SetScript(const Script & script, intptr_t token_pos) { |
script_ = script.raw(); |
tokens_iterator_.SetStream(TokenStream::Handle(script.tokens()), token_pos); |
@@ -2360,6 +2375,23 @@ |
} |
+void Parser::CheckRecursiveInvocation() { |
+ const GrowableObjectArray& pending_functions = |
+ GrowableObjectArray::Handle( |
+ isolate()->object_store()->pending_functions()); |
+ for (int i = 0; i < pending_functions.Length(); i++) { |
+ if (pending_functions.At(i) == current_function().raw()) { |
+ const String& fname = |
+ String::Handle(current_function().UserVisibleName()); |
+ ErrorMsg("circular dependency for function %s", fname.ToCString()); |
+ } |
+ } |
+ ASSERT(!unregister_pending_function_); |
+ pending_functions.Add(current_function()); |
+ unregister_pending_function_ = true; |
+} |
+ |
+ |
// Parser is at the opening parenthesis of the formal parameter declaration |
// of function. Parse the formal parameters, initializers and code. |
SequenceNode* Parser::ParseConstructor(const Function& func, |
@@ -2372,6 +2404,8 @@ |
const Class& cls = Class::Handle(func.Owner()); |
ASSERT(!cls.IsNull()); |
+ CheckRecursiveInvocation(); |
+ |
if (func.IsImplicitConstructor()) { |
// Special case: implicit constructor. |
// The parser adds an implicit default constructor when a class |