This patch to libgo is a copy of a patch I recently made to the master
Go library.  This changes the reflect package to allocate memory using
the correct types for interface conversions.  The code was incorrectly
allocating an empty interface type to hold a non-empty interface
value.  This was working in the master library because it
coincidentally always handled the values correctly.  This was working
in gccgo because we almost never have the types anyhow, although we
plan to change that shortly.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian
diff -r 87f8de53800a libgo/go/reflect/value.go
--- a/libgo/go/reflect/value.go Fri Oct 17 17:41:04 2014 -0700
+++ b/libgo/go/reflect/value.go Mon Oct 20 10:59:43 2014 -0700
@@ -1405,9 +1405,9 @@
 func (v Value) Set(x Value) {
        v.mustBeAssignable()
        x.mustBeExported() // do not let unexported x leak
-       var target *interface{}
+       var target unsafe.Pointer
        if v.kind() == Interface {
-               target = (*interface{})(v.ptr)
+               target = v.ptr
        }
        x = x.assignTo("reflect.Set", v.typ, target)
        if x.flag&flagIndir != 0 {
@@ -2230,7 +2230,7 @@
 // assignTo returns a value v that can be assigned directly to typ.
 // It panics if v is not assignable to typ.
 // For a conversion to an interface type, target is a suggested scratch space 
to use.
-func (v Value) assignTo(context string, dst *rtype, target *interface{}) Value 
{
+func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) 
Value {
        if v.flag&flagMethod != 0 {
                v = makeMethodValue(context, v)
        }
@@ -2246,15 +2246,15 @@
 
        case implements(dst, v.typ):
                if target == nil {
-                       target = new(interface{})
+                       target = unsafe_New(dst)
                }
                x := valueInterface(v, false)
                if dst.NumMethod() == 0 {
-                       *target = x
+                       *(*interface{})(target) = x
                } else {
-                       ifaceE2I(dst, x, unsafe.Pointer(target))
+                       ifaceE2I(dst, x, target)
                }
-               return Value{dst, unsafe.Pointer(target) /* 0, */, flagIndir | 
flag(Interface)<<flagKindShift}
+               return Value{dst, target /* 0, */, flagIndir | 
flag(Interface)<<flagKindShift}
        }
 
        // Failed.
@@ -2537,14 +2537,14 @@
 
 // convertOp: concrete -> interface
 func cvtT2I(v Value, typ Type) Value {
-       target := new(interface{})
+       target := unsafe_New(typ.common())
        x := valueInterface(v, false)
        if typ.NumMethod() == 0 {
-               *target = x
+               *(*interface{})(target) = x
        } else {
-               ifaceE2I(typ.(*rtype), x, unsafe.Pointer(target))
+               ifaceE2I(typ.(*rtype), x, target)
        }
-       return Value{typ.common(), unsafe.Pointer(target) /* 0, */, 
v.flag&flagRO | flagIndir | flag(Interface)<<flagKindShift}
+       return Value{typ.common(), target /* 0, */, v.flag&flagRO | flagIndir | 
flag(Interface)<<flagKindShift}
 }
 
 // convertOp: interface -> interface

Reply via email to