Patchwork Go patch committed: Reject type switch on non-interface type

login
register
mail settings
Submitter Ian Taylor
Date Aug. 11, 2012, 4:09 a.m.
Message ID <mcr4noagjcy.fsf@dhcp-172-18-216-180.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/176660/
State New
Headers show

Comments

Ian Taylor - Aug. 11, 2012, 4:09 a.m.
The Go language does not permit a type switch on a non-interface type.
This patch modifies the gccgo frontend to reject this case.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline and 4.7 branch.

Ian

Patch

diff -r cadd7e3bec3f go/statements.cc
--- a/go/statements.cc	Thu Aug 09 23:07:16 2012 -0700
+++ b/go/statements.cc	Fri Aug 10 18:03:43 2012 -0700
@@ -4192,55 +4192,41 @@ 
 		    ? 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);