1
0
mirror of https://github.com/golang/go synced 2024-09-24 23:20:12 -06:00

reflect: fix variadic arg for funcs created by MakeFunc.

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
This commit is contained in:
Carl Chatfield 2014-04-08 22:35:23 -04:00 committed by Russ Cox
parent 89e128dd76
commit 772d22885b
2 changed files with 28 additions and 11 deletions

View 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
}

View 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