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