From 3af76e5a95e8cef562136a40a78bb19f83df59dd Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 11 Aug 2012 04:09:21 +0000 Subject: [PATCH] compiler: Reject type switch using non-interface type. Fixes issue 16. From-SVN: r190310 --- gcc/go/gofrontend/statements.cc | 62 +++++++++++++-------------------- 1 file changed, 24 insertions(+), 38 deletions(-) diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 7f91e553a4d..fa7f20836ad 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -4192,55 +4192,41 @@ Type_switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing, ? this->var_->var_value()->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 Type* descriptor_type = Type::make_type_descriptor_ptr_type(); Temporary_statement* descriptor_temp = Statement::make_temporary(descriptor_type, NULL, loc); b->add_statement(descriptor_temp); - if (val_type->interface_type() == NULL) - { - // Doing a type switch on a non-interface type. Should we issue - // a warning for this case? - Expression* lhs = Expression::make_temporary_reference(descriptor_temp, - loc); - 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); - } + // descriptor_temp = ifacetype(val_temp) FIXME: This should be + // inlined. + bool is_empty = val_type->interface_type()->is_empty(); + Expression* ref; + if (this->var_ == NULL) + ref = this->expr_; else - { - // descriptor_temp = ifacetype(val_temp) - // FIXME: This should be inlined. - bool is_empty = val_type->interface_type()->is_empty(); - Expression* ref; - if (this->var_ == NULL) - ref = this->expr_; - else - ref = Expression::make_var_reference(this->var_, loc); - Expression* call = Runtime::make_call((is_empty - ? 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); - } + ref = Expression::make_var_reference(this->var_, loc); + Expression* call = Runtime::make_call((is_empty + ? 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) 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); return Statement::make_block_statement(b, loc); -- 2.30.2