go/callgraph/vta: remove interprocedural flows for receiver objects

Suppose a call i.Foo(j) and suppose that the initial call graph resolves
this call to just a.Foo(x). Here, i is an interface and a is concrete
type. VTA then creates flows between j and x. However, it also tries to
create flows between i and a.

The latter flows are not needed. The flow from i to a will not be
registered in the type flow graph as it does not make sense. The flow
from a to i would bake in the information from the initial call graph
which would defy the purpose of VTA.

Note that the flow a -> i doesn't occur in practice as that flow is only
created when a and i can alias.

Change-Id: Ia4087651c72a14b94d83d07bb5e6d77603842362
Reviewed-on: https://go-review.googlesource.com/c/tools/+/416517
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Tim King <taking@google.com>
This commit is contained in:
Zvonimir Pavlinovic 2022-07-08 12:55:50 -07:00
parent 6e6f3131ec
commit 7c06b01db6
1 changed files with 5 additions and 5 deletions

View File

@ -586,14 +586,14 @@ func addArgumentFlows(b *builder, c ssa.CallInstruction, f *ssa.Function) {
return
}
cc := c.Common()
// When c is an unresolved method call (cc.Method != nil), cc.Value contains
// the receiver object rather than cc.Args[0].
if cc.Method != nil {
b.addInFlowAliasEdges(b.nodeFromVal(f.Params[0]), b.nodeFromVal(cc.Value))
}
offset := 0
if cc.Method != nil {
// We don't add interprocedural flows for receiver objects.
// At a call site, the receiver object is interface while the
// callee object is concrete. The flow from interface to
// concrete type does not make sense. The flow other way around
// would bake in information from the initial call graph.
offset = 1
}
for i, v := range cc.Args {