go.tools/go/types: fix unsafe.Pointer conversions
Make compliant with gc. Spec is not very clear. Also: Fix error handling (don't destroy x before using it in error message). Fixes golang/go#6326. R=adonovan CC=golang-dev https://golang.org/cl/13632043
This commit is contained in:
parent
932a87ce16
commit
6688b01dc1
|
|
@ -11,12 +11,13 @@ import "code.google.com/p/go.tools/go/exact"
|
|||
// Conversion type-checks the conversion T(x).
|
||||
// The result is in x.
|
||||
func (check *checker) conversion(x *operand, T Type) {
|
||||
var ok bool
|
||||
switch {
|
||||
case x.mode == constant && isConstType(T):
|
||||
// constant conversion
|
||||
switch t := T.Underlying().(*Basic); {
|
||||
case isRepresentableConst(x.val, check.conf, t.kind, &x.val):
|
||||
// nothing to do
|
||||
ok = true
|
||||
case x.isInteger() && isString(t):
|
||||
codepoint := int64(-1)
|
||||
if i, ok := exact.Int64Val(x.val); ok {
|
||||
|
|
@ -26,18 +27,17 @@ func (check *checker) conversion(x *operand, T Type) {
|
|||
// conversion. This is the same as converting any other out-of-range
|
||||
// value - let string(codepoint) do the work.
|
||||
x.val = exact.MakeString(string(codepoint))
|
||||
default:
|
||||
x.mode = invalid
|
||||
ok = true
|
||||
}
|
||||
case x.isConvertible(check.conf, T):
|
||||
// non-constant conversion
|
||||
x.mode = value
|
||||
default:
|
||||
x.mode = invalid
|
||||
ok = true
|
||||
}
|
||||
|
||||
if x.mode == invalid {
|
||||
if !ok {
|
||||
check.errorf(x.pos(), "cannot convert %s to %s", x, T)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -116,17 +116,20 @@ func (x *operand) isConvertible(conf *Config, T Type) bool {
|
|||
}
|
||||
|
||||
func isUintptr(typ Type) bool {
|
||||
t, ok := typ.(*Basic)
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.kind == Uintptr
|
||||
}
|
||||
|
||||
func isUnsafePointer(typ Type) bool {
|
||||
t, ok := typ.(*Basic)
|
||||
// TODO(gri): Is this (typ.Underlying() instead of just typ) correct?
|
||||
// The spec does't say so, but gc claims it is. See also
|
||||
// issue 6326.
|
||||
t, ok := typ.Underlying().(*Basic)
|
||||
return ok && t.kind == UnsafePointer
|
||||
}
|
||||
|
||||
func isPointer(typ Type) bool {
|
||||
_, ok := typ.(*Pointer)
|
||||
_, ok := typ.Underlying().(*Pointer)
|
||||
return ok
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
package conversions
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// argument count
|
||||
var (
|
||||
_ = int() /* ERROR "missing argument" */
|
||||
|
|
@ -77,4 +79,10 @@ func interface_conversions() {
|
|||
_ = I3(i3)
|
||||
|
||||
// TODO(gri) add more tests, improve error message
|
||||
}
|
||||
}
|
||||
|
||||
func issue6326() {
|
||||
type T unsafe.Pointer
|
||||
var x T
|
||||
_ = uintptr(x) // see issue 6326
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue