diff options
Diffstat (limited to 'gcc/go/gofrontend/parse.cc')
-rw-r--r-- | gcc/go/gofrontend/parse.cc | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index d7a18d023be..b562a78ad00 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -2627,7 +2627,11 @@ Parse::enclosing_var_reference(Named_object* in_function, Named_object* var, Named_object* this_function = this->gogo_->current_function(); Named_object* closure = this_function->func_value()->closure_var(); - Enclosing_var ev(var, in_function, this->enclosing_vars_.size()); + // The last argument to the Enclosing_var constructor is the index + // of this variable in the closure. We add 1 to the current number + // of enclosed variables, because the first field in the closure + // points to the function code. + Enclosing_var ev(var, in_function, this->enclosing_vars_.size() + 1); std::pair<Enclosing_vars::iterator, bool> ins = this->enclosing_vars_.insert(ev); if (ins.second) @@ -2882,8 +2886,9 @@ Parse::function_lit() // Create a closure for the nested function FUNCTION. This is based // on ENCLOSING_VARS, which is a list of all variables defined in // enclosing functions and referenced from FUNCTION. A closure is the -// address of a struct which contains the addresses of all the -// referenced variables. This returns NULL if no closure is required. +// address of a struct which point to the real function code and +// contains the addresses of all the referenced variables. This +// returns NULL if no closure is required. Expression* Parse::create_closure(Named_object* function, Enclosing_vars* enclosing_vars, @@ -2899,16 +2904,25 @@ Parse::create_closure(Named_object* function, Enclosing_vars* enclosing_vars, for (Enclosing_vars::const_iterator p = enclosing_vars->begin(); p != enclosing_vars->end(); ++p) - ev[p->index()] = *p; + { + // Subtract 1 because index 0 is the function code. + ev[p->index() - 1] = *p; + } // Build an initializer for a composite literal of the closure's // type. Named_object* enclosing_function = this->gogo_->current_function(); Expression_list* initializer = new Expression_list; + + initializer->push_back(Expression::make_func_code_reference(function, + location)); + for (size_t i = 0; i < enclosing_var_count; ++i) { - go_assert(ev[i].index() == i); + // Add 1 to i because the first field in the closure is a + // pointer to the function code. + go_assert(ev[i].index() == i + 1); Named_object* var = ev[i].var(); Expression* ref; if (ev[i].in_function() == enclosing_function) |