pkg/proc: fix can not call method of an embedded filed directly (#1691)

`func (v *Variable) findMethod` should support for searching methods of an
embedded filed.

Fixes #1688
This commit is contained in:
chainhelen
2019-09-26 09:37:23 -05:00
committed by Derek Parker
parent 4905cff3c8
commit a82e6d6987
3 changed files with 45 additions and 1 deletions

View File

@ -121,6 +121,19 @@ func noreturncall(n int) {
return return
} }
type Base struct{
y int
}
type Derived struct {
x int
Base
}
func (b *Base) Method() int {
return b.y
}
func main() { func main() {
one, two := 1, 2 one, two := 1, 2
intslice := []int{1, 2, 3} intslice := []int{1, 2, 3}
@ -142,9 +155,13 @@ func main() {
fn2ptrmeth := pa.PRcvr fn2ptrmeth := pa.PRcvr
var fn2nil func() var fn2nil func()
d := &Derived{3, Base{4}}
runtime.Breakpoint() runtime.Breakpoint()
call1(one, two) call1(one, two)
fn2clos(2) fn2clos(2)
strings.LastIndexByte(stringslice[1], 'w') strings.LastIndexByte(stringslice[1], 'w')
fmt.Println(one, two, zero, callpanic, callstacktrace, stringsJoin, intslice, stringslice, comma, a.VRcvr, a.PRcvr, pa, vable_a, vable_pa, pable_pa, fn2clos, fn2glob, fn2valmeth, fn2ptrmeth, fn2nil, ga, escapeArg, a2, square, intcallpanic, onetwothree, curriedAdd, getAStruct, getAStructPtr, getVRcvrableFromAStruct, getPRcvrableFromAStructPtr, getVRcvrableFromAStructPtr, pa2, noreturncall, str) d.Method()
d.Base.Method()
fmt.Println(one, two, zero, callpanic, callstacktrace, stringsJoin, intslice, stringslice, comma, a.VRcvr, a.PRcvr, pa, vable_a, vable_pa, pable_pa, fn2clos, fn2glob, fn2valmeth, fn2ptrmeth, fn2nil, ga, escapeArg, a2, square, intcallpanic, onetwothree, curriedAdd, getAStruct, getAStructPtr, getVRcvrableFromAStruct, getPRcvrableFromAStructPtr, getVRcvrableFromAStructPtr, pa2, noreturncall, str, d)
} }

View File

@ -1847,7 +1847,32 @@ func (v *Variable) findMethod(mname string) (*Variable, error) {
} }
return r, nil return r, nil
} }
return v.tryFindMethodInEmbeddedFields(mname)
}
func (v *Variable) tryFindMethodInEmbeddedFields(mname string) (*Variable, error) {
structVar := v.maybeDereference()
structVar.Name = v.Name
if structVar.Unreadable != nil {
return structVar, nil
}
switch t := structVar.RealType.(type) {
case *godwarf.StructType:
for _, field := range t.Field {
if field.Embedded {
// Recursively check for promoted fields on the embedded field
embeddedVar, err := structVar.toField(field)
if err != nil {
return nil, err
}
if embeddedMethod, err := embeddedVar.findMethod(mname); err != nil {
return nil, err
} else if embeddedMethod != nil {
return embeddedMethod, nil
}
}
}
}
return nil, nil return nil, nil
} }

View File

@ -1181,6 +1181,8 @@ func TestCallFunction(t *testing.T) {
{`strings.Join(stringslice, ",")`, []string{`:string:"one,two,three"`}, nil}, {`strings.Join(stringslice, ",")`, []string{`:string:"one,two,three"`}, nil},
{`strings.LastIndexByte(stringslice[1], 'w')`, []string{":int:1"}, nil}, {`strings.LastIndexByte(stringslice[1], 'w')`, []string{":int:1"}, nil},
{`strings.LastIndexByte(stringslice[1], 'o')`, []string{":int:2"}, nil}, {`strings.LastIndexByte(stringslice[1], 'o')`, []string{":int:2"}, nil},
{`d.Base.Method()`, []string{ `:int:4` }, nil },
{`d.Method()`, []string{ `:int:4` }, nil },
} }
var testcases113 = []testCaseCallFunction{ var testcases113 = []testCaseCallFunction{