oracle: handle implicit selections in callees
The types only optimization for callees looked at the type of the receiver to figure out if it was a dynamic call. If the selection involves any implicit selections, we cannot be sure that this type is the one that will actually receive the call. Fix by working backwards from function signature to find the true receiver Change-Id: If79e3de7af33480e37bcf1081abe44bb04914da4 Reviewed-on: https://go-review.googlesource.com/18563 Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
parent
5a2875abe7
commit
ae18226edd
|
@ -92,12 +92,17 @@ func callees(q *Query) error {
|
|||
return nil
|
||||
}
|
||||
} else if sel.Kind() == types.MethodVal {
|
||||
recvtype := sel.Recv()
|
||||
// Inspect the receiver type of the selected method.
|
||||
// If it is concrete, the call is statically dispatched.
|
||||
// (Due to implicit field selections, it is not enough to look
|
||||
// at sel.Recv(), the type of the actual receiver expression.)
|
||||
method := sel.Obj().(*types.Func)
|
||||
recvtype := method.Type().(*types.Signature).Recv().Type()
|
||||
if !types.IsInterface(recvtype) {
|
||||
// static method call
|
||||
q.result = &calleesTypesResult{
|
||||
site: e,
|
||||
callee: sel.Obj().(*types.Func),
|
||||
callee: method,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -92,12 +92,17 @@ func callees(q *Query) error {
|
|||
return nil
|
||||
}
|
||||
} else if sel.Kind() == types.MethodVal {
|
||||
recvtype := sel.Recv()
|
||||
// Inspect the receiver type of the selected method.
|
||||
// If it is concrete, the call is statically dispatched.
|
||||
// (Due to implicit field selections, it is not enough to look
|
||||
// at sel.Recv(), the type of the actual receiver expression.)
|
||||
method := sel.Obj().(*types.Func)
|
||||
recvtype := method.Type().(*types.Signature).Recv().Type()
|
||||
if !types.IsInterface(recvtype) {
|
||||
// static method call
|
||||
q.result = &calleesTypesResult{
|
||||
site: e,
|
||||
callee: sel.Obj().(*types.Func),
|
||||
callee: method,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -83,6 +83,9 @@ func main() {
|
|||
fmt.Println() // @callees callees-qualified-call "Println"
|
||||
m := new(method)
|
||||
m.f() // @callees callees-static-method-call "f"
|
||||
g := new(embeddedIface)
|
||||
g.iface = m
|
||||
g.f() // @callees callees-implicit-selection-method-call "f"
|
||||
}
|
||||
|
||||
type myint int
|
||||
|
@ -96,6 +99,14 @@ type method int
|
|||
func (method) f() {
|
||||
}
|
||||
|
||||
type embeddedIface struct {
|
||||
iface
|
||||
}
|
||||
|
||||
type iface interface {
|
||||
f()
|
||||
}
|
||||
|
||||
var dynamic = func() {}
|
||||
|
||||
func deadcode() {
|
||||
|
|
|
@ -96,6 +96,10 @@ this static function call dispatches to:
|
|||
this static function call dispatches to:
|
||||
(main.method).f
|
||||
|
||||
-------- @callees callees-implicit-selection-method-call --------
|
||||
this dynamic method call dispatches to:
|
||||
(main.method).f
|
||||
|
||||
-------- @callers callers-not-a-wrapper --------
|
||||
(main.myint).f is called from these 1 sites:
|
||||
dynamic method call from main.main
|
||||
|
|
Loading…
Reference in New Issue