OSDN Git Service

compiler: Prohibit comparisons of funcs, maps, and slices to non-nil.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Dec 2011 03:46:20 +0000 (03:46 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Dec 2011 03:46:20 +0000 (03:46 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@182703 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/types.cc
gcc/testsuite/go.test/test/closure.go
gcc/testsuite/go.test/test/cmp1.go [deleted file]
gcc/testsuite/go.test/test/fixedbugs/bug285.go
gcc/testsuite/go.test/test/typeswitch.go

index 3c75f8a..dfe9b51 100644 (file)
@@ -6052,11 +6052,11 @@ Binary_expression::do_determine_type(const Type_context* context)
 }
 
 // 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(Operator op, Type* type,
                    "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 6da507b..4e06b24 100644 (file)
@@ -1147,9 +1147,9 @@ class Binary_expression : public Expression
   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 45545df..d1901e1 100644 (file)
@@ -1235,8 +1235,6 @@ Type::type_functions(const char** hash_fn, const char** equal_fn) const
     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_fn, const char** equal_fn) const
 
     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 3033c02..191514d 100644 (file)
@@ -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")
diff --git a/gcc/testsuite/go.test/test/cmp1.go b/gcc/testsuite/go.test/test/cmp1.go
deleted file mode 100644 (file)
index 698544c..0000000
+++ /dev/null
@@ -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 544d348..7eed8fb 100644 (file)
@@ -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)
index 83fb098..aa911f9 100644 (file)
@@ -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")
        }
-
 }