aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2014-12-19 16:14:01 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2014-12-19 16:14:01 +0000
commit16f72d88dd84fd56a31eca8767a8f3c8d0fab88b (patch)
tree4702937af89d3c818a0457703cf47e93b835ba15 /gcc/go
parent6b0e0695a52d1a7f82b2adfe460c79254c361e14 (diff)
downloadgcc-16f72d88dd84fd56a31eca8767a8f3c8d0fab88b.zip
gcc-16f72d88dd84fd56a31eca8767a8f3c8d0fab88b.tar.gz
gcc-16f72d88dd84fd56a31eca8767a8f3c8d0fab88b.tar.bz2
compiler: More cases that need a temporary for interface conversion.
From-SVN: r218952
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/expressions.cc64
-rw-r--r--gcc/go/gofrontend/statements.cc29
-rw-r--r--gcc/go/gofrontend/statements.h3
3 files changed, 74 insertions, 22 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 6f5acc1..5b95b21 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -5142,6 +5142,9 @@ Expression*
Binary_expression::do_flatten(Gogo* gogo, Named_object*,
Statement_inserter* inserter)
{
+ if (this->classification() == EXPRESSION_ERROR)
+ return this;
+
Location loc = this->location();
Temporary_statement* temp;
if (this->left_->type()->is_string_type()
@@ -6877,30 +6880,53 @@ Expression*
Builtin_call_expression::do_flatten(Gogo*, Named_object*,
Statement_inserter* inserter)
{
- if (this->code_ == BUILTIN_APPEND
- || this->code_ == BUILTIN_COPY)
+ Location loc = this->location();
+
+ switch (this->code_)
{
- Location loc = this->location();
- Type* at = this->args()->front()->type();
+ default:
+ 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();
- pa != this->args()->end();
- ++pa)
- {
- if ((*pa)->is_nil_expression())
+ pa != this->args()->end();
+ ++pa)
+ {
+ if (!(*pa)->is_variable() && (*pa)->type()->interface_type() != NULL)
{
- 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);
+ Temporary_statement* temp =
+ Statement::make_temporary(NULL, *pa, 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;
}
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index c84df3b..5da0471 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -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.
Bstatement*
@@ -440,9 +462,10 @@ Temporary_statement::do_get_backend(Translate_context* context)
binit = this->init_->get_backend(context);
else
{
- Expression* init = Expression::make_cast(this->type_, this->init_,
- this->location());
- context->gogo()->lower_expression(context->function(), NULL, &init);
+ Expression* init = Expression::convert_for_assignment(context->gogo(),
+ this->type_,
+ this->init_,
+ this->location());
binit = init->get_backend(context);
}
diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h
index aaad66e..5634b61 100644
--- a/gcc/go/gofrontend/statements.h
+++ b/gcc/go/gofrontend/statements.h
@@ -550,6 +550,9 @@ class Temporary_statement : public Statement
void
do_check_types(Gogo*);
+ Statement*
+ do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*);
+
Bstatement*
do_get_backend(Translate_context*);