diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-08-11 04:09:21 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2012-08-11 04:09:21 +0000 |
commit | 3af76e5a95e8cef562136a40a78bb19f83df59dd (patch) | |
tree | 1ee84031cdc6b2307a5388a951c30e9a28326c5e | |
parent | 7380e6efdd990e0286da69d7b583240eccf40694 (diff) | |
download | gcc-3af76e5a95e8cef562136a40a78bb19f83df59dd.zip gcc-3af76e5a95e8cef562136a40a78bb19f83df59dd.tar.gz gcc-3af76e5a95e8cef562136a40a78bb19f83df59dd.tar.bz2 |
compiler: Reject type switch using non-interface type.
Fixes issue 16.
From-SVN: r190310
-rw-r--r-- | gcc/go/gofrontend/statements.cc | 62 |
1 files changed, 24 insertions, 38 deletions
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 7f91e55..fa7f208 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); |