Commit 16f72d88 by Ian Lance Taylor

compiler: More cases that need a temporary for interface conversion.

From-SVN: r218952
parent 6b0e0695
...@@ -5142,6 +5142,9 @@ Expression* ...@@ -5142,6 +5142,9 @@ Expression*
Binary_expression::do_flatten(Gogo* gogo, Named_object*, Binary_expression::do_flatten(Gogo* gogo, Named_object*,
Statement_inserter* inserter) Statement_inserter* inserter)
{ {
if (this->classification() == EXPRESSION_ERROR)
return this;
Location loc = this->location(); Location loc = this->location();
Temporary_statement* temp; Temporary_statement* temp;
if (this->left_->type()->is_string_type() if (this->left_->type()->is_string_type()
...@@ -6877,30 +6880,53 @@ Expression* ...@@ -6877,30 +6880,53 @@ Expression*
Builtin_call_expression::do_flatten(Gogo*, Named_object*, Builtin_call_expression::do_flatten(Gogo*, Named_object*,
Statement_inserter* inserter) Statement_inserter* inserter)
{ {
if (this->code_ == BUILTIN_APPEND Location loc = this->location();
|| this->code_ == BUILTIN_COPY)
switch (this->code_)
{ {
Location loc = this->location(); default:
Type* at = this->args()->front()->type(); break;
case BUILTIN_APPEND:
case BUILTIN_COPY:
{
Type* at = this->args()->front()->type();
for (Expression_list::iterator pa = this->args()->begin();
pa != this->args()->end();
++pa)
{
if ((*pa)->is_nil_expression())
{
Expression* nil = Expression::make_nil(loc);
Expression* zero = Expression::make_integer_ul(0, NULL, loc);
*pa = Expression::make_slice_value(at, nil, zero, zero, loc);
}
if (!(*pa)->is_variable())
{
Temporary_statement* temp =
Statement::make_temporary(NULL, *pa, loc);
inserter->insert(temp);
*pa = Expression::make_temporary_reference(temp, loc);
}
}
}
break;
case BUILTIN_PANIC:
for (Expression_list::iterator pa = this->args()->begin(); for (Expression_list::iterator pa = this->args()->begin();
pa != this->args()->end(); pa != this->args()->end();
++pa) ++pa)
{ {
if ((*pa)->is_nil_expression()) if (!(*pa)->is_variable() && (*pa)->type()->interface_type() != NULL)
{ {
Expression* nil = Expression::make_nil(loc); Temporary_statement* temp =
Expression* zero = Expression::make_integer_ul(0, NULL, loc); Statement::make_temporary(NULL, *pa, loc);
*pa = Expression::make_slice_value(at, nil, zero, zero, loc); inserter->insert(temp);
*pa = Expression::make_temporary_reference(temp, loc);
} }
if (!(*pa)->is_variable()) }
{
Temporary_statement* temp =
Statement::make_temporary(NULL, *pa, loc);
inserter->insert(temp);
*pa = Expression::make_temporary_reference(temp, loc);
}
}
} }
return this; return this;
} }
......
...@@ -421,6 +421,28 @@ Temporary_statement::do_check_types(Gogo*) ...@@ -421,6 +421,28 @@ Temporary_statement::do_check_types(Gogo*)
} }
} }
// Flatten a temporary statement: add another temporary when it might
// be needed for interface conversion.
Statement*
Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
Statement_inserter* inserter)
{
if (this->type_ != NULL
&& this->init_ != NULL
&& !Type::are_identical(this->type_, this->init_->type(), false, NULL)
&& this->init_->type()->interface_type() != NULL
&& !this->init_->is_variable())
{
Temporary_statement *temp =
Statement::make_temporary(NULL, this->init_, this->location());
inserter->insert(temp);
this->init_ = Expression::make_temporary_reference(temp,
this->location());
}
return this;
}
// Convert to backend representation. // Convert to backend representation.
Bstatement* Bstatement*
...@@ -440,9 +462,10 @@ Temporary_statement::do_get_backend(Translate_context* context) ...@@ -440,9 +462,10 @@ Temporary_statement::do_get_backend(Translate_context* context)
binit = this->init_->get_backend(context); binit = this->init_->get_backend(context);
else else
{ {
Expression* init = Expression::make_cast(this->type_, this->init_, Expression* init = Expression::convert_for_assignment(context->gogo(),
this->location()); this->type_,
context->gogo()->lower_expression(context->function(), NULL, &init); this->init_,
this->location());
binit = init->get_backend(context); binit = init->get_backend(context);
} }
......
...@@ -550,6 +550,9 @@ class Temporary_statement : public Statement ...@@ -550,6 +550,9 @@ class Temporary_statement : public Statement
void void
do_check_types(Gogo*); do_check_types(Gogo*);
Statement*
do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*);
Bstatement* Bstatement*
do_get_backend(Translate_context*); do_get_backend(Translate_context*);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment