mirror of
https://github.com/golang/go
synced 2024-11-18 21:24:44 -07:00
go/ssa: convert the objlookup tests to the new marker syntax
Change-Id: I5df3a3cc3d3ab236a6ad964914393a2ccb29803b Reviewed-on: https://go-review.googlesource.com/c/145637 Run-TryBot: Ian Cottrell <iancottrell@google.com> Run-TryBot: Michael Matloob <matloob@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
parent
7529026f5b
commit
c779628d65
@ -13,8 +13,8 @@ import (
|
|||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -32,10 +32,14 @@ func TestObjValueLookup(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
conf := loader.Config{ParserMode: parser.ParseComments}
|
conf := loader.Config{ParserMode: parser.ParseComments}
|
||||||
f, err := conf.ParseFile("testdata/objlookup.go", nil)
|
src, err := ioutil.ReadFile("testdata/objlookup.go")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Fatal(err)
|
||||||
return
|
}
|
||||||
|
readFile := func(filename string) ([]byte, error) { return src, nil }
|
||||||
|
f, err := conf.ParseFile("testdata/objlookup.go", src)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
conf.CreateFromFiles("main", f)
|
conf.CreateFromFiles("main", f)
|
||||||
|
|
||||||
@ -43,16 +47,40 @@ func TestObjValueLookup(t *testing.T) {
|
|||||||
// kind of ssa.Value we expect (represented "Constant", "&Alloc").
|
// kind of ssa.Value we expect (represented "Constant", "&Alloc").
|
||||||
expectations := make(map[string]string)
|
expectations := make(map[string]string)
|
||||||
|
|
||||||
// Find all annotations of form x::BinOp, &y::Alloc, etc.
|
// Each note of the form @ssa(x, "BinOp") in testdata/objlookup.go
|
||||||
re := regexp.MustCompile(`(\b|&)?(\w*)::(\w*)\b`)
|
// specifies an expectation that an object named x declared on the
|
||||||
for _, c := range f.Comments {
|
// same line is associated with an an ssa.Value of type *ssa.BinOp.
|
||||||
text := c.Text()
|
notes, err := expect.Extract(conf.Fset, f)
|
||||||
pos := conf.Fset.Position(c.Pos())
|
if err != nil {
|
||||||
for _, m := range re.FindAllStringSubmatch(text, -1) {
|
t.Fatal(err)
|
||||||
key := fmt.Sprintf("%s:%d", m[2], pos.Line)
|
}
|
||||||
value := m[1] + m[3]
|
for _, n := range notes {
|
||||||
expectations[key] = value
|
if n.Name != "ssa" {
|
||||||
|
t.Errorf("%v: unexpected note type %q, want \"ssa\"", conf.Fset.Position(n.Pos), n.Name)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
if len(n.Args) != 2 {
|
||||||
|
t.Errorf("%v: ssa has %d args, want 2", conf.Fset.Position(n.Pos), len(n.Args))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ident, ok := n.Args[0].(expect.Identifier)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("%v: got %v for arg 1, want identifier", conf.Fset.Position(n.Pos), n.Args[0])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
exp, ok := n.Args[1].(string)
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("%v: got %v for arg 2, want string", conf.Fset.Position(n.Pos), n.Args[1])
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p, _, err := expect.MatchBefore(conf.Fset, readFile, n.Pos, string(ident))
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pos := conf.Fset.Position(p)
|
||||||
|
key := fmt.Sprintf("%s:%d", ident, pos.Line)
|
||||||
|
expectations[key] = exp
|
||||||
}
|
}
|
||||||
|
|
||||||
iprog, err := conf.Load()
|
iprog, err := conf.Load()
|
||||||
|
150
go/ssa/testdata/objlookup.go
vendored
150
go/ssa/testdata/objlookup.go
vendored
@ -24,7 +24,7 @@ func (*J) method() {}
|
|||||||
|
|
||||||
const globalConst = 0
|
const globalConst = 0
|
||||||
|
|
||||||
var globalVar int // &globalVar::Global
|
var globalVar int //@ ssa(globalVar,"&Global")
|
||||||
|
|
||||||
func globalFunc() {}
|
func globalFunc() {}
|
||||||
|
|
||||||
@ -33,128 +33,128 @@ type I interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type S struct {
|
type S struct {
|
||||||
x int // x::nil
|
x int //@ ssa(x,"nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
print(globalVar) // globalVar::UnOp
|
print(globalVar) //@ ssa(globalVar,"UnOp")
|
||||||
globalVar = 1 // globalVar::Const
|
globalVar = 1 //@ ssa(globalVar,"Const")
|
||||||
|
|
||||||
var v0 int = 1 // v0::Const (simple local value spec)
|
var v0 int = 1 //@ ssa(v0,"Const") // simple local value spec
|
||||||
if v0 > 0 { // v0::Const
|
if v0 > 0 { //@ ssa(v0,"Const")
|
||||||
v0 = 2 // v0::Const
|
v0 = 2 //@ ssa(v0,"Const")
|
||||||
}
|
}
|
||||||
print(v0) // v0::Phi
|
print(v0) //@ ssa(v0,"Phi")
|
||||||
|
|
||||||
// v1 is captured and thus implicitly address-taken.
|
// v1 is captured and thus implicitly address-taken.
|
||||||
var v1 int = 1 // v1::Const
|
var v1 int = 1 //@ ssa(v1,"Const")
|
||||||
v1 = 2 // v1::Const
|
v1 = 2 //@ ssa(v1,"Const")
|
||||||
fmt.Println(v1) // v1::UnOp (load)
|
fmt.Println(v1) //@ ssa(v1,"UnOp") // load
|
||||||
f := func(param int) { // f::MakeClosure param::Parameter
|
f := func(param int) { //@ ssa(f,"MakeClosure"), ssa(param,"Parameter")
|
||||||
if y := 1; y > 0 { // y::Const
|
if y := 1; y > 0 { //@ ssa(y,"Const")
|
||||||
print(v1, param) // v1::UnOp (load) param::Parameter
|
print(v1, param) //@ ssa(v1,"UnOp") /*load*/, ssa(param,"Parameter")
|
||||||
}
|
}
|
||||||
param = 2 // param::Const
|
param = 2 //@ ssa(param,"Const")
|
||||||
println(param) // param::Const
|
println(param) //@ ssa(param,"Const")
|
||||||
}
|
}
|
||||||
|
|
||||||
f(0) // f::MakeClosure
|
f(0) //@ ssa(f,"MakeClosure")
|
||||||
|
|
||||||
var v2 int // v2::Const (implicitly zero-initialized local value spec)
|
var v2 int //@ ssa(v2,"Const") // implicitly zero-initialized local value spec
|
||||||
print(v2) // v2::Const
|
print(v2) //@ ssa(v2,"Const")
|
||||||
|
|
||||||
m := make(map[string]int) // m::MakeMap
|
m := make(map[string]int) //@ ssa(m,"MakeMap")
|
||||||
|
|
||||||
// Local value spec with multi-valued RHS:
|
// Local value spec with multi-valued RHS:
|
||||||
var v3, v4 = m[""] // v3::Extract v4::Extract m::MakeMap
|
var v3, v4 = m[""] //@ ssa(v3,"Extract"), ssa(v4,"Extract"), ssa(m,"MakeMap")
|
||||||
print(v3) // v3::Extract
|
print(v3) //@ ssa(v3,"Extract")
|
||||||
print(v4) // v4::Extract
|
print(v4) //@ ssa(v4,"Extract")
|
||||||
|
|
||||||
v3++ // v3::BinOp (assign with op)
|
v3++ //@ ssa(v3,"BinOp") // assign with op
|
||||||
v3 += 2 // v3::BinOp (assign with op)
|
v3 += 2 //@ ssa(v3,"BinOp") // assign with op
|
||||||
|
|
||||||
v5, v6 := false, "" // v5::Const v6::Const (defining assignment)
|
v5, v6 := false, "" //@ ssa(v5,"Const"), ssa(v6,"Const") // defining assignment
|
||||||
print(v5) // v5::Const
|
print(v5) //@ ssa(v5,"Const")
|
||||||
print(v6) // v6::Const
|
print(v6) //@ ssa(v6,"Const")
|
||||||
|
|
||||||
var v7 S // &v7::Alloc
|
var v7 S //@ ssa(v7,"&Alloc")
|
||||||
v7.x = 1 // &v7::Alloc &x::FieldAddr
|
v7.x = 1 //@ ssa(v7,"&Alloc"), ssa(x,"&FieldAddr")
|
||||||
print(v7.x) // &v7::Alloc &x::FieldAddr
|
print(v7.x) //@ ssa(v7,"&Alloc"), ssa(x,"&FieldAddr")
|
||||||
|
|
||||||
var v8 [1]int // &v8::Alloc
|
var v8 [1]int //@ ssa(v8,"&Alloc")
|
||||||
v8[0] = 0 // &v8::Alloc
|
v8[0] = 0 //@ ssa(v8,"&Alloc")
|
||||||
print(v8[:]) // &v8::Alloc
|
print(v8[:]) //@ ssa(v8,"&Alloc")
|
||||||
_ = v8[0] // &v8::Alloc
|
_ = v8[0] //@ ssa(v8,"&Alloc")
|
||||||
_ = v8[:][0] // &v8::Alloc
|
_ = v8[:][0] //@ ssa(v8,"&Alloc")
|
||||||
v8ptr := &v8 // v8ptr::Alloc &v8::Alloc
|
v8ptr := &v8 //@ ssa(v8ptr,"Alloc"), ssa(v8,"&Alloc")
|
||||||
_ = v8ptr[0] // v8ptr::Alloc
|
_ = v8ptr[0] //@ ssa(v8ptr,"Alloc")
|
||||||
_ = *v8ptr // v8ptr::Alloc
|
_ = *v8ptr //@ ssa(v8ptr,"Alloc")
|
||||||
|
|
||||||
v8a := make([]int, 1) // v8a::Slice
|
v8a := make([]int, 1) //@ ssa(v8a,"Slice")
|
||||||
v8a[0] = 0 // v8a::Slice
|
v8a[0] = 0 //@ ssa(v8a,"Slice")
|
||||||
print(v8a[:]) // v8a::Slice
|
print(v8a[:]) //@ ssa(v8a,"Slice")
|
||||||
|
|
||||||
v9 := S{} // &v9::Alloc
|
v9 := S{} //@ ssa(v9,"&Alloc")
|
||||||
|
|
||||||
v10 := &v9 // v10::Alloc &v9::Alloc
|
v10 := &v9 //@ ssa(v10,"Alloc"), ssa(v9,"&Alloc")
|
||||||
_ = v10 // v10::Alloc
|
_ = v10 //@ ssa(v10,"Alloc")
|
||||||
|
|
||||||
var v11 *J = nil // v11::Const
|
var v11 *J = nil //@ ssa(v11,"Const")
|
||||||
v11.method() // v11::Const
|
v11.method() //@ ssa(v11,"Const")
|
||||||
|
|
||||||
var v12 J // &v12::Alloc
|
var v12 J //@ ssa(v12,"&Alloc")
|
||||||
v12.method() // &v12::Alloc (implicitly address-taken)
|
v12.method() //@ ssa(v12,"&Alloc") // implicitly address-taken
|
||||||
|
|
||||||
// NB, in the following, 'method' resolves to the *types.Func
|
// NB, in the following, 'method' resolves to the *types.Func
|
||||||
// of (*J).method, so it doesn't help us locate the specific
|
// of (*J).method, so it doesn't help us locate the specific
|
||||||
// ssa.Values here: a bound-method closure and a promotion
|
// ssa.Values here: a bound-method closure and a promotion
|
||||||
// wrapper.
|
// wrapper.
|
||||||
_ = v11.method // v11::Const
|
_ = v11.method //@ ssa(v11,"Const")
|
||||||
_ = (*struct{ J }).method // J::nil
|
_ = (*struct{ J }).method //@ ssa(J,"nil")
|
||||||
|
|
||||||
// These vars are not optimised away.
|
// These vars are not optimised away.
|
||||||
if false {
|
if false {
|
||||||
v13 := 0 // v13::Const
|
v13 := 0 //@ ssa(v13,"Const")
|
||||||
println(v13) // v13::Const
|
println(v13) //@ ssa(v13,"Const")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch x := 1; x { // x::Const
|
switch x := 1; x { //@ ssa(x,"Const")
|
||||||
case v0: // v0::Phi
|
case v0: //@ ssa(v0,"Phi")
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range m { // k::Extract v::Extract m::MakeMap
|
for k, v := range m { //@ ssa(k,"Extract"), ssa(v,"Extract"), ssa(m,"MakeMap")
|
||||||
_ = k // k::Extract
|
_ = k //@ ssa(k,"Extract")
|
||||||
v++ // v::BinOp
|
v++ //@ ssa(v,"BinOp")
|
||||||
}
|
}
|
||||||
|
|
||||||
if y := 0; y > 1 { // y::Const y::Const
|
if y := 0; y > 1 { //@ ssa(y,"Const"), ssa(y,"Const")
|
||||||
}
|
}
|
||||||
|
|
||||||
var i interface{} // i::Const (nil interface)
|
var i interface{} //@ ssa(i,"Const") // nil interface
|
||||||
i = 1 // i::MakeInterface
|
i = 1 //@ ssa(i,"MakeInterface")
|
||||||
switch i := i.(type) { // i::MakeInterface i::MakeInterface
|
switch i := i.(type) { //@ ssa(i,"MakeInterface"), ssa(i,"MakeInterface")
|
||||||
case int:
|
case int:
|
||||||
println(i) // i::Extract
|
println(i) //@ ssa(i,"Extract")
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := make(chan int) // ch::MakeChan
|
ch := make(chan int) //@ ssa(ch,"MakeChan")
|
||||||
select {
|
select {
|
||||||
case x := <-ch: // x::UnOp (receive) ch::MakeChan
|
case x := <-ch: //@ ssa(x,"UnOp") /*receive*/, ssa(ch,"MakeChan")
|
||||||
_ = x // x::UnOp
|
_ = x //@ ssa(x,"UnOp")
|
||||||
}
|
}
|
||||||
|
|
||||||
// .Op is an inter-package FieldVal-selection.
|
// .Op is an inter-package FieldVal-selection.
|
||||||
var err os.PathError // &err::Alloc
|
var err os.PathError //@ ssa(err,"&Alloc")
|
||||||
_ = err.Op // &err::Alloc &Op::FieldAddr
|
_ = err.Op //@ ssa(err,"&Alloc"), ssa(Op,"&FieldAddr")
|
||||||
_ = &err.Op // &err::Alloc &Op::FieldAddr
|
_ = &err.Op //@ ssa(err,"&Alloc"), ssa(Op,"&FieldAddr")
|
||||||
|
|
||||||
// Exercise corner-cases of lvalues vs rvalues.
|
// Exercise corner-cases of lvalues vs rvalues.
|
||||||
// (Guessing IsAddr from the 'pointerness' won't cut it here.)
|
// (Guessing IsAddr from the 'pointerness' won't cut it here.)
|
||||||
type N *N
|
type N *N
|
||||||
var n N // n::Const
|
var n N //@ ssa(n,"Const")
|
||||||
n1 := n // n1::Const n::Const
|
n1 := n //@ ssa(n1,"Const"), ssa(n,"Const")
|
||||||
n2 := &n1 // n2::Alloc &n1::Alloc
|
n2 := &n1 //@ ssa(n2,"Alloc"), ssa(n1,"&Alloc")
|
||||||
n3 := *n2 // n3::UnOp n2::Alloc
|
n3 := *n2 //@ ssa(n3,"UnOp"), ssa(n2,"Alloc")
|
||||||
n4 := **n3 // n4::UnOp n3::UnOp
|
n4 := **n3 //@ ssa(n4,"UnOp"), ssa(n3,"UnOp")
|
||||||
_ = n4 // n4::UnOp
|
_ = n4 //@ ssa(n4,"UnOp")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user