if (this->classification() == EXPRESSION_ERROR)
return this;
+ if (this->is_flattened_)
+ return this;
+ this->is_flattened_ = true;
+
// Add temporary variables for all arguments that require type
// conversion.
Function_type* fntype = this->get_function_type();
// recomputation.
Expression*
-Map_index_expression::do_flatten(Gogo*, Named_object*,
+Map_index_expression::do_flatten(Gogo* gogo, Named_object*,
Statement_inserter* inserter)
{
+ Location loc = this->location();
Map_type* mt = this->get_map_type();
- if (this->index_->type() != mt->key_type())
- this->index_ = Expression::make_cast(mt->key_type(), this->index_,
- this->location());
+ if (!Type::are_identical(mt->key_type(), this->index_->type(), false, NULL))
+ {
+ 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())
{
Temporary_statement* temp = Statement::make_temporary(NULL, this->index_,
- this->location());
+ loc);
inserter->insert(temp);
- this->index_ = Expression::make_temporary_reference(temp,
- this->location());
+ this->index_ = Expression::make_temporary_reference(temp, loc);
}
if (this->value_pointer_ == NULL)
if (!this->value_pointer_->is_variable())
{
Temporary_statement* temp =
- Statement::make_temporary(NULL, this->value_pointer_,
- this->location());
+ Statement::make_temporary(NULL, this->value_pointer_, loc);
inserter->insert(temp);
- this->value_pointer_ =
- Expression::make_temporary_reference(temp, this->location());
+ this->value_pointer_ = Expression::make_temporary_reference(temp, loc);
}
return this;
++pv, ++i)
{
Expression_list* key_value_pair = new Expression_list();
- Expression* key =
- Expression::convert_for_assignment(gogo, key_type, *pv, loc);
+ Expression* key = *pv;
+ 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;
- Expression* val =
- Expression::convert_for_assignment(gogo, val_type, *pv, loc);
+ Expression* val = *pv;
+ 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(val);
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_multi_value_arg_(false)
+ is_deferred_(false), issued_error_(false), is_multi_value_arg_(false),
+ is_flattened_(false)
{ }
// The function to call.
bool issued_error_;
// True if this call is used as an argument that returns multiple results.
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.