summaryrefslogtreecommitdiff
path: root/libgo
diff options
context:
space:
mode:
Diffstat (limited to 'libgo')
-rw-r--r--libgo/go/reflect/all_test.go95
-rw-r--r--libgo/go/reflect/type.go83
-rw-r--r--libgo/go/reflect/value.go4
3 files changed, 89 insertions, 93 deletions
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index 3686167ed42..6ac33526774 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -4184,50 +4184,58 @@ func TestStructOfExportRules(t *testing.T) {
f()
}
- for i, test := range []struct {
+ tests := []struct {
field StructField
mustPanic bool
exported bool
}{
{
- field: StructField{Name: "", Type: TypeOf(S1{})},
- mustPanic: false,
- exported: true,
+ field: StructField{Name: "S1", Anonymous: true, Type: TypeOf(S1{})},
+ exported: true,
},
{
- field: StructField{Name: "", Type: TypeOf((*S1)(nil))},
- mustPanic: false,
- exported: true,
+ field: StructField{Name: "S1", Anonymous: true, Type: TypeOf((*S1)(nil))},
+ exported: true,
},
{
- field: StructField{Name: "", Type: TypeOf(s2{})},
- mustPanic: false,
- exported: false,
+ field: StructField{Name: "s2", Anonymous: true, Type: TypeOf(s2{})},
+ mustPanic: true,
},
{
- field: StructField{Name: "", Type: TypeOf((*s2)(nil))},
- mustPanic: false,
- exported: false,
+ field: StructField{Name: "s2", Anonymous: true, Type: TypeOf((*s2)(nil))},
+ mustPanic: true,
},
{
- field: StructField{Name: "", Type: TypeOf(S1{}), PkgPath: "other/pkg"},
+ field: StructField{Name: "Name", Type: nil, PkgPath: ""},
mustPanic: true,
- exported: true,
},
{
- field: StructField{Name: "", Type: TypeOf((*S1)(nil)), PkgPath: "other/pkg"},
+ field: StructField{Name: "", Type: TypeOf(S1{}), PkgPath: ""},
+ mustPanic: true,
+ },
+ {
+ field: StructField{Name: "S1", Anonymous: true, Type: TypeOf(S1{}), PkgPath: "other/pkg"},
+ mustPanic: true,
+ },
+ {
+ field: StructField{Name: "S1", Anonymous: true, Type: TypeOf((*S1)(nil)), PkgPath: "other/pkg"},
+ mustPanic: true,
+ },
+ {
+ field: StructField{Name: "s2", Anonymous: true, Type: TypeOf(s2{}), PkgPath: "other/pkg"},
mustPanic: true,
- exported: true,
},
{
- field: StructField{Name: "", Type: TypeOf(s2{}), PkgPath: "other/pkg"},
+ field: StructField{Name: "s2", Anonymous: true, Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"},
mustPanic: true,
- exported: false,
},
{
- field: StructField{Name: "", Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"},
+ field: StructField{Name: "s2", Type: TypeOf(int(0)), PkgPath: "other/pkg"},
+ mustPanic: true,
+ },
+ {
+ field: StructField{Name: "s2", Type: TypeOf(int(0)), PkgPath: "other/pkg"},
mustPanic: true,
- exported: false,
},
{
field: StructField{Name: "S", Type: TypeOf(S1{})},
@@ -4235,81 +4243,68 @@ func TestStructOfExportRules(t *testing.T) {
exported: true,
},
{
- field: StructField{Name: "S", Type: TypeOf((*S1)(nil))},
- mustPanic: false,
- exported: true,
+ field: StructField{Name: "S", Type: TypeOf((*S1)(nil))},
+ exported: true,
},
{
- field: StructField{Name: "S", Type: TypeOf(s2{})},
- mustPanic: false,
- exported: true,
+ field: StructField{Name: "S", Type: TypeOf(s2{})},
+ exported: true,
},
{
- field: StructField{Name: "S", Type: TypeOf((*s2)(nil))},
- mustPanic: false,
- exported: true,
+ field: StructField{Name: "S", Type: TypeOf((*s2)(nil))},
+ exported: true,
},
{
field: StructField{Name: "s", Type: TypeOf(S1{})},
mustPanic: true,
- exported: false,
},
{
field: StructField{Name: "s", Type: TypeOf((*S1)(nil))},
mustPanic: true,
- exported: false,
},
{
field: StructField{Name: "s", Type: TypeOf(s2{})},
mustPanic: true,
- exported: false,
},
{
field: StructField{Name: "s", Type: TypeOf((*s2)(nil))},
mustPanic: true,
- exported: false,
},
{
field: StructField{Name: "s", Type: TypeOf(S1{}), PkgPath: "other/pkg"},
mustPanic: true, // TODO(sbinet): creating a name with a package path
- exported: false,
},
{
field: StructField{Name: "s", Type: TypeOf((*S1)(nil)), PkgPath: "other/pkg"},
mustPanic: true, // TODO(sbinet): creating a name with a package path
- exported: false,
},
{
field: StructField{Name: "s", Type: TypeOf(s2{}), PkgPath: "other/pkg"},
mustPanic: true, // TODO(sbinet): creating a name with a package path
- exported: false,
},
{
field: StructField{Name: "s", Type: TypeOf((*s2)(nil)), PkgPath: "other/pkg"},
mustPanic: true, // TODO(sbinet): creating a name with a package path
- exported: false,
},
{
field: StructField{Name: "", Type: TypeOf(ΦType{})},
- mustPanic: false,
- exported: true,
+ mustPanic: true,
},
{
field: StructField{Name: "", Type: TypeOf(φType{})},
- mustPanic: false,
- exported: false,
+ mustPanic: true,
},
{
- field: StructField{Name: "Φ", Type: TypeOf(0)},
- mustPanic: false,
- exported: true,
+ field: StructField{Name: "Φ", Type: TypeOf(0)},
+ exported: true,
},
{
- field: StructField{Name: "φ", Type: TypeOf(0)},
- mustPanic: false,
- exported: false,
+ field: StructField{Name: "φ", Type: TypeOf(0)},
+ exported: false,
},
- } {
+ }
+
+ for i, test := range tests {
testPanic(i, test.mustPanic, func() {
typ := StructOf([]StructField{test.field})
if typ == nil {
@@ -4319,7 +4314,7 @@ func TestStructOfExportRules(t *testing.T) {
field := typ.Field(0)
n := field.Name
if n == "" {
- n = field.Type.Name()
+ panic("field.Name must not be empty")
}
exported := isExported(n)
if exported != test.exported {
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index 3ae0f182b3a..97b986a7bba 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -370,11 +370,19 @@ type sliceType struct {
// Struct field
type structField struct {
- name *string // nil for embedded fields
- pkgPath *string // nil for exported Names; otherwise import path
- typ *rtype // type of field
- tag *string // nil if no tag
- offset uintptr // byte offset of field within struct
+ name *string // name is always non-empty
+ pkgPath *string // nil for exported Names; otherwise import path
+ typ *rtype // type of field
+ tag *string // nil if no tag
+ offsetAnon uintptr // byte offset of field<<1 | isAnonymous
+}
+
+func (f *structField) offset() uintptr {
+ return f.offsetAnon >> 1
+}
+
+func (f *structField) anon() bool {
+ return f.offsetAnon&1 != 0
}
// structType represents a struct type.
@@ -880,23 +888,15 @@ func (t *structType) Field(i int) (f StructField) {
}
p := &t.fields[i]
f.Type = toType(p.typ)
- if p.name != nil {
- f.Name = *p.name
- } else {
- t := f.Type
- if t.Kind() == Ptr {
- t = t.Elem()
- }
- f.Name = t.Name()
- f.Anonymous = true
- }
+ f.Name = *p.name
+ f.Anonymous = p.anon()
if p.pkgPath != nil {
f.PkgPath = *p.pkgPath
}
if p.tag != nil {
f.Tag = StructTag(*p.tag)
}
- f.Offset = p.offset
+ f.Offset = p.offset()
// NOTE(rsc): This is the only allocation in the interface
// presented by a reflect.Type. It would be nice to avoid,
@@ -984,18 +984,15 @@ func (t *structType) FieldByNameFunc(match func(string) bool) (result StructFiel
for i := range t.fields {
f := &t.fields[i]
// Find name and type for field f.
- var fname string
+ fname := *f.name
var ntyp *rtype
- if f.name != nil {
- fname = *f.name
- } else {
+ if f.anon() {
// Anonymous field of type T or *T.
// Name taken from type.
ntyp = f.typ
if ntyp.Kind() == Ptr {
ntyp = ntyp.Elem().common()
}
- fname = ntyp.Name()
}
// Does it match?
@@ -1053,13 +1050,12 @@ func (t *structType) FieldByName(name string) (f StructField, present bool) {
if name != "" {
for i := range t.fields {
tf := &t.fields[i]
- if tf.name == nil {
- hasAnon = true
- continue
- }
if *tf.name == name {
return t.Field(i), true
}
+ if tf.anon() {
+ hasAnon = true
+ }
}
}
if !hasAnon {
@@ -1390,7 +1386,7 @@ func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
if cmpTags && tf.tag != vf.tag && (tf.tag == nil || vf.tag == nil || *tf.tag != *vf.tag) {
return false
}
- if tf.offset != vf.offset {
+ if tf.offsetAnon != vf.offsetAnon {
return false
}
}
@@ -1946,11 +1942,10 @@ func StructOf(fields []StructField) Type {
hasPtr = true
}
- name := ""
// Update string and hash
+ name := *f.name
hash = (hash << 1) + ft.hash
- if f.name != nil {
- name = *f.name
+ if !f.anon() {
repr = append(repr, (" " + name)...)
} else {
// Embedded field
@@ -2009,11 +2004,12 @@ func StructOf(fields []StructField) Type {
comparable = comparable && (ft.equalfn != nil)
hashable = hashable && (ft.hashfn != nil)
- f.offset = align(size, uintptr(ft.fieldAlign))
+ offset := align(size, uintptr(ft.fieldAlign))
if int8(ft.fieldAlign) > typalign {
typalign = int8(ft.fieldAlign)
}
- size = f.offset + ft.size
+ size = offset + ft.size
+ f.offsetAnon |= offset << 1
if ft.size == 0 {
lastzero = size
@@ -2148,7 +2144,7 @@ func StructOf(fields []StructField) Type {
typ.hashfn = func(p unsafe.Pointer, seed uintptr) uintptr {
o := seed
for _, ft := range typ.fields {
- pi := unsafe.Pointer(uintptr(p) + ft.offset)
+ pi := unsafe.Pointer(uintptr(p) + ft.offset())
o = ft.typ.hashfn(pi, o)
}
return o
@@ -2160,8 +2156,8 @@ func StructOf(fields []StructField) Type {
if comparable {
typ.equalfn = func(p, q unsafe.Pointer) bool {
for _, ft := range typ.fields {
- pi := unsafe.Pointer(uintptr(p) + ft.offset)
- qi := unsafe.Pointer(uintptr(q) + ft.offset)
+ pi := unsafe.Pointer(uintptr(p) + ft.offset())
+ qi := unsafe.Pointer(uintptr(q) + ft.offset())
if !ft.typ.equalfn(pi, qi) {
return false
}
@@ -2196,6 +2192,11 @@ func runtimeStructField(field StructField) structField {
}
}
+ offsetAnon := uintptr(0)
+ if field.Anonymous {
+ offsetAnon |= 1
+ }
+
var pkgPath *string
if field.PkgPath != "" {
s := field.PkgPath
@@ -2212,11 +2213,11 @@ func runtimeStructField(field StructField) structField {
}
return structField{
- name: name,
- pkgPath: pkgPath,
- typ: field.Type.common(),
- tag: tag,
- offset: 0,
+ name: name,
+ pkgPath: pkgPath,
+ typ: field.Type.common(),
+ tag: tag,
+ offsetAnon: offsetAnon,
}
}
@@ -2239,7 +2240,7 @@ func typeptrdata(t *rtype) uintptr {
}
}
f := st.fields[field]
- return f.offset + f.typ.ptrdata
+ return f.offset() + f.typ.ptrdata
default:
panic("reflect.typeptrdata: unexpected type, " + t.String())
@@ -2513,7 +2514,7 @@ func addTypeBits(bv *bitVector, offset uintptr, t *rtype) {
tt := (*structType)(unsafe.Pointer(t))
for i := range tt.fields {
f := &tt.fields[i]
- addTypeBits(bv, offset+f.offset, f.typ)
+ addTypeBits(bv, offset+f.offset(), f.typ)
}
}
}
diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go
index 1b4c5407e57..208bb2f4c01 100644
--- a/libgo/go/reflect/value.go
+++ b/libgo/go/reflect/value.go
@@ -625,7 +625,7 @@ func (v Value) Field(i int) Value {
fl := v.flag&(flagStickyRO|flagIndir|flagAddr) | flag(typ.Kind())
// Using an unexported field forces flagRO.
if field.pkgPath != nil {
- if field.name == nil {
+ if field.anon() {
fl |= flagEmbedRO
} else {
fl |= flagStickyRO
@@ -636,7 +636,7 @@ func (v Value) Field(i int) Value {
// In the former case, we want v.ptr + offset.
// In the latter case, we must have field.offset = 0,
// so v.ptr + field.offset is still okay.
- ptr := unsafe.Pointer(uintptr(v.ptr) + field.offset)
+ ptr := unsafe.Pointer(uintptr(v.ptr) + field.offset())
return Value{typ, ptr, fl}
}