Skip to content

Commit be2a33b

Browse files
author
Chris Manghane
committed
compiler: Do not mark unused variables as used inside closures.
Fixes golang/go#6415. LGTM=iant R=iant CC=gofrontend-dev https://codereview.appspot.com/195060043 Committer: Ian Lance Taylor <[email protected]>
1 parent a0d4902 commit be2a33b

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

go/parse.cc

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2450,7 +2450,7 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized)
24502450
&& (named_object->is_variable()
24512451
|| named_object->is_result_variable()))
24522452
return this->enclosing_var_reference(in_function, named_object,
2453-
location);
2453+
may_be_sink, location);
24542454

24552455
switch (named_object->classification())
24562456
{
@@ -2591,11 +2591,14 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized)
25912591

25922592
Expression*
25932593
Parse::enclosing_var_reference(Named_object* in_function, Named_object* var,
2594-
Location location)
2594+
bool may_be_sink, Location location)
25952595
{
25962596
go_assert(var->is_variable() || var->is_result_variable());
25972597

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);
25992602

26002603
Named_object* this_function = this->gogo_->current_function();
26012604
Named_object* closure = this_function->func_value()->closure_var();
@@ -2912,7 +2915,7 @@ Parse::create_closure(Named_object* function, Enclosing_vars* enclosing_vars,
29122915
ref = Expression::make_var_reference(var, location);
29132916
else
29142917
ref = this->enclosing_var_reference(ev[i].in_function(), var,
2915-
location);
2918+
true, location);
29162919
Expression* refaddr = Expression::make_unary(OPERATOR_AND, ref,
29172920
location);
29182921
initializer->push_back(refaddr);
@@ -3215,7 +3218,7 @@ Parse::id_to_expression(const std::string& name, Location location,
32153218
if (in_function != NULL
32163219
&& in_function != this->gogo_->current_function()
32173220
&& (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,
32193222
location);
32203223

32213224
switch (named_object->classification())
@@ -5722,6 +5725,20 @@ Parse::verify_not_sink(Expression* expr)
57225725
Var_expression* ve = expr->var_expression();
57235726
if (ve != NULL)
57245727
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+
}
57255742

57265743
return expr;
57275744
}

go/parse.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ class Parse
218218
Typed_identifier* receiver();
219219
Expression* operand(bool may_be_sink, bool *is_parenthesized);
220220
Expression* enclosing_var_reference(Named_object*, Named_object*,
221-
Location);
221+
bool may_be_sink, Location);
222222
Expression* composite_lit(Type*, int depth, Location);
223223
Expression* function_lit();
224224
Expression* create_closure(Named_object* function, Enclosing_vars*,

0 commit comments

Comments
 (0)