diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index d7d3a072040..90f1a3405c1 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -2115,8 +2115,8 @@ Parse::simple_var_decl_or_assignment(const std::string& name, for (Typed_identifier_list::const_iterator p = til.begin(); p != til.end(); ++p) - exprs->push_back(this->id_to_expression(p->name(), - p->location())); + exprs->push_back(this->id_to_expression(p->name(), p->location(), + true)); Expression_list* more_exprs = this->expression_list(NULL, true, may_be_composite_lit); @@ -2509,7 +2509,10 @@ Parse::operand(bool may_be_sink, bool* is_parenthesized) } case Named_object::NAMED_OBJECT_VAR: case Named_object::NAMED_OBJECT_RESULT_VAR: - this->mark_var_used(named_object); + // 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(named_object); return Expression::make_var_reference(named_object, location); case Named_object::NAMED_OBJECT_SINK: if (may_be_sink) @@ -2724,7 +2727,7 @@ Parse::composite_lit(Type* type, int depth, Location location) Gogo* gogo = this->gogo_; val = this->id_to_expression(gogo->pack_hidden_name(identifier, is_exported), - location); + location, false); is_name = true; } else @@ -3241,7 +3244,8 @@ Parse::call(Expression* func) // Return an expression for a single unqualified identifier. Expression* -Parse::id_to_expression(const std::string& name, Location location) +Parse::id_to_expression(const std::string& name, Location location, + bool is_lhs) { Named_object* in_function; Named_object* named_object = this->gogo_->lookup(name, &in_function); @@ -3260,7 +3264,8 @@ Parse::id_to_expression(const std::string& name, Location location) return Expression::make_const_reference(named_object, location); case Named_object::NAMED_OBJECT_VAR: case Named_object::NAMED_OBJECT_RESULT_VAR: - this->mark_var_used(named_object); + if (!is_lhs) + this->mark_var_used(named_object); return Expression::make_var_reference(named_object, location); case Named_object::NAMED_OBJECT_SINK: return Expression::make_sink(location); @@ -5025,7 +5030,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val, *val = this->id_to_expression(gogo->pack_hidden_name(recv_var, is_rv_exported), - recv_var_loc); + recv_var_loc, true); saw_comma = true; } else @@ -5727,6 +5732,13 @@ Parse::verify_not_sink(Expression* expr) error_at(expr->location(), "cannot use _ as value"); expr = Expression::make_error(expr->location()); } + + // If this can not be a sink, and it is a variable, then we are + // using the variable, not just assigning to it. + Var_expression* ve = expr->var_expression(); + if (ve != NULL) + this->mark_var_used(ve->named_object()); + return expr; } diff --git a/gcc/go/gofrontend/parse.h b/gcc/go/gofrontend/parse.h index 99e0eeebc24..3a7bbd53700 100644 --- a/gcc/go/gofrontend/parse.h +++ b/gcc/go/gofrontend/parse.h @@ -236,7 +236,7 @@ class Parse bool* is_type_switch, bool* is_parenthesized); Type* reassociate_chan_direction(Channel_type*, Location); Expression* qualified_expr(Expression*, Location); - Expression* id_to_expression(const std::string&, Location); + Expression* id_to_expression(const std::string&, Location, bool); void statement(Label*); bool statement_may_start_here(); void labeled_stmt(const std::string&, Location); diff --git a/gcc/testsuite/go.test/test/shift1.go b/gcc/testsuite/go.test/test/shift1.go index 44a3792c4fa..04f5321b73f 100644 --- a/gcc/testsuite/go.test/test/shift1.go +++ b/gcc/testsuite/go.test/test/shift1.go @@ -238,4 +238,6 @@ func _() { z = (1. << s) << (1 << s) // ERROR "non-integer|type complex128" z = (1. << s) << (1. << s) // ERROR "non-integer|type complex128" z = (1.1 << s) << (1.1 << s) // ERROR "invalid|truncated|complex128" + + _, _, _ = x, y, z }