mirror of https://github.com/golang/go.git
go/callgraph/vta: avoid panic on missing function definitions
For golang/go#50670 Change-Id: I86d4aee70584cf255f0972e56726b29555120e6d Reviewed-on: https://go-review.googlesource.com/c/tools/+/380795 Reviewed-by: Guodong Li <guodongli@google.com> Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Trust: Michael Knyszek <mknyszek@google.com> Reviewed-by: Tim King <taking@google.com>
This commit is contained in:
parent
845bb90a1d
commit
0f0bbfd77b
|
|
@ -573,6 +573,13 @@ func (b *builder) call(c ssa.CallInstruction) {
|
|||
}
|
||||
|
||||
func addArgumentFlows(b *builder, c ssa.CallInstruction, f *ssa.Function) {
|
||||
// When f has no paremeters (including receiver), there is no type
|
||||
// flow here. Also, f's body and parameters might be missing, such
|
||||
// as when vta is used within the golang.org/x/tools/go/analysis
|
||||
// framework (see github.com/golang/go/issues/50670).
|
||||
if len(f.Params) == 0 {
|
||||
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].
|
||||
|
|
@ -585,6 +592,14 @@ func addArgumentFlows(b *builder, c ssa.CallInstruction, f *ssa.Function) {
|
|||
offset = 1
|
||||
}
|
||||
for i, v := range cc.Args {
|
||||
// Parameters of f might not be available, as in the case
|
||||
// when vta is used within the golang.org/x/tools/go/analysis
|
||||
// framework (see github.com/golang/go/issues/50670).
|
||||
//
|
||||
// TODO: investigate other cases of missing body and parameters
|
||||
if len(f.Params) <= i+offset {
|
||||
return
|
||||
}
|
||||
b.addInFlowAliasEdges(b.nodeFromVal(f.Params[i+offset]), b.nodeFromVal(v))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package d
|
||||
|
||||
func D(i int) int {
|
||||
return i + 1
|
||||
}
|
||||
|
||||
type Data struct {
|
||||
V int
|
||||
}
|
||||
|
||||
func (d Data) Do() int {
|
||||
return d.V - 1
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package t
|
||||
|
||||
import "d"
|
||||
|
||||
func t(i int) int {
|
||||
data := d.Data{V: i}
|
||||
return d.D(i) + data.Do()
|
||||
}
|
||||
|
|
@ -7,6 +7,9 @@ package vta
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/analysistest"
|
||||
"golang.org/x/tools/go/analysis/passes/buildssa"
|
||||
"golang.org/x/tools/go/callgraph/cha"
|
||||
"golang.org/x/tools/go/ssa"
|
||||
"golang.org/x/tools/go/ssa/ssautil"
|
||||
|
|
@ -76,3 +79,35 @@ func TestVTAProgVsFuncSet(t *testing.T) {
|
|||
t.Errorf("pruned callgraph %v should contain %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestVTAPanicMissingDefinitions tests if VTA gracefully handles the case
|
||||
// where VTA panics when a definition of a function or method is not
|
||||
// available, which can happen when using analysis package. A successful
|
||||
// test simply does not panic.
|
||||
func TestVTAPanicMissingDefinitions(t *testing.T) {
|
||||
run := func(pass *analysis.Pass) (interface{}, error) {
|
||||
s := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA)
|
||||
CallGraph(ssautil.AllFunctions(s.Pkg.Prog), cha.CallGraph(s.Pkg.Prog))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
analyzer := &analysis.Analyzer{
|
||||
Name: "test",
|
||||
Doc: "test",
|
||||
Run: run,
|
||||
Requires: []*analysis.Analyzer{
|
||||
buildssa.Analyzer,
|
||||
},
|
||||
}
|
||||
|
||||
testdata := analysistest.TestData()
|
||||
res := analysistest.Run(t, testdata, analyzer, "t", "d")
|
||||
if len(res) != 2 {
|
||||
t.Errorf("want analysis results for 2 packages; got %v", len(res))
|
||||
}
|
||||
for _, r := range res {
|
||||
if r.Err != nil {
|
||||
t.Errorf("want no error for package %v; got %v", r.Pass.Pkg.Path(), r.Err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue