compiler: Prohibit comparisons of funcs, maps, and slices to non-nil.
From-SVN: r182703
This commit is contained in:
parent
9437ab32a5
commit
1358551fc6
7 changed files with 25 additions and 160 deletions
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue