diff mbox

Go patch committed: No func, map or slice comparisons

Message ID mcrpqf99x4e.fsf@dhcp-172-18-216-180.mtv.corp.google.com
State New
Headers show

Commit Message

Ian Lance Taylor Dec. 28, 2011, 3:46 a.m. UTC
The Go language was changed to prohibit comparing values of func, map,
or slice type, except for comparisons to nil.  This patch implements
that in the Go frontend.  The patch includes some testsuite updates.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian
diff mbox

Patch

Index: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h	(revision 182696)
+++ gcc/go/gofrontend/expressions.h	(working copy)
@@ -1147,9 +1147,9 @@  class Binary_expression : public Express
   do_import(Import*);
 
   // Report an error if OP can not be applied to TYPE.  Return whether
-  // it can.
+  // it can.  OTYPE is the type of the other operand.
   static bool
-  check_operator_type(Operator op, Type* type, Location);
+  check_operator_type(Operator op, Type* type, Type* otype, Location);
 
  protected:
   int
Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 182696)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -1235,8 +1235,6 @@  Type::type_functions(const char** hash_f
     case Type::TYPE_FLOAT:
     case Type::TYPE_COMPLEX:
     case Type::TYPE_POINTER:
-    case Type::TYPE_FUNCTION:
-    case Type::TYPE_MAP:
     case Type::TYPE_CHANNEL:
       *hash_fn = "__go_type_hash_identity";
       *equal_fn = "__go_type_equal_identity";
@@ -1249,6 +1247,8 @@  Type::type_functions(const char** hash_f
 
     case Type::TYPE_STRUCT:
     case Type::TYPE_ARRAY:
+    case Type::TYPE_FUNCTION:
+    case Type::TYPE_MAP:
       // These types can not be hashed or compared.
       *hash_fn = "__go_type_hash_error";
       *equal_fn = "__go_type_equal_error";
@@ -4731,7 +4731,9 @@  bool
 Map_type::do_verify()
 {
   if (this->key_type_->struct_type() != NULL
-      || this->key_type_->array_type() != NULL)
+      || this->key_type_->array_type() != NULL
+      || this->key_type_->function_type() != NULL
+      || this->key_type_->map_type() != NULL)
     {
       error_at(this->location_, "invalid map key type");
       return false;
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 182696)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -6052,11 +6052,11 @@  Binary_expression::do_determine_type(con
 }
 
 // Report an error if the binary operator OP does not support TYPE.
-// Return whether the operation is OK.  This should not be used for
-// shift.
+// OTYPE is the type of the other operand.  Return whether the
+// operation is OK.  This should not be used for shift.
 
 bool
-Binary_expression::check_operator_type(Operator op, Type* type,
+Binary_expression::check_operator_type(Operator op, Type* type, Type* otype,
 				       Location location)
 {
   switch (op)
@@ -6092,6 +6092,16 @@  Binary_expression::check_operator_type(O
 		    "or function type"));
 	  return false;
 	}
+      if ((type->is_slice_type()
+	   || type->map_type() != NULL
+	   || type->function_type() != NULL)
+	  && !otype->is_nil_type())
+	{
+	  error_at(location,
+		   ("slice, map, and function types may only "
+		    "be compared to nil"));
+	  return false;
+	}
       break;
 
     case OPERATOR_LT:
@@ -6189,8 +6199,10 @@  Binary_expression::do_check_types(Gogo*)
 	  return;
 	}
       if (!Binary_expression::check_operator_type(this->op_, left_type,
+						  right_type,
 						  this->location())
 	  || !Binary_expression::check_operator_type(this->op_, right_type,
+						     left_type,
 						     this->location()))
 	{
 	  this->set_is_error();
@@ -6205,6 +6217,7 @@  Binary_expression::do_check_types(Gogo*)
 	  return;
 	}
       if (!Binary_expression::check_operator_type(this->op_, left_type,
+						  right_type,
 						  this->location()))
 	{
 	  this->set_is_error();
Index: gcc/testsuite/go.test/test/closure.go
===================================================================
--- gcc/testsuite/go.test/test/closure.go	(revision 182418)
+++ gcc/testsuite/go.test/test/closure.go	(working copy)
@@ -76,7 +76,6 @@  func h() {
 
 func newfunc() func(int) int { return func(x int) int { return x } }
 
-
 func main() {
 	go f()
 	check([]int{1, 4, 5, 4})
@@ -90,10 +89,6 @@  func main() {
 	check([]int{100, 200, 101, 201, 500, 101, 201, 500})
 
 	x, y := newfunc(), newfunc()
-	if x == y {
-		println("newfunc returned same func")
-		panic("fail")
-	}
 	if x(1) != 1 || y(2) != 2 {
 		println("newfunc returned broken funcs")
 		panic("fail")
Index: gcc/testsuite/go.test/test/cmp1.go
===================================================================
--- gcc/testsuite/go.test/test/cmp1.go	(revision 182418)
+++ gcc/testsuite/go.test/test/cmp1.go	(working copy)
@@ -1,130 +0,0 @@ 
-// $G $D/$F.go && $L $F.$A && ./$A.out
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "unsafe"
-
-func use(bool) {}
-
-func stringptr(s string) uintptr { return *(*uintptr)(unsafe.Pointer(&s)) }
-
-func isfalse(b bool) {
-	if b {
-		// stack will explain where
-		panic("wanted false, got true")
-	}
-}
-
-func istrue(b bool) {
-	if !b {
-		// stack will explain where
-		panic("wanted true, got false")
-	}
-}
-
-type T *int
-
-func main() {
-	var a []int
-	var b map[string]int
-
-	var c string = "hello"
-	var d string = "hel" // try to get different pointer
-	d = d + "lo"
-	if stringptr(c) == stringptr(d) {
-		panic("compiler too smart -- got same string")
-	}
-
-	var e = make(chan int)
-
-	var ia interface{} = a
-	var ib interface{} = b
-	var ic interface{} = c
-	var id interface{} = d
-	var ie interface{} = e
-
-	// these comparisons are okay because
-	// string compare is okay and the others
-	// are comparisons where the types differ.
-	isfalse(ia == ib)
-	isfalse(ia == ic)
-	isfalse(ia == id)
-	isfalse(ib == ic)
-	isfalse(ib == id)
-	istrue(ic == id)
-	istrue(ie == ie)
-	
-	// these are okay because one side of the
-	// comparison need only be assignable to the other.
-	isfalse(a == ib)
-	isfalse(a == ic)
-	isfalse(a == id)
-	isfalse(b == ic)
-	isfalse(b == id)
-	istrue(c == id)
-	istrue(e == ie)
-
-	isfalse(ia == b)
-	isfalse(ia == c)
-	isfalse(ia == d)
-	isfalse(ib == c)
-	isfalse(ib == d)
-	istrue(ic == d)
-	istrue(ie == e)
-
-	// 6g used to let this go through as true.
-	var g uint64 = 123
-	var h int64 = 123
-	var ig interface{} = g
-	var ih interface{} = h
-	isfalse(ig == ih)
-
-	// map of interface should use == on interface values,
-	// not memory.
-	// TODO: should m[c], m[d] be valid here?
-	var m = make(map[interface{}]int)
-	m[ic] = 1
-	m[id] = 2
-	if m[ic] != 2 {
-		println("m[ic] = ", m[ic])
-		panic("bad m[ic]")
-	}
-	
-	// non-interface comparisons
-	{
-		c := make(chan int)
-		c1 := (<-chan int)(c)
-		c2 := (chan<- int)(c)
-		istrue(c == c1)
-		istrue(c == c2)
-		istrue(c1 == c)
-		istrue(c2 == c)
-		
-		d := make(chan int)
-		isfalse(c == d)
-		isfalse(d == c)
-		isfalse(d == c1)
-		isfalse(d == c2)
-		isfalse(c1 == d)
-		isfalse(c2 == d)
-	}
-
-	// named types vs not
-	{
-		var x = new(int)
-		var y T
-		var z T = x
-		
-		isfalse(x == y)
-		istrue(x == z)
-		isfalse(y == z)
-
-		isfalse(y == x)
-		istrue(z == x)
-		isfalse(z == y)
-	}
-}
Index: gcc/testsuite/go.test/test/typeswitch.go
===================================================================
--- gcc/testsuite/go.test/test/typeswitch.go	(revision 182418)
+++ gcc/testsuite/go.test/test/typeswitch.go	(working copy)
@@ -82,9 +82,9 @@  func main() {
 		case []int:
 			assert(x[3] == 3 && i == Array, "array")
 		case map[string]int:
-			assert(x == m && i == Map, "map")
+			assert(x != nil && i == Map, "map")
 		case func(i int) interface{}:
-			assert(x == f && i == Func, "fun")
+			assert(x != nil && i == Func, "fun")
 		default:
 			assert(false, "unknown")
 		}
@@ -111,5 +111,4 @@  func main() {
 	default:
 		assert(false, "switch 4 unknown")
 	}
-
 }
Index: gcc/testsuite/go.test/test/fixedbugs/bug285.go
===================================================================
--- gcc/testsuite/go.test/test/fixedbugs/bug285.go	(revision 182418)
+++ gcc/testsuite/go.test/test/fixedbugs/bug285.go	(working copy)
@@ -45,20 +45,6 @@  func main() {
 	mp[p] = 42
 	mp[&T{7}] = 42
 
-	type F func(x int)
-	f := func(x int) {}
-	mf := make(map[F]int)
-	mf[nil] = 42
-	mf[f] = 42
-	mf[func(x int) {}] = 42
-
-	type M map[int]int
-	m := make(M)
-	mm := make(map[M]int)
-	mm[nil] = 42
-	mm[m] = 42
-	mm[make(M)] = 42
-
 	type C chan int
 	c := make(C)
 	mc := make(map[C]int)