This patch from Michael Hudson-Doyle fixes libgo to correctly handle reflect.Call when passing or returning a struct with no fields. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 76b3c32eef84 libgo/go/reflect/all_test.go --- a/libgo/go/reflect/all_test.go Mon Nov 18 18:17:49 2013 -0800 +++ b/libgo/go/reflect/all_test.go Mon Nov 18 18:28:13 2013 -0800 @@ -1434,6 +1434,46 @@ } } +type emptyStruct struct{} + +type nonEmptyStruct struct { + member int +} + +func returnEmpty() emptyStruct { + return emptyStruct{} +} + +func takesEmpty(e emptyStruct) { +} + +func returnNonEmpty(i int) nonEmptyStruct { + return nonEmptyStruct{member: i} +} + +func takesNonEmpty(n nonEmptyStruct) int { + return n.member +} + +func TestCallWithStruct(t *testing.T) { + r := ValueOf(returnEmpty).Call([]Value{}) + if len(r) != 1 || r[0].Type() != TypeOf(emptyStruct{}) { + t.Errorf("returning empty struct returned %s instead", r) + } + r = ValueOf(takesEmpty).Call([]Value{ValueOf(emptyStruct{})}) + if len(r) != 0 { + t.Errorf("takesEmpty returned values: %s", r) + } + r = ValueOf(returnNonEmpty).Call([]Value{ValueOf(42)}) + if len(r) != 1 || r[0].Type() != TypeOf(nonEmptyStruct{}) || r[0].Field(0).Int() != 42 { + t.Errorf("returnNonEmpty returned %s", r) + } + r = ValueOf(takesNonEmpty).Call([]Value{ValueOf(nonEmptyStruct{member: 42})}) + if len(r) != 1 || r[0].Type() != TypeOf(1) || r[0].Int() != 42 { + t.Errorf("takesNonEmpty returned %s", r) + } +} + func TestMakeFunc(t *testing.T) { switch runtime.GOARCH { case "amd64", "386": diff -r 76b3c32eef84 libgo/runtime/go-reflect-call.c --- a/libgo/runtime/go-reflect-call.c Mon Nov 18 18:17:49 2013 -0800 +++ b/libgo/runtime/go-reflect-call.c Mon Nov 18 18:28:13 2013 -0800 @@ -98,9 +98,12 @@ const struct __go_struct_field *fields; int i; + field_count = descriptor->__fields.__count; + if (field_count == 0) { + return &ffi_type_void; + } ret = (ffi_type *) __go_alloc (sizeof (ffi_type)); ret->type = FFI_TYPE_STRUCT; - field_count = descriptor->__fields.__count; fields = (const struct __go_struct_field *) descriptor->__fields.__values; ret->elements = (ffi_type **) __go_alloc ((field_count + 1) * sizeof (ffi_type *));