diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 3c75f8ace06..dfe9b5167bb 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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(); diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 6da507b57ca..4e06b246d18 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -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 diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 45545dfe6a9..d1901e17e71 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -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; diff --git a/gcc/testsuite/go.test/test/closure.go b/gcc/testsuite/go.test/test/closure.go index 3033c02ed81..191514def49 100644 --- a/gcc/testsuite/go.test/test/closure.go +++ b/gcc/testsuite/go.test/test/closure.go @@ -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 index 698544c5821..00000000000 --- a/gcc/testsuite/go.test/test/cmp1.go +++ /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) - } -} diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug285.go b/gcc/testsuite/go.test/test/fixedbugs/bug285.go index 544d3487eff..7eed8fb7abc 100644 --- a/gcc/testsuite/go.test/test/fixedbugs/bug285.go +++ b/gcc/testsuite/go.test/test/fixedbugs/bug285.go @@ -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) diff --git a/gcc/testsuite/go.test/test/typeswitch.go b/gcc/testsuite/go.test/test/typeswitch.go index 83fb0985a91..aa911f9b621 100644 --- a/gcc/testsuite/go.test/test/typeswitch.go +++ b/gcc/testsuite/go.test/test/typeswitch.go @@ -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") } - }