ソースを参照

goprotobuf: clean-up. reflect.NewValue's returned value is never addressable.

R=r, rsc
CC=golang-dev
http://codereview.appspot.com/4426050
David Symonds 15 年 前
コミット
d01278e4c6
1 ファイル変更7 行追加18 行削除
  1. 7 18
      proto/extensions.go

+ 7 - 18
proto/extensions.go

@@ -160,7 +160,8 @@ func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{
 	if err := checkExtensionTypes(pb, extension); err != nil {
 		return err
 	}
-	if reflect.Typeof(extension.ExtensionType) != reflect.Typeof(value) {
+	typ := reflect.Typeof(extension.ExtensionType)
+	if typ != reflect.Typeof(value) {
 		return os.NewError("bad extension value type")
 	}
 
@@ -168,25 +169,13 @@ func SetExtension(pb extendableProto, extension *ExtensionDesc, value interface{
 	props.Init(reflect.Typeof(extension.ExtensionType), "unknown_name", extension.Tag, 0)
 
 	p := NewBuffer(nil)
-	v := reflect.NewValue(value)
-	if err := props.enc(p, props, unsafeAddr(v)); err != nil {
+	// The encoder must be passed a pointer to value.
+	// Allocate a copy of value so that we can use its address.
+	x := reflect.New(typ)
+	x.Elem().Set(reflect.NewValue(value))
+	if err := props.enc(p, props, x.Pointer()); err != nil {
 		return err
 	}
 	pb.ExtensionMap()[extension.Field] = p.buf
 	return nil
 }
-
-// SetExtension assumes it can call UnsafeAddr on any Value
-// in order to get a pointer it can copy data from.
-// Values that have just been created and do not point
-// into existing structs or slices cannot be addressed,
-// so simulate it by returning a pointer to a copy.
-// Each call allocates once.
-func unsafeAddr(v reflect.Value) uintptr {
-	if v.CanAddr() {
-		return v.UnsafeAddr()
-	}
-	x := reflect.New(v.Type()).Elem()
-	x.Set(v)
-	return x.UnsafeAddr()
-}