aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/reflect/value.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/reflect/value.go')
-rw-r--r--libgo/go/reflect/value.go66
1 files changed, 58 insertions, 8 deletions
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 0b4f094..300ef1a 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -5,6 +5,7 @@
package reflect
import (
+ "internal/itoa"
"internal/unsafeheader"
"math"
"runtime"
@@ -350,6 +351,8 @@ func (v Value) CallSlice(in []Value) []Value {
var callGC bool // for testing; see TestCallMethodJump
+const debugReflectCall = false
+
func (v Value) call(op string, in []Value) []Value {
// Get function pointer, type.
t := (*funcType)(unsafe.Pointer(v.typ))
@@ -372,8 +375,9 @@ func (v Value) call(op string, in []Value) []Value {
isSlice := op == "CallSlice"
n := t.NumIn()
+ isVariadic := t.IsVariadic()
if isSlice {
- if !t.IsVariadic() {
+ if !isVariadic {
panic("reflect: CallSlice of non-variadic function")
}
if len(in) < n {
@@ -383,13 +387,13 @@ func (v Value) call(op string, in []Value) []Value {
panic("reflect: CallSlice with too many input arguments")
}
} else {
- if t.IsVariadic() {
+ if isVariadic {
n--
}
if len(in) < n {
panic("reflect: Call with too few input arguments")
}
- if !t.IsVariadic() && len(in) > n {
+ if !isVariadic && len(in) > n {
panic("reflect: Call with too many input arguments")
}
}
@@ -403,7 +407,7 @@ func (v Value) call(op string, in []Value) []Value {
panic("reflect: " + op + " using " + xt.String() + " as type " + targ.String())
}
}
- if !isSlice && t.IsVariadic() {
+ if !isSlice && isVariadic {
// prepare slice for remaining values
m := len(in) - n
slice := MakeSlice(t.In(n), m, m)
@@ -857,10 +861,16 @@ func valueInterface(v Value, safe bool) interface{} {
return packEface(v)
}
-// InterfaceData returns the interface v's value as a uintptr pair.
+// InterfaceData returns a pair of unspecified uintptr values.
// It panics if v's Kind is not Interface.
+//
+// In earlier versions of Go, this function returned the interface's
+// value as a uintptr pair. As of Go 1.4, the implementation of
+// interface values precludes any defined use of InterfaceData.
+//
+// Deprecated: The memory representation of interface values is not
+// compatible with InterfaceData.
func (v Value) InterfaceData() [2]uintptr {
- // TODO: deprecate this
v.mustBe(Interface)
// We treat this as a read operation, so we allow
// it even for unexported data, because the caller
@@ -2200,9 +2210,14 @@ func New(typ Type) Value {
panic("reflect: New(nil)")
}
t := typ.(*rtype)
+ pt := t.ptrTo()
+ if ifaceIndir(pt) {
+ // This is a pointer to a go:notinheap type.
+ panic("reflect: New of type that may not be allocated in heap (possibly undefined cgo C type)")
+ }
ptr := unsafe_New(t)
fl := flag(Ptr)
- return Value{t.ptrTo(), ptr, fl}
+ return Value{pt, ptr, fl}
}
// NewAt returns a Value representing a pointer to a value of the
@@ -2255,7 +2270,7 @@ func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value
// Convert returns the value v converted to type t.
// If the usual Go conversion rules do not allow conversion
-// of the value v to type t, Convert panics.
+// of the value v to type t, or if converting v to type t panics, Convert panics.
func (v Value) Convert(t Type) Value {
if v.flag&flagMethod != 0 {
v = makeMethodValue("Convert", v)
@@ -2267,6 +2282,26 @@ func (v Value) Convert(t Type) Value {
return op(v, t)
}
+// CanConvert reports whether the value v can be converted to type t.
+// If v.CanConvert(t) returns true then v.Convert(t) will not panic.
+func (v Value) CanConvert(t Type) bool {
+ vt := v.Type()
+ if !vt.ConvertibleTo(t) {
+ return false
+ }
+ // Currently the only conversion that is OK in terms of type
+ // but that can panic depending on the value is converting
+ // from slice to pointer-to-array.
+ if vt.Kind() == Slice && t.Kind() == Ptr && t.Elem().Kind() == Array {
+ n := t.Elem().Len()
+ h := (*unsafeheader.Slice)(v.ptr)
+ if n > h.Len {
+ return false
+ }
+ }
+ return true
+}
+
// convertOp returns the function to convert a value of type src
// to a value of type dst. If the conversion is illegal, convertOp returns nil.
func convertOp(dst, src *rtype) func(Value, Type) Value {
@@ -2326,6 +2361,11 @@ func convertOp(dst, src *rtype) func(Value, Type) Value {
return cvtRunesString
}
}
+ // "x is a slice, T is a pointer-to-array type,
+ // and the slice and array types have identical element types."
+ if dst.Kind() == Ptr && dst.Elem().Kind() == Array && src.Elem() == dst.Elem().Elem() {
+ return cvtSliceArrayPtr
+ }
case Chan:
if dst.Kind() == Chan && specialChannelAssignability(dst, src) {
@@ -2519,6 +2559,16 @@ func cvtStringRunes(v Value, t Type) Value {
return makeRunes(v.flag.ro(), []rune(v.String()), t)
}
+// convertOp: []T -> *[N]T
+func cvtSliceArrayPtr(v Value, t Type) Value {
+ n := t.Elem().Len()
+ h := (*unsafeheader.Slice)(v.ptr)
+ if n > h.Len {
+ panic("reflect: cannot convert slice with length " + itoa.Itoa(h.Len) + " to pointer to array with length " + itoa.Itoa(n))
+ }
+ return Value{t.common(), h.Data, v.flag&^(flagIndir|flagAddr|flagKindMask) | flag(Ptr)}
+}
+
// convertOp: direct copy
func cvtDirect(v Value, typ Type) Value {
f := v.flag