]> Cypherpunks repositories - gostls13.git/commitdiff
reflect: fix variadic arg for funcs created by MakeFunc.
authorCarl Chatfield <carlchatfield@gmail.com>
Wed, 9 Apr 2014 02:35:23 +0000 (22:35 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 9 Apr 2014 02:35:23 +0000 (22:35 -0400)
Short circuit for calling values funcs by MakeFunc was placed
before variadic arg rearrangement code in reflect.call.
Fixes #7534.

LGTM=khr
R=golang-codereviews, bradfitz, khr, rsc
CC=golang-codereviews
https://golang.org/cl/75370043

src/pkg/reflect/all_test.go
src/pkg/reflect/value.go

index c81f5250945261f75aab58e83caaf661b42b5e1c..1e6341bd0bf544c34d176694a0d32ab5abfdfeea 100644 (file)
@@ -1512,6 +1512,23 @@ func TestMakeFuncInterface(t *testing.T) {
        }
 }
 
+func TestMakeFuncVariadic(t *testing.T) {
+       // Test that variadic arguments are packed into a slice and passed as last arg
+       fn := func(_ int, is ...int) []int { return nil }
+       fv := MakeFunc(TypeOf(fn), func(in []Value) []Value { return in[1:2] })
+       ValueOf(&fn).Elem().Set(fv)
+
+       r := fv.Call([]Value{ValueOf(1), ValueOf(2), ValueOf(3)})[0].Interface().([]int)
+       if r[0] != 2 || r[1] != 3 {
+               t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+       }
+
+       r = fv.CallSlice([]Value{ValueOf(1), ValueOf([]int{2, 3})})[0].Interface().([]int)
+       if r[0] != 2 || r[1] != 3 {
+               t.Errorf("Call returned [%v, %v]; want 2, 3", r[0], r[1])
+       }
+}
+
 type Point struct {
        x, y int
 }
index a14b3a2f80a62db41ac746709d3e50078f4eeb72..720090bd66d8e5e749e18f153e4c067268b4609e 100644 (file)
@@ -453,17 +453,6 @@ func (v Value) call(op string, in []Value) []Value {
                panic("reflect.Value.Call: call of nil function")
        }
 
-       // If target is makeFuncStub, short circuit the unpack onto stack /
-       // pack back into []Value for the args and return values.  Just do the
-       // call directly.
-       // We need to do this here because otherwise we have a situation where
-       // reflect.callXX calls makeFuncStub, neither of which knows the
-       // layout of the args.  That's bad for precise gc & stack copying.
-       x := (*makeFuncImpl)(fn)
-       if x.code == makeFuncStubCode {
-               return x.fn(in)
-       }
-
        isSlice := op == "CallSlice"
        n := t.NumIn()
        if isSlice {
@@ -521,6 +510,17 @@ func (v Value) call(op string, in []Value) []Value {
        }
        nout := t.NumOut()
 
+       // If target is makeFuncStub, short circuit the unpack onto stack /
+       // pack back into []Value for the args and return values.  Just do the
+       // call directly.
+       // We need to do this here because otherwise we have a situation where
+       // reflect.callXX calls makeFuncStub, neither of which knows the
+       // layout of the args.  That's bad for precise gc & stack copying.
+       x := (*makeFuncImpl)(fn)
+       if x.code == makeFuncStubCode {
+               return x.fn(in)
+       }
+
        // If the target is methodValueCall, do its work here: add the receiver
        // argument and call the real target directly.
        // We need to do this here because otherwise we have a situation where