From: Ian Lance Taylor Date: Fri, 19 Dec 2014 16:14:01 +0000 (+0000) Subject: compiler: More cases that need a temporary for interface conversion. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=16f72d88dd84fd56a31eca8767a8f3c8d0fab88b;p=gcc.git compiler: More cases that need a temporary for interface conversion. From-SVN: r218952 --- diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 6f5acc1f92e..5b95b21b587 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 c84df3b5a3e..5da04710e39 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 aaad66e7fca..5634b61f339 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*);