aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-01-24 23:26:20 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-01-24 23:26:20 +0000
commitd1cab3a6152a8ffe3049ca9ceb4ec639a6f04890 (patch)
treeb4bc748a96c1b04b4fbd292637ffb97951572147
parent5fca1e3f90ddcafc38ec98c3bf5cf78ab91ee7ca (diff)
downloadgcc-d1cab3a6152a8ffe3049ca9ceb4ec639a6f04890.zip
gcc-d1cab3a6152a8ffe3049ca9ceb4ec639a6f04890.tar.gz
gcc-d1cab3a6152a8ffe3049ca9ceb4ec639a6f04890.tar.bz2
compiler: Error if type switch case can not implement switch value.
From-SVN: r183500
-rw-r--r--gcc/go/gofrontend/statements.cc28
-rw-r--r--gcc/go/gofrontend/statements.h4
2 files changed, 25 insertions, 7 deletions
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index bb74db8..e55dc74 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 016ca18..5bbfd37 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.