@@ -2450,7 +2450,7 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized)
2450
2450
&& (named_object->is_variable()
2451
2451
|| named_object->is_result_variable()))
2452
2452
return this->enclosing_var_reference(in_function, named_object,
2453
- location);
2453
+ may_be_sink, location);
2454
2454
2455
2455
switch (named_object->classification())
2456
2456
{
@@ -2591,11 +2591,14 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized)
2591
2591
2592
2592
Expression*
2593
2593
Parse::enclosing_var_reference(Named_object* in_function, Named_object* var,
2594
- Location location)
2594
+ bool may_be_sink, Location location)
2595
2595
{
2596
2596
go_assert(var->is_variable() || var->is_result_variable());
2597
2597
2598
- this->mark_var_used(var);
2598
+ // Any left-hand-side can be a sink, so if this can not be
2599
+ // a sink, then it must be a use of the variable.
2600
+ if (!may_be_sink)
2601
+ this->mark_var_used(var);
2599
2602
2600
2603
Named_object* this_function = this->gogo_->current_function();
2601
2604
Named_object* closure = this_function->func_value()->closure_var();
@@ -2912,7 +2915,7 @@ Parse::create_closure(Named_object* function, Enclosing_vars* enclosing_vars,
2912
2915
ref = Expression::make_var_reference(var, location);
2913
2916
else
2914
2917
ref = this->enclosing_var_reference(ev[i].in_function(), var,
2915
- location);
2918
+ true, location);
2916
2919
Expression* refaddr = Expression::make_unary(OPERATOR_AND, ref,
2917
2920
location);
2918
2921
initializer->push_back(refaddr);
@@ -3215,7 +3218,7 @@ Parse::id_to_expression(const std::string& name, Location location,
3215
3218
if (in_function != NULL
3216
3219
&& in_function != this->gogo_->current_function()
3217
3220
&& (named_object->is_variable() || named_object->is_result_variable()))
3218
- return this->enclosing_var_reference(in_function, named_object,
3221
+ return this->enclosing_var_reference(in_function, named_object, is_lhs,
3219
3222
location);
3220
3223
3221
3224
switch (named_object->classification())
@@ -5722,6 +5725,20 @@ Parse::verify_not_sink(Expression* expr)
5722
5725
Var_expression* ve = expr->var_expression();
5723
5726
if (ve != NULL)
5724
5727
this->mark_var_used(ve->named_object());
5728
+ else if (expr->deref()->field_reference_expression() != NULL
5729
+ && this->gogo_->current_function() != NULL)
5730
+ {
5731
+ // We could be looking at a variable referenced from a closure.
5732
+ // If so, we need to get the enclosed variable and mark it as used.
5733
+ Function* this_function = this->gogo_->current_function()->func_value();
5734
+ Named_object* closure = this_function->closure_var();
5735
+ if (closure != NULL)
5736
+ {
5737
+ unsigned int var_index =
5738
+ expr->deref()->field_reference_expression()->field_index();
5739
+ this->mark_var_used(this_function->enclosing_var(var_index - 1));
5740
+ }
5741
+ }
5725
5742
5726
5743
return expr;
5727
5744
}
0 commit comments