Commit 3af76e5a by Ian Lance Taylor

compiler: Reject type switch using non-interface type.

Fixes issue 16.

From-SVN: r190310
parent 7380e6ef
...@@ -4192,55 +4192,41 @@ Type_switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing, ...@@ -4192,55 +4192,41 @@ Type_switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
? this->var_->var_value()->type() ? this->var_->var_value()->type()
: this->expr_->type()); : this->expr_->type());
if (val_type->interface_type() == NULL)
{
if (!val_type->is_error())
this->report_error(_("cannot type switch on non-interface value"));
return Statement::make_error_statement(loc);
}
// var descriptor_temp DESCRIPTOR_TYPE // var descriptor_temp DESCRIPTOR_TYPE
Type* descriptor_type = Type::make_type_descriptor_ptr_type(); Type* descriptor_type = Type::make_type_descriptor_ptr_type();
Temporary_statement* descriptor_temp = Temporary_statement* descriptor_temp =
Statement::make_temporary(descriptor_type, NULL, loc); Statement::make_temporary(descriptor_type, NULL, loc);
b->add_statement(descriptor_temp); b->add_statement(descriptor_temp);
if (val_type->interface_type() == NULL) // descriptor_temp = ifacetype(val_temp) FIXME: This should be
{ // inlined.
// Doing a type switch on a non-interface type. Should we issue bool is_empty = val_type->interface_type()->is_empty();
// a warning for this case? Expression* ref;
Expression* lhs = Expression::make_temporary_reference(descriptor_temp, if (this->var_ == NULL)
loc); ref = this->expr_;
Expression* rhs;
if (val_type->is_nil_type())
rhs = Expression::make_nil(loc);
else
{
if (val_type->is_abstract())
val_type = val_type->make_non_abstract_type();
rhs = Expression::make_type_descriptor(val_type, loc);
}
Statement* s = Statement::make_assignment(lhs, rhs, loc);
b->add_statement(s);
}
else else
{ ref = Expression::make_var_reference(this->var_, loc);
// descriptor_temp = ifacetype(val_temp) Expression* call = Runtime::make_call((is_empty
// FIXME: This should be inlined. ? Runtime::EFACETYPE
bool is_empty = val_type->interface_type()->is_empty(); : Runtime::IFACETYPE),
Expression* ref; loc, 1, ref);
if (this->var_ == NULL) Temporary_reference_expression* lhs =
ref = this->expr_; Expression::make_temporary_reference(descriptor_temp, loc);
else lhs->set_is_lvalue();
ref = Expression::make_var_reference(this->var_, loc); Statement* s = Statement::make_assignment(lhs, call, loc);
Expression* call = Runtime::make_call((is_empty b->add_statement(s);
? Runtime::EFACETYPE
: Runtime::IFACETYPE),
loc, 1, ref);
Temporary_reference_expression* lhs =
Expression::make_temporary_reference(descriptor_temp, loc);
lhs->set_is_lvalue();
Statement* s = Statement::make_assignment(lhs, call, loc);
b->add_statement(s);
}
if (this->clauses_ != NULL) if (this->clauses_ != NULL)
this->clauses_->lower(val_type, b, descriptor_temp, this->break_label()); this->clauses_->lower(val_type, b, descriptor_temp, this->break_label());
Statement* s = Statement::make_unnamed_label_statement(this->break_label_); s = Statement::make_unnamed_label_statement(this->break_label_);
b->add_statement(s); b->add_statement(s);
return Statement::make_block_statement(b, loc); return Statement::make_block_statement(b, loc);
......
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