if (this->type_ != NULL && this->init_ != NULL)
{
std::string reason;
- if (!Type::are_assignable(this->type_, this->init_->type(), &reason))
+ bool ok;
+ if (this->are_hidden_fields_ok_)
+ ok = Type::are_assignable_hidden_ok(this->type_, this->init_->type(),
+ &reason);
+ else
+ ok = Type::are_assignable(this->type_, this->init_->type(), &reason);
+ if (!ok)
{
if (reason.empty())
error_at(this->location(), "incompatible types in assignment");
Assignment_statement(Expression* lhs, Expression* rhs,
source_location location)
: Statement(STATEMENT_ASSIGNMENT, location),
- lhs_(lhs), rhs_(rhs)
+ lhs_(lhs), rhs_(rhs), are_hidden_fields_ok_(false)
{ }
+ // Note that it is OK for this assignment statement to set hidden
+ // fields.
+ void
+ set_hidden_fields_are_ok()
+ { this->are_hidden_fields_ok_ = true; }
+
protected:
int
do_traverse(Traverse* traverse);
Expression* lhs_;
// Right hand side--the rvalue.
Expression* rhs_;
+ // True if this statement may set hidden fields in the assignment
+ // statement. This is used for generated method stubs.
+ bool are_hidden_fields_ok_;
};
// Traversal.
Type* lhs_type = this->lhs_->type();
Type* rhs_type = this->rhs_->type();
std::string reason;
- if (!Type::are_assignable(lhs_type, rhs_type, &reason))
+ bool ok;
+ if (this->are_hidden_fields_ok_)
+ ok = Type::are_assignable_hidden_ok(lhs_type, rhs_type, &reason);
+ else
+ ok = Type::are_assignable(lhs_type, rhs_type, &reason);
+ if (!ok)
{
if (reason.empty())
error_at(this->location(), "incompatible types in assignment");
Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
source_location location)
: Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
- lhs_(lhs), rhs_(rhs)
+ lhs_(lhs), rhs_(rhs), are_hidden_fields_ok_(false)
{ }
+ // Note that it is OK for this assignment statement to set hidden
+ // fields.
+ void
+ set_hidden_fields_are_ok()
+ { this->are_hidden_fields_ok_ = true; }
+
protected:
int
do_traverse(Traverse* traverse);
Expression_list* lhs_;
// Right hand side--a list of rvalues.
Expression_list* rhs_;
+ // True if this statement may set hidden fields in the assignment
+ // statement. This is used for generated method stubs.
+ bool are_hidden_fields_ok_;
};
// Traversal.
Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
*prhs, loc);
+ if (this->are_hidden_fields_ok_)
+ temp->set_hidden_fields_are_ok();
b->add_statement(temp);
temps.push_back(temp);
Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
Statement* s = Statement::make_assignment(*plhs, ref, loc);
+ if (this->are_hidden_fields_ok_)
+ {
+ Assignment_statement* as = static_cast<Assignment_statement*>(s);
+ as->set_hidden_fields_are_ok();
+ }
b->add_statement(s);
++ptemp;
}
// Lower a return statement. If we are returning a function call
// which returns multiple values which match the current function,
-// split up the call's results. If the function has named result
-// variables, and the return statement lists explicit values, then
-// implement it by assigning the values to the result variables and
-// changing the statement to not list any values. This lets
-// panic/recover work correctly.
+// split up the call's results. If the return statement lists
+// explicit values, implement this statement by assigning the values
+// to the result variables and change this statement to a naked
+// return. This lets panic/recover work correctly.
Statement*
Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing,
e->determine_type(&type_context);
std::string reason;
- if (Type::are_assignable(rvtype, e->type(), &reason))
+ bool ok;
+ if (this->are_hidden_fields_ok_)
+ ok = Type::are_assignable_hidden_ok(rvtype, e->type(), &reason);
+ else
+ ok = Type::are_assignable(rvtype, e->type(), &reason);
+ if (ok)
{
Expression* ve = Expression::make_var_reference(rv, e->location());
lhs->push_back(ve);
;
else if (lhs->size() == 1)
{
- b->add_statement(Statement::make_assignment(lhs->front(), rhs->front(),
- loc));
+ Statement* s = Statement::make_assignment(lhs->front(), rhs->front(),
+ loc);
+ if (this->are_hidden_fields_ok_)
+ {
+ Assignment_statement* as = static_cast<Assignment_statement*>(s);
+ as->set_hidden_fields_are_ok();
+ }
+ b->add_statement(s);
delete lhs;
delete rhs;
}
else
- b->add_statement(Statement::make_tuple_assignment(lhs, rhs, loc));
+ {
+ Statement* s = Statement::make_tuple_assignment(lhs, rhs, loc);
+ if (this->are_hidden_fields_ok_)
+ {
+ Tuple_assignment_statement* tas =
+ static_cast<Tuple_assignment_statement*>(s);
+ tas->set_hidden_fields_are_ok();
+ }
+ b->add_statement(s);
+ }
b->add_statement(this);
// Make a return statement.
-Statement*
+Return_statement*
Statement::make_return_statement(Expression_list* vals,
source_location location)
{