re PR go/61316 (gccgo: spurious "incompatible types in assignment" error [GoSmith])

PR go/61316
compiler: Don't lower multi-valued arguments into temporaries.

From-SVN: r218606
This commit is contained in:
Ian Lance Taylor 2014-12-10 20:38:13 +00:00
parent 1b457aa45d
commit c44f74e4cb
3 changed files with 26 additions and 1 deletions

View File

@ -8525,6 +8525,7 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
|| fntype->is_builtin()))
{
Call_expression* call = this->args_->front()->call_expression();
call->set_is_multi_value_arg();
Expression_list* args = new Expression_list;
for (size_t i = 0; i < rc; ++i)
args->push_back(Expression::make_call_result(call, i));

View File

@ -1632,7 +1632,7 @@ class Call_expression : public Expression
fn_(fn), args_(args), type_(NULL), results_(NULL), call_(NULL),
call_temp_(NULL), expected_result_count_(0), is_varargs_(is_varargs),
varargs_are_lowered_(false), types_are_determined_(false),
is_deferred_(false), issued_error_(false)
is_deferred_(false), issued_error_(false), is_multi_value_arg_(false)
{ }
// The function to call.
@ -1703,6 +1703,17 @@ class Call_expression : public Expression
bool
issue_error();
// Whether this call returns multiple results that are used as an
// multi-valued argument.
bool
is_multi_value_arg() const
{ return this->is_multi_value_arg_; }
// Note this call is used as a multi-valued argument.
void
set_is_multi_value_arg()
{ this->is_multi_value_arg_ = true; }
protected:
int
do_traverse(Traverse*);
@ -1806,6 +1817,8 @@ class Call_expression : public Expression
// results and uses. This is to avoid producing multiple errors
// when there are multiple Call_result_expressions.
bool issued_error_;
// True if this call is used as an argument that returns multiple results.
bool is_multi_value_arg_;
};
// An expression which represents a pointer to a function.

View File

@ -726,6 +726,17 @@ Move_ordered_evals::expression(Expression** pexpr)
if ((*pexpr)->must_eval_in_order())
{
Call_expression* call = (*pexpr)->call_expression();
if (call != NULL && call->is_multi_value_arg())
{
// A call expression which returns multiple results as an argument
// to another call must be handled specially. We can't create a
// temporary because there is no type to give it. Instead, group
// the caller and this multi-valued call argument and use a temporary
// variable to hold them.
return TRAVERSE_SKIP_COMPONENTS;
}
Location loc = (*pexpr)->location();
Temporary_statement* temp = Statement::make_temporary(NULL, *pexpr, loc);
this->block_->add_statement(temp);