mirror of https://github.com/golang/go.git
go/callgraph/vta: not panic on the SliceToArrayPointer instruction
No interesting type flows so the change to vta itself is to not reject the instruction. Updates golang/go#47326 Change-Id: Ifd11a7ef854afaee3978796f3113ca3254301d19 Reviewed-on: https://go-review.googlesource.com/c/tools/+/338849 Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com> Run-TryBot: Zvonimir Pavlinovic <zpavlinovic@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Go Bot <gobot@golang.org> Trust: Zvonimir Pavlinovic <zpavlinovic@google.com> Trust: Roland Shoemaker <roland@golang.org>
This commit is contained in:
parent
f68a40bc0d
commit
f367f012d5
|
|
@ -72,7 +72,7 @@ func (mv mapValue) String() string {
|
|||
return fmt.Sprintf("MapValue(%v)", mv.Type())
|
||||
}
|
||||
|
||||
// sliceElem node for VTA, modeling reachable slice element types.
|
||||
// sliceElem node for VTA, modeling reachable slice and array element types.
|
||||
type sliceElem struct {
|
||||
typ types.Type
|
||||
}
|
||||
|
|
@ -346,8 +346,11 @@ func (b *builder) instr(instr ssa.Instruction) {
|
|||
b.rtrn(i)
|
||||
case *ssa.MakeChan, *ssa.MakeMap, *ssa.MakeSlice, *ssa.BinOp,
|
||||
*ssa.Alloc, *ssa.DebugRef, *ssa.Convert, *ssa.Jump, *ssa.If,
|
||||
*ssa.Slice, *ssa.Range, *ssa.RunDefers:
|
||||
*ssa.Slice, *ssa.SliceToArrayPointer, *ssa.Range, *ssa.RunDefers:
|
||||
// No interesting flow here.
|
||||
// Notes on individual instructions:
|
||||
// SliceToArrayPointer: t1 = slice to array pointer *[4]T <- []T (t0)
|
||||
// No interesting flow as sliceArrayElem(t1) == sliceArrayElem(t0).
|
||||
return
|
||||
default:
|
||||
panic(fmt.Sprintf("unsupported instruction %v\n", instr))
|
||||
|
|
|
|||
|
|
@ -5,11 +5,14 @@
|
|||
package vta
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"io/ioutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/go/callgraph"
|
||||
"golang.org/x/tools/go/ssa/ssautil"
|
||||
|
||||
"golang.org/x/tools/go/loader"
|
||||
|
|
@ -81,3 +84,31 @@ func funcName(f *ssa.Function) string {
|
|||
tp := recv.Type().String()
|
||||
return tp[strings.LastIndex(tp, ".")+1:] + "." + f.Name()
|
||||
}
|
||||
|
||||
// callGraphStr stringifes `g` into a list of strings where
|
||||
// each entry is of the form
|
||||
// f: cs1 -> f1, f2, ...; ...; csw -> fx, fy, ...
|
||||
// f is a function, cs1, ..., csw are call sites in f, and
|
||||
// f1, f2, ..., fx, fy, ... are the resolved callees.
|
||||
func callGraphStr(g *callgraph.Graph) []string {
|
||||
var gs []string
|
||||
for f, n := range g.Nodes {
|
||||
c := make(map[string][]string)
|
||||
for _, edge := range n.Out {
|
||||
cs := edge.Site.String()
|
||||
c[cs] = append(c[cs], funcName(edge.Callee.Func))
|
||||
}
|
||||
|
||||
var cs []string
|
||||
for site, fs := range c {
|
||||
sort.Strings(fs)
|
||||
entry := fmt.Sprintf("%v -> %v", site, strings.Join(fs, ", "))
|
||||
cs = append(cs, entry)
|
||||
}
|
||||
|
||||
sort.Strings(cs)
|
||||
entry := fmt.Sprintf("%v: %v", funcName(f), strings.Join(cs, "; "))
|
||||
gs = append(gs, entry)
|
||||
}
|
||||
return gs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// go:build ignore
|
||||
|
||||
package testdata
|
||||
|
||||
type J interface {
|
||||
Foo()
|
||||
Bar()
|
||||
}
|
||||
|
||||
type B struct {
|
||||
p int
|
||||
}
|
||||
|
||||
func (b B) Foo() {}
|
||||
func (b B) Bar() {}
|
||||
|
||||
func Wobble(b *B, s []J) {
|
||||
x := (*[3]J)(s)
|
||||
x[1] = b
|
||||
|
||||
a := &s[2]
|
||||
(*a).Bar()
|
||||
}
|
||||
|
||||
// Relevant SSA:
|
||||
// func Wobble(b *B, s []J):
|
||||
// t0 = slice to array pointer *[3]J <- []J (s) *[3]J
|
||||
// t1 = &t0[1:int] *J
|
||||
// t2 = make J <- *B (b) J
|
||||
// *t1 = t2
|
||||
// t3 = &s[2:int] *J
|
||||
// ...
|
||||
|
||||
// WANT:
|
||||
// Local(t1) -> Slice([]testdata.J)
|
||||
// Slice([]testdata.J) -> Local(t1), Local(t3)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.17
|
||||
// +build go1.17
|
||||
|
||||
package vta
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/callgraph/cha"
|
||||
"golang.org/x/tools/go/ssa/ssautil"
|
||||
)
|
||||
|
||||
func TestVTACallGraphGo117(t *testing.T) {
|
||||
file := "testdata/go117.go"
|
||||
prog, want, err := testProg(file)
|
||||
if err != nil {
|
||||
t.Fatalf("couldn't load test file '%s': %s", file, err)
|
||||
}
|
||||
if len(want) == 0 {
|
||||
t.Fatalf("couldn't find want in `%s`", file)
|
||||
}
|
||||
|
||||
g, _ := typePropGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))
|
||||
if gs := vtaGraphStr(g); !subGraph(want, gs) {
|
||||
t.Errorf("`%s`: want superset of %v;\n got %v", file, want, gs)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,46 +5,13 @@
|
|||
package vta
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/tools/go/callgraph"
|
||||
"golang.org/x/tools/go/callgraph/cha"
|
||||
"golang.org/x/tools/go/ssa"
|
||||
|
||||
"golang.org/x/tools/go/ssa/ssautil"
|
||||
)
|
||||
|
||||
// callGraphStr stringifes `g` into a list of strings where
|
||||
// each entry is of the form
|
||||
// f: cs1 -> f1, f2, ...; ...; csw -> fx, fy, ...
|
||||
// f is a function, cs1, ..., csw are call sites in f, and
|
||||
// f1, f2, ..., fx, fy, ... are the resolved callees.
|
||||
func callGraphStr(g *callgraph.Graph) []string {
|
||||
var gs []string
|
||||
for f, n := range g.Nodes {
|
||||
c := make(map[string][]string)
|
||||
for _, edge := range n.Out {
|
||||
cs := edge.Site.String()
|
||||
c[cs] = append(c[cs], funcName(edge.Callee.Func))
|
||||
}
|
||||
|
||||
var cs []string
|
||||
for site, fs := range c {
|
||||
sort.Strings(fs)
|
||||
entry := fmt.Sprintf("%v -> %v", site, strings.Join(fs, ", "))
|
||||
cs = append(cs, entry)
|
||||
}
|
||||
|
||||
sort.Strings(cs)
|
||||
entry := fmt.Sprintf("%v: %v", funcName(f), strings.Join(cs, "; "))
|
||||
gs = append(gs, entry)
|
||||
}
|
||||
return gs
|
||||
}
|
||||
|
||||
func TestVTACallGraph(t *testing.T) {
|
||||
for _, file := range []string{
|
||||
"testdata/callgraph_static.go",
|
||||
|
|
|
|||
Loading…
Reference in New Issue