From d1cab3a6152a8ffe3049ca9ceb4ec639a6f04890 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 24 Jan 2012 23:26:20 +0000 Subject: [PATCH] compiler: Error if type switch case can not implement switch value. From-SVN: r183500 --- gcc/go/gofrontend/statements.cc | 28 +++++++++++++++++++++++----- gcc/go/gofrontend/statements.h | 4 ++-- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index bb74db85d80..e55dc74b3b7 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -3940,7 +3940,8 @@ Type_case_clauses::Type_case_clause::traverse(Traverse* traverse) // statements. void -Type_case_clauses::Type_case_clause::lower(Block* b, +Type_case_clauses::Type_case_clause::lower(Type* switch_val_type, + Block* b, Temporary_statement* descriptor_temp, Unnamed_label* break_label, Unnamed_label** stmts_label) const @@ -3952,6 +3953,20 @@ Type_case_clauses::Type_case_clause::lower(Block* b, { Type* type = this->type_; + std::string reason; + if (switch_val_type->interface_type() != NULL + && !type->is_nil_constant_as_type() + && type->interface_type() == NULL + && !switch_val_type->interface_type()->implements_interface(type, + &reason)) + { + if (reason.empty()) + error_at(this->location_, "impossible type switch case"); + else + error_at(this->location_, "impossible type switch case (%s)", + reason.c_str()); + } + Expression* ref = Expression::make_temporary_reference(descriptor_temp, loc); @@ -4102,7 +4117,8 @@ Type_case_clauses::check_duplicates() const // BREAK_LABEL is the label at the end of the type switch. void -Type_case_clauses::lower(Block* b, Temporary_statement* descriptor_temp, +Type_case_clauses::lower(Type* switch_val_type, Block* b, + Temporary_statement* descriptor_temp, Unnamed_label* break_label) const { const Type_case_clause* default_case = NULL; @@ -4113,7 +4129,8 @@ Type_case_clauses::lower(Block* b, Temporary_statement* descriptor_temp, ++p) { if (!p->is_default()) - p->lower(b, descriptor_temp, break_label, &stmts_label); + p->lower(switch_val_type, b, descriptor_temp, break_label, + &stmts_label); else { // We are generating a series of tests, which means that we @@ -4124,7 +4141,8 @@ Type_case_clauses::lower(Block* b, Temporary_statement* descriptor_temp, go_assert(stmts_label == NULL); if (default_case != NULL) - default_case->lower(b, descriptor_temp, break_label, NULL); + default_case->lower(switch_val_type, b, descriptor_temp, break_label, + NULL); } // Dump the AST representation for case clauses (from a switch statement) @@ -4222,7 +4240,7 @@ Type_switch_statement::do_lower(Gogo*, Named_object*, Block* enclosing, } if (this->clauses_ != NULL) - this->clauses_->lower(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_); b->add_statement(s); diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index 016ca189569..5bbfd373669 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -1441,7 +1441,7 @@ class Type_case_clauses // Lower to if and goto statements. void - lower(Block*, Temporary_statement* descriptor_temp, + lower(Type*, Block*, Temporary_statement* descriptor_temp, Unnamed_label* break_label) const; // Dump the AST representation to a dump context. @@ -1485,7 +1485,7 @@ class Type_case_clauses // Lower to if and goto statements. void - lower(Block*, Temporary_statement* descriptor_temp, + lower(Type*, Block*, Temporary_statement* descriptor_temp, Unnamed_label* break_label, Unnamed_label** stmts_label) const; // Dump the AST representation to a dump context.