aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2015-01-20 21:29:28 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2015-01-20 21:29:28 +0000
commit2d8536f61419a898706e351bba964250af57006a (patch)
tree2b48fadd2f5cb2e9e9354f1c242d17a3d34362f6 /gcc
parent039ad4c2f435f8e345e123af8a324c50d1a85c86 (diff)
downloadgcc-2d8536f61419a898706e351bba964250af57006a.zip
gcc-2d8536f61419a898706e351bba964250af57006a.tar.gz
gcc-2d8536f61419a898706e351bba964250af57006a.tar.bz2
compiler: Do not mark unused variables as used inside closures.
Fixes golang/go#6415. From-SVN: r219916
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/parse.cc27
-rw-r--r--gcc/go/gofrontend/parse.h2
2 files changed, 23 insertions, 6 deletions
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index a98dd47..3e7c372 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -2450,7 +2450,7 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized)
&& (named_object->is_variable()
|| named_object->is_result_variable()))
return this->enclosing_var_reference(in_function, named_object,
- location);
+ may_be_sink, location);
switch (named_object->classification())
{
@@ -2591,11 +2591,14 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized)
Expression*
Parse::enclosing_var_reference(Named_object* in_function, Named_object* var,
- Location location)
+ bool may_be_sink, Location location)
{
go_assert(var->is_variable() || var->is_result_variable());
- this->mark_var_used(var);
+ // Any left-hand-side can be a sink, so if this can not be
+ // a sink, then it must be a use of the variable.
+ if (!may_be_sink)
+ this->mark_var_used(var);
Named_object* this_function = this->gogo_->current_function();
Named_object* closure = this_function->func_value()->closure_var();
@@ -2912,7 +2915,7 @@ Parse::create_closure(Named_object* function, Enclosing_vars* enclosing_vars,
ref = Expression::make_var_reference(var, location);
else
ref = this->enclosing_var_reference(ev[i].in_function(), var,
- location);
+ true, location);
Expression* refaddr = Expression::make_unary(OPERATOR_AND, ref,
location);
initializer->push_back(refaddr);
@@ -3215,7 +3218,7 @@ Parse::id_to_expression(const std::string& name, Location location,
if (in_function != NULL
&& in_function != this->gogo_->current_function()
&& (named_object->is_variable() || named_object->is_result_variable()))
- return this->enclosing_var_reference(in_function, named_object,
+ return this->enclosing_var_reference(in_function, named_object, is_lhs,
location);
switch (named_object->classification())
@@ -5722,6 +5725,20 @@ Parse::verify_not_sink(Expression* expr)
Var_expression* ve = expr->var_expression();
if (ve != NULL)
this->mark_var_used(ve->named_object());
+ else if (expr->deref()->field_reference_expression() != NULL
+ && this->gogo_->current_function() != NULL)
+ {
+ // We could be looking at a variable referenced from a closure.
+ // If so, we need to get the enclosed variable and mark it as used.
+ Function* this_function = this->gogo_->current_function()->func_value();
+ Named_object* closure = this_function->closure_var();
+ if (closure != NULL)
+ {
+ unsigned int var_index =
+ expr->deref()->field_reference_expression()->field_index();
+ this->mark_var_used(this_function->enclosing_var(var_index - 1));
+ }
+ }
return expr;
}
diff --git a/gcc/go/gofrontend/parse.h b/gcc/go/gofrontend/parse.h
index d55798b..9dd3b16 100644
--- a/gcc/go/gofrontend/parse.h
+++ b/gcc/go/gofrontend/parse.h
@@ -218,7 +218,7 @@ class Parse
Typed_identifier* receiver();
Expression* operand(bool may_be_sink, bool *is_parenthesized);
Expression* enclosing_var_reference(Named_object*, Named_object*,
- Location);
+ bool may_be_sink, Location);
Expression* composite_lit(Type*, int depth, Location);
Expression* function_lit();
Expression* create_closure(Named_object* function, Enclosing_vars*,