proc: allow accessing captured variable as if they were struct fields (#3866)
If 'a' is a captured variable in a function pointer called 'f' let 'f.a' evaluate to its value.
This commit is contained in:
parent
9af09688ea
commit
7b9a379e59
@ -5479,8 +5479,8 @@ func TestReadClosure(t *testing.T) {
|
||||
accV := evalVariable(p, t, "acc")
|
||||
t.Log(api.ConvertVar(accV).MultilineString("", ""))
|
||||
if len(accV.Children) != 2 {
|
||||
t.Error("wrong number of children")
|
||||
} else {
|
||||
t.Fatal("wrong number of children")
|
||||
}
|
||||
found := 0
|
||||
for j := range accV.Children {
|
||||
v := &accV.Children[j]
|
||||
@ -5500,7 +5500,9 @@ func TestReadClosure(t *testing.T) {
|
||||
if found != 2 {
|
||||
t.Error("wrong captured variables")
|
||||
}
|
||||
}
|
||||
|
||||
assertVariable(t, evalVariable(p, t, "acc.scale"), varTest{name: "acc.scale", preserveName: true, value: "3", varType: "int"})
|
||||
assertVariable(t, evalVariable(p, t, "acc.a"), varTest{name: "acc.a", preserveName: true, value: fmt.Sprintf("%d", avalues[i]), varType: "int"})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1101,6 +1101,7 @@ func (v *Variable) structMember(memberName string) (*Variable, error) {
|
||||
}
|
||||
return nil, fmt.Errorf("%s has no member %s", vname, memberName)
|
||||
}
|
||||
closure := false
|
||||
switch v.Kind {
|
||||
case reflect.Chan:
|
||||
v = v.clone()
|
||||
@ -1110,6 +1111,19 @@ func (v *Variable) structMember(memberName string) (*Variable, error) {
|
||||
if len(v.Children) > 0 {
|
||||
v = &v.Children[0]
|
||||
}
|
||||
case reflect.Func:
|
||||
v.loadFunctionPtr(0, LoadConfig{MaxVariableRecurse: -1})
|
||||
if v.Unreadable != nil {
|
||||
return nil, v.Unreadable
|
||||
}
|
||||
if v.closureAddr != 0 {
|
||||
fn := v.bi.PCToFunc(v.Base)
|
||||
if fn != nil {
|
||||
cst := fn.extra(v.bi).closureStructType
|
||||
v = v.newVariable(v.Name, v.closureAddr, cst, v.mem)
|
||||
closure = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
queue := []*Variable{v}
|
||||
@ -1136,6 +1150,13 @@ func (v *Variable) structMember(memberName string) (*Variable, error) {
|
||||
if field.Name == memberName {
|
||||
return structVar.toField(field)
|
||||
}
|
||||
if len(queue) == 0 && field.Name == "&"+memberName && closure {
|
||||
f, err := structVar.toField(field)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return f.maybeDereference(), nil
|
||||
}
|
||||
isEmbeddedStructMember :=
|
||||
field.Embedded ||
|
||||
(field.Type.Common().Name == field.Name) ||
|
||||
|
Loading…
Reference in New Issue
Block a user