mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile/internal/gc: make embedded unexported structs RO
gc will need to be rebuild. Package that assume f.PkgPath != nil means a field is unexported and must be ignored must be revised to check for f.PkgPath != nil && !f.Anonymous, so that they do try to walk into the embedded fields to look for exported fields contained within. Closes #12367, fixes #7363, fixes #11007, and fixes #7247. Change-Id: I16402ee21ccfede80f277f84b3995cf26e97433d Reviewed-on: https://go-review.googlesource.com/14085 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
34f04a675c
commit
afe9837b23
2 changed files with 192 additions and 1 deletions
|
|
@ -2776,14 +2776,27 @@ func TestSetBytes(t *testing.T) {
|
|||
type Private struct {
|
||||
x int
|
||||
y **int
|
||||
Z int
|
||||
}
|
||||
|
||||
func (p *Private) m() {
|
||||
}
|
||||
|
||||
type private struct {
|
||||
Z int
|
||||
z int
|
||||
S string
|
||||
A [1]Private
|
||||
T []Private
|
||||
}
|
||||
|
||||
func (p *private) P() {
|
||||
}
|
||||
|
||||
type Public struct {
|
||||
X int
|
||||
Y **int
|
||||
private
|
||||
}
|
||||
|
||||
func (p *Public) M() {
|
||||
|
|
@ -2791,17 +2804,30 @@ func (p *Public) M() {
|
|||
|
||||
func TestUnexported(t *testing.T) {
|
||||
var pub Public
|
||||
pub.S = "S"
|
||||
pub.T = pub.A[:]
|
||||
v := ValueOf(&pub)
|
||||
isValid(v.Elem().Field(0))
|
||||
isValid(v.Elem().Field(1))
|
||||
isValid(v.Elem().Field(2))
|
||||
isValid(v.Elem().FieldByName("X"))
|
||||
isValid(v.Elem().FieldByName("Y"))
|
||||
isValid(v.Elem().FieldByName("Z"))
|
||||
isValid(v.Type().Method(0).Func)
|
||||
m, _ := v.Type().MethodByName("M")
|
||||
isValid(m.Func)
|
||||
m, _ = v.Type().MethodByName("P")
|
||||
isValid(m.Func)
|
||||
isNonNil(v.Elem().Field(0).Interface())
|
||||
isNonNil(v.Elem().Field(1).Interface())
|
||||
isNonNil(v.Elem().Field(2).Field(2).Index(0))
|
||||
isNonNil(v.Elem().FieldByName("X").Interface())
|
||||
isNonNil(v.Elem().FieldByName("Y").Interface())
|
||||
isNonNil(v.Elem().FieldByName("Z").Interface())
|
||||
isNonNil(v.Elem().FieldByName("S").Index(0).Interface())
|
||||
isNonNil(v.Type().Method(0).Func.Interface())
|
||||
m, _ = v.Type().MethodByName("P")
|
||||
isNonNil(m.Func.Interface())
|
||||
|
||||
var priv Private
|
||||
v = ValueOf(&priv)
|
||||
|
|
@ -2817,6 +2843,170 @@ func TestUnexported(t *testing.T) {
|
|||
shouldPanic(func() { v.Type().Method(0).Func.Interface() })
|
||||
}
|
||||
|
||||
func TestSetPanic(t *testing.T) {
|
||||
ok := func(f func()) { f() }
|
||||
bad := shouldPanic
|
||||
clear := func(v Value) { v.Set(Zero(v.Type())) }
|
||||
|
||||
type t0 struct {
|
||||
W int
|
||||
}
|
||||
|
||||
type t1 struct {
|
||||
Y int
|
||||
t0
|
||||
}
|
||||
|
||||
type T2 struct {
|
||||
Z int
|
||||
namedT0 t0
|
||||
}
|
||||
|
||||
type T struct {
|
||||
X int
|
||||
t1
|
||||
T2
|
||||
NamedT1 t1
|
||||
NamedT2 T2
|
||||
namedT1 t1
|
||||
namedT2 T2
|
||||
}
|
||||
|
||||
// not addressable
|
||||
v := ValueOf(T{})
|
||||
bad(func() { clear(v.Field(0)) }) // .X
|
||||
bad(func() { clear(v.Field(1)) }) // .t1
|
||||
bad(func() { clear(v.Field(1).Field(0)) }) // .t1.Y
|
||||
bad(func() { clear(v.Field(1).Field(1)) }) // .t1.t0
|
||||
bad(func() { clear(v.Field(1).Field(1).Field(0)) }) // .t1.t0.W
|
||||
bad(func() { clear(v.Field(2)) }) // .T2
|
||||
bad(func() { clear(v.Field(2).Field(0)) }) // .T2.Z
|
||||
bad(func() { clear(v.Field(2).Field(1)) }) // .T2.namedT0
|
||||
bad(func() { clear(v.Field(2).Field(1).Field(0)) }) // .T2.namedT0.W
|
||||
bad(func() { clear(v.Field(3)) }) // .NamedT1
|
||||
bad(func() { clear(v.Field(3).Field(0)) }) // .NamedT1.Y
|
||||
bad(func() { clear(v.Field(3).Field(1)) }) // .NamedT1.t0
|
||||
bad(func() { clear(v.Field(3).Field(1).Field(0)) }) // .NamedT1.t0.W
|
||||
bad(func() { clear(v.Field(4)) }) // .NamedT2
|
||||
bad(func() { clear(v.Field(4).Field(0)) }) // .NamedT2.Z
|
||||
bad(func() { clear(v.Field(4).Field(1)) }) // .NamedT2.namedT0
|
||||
bad(func() { clear(v.Field(4).Field(1).Field(0)) }) // .NamedT2.namedT0.W
|
||||
bad(func() { clear(v.Field(5)) }) // .namedT1
|
||||
bad(func() { clear(v.Field(5).Field(0)) }) // .namedT1.Y
|
||||
bad(func() { clear(v.Field(5).Field(1)) }) // .namedT1.t0
|
||||
bad(func() { clear(v.Field(5).Field(1).Field(0)) }) // .namedT1.t0.W
|
||||
bad(func() { clear(v.Field(6)) }) // .namedT2
|
||||
bad(func() { clear(v.Field(6).Field(0)) }) // .namedT2.Z
|
||||
bad(func() { clear(v.Field(6).Field(1)) }) // .namedT2.namedT0
|
||||
bad(func() { clear(v.Field(6).Field(1).Field(0)) }) // .namedT2.namedT0.W
|
||||
|
||||
// addressable
|
||||
v = ValueOf(&T{}).Elem()
|
||||
ok(func() { clear(v.Field(0)) }) // .X
|
||||
bad(func() { clear(v.Field(1)) }) // .t1
|
||||
ok(func() { clear(v.Field(1).Field(0)) }) // .t1.Y
|
||||
bad(func() { clear(v.Field(1).Field(1)) }) // .t1.t0
|
||||
ok(func() { clear(v.Field(1).Field(1).Field(0)) }) // .t1.t0.W
|
||||
ok(func() { clear(v.Field(2)) }) // .T2
|
||||
ok(func() { clear(v.Field(2).Field(0)) }) // .T2.Z
|
||||
bad(func() { clear(v.Field(2).Field(1)) }) // .T2.namedT0
|
||||
bad(func() { clear(v.Field(2).Field(1).Field(0)) }) // .T2.namedT0.W
|
||||
ok(func() { clear(v.Field(3)) }) // .NamedT1
|
||||
ok(func() { clear(v.Field(3).Field(0)) }) // .NamedT1.Y
|
||||
bad(func() { clear(v.Field(3).Field(1)) }) // .NamedT1.t0
|
||||
ok(func() { clear(v.Field(3).Field(1).Field(0)) }) // .NamedT1.t0.W
|
||||
ok(func() { clear(v.Field(4)) }) // .NamedT2
|
||||
ok(func() { clear(v.Field(4).Field(0)) }) // .NamedT2.Z
|
||||
bad(func() { clear(v.Field(4).Field(1)) }) // .NamedT2.namedT0
|
||||
bad(func() { clear(v.Field(4).Field(1).Field(0)) }) // .NamedT2.namedT0.W
|
||||
bad(func() { clear(v.Field(5)) }) // .namedT1
|
||||
bad(func() { clear(v.Field(5).Field(0)) }) // .namedT1.Y
|
||||
bad(func() { clear(v.Field(5).Field(1)) }) // .namedT1.t0
|
||||
bad(func() { clear(v.Field(5).Field(1).Field(0)) }) // .namedT1.t0.W
|
||||
bad(func() { clear(v.Field(6)) }) // .namedT2
|
||||
bad(func() { clear(v.Field(6).Field(0)) }) // .namedT2.Z
|
||||
bad(func() { clear(v.Field(6).Field(1)) }) // .namedT2.namedT0
|
||||
bad(func() { clear(v.Field(6).Field(1).Field(0)) }) // .namedT2.namedT0.W
|
||||
}
|
||||
|
||||
type timp int
|
||||
|
||||
func (t timp) W() {}
|
||||
func (t timp) Y() {}
|
||||
func (t timp) w() {}
|
||||
func (t timp) y() {}
|
||||
|
||||
func TestCallPanic(t *testing.T) {
|
||||
type t0 interface {
|
||||
W()
|
||||
w()
|
||||
}
|
||||
type T1 interface {
|
||||
Y()
|
||||
y()
|
||||
}
|
||||
type T2 struct {
|
||||
T1
|
||||
t0
|
||||
}
|
||||
type T struct {
|
||||
t0 // 0
|
||||
T1 // 1
|
||||
|
||||
NamedT0 t0 // 2
|
||||
NamedT1 T1 // 3
|
||||
NamedT2 T2 // 4
|
||||
|
||||
namedT0 t0 // 5
|
||||
namedT1 T1 // 6
|
||||
namedT2 T2 // 7
|
||||
}
|
||||
ok := func(f func()) { f() }
|
||||
bad := shouldPanic
|
||||
call := func(v Value) { v.Call(nil) }
|
||||
|
||||
i := timp(0)
|
||||
v := ValueOf(T{i, i, i, i, T2{i, i}, i, i, T2{i, i}})
|
||||
ok(func() { call(v.Field(0).Method(0)) }) // .t0.W
|
||||
ok(func() { call(v.Field(0).Elem().Method(0)) }) // .t0.W
|
||||
bad(func() { call(v.Field(0).Method(1)) }) // .t0.w
|
||||
bad(func() { call(v.Field(0).Elem().Method(2)) }) // .t0.w
|
||||
ok(func() { call(v.Field(1).Method(0)) }) // .T1.Y
|
||||
ok(func() { call(v.Field(1).Elem().Method(0)) }) // .T1.Y
|
||||
bad(func() { call(v.Field(1).Method(1)) }) // .T1.y
|
||||
bad(func() { call(v.Field(1).Elem().Method(2)) }) // .T1.y
|
||||
|
||||
ok(func() { call(v.Field(2).Method(0)) }) // .NamedT0.W
|
||||
ok(func() { call(v.Field(2).Elem().Method(0)) }) // .NamedT0.W
|
||||
bad(func() { call(v.Field(2).Method(1)) }) // .NamedT0.w
|
||||
bad(func() { call(v.Field(2).Elem().Method(2)) }) // .NamedT0.w
|
||||
|
||||
ok(func() { call(v.Field(3).Method(0)) }) // .NamedT1.Y
|
||||
ok(func() { call(v.Field(3).Elem().Method(0)) }) // .NamedT1.Y
|
||||
bad(func() { call(v.Field(3).Method(1)) }) // .NamedT1.y
|
||||
bad(func() { call(v.Field(3).Elem().Method(3)) }) // .NamedT1.y
|
||||
|
||||
ok(func() { call(v.Field(4).Field(0).Method(0)) }) // .NamedT2.T1.Y
|
||||
ok(func() { call(v.Field(4).Field(0).Elem().Method(0)) }) // .NamedT2.T1.W
|
||||
ok(func() { call(v.Field(4).Field(1).Method(0)) }) // .NamedT2.t0.W
|
||||
ok(func() { call(v.Field(4).Field(1).Elem().Method(0)) }) // .NamedT2.t0.W
|
||||
|
||||
bad(func() { call(v.Field(5).Method(0)) }) // .namedT0.W
|
||||
bad(func() { call(v.Field(5).Elem().Method(0)) }) // .namedT0.W
|
||||
bad(func() { call(v.Field(5).Method(1)) }) // .namedT0.w
|
||||
bad(func() { call(v.Field(5).Elem().Method(2)) }) // .namedT0.w
|
||||
|
||||
bad(func() { call(v.Field(6).Method(0)) }) // .namedT1.Y
|
||||
bad(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.Y
|
||||
bad(func() { call(v.Field(6).Method(0)) }) // .namedT1.y
|
||||
bad(func() { call(v.Field(6).Elem().Method(0)) }) // .namedT1.y
|
||||
|
||||
bad(func() { call(v.Field(7).Field(0).Method(0)) }) // .namedT2.T1.Y
|
||||
bad(func() { call(v.Field(7).Field(0).Elem().Method(0)) }) // .namedT2.T1.W
|
||||
bad(func() { call(v.Field(7).Field(1).Method(0)) }) // .namedT2.t0.W
|
||||
bad(func() { call(v.Field(7).Field(1).Elem().Method(0)) }) // .namedT2.t0.W
|
||||
}
|
||||
|
||||
func shouldPanic(f func()) {
|
||||
defer func() {
|
||||
if recover() == nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue