Commit 72db90a9 by Ian Lance Taylor

compiler: Add temporaries required in cases of interface conversion.

From-SVN: r218979
parent e8af59bc
...@@ -8786,6 +8786,10 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*, ...@@ -8786,6 +8786,10 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
if (this->classification() == EXPRESSION_ERROR) if (this->classification() == EXPRESSION_ERROR)
return this; return this;
if (this->is_flattened_)
return this;
this->is_flattened_ = true;
// Add temporary variables for all arguments that require type // Add temporary variables for all arguments that require type
// conversion. // conversion.
Function_type* fntype = this->get_function_type(); Function_type* fntype = this->get_function_type();
...@@ -10590,21 +10594,31 @@ Map_index_expression::do_traverse(Traverse* traverse) ...@@ -10590,21 +10594,31 @@ Map_index_expression::do_traverse(Traverse* traverse)
// recomputation. // recomputation.
Expression* Expression*
Map_index_expression::do_flatten(Gogo*, Named_object*, Map_index_expression::do_flatten(Gogo* gogo, Named_object*,
Statement_inserter* inserter) Statement_inserter* inserter)
{ {
Location loc = this->location();
Map_type* mt = this->get_map_type(); Map_type* mt = this->get_map_type();
if (this->index_->type() != mt->key_type()) if (!Type::are_identical(mt->key_type(), this->index_->type(), false, NULL))
this->index_ = Expression::make_cast(mt->key_type(), this->index_, {
this->location()); if (this->index_->type()->interface_type() != NULL
&& !this->index_->is_variable())
{
Temporary_statement* temp =
Statement::make_temporary(NULL, this->index_, loc);
inserter->insert(temp);
this->index_ = Expression::make_temporary_reference(temp, loc);
}
this->index_ = Expression::convert_for_assignment(gogo, mt->key_type(),
this->index_, loc);
}
if (!this->index_->is_variable()) if (!this->index_->is_variable())
{ {
Temporary_statement* temp = Statement::make_temporary(NULL, this->index_, Temporary_statement* temp = Statement::make_temporary(NULL, this->index_,
this->location()); loc);
inserter->insert(temp); inserter->insert(temp);
this->index_ = Expression::make_temporary_reference(temp, this->index_ = Expression::make_temporary_reference(temp, loc);
this->location());
} }
if (this->value_pointer_ == NULL) if (this->value_pointer_ == NULL)
...@@ -10612,11 +10626,9 @@ Map_index_expression::do_flatten(Gogo*, Named_object*, ...@@ -10612,11 +10626,9 @@ Map_index_expression::do_flatten(Gogo*, Named_object*,
if (!this->value_pointer_->is_variable()) if (!this->value_pointer_->is_variable())
{ {
Temporary_statement* temp = Temporary_statement* temp =
Statement::make_temporary(NULL, this->value_pointer_, Statement::make_temporary(NULL, this->value_pointer_, loc);
this->location());
inserter->insert(temp); inserter->insert(temp);
this->value_pointer_ = this->value_pointer_ = Expression::make_temporary_reference(temp, loc);
Expression::make_temporary_reference(temp, this->location());
} }
return this; return this;
...@@ -12540,12 +12552,26 @@ Map_construction_expression::do_flatten(Gogo* gogo, Named_object*, ...@@ -12540,12 +12552,26 @@ Map_construction_expression::do_flatten(Gogo* gogo, Named_object*,
++pv, ++i) ++pv, ++i)
{ {
Expression_list* key_value_pair = new Expression_list(); Expression_list* key_value_pair = new Expression_list();
Expression* key = Expression* key = *pv;
Expression::convert_for_assignment(gogo, key_type, *pv, loc); if (key->type()->interface_type() != NULL && !key->is_variable())
{
Temporary_statement* temp =
Statement::make_temporary(NULL, key, loc);
inserter->insert(temp);
key = Expression::make_temporary_reference(temp, loc);
}
key = Expression::convert_for_assignment(gogo, key_type, key, loc);
++pv; ++pv;
Expression* val = Expression* val = *pv;
Expression::convert_for_assignment(gogo, val_type, *pv, loc); if (val->type()->interface_type() != NULL && !val->is_variable())
{
Temporary_statement* temp =
Statement::make_temporary(NULL, val, loc);
inserter->insert(temp);
val = Expression::make_temporary_reference(temp, loc);
}
val = Expression::convert_for_assignment(gogo, val_type, val, loc);
key_value_pair->push_back(key); key_value_pair->push_back(key);
key_value_pair->push_back(val); key_value_pair->push_back(val);
......
...@@ -1632,7 +1632,8 @@ class Call_expression : public Expression ...@@ -1632,7 +1632,8 @@ class Call_expression : public Expression
fn_(fn), args_(args), type_(NULL), results_(NULL), call_(NULL), fn_(fn), args_(args), type_(NULL), results_(NULL), call_(NULL),
call_temp_(NULL), expected_result_count_(0), is_varargs_(is_varargs), call_temp_(NULL), expected_result_count_(0), is_varargs_(is_varargs),
varargs_are_lowered_(false), types_are_determined_(false), varargs_are_lowered_(false), types_are_determined_(false),
is_deferred_(false), issued_error_(false), is_multi_value_arg_(false) is_deferred_(false), issued_error_(false), is_multi_value_arg_(false),
is_flattened_(false)
{ } { }
// The function to call. // The function to call.
...@@ -1817,6 +1818,8 @@ class Call_expression : public Expression ...@@ -1817,6 +1818,8 @@ class Call_expression : public Expression
bool issued_error_; bool issued_error_;
// True if this call is used as an argument that returns multiple results. // True if this call is used as an argument that returns multiple results.
bool is_multi_value_arg_; bool is_multi_value_arg_;
// True if this expression has already been flattened.
bool is_flattened_;
}; };
// An expression which represents a pointer to a function. // An expression which represents a pointer to a function.
......
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