summaryrefslogtreecommitdiffstats
path: root/gcc/go/gofrontend/parse.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/gofrontend/parse.cc')
-rw-r--r--gcc/go/gofrontend/parse.cc24
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)
OpenPOWER on IntegriCloud