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>
diff --git a/go/ssa/source_test.go b/go/ssa/source_test.go
index e3e7023..9dc3c66 100644
--- a/go/ssa/source_test.go
+++ b/go/ssa/source_test.go
@@ -13,8 +13,8 @@
 	"go/parser"
 	"go/token"
 	"go/types"
+	"io/ioutil"
 	"os"
-	"regexp"
 	"runtime"
 	"strings"
 	"testing"
@@ -32,10 +32,14 @@
 	}
 
 	conf := loader.Config{ParserMode: parser.ParseComments}
-	f, err := conf.ParseFile("testdata/objlookup.go", nil)
+	src, err := ioutil.ReadFile("testdata/objlookup.go")
 	if err != nil {
-		t.Error(err)
-		return
+		t.Fatal(err)
+	}
+	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)
 
@@ -43,16 +47,40 @@
 	// kind of ssa.Value we expect (represented "Constant", "&Alloc").
 	expectations := make(map[string]string)
 
-	// Find all annotations of form x::BinOp, &y::Alloc, etc.
-	re := regexp.MustCompile(`(\b|&)?(\w*)::(\w*)\b`)
-	for _, c := range f.Comments {
-		text := c.Text()
-		pos := conf.Fset.Position(c.Pos())
-		for _, m := range re.FindAllStringSubmatch(text, -1) {
-			key := fmt.Sprintf("%s:%d", m[2], pos.Line)
-			value := m[1] + m[3]
-			expectations[key] = value
+	// Each note of the form @ssa(x, "BinOp") in testdata/objlookup.go
+	// specifies an expectation that an object named x declared on the
+	// same line is associated with an an ssa.Value of type *ssa.BinOp.
+	notes, err := expect.Extract(conf.Fset, f)
+	if err != nil {
+		t.Fatal(err)
+	}
+	for _, n := range notes {
+		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()
diff --git a/go/ssa/testdata/objlookup.go b/go/ssa/testdata/objlookup.go
index 1aaa417..d110add 100644
--- a/go/ssa/testdata/objlookup.go
+++ b/go/ssa/testdata/objlookup.go
@@ -24,7 +24,7 @@
 
 const globalConst = 0
 
-var globalVar int // &globalVar::Global
+var globalVar int //@ ssa(globalVar,"&Global")
 
 func globalFunc() {}
 
@@ -33,128 +33,128 @@
 }
 
 type S struct {
-	x int // x::nil
+	x int //@ ssa(x,"nil")
 }
 
 func main() {
-	print(globalVar) // globalVar::UnOp
-	globalVar = 1    // globalVar::Const
+	print(globalVar) //@ ssa(globalVar,"UnOp")
+	globalVar = 1    //@ ssa(globalVar,"Const")
 
-	var v0 int = 1 // v0::Const (simple local value spec)
-	if v0 > 0 {    // v0::Const
-		v0 = 2 // v0::Const
+	var v0 int = 1 //@ ssa(v0,"Const") // simple local value spec
+	if v0 > 0 {    //@ ssa(v0,"Const")
+		v0 = 2 //@ ssa(v0,"Const")
 	}
-	print(v0) // v0::Phi
+	print(v0) //@ ssa(v0,"Phi")
 
 	// v1 is captured and thus implicitly address-taken.
-	var v1 int = 1         // v1::Const
-	v1 = 2                 // v1::Const
-	fmt.Println(v1)        // v1::UnOp (load)
-	f := func(param int) { // f::MakeClosure param::Parameter
-		if y := 1; y > 0 { // y::Const
-			print(v1, param) // v1::UnOp (load) param::Parameter
+	var v1 int = 1         //@ ssa(v1,"Const")
+	v1 = 2                 //@ ssa(v1,"Const")
+	fmt.Println(v1)        //@ ssa(v1,"UnOp") // load
+	f := func(param int) { //@ ssa(f,"MakeClosure"), ssa(param,"Parameter")
+		if y := 1; y > 0 { //@ ssa(y,"Const")
+			print(v1, param) //@ ssa(v1,"UnOp") /*load*/, ssa(param,"Parameter")
 		}
-		param = 2      // param::Const
-		println(param) // param::Const
+		param = 2      //@ ssa(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)
-	print(v2)  // v2::Const
+	var v2 int //@ ssa(v2,"Const") // implicitly zero-initialized local value spec
+	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:
-	var v3, v4 = m[""] // v3::Extract v4::Extract m::MakeMap
-	print(v3)          // v3::Extract
-	print(v4)          // v4::Extract
+	var v3, v4 = m[""] //@ ssa(v3,"Extract"), ssa(v4,"Extract"), ssa(m,"MakeMap")
+	print(v3)          //@ ssa(v3,"Extract")
+	print(v4)          //@ ssa(v4,"Extract")
 
-	v3++    // v3::BinOp (assign with op)
-	v3 += 2 // v3::BinOp (assign with op)
+	v3++    //@ ssa(v3,"BinOp") // assign with op
+	v3 += 2 //@ ssa(v3,"BinOp") // assign with op
 
-	v5, v6 := false, "" // v5::Const v6::Const (defining assignment)
-	print(v5)           // v5::Const
-	print(v6)           // v6::Const
+	v5, v6 := false, "" //@ ssa(v5,"Const"), ssa(v6,"Const") // defining assignment
+	print(v5)           //@ ssa(v5,"Const")
+	print(v6)           //@ ssa(v6,"Const")
 
-	var v7 S    // &v7::Alloc
-	v7.x = 1    // &v7::Alloc &x::FieldAddr
-	print(v7.x) // &v7::Alloc &x::FieldAddr
+	var v7 S    //@ ssa(v7,"&Alloc")
+	v7.x = 1    //@ ssa(v7,"&Alloc"), ssa(x,"&FieldAddr")
+	print(v7.x) //@ ssa(v7,"&Alloc"), ssa(x,"&FieldAddr")
 
-	var v8 [1]int // &v8::Alloc
-	v8[0] = 0     // &v8::Alloc
-	print(v8[:])  // &v8::Alloc
-	_ = v8[0]     // &v8::Alloc
-	_ = v8[:][0]  // &v8::Alloc
-	v8ptr := &v8  // v8ptr::Alloc &v8::Alloc
-	_ = v8ptr[0]  // v8ptr::Alloc
-	_ = *v8ptr    // v8ptr::Alloc
+	var v8 [1]int //@ ssa(v8,"&Alloc")
+	v8[0] = 0     //@ ssa(v8,"&Alloc")
+	print(v8[:])  //@ ssa(v8,"&Alloc")
+	_ = v8[0]     //@ ssa(v8,"&Alloc")
+	_ = v8[:][0]  //@ ssa(v8,"&Alloc")
+	v8ptr := &v8  //@ ssa(v8ptr,"Alloc"), ssa(v8,"&Alloc")
+	_ = v8ptr[0]  //@ ssa(v8ptr,"Alloc")
+	_ = *v8ptr    //@ ssa(v8ptr,"Alloc")
 
-	v8a := make([]int, 1) // v8a::Slice
-	v8a[0] = 0            // v8a::Slice
-	print(v8a[:])         // v8a::Slice
+	v8a := make([]int, 1) //@ ssa(v8a,"Slice")
+	v8a[0] = 0            //@ ssa(v8a,"Slice")
+	print(v8a[:])         //@ ssa(v8a,"Slice")
 
-	v9 := S{} // &v9::Alloc
+	v9 := S{} //@ ssa(v9,"&Alloc")
 
-	v10 := &v9 // v10::Alloc &v9::Alloc
-	_ = v10    // v10::Alloc
+	v10 := &v9 //@ ssa(v10,"Alloc"), ssa(v9,"&Alloc")
+	_ = v10    //@ ssa(v10,"Alloc")
 
-	var v11 *J = nil // v11::Const
-	v11.method()     // v11::Const
+	var v11 *J = nil //@ ssa(v11,"Const")
+	v11.method()     //@ ssa(v11,"Const")
 
-	var v12 J    // &v12::Alloc
-	v12.method() // &v12::Alloc (implicitly address-taken)
+	var v12 J    //@ ssa(v12,"&Alloc")
+	v12.method() //@ ssa(v12,"&Alloc") // implicitly address-taken
 
 	// NB, in the following, 'method' resolves to the *types.Func
 	// of (*J).method, so it doesn't help us locate the specific
 	// ssa.Values here: a bound-method closure and a promotion
 	// wrapper.
-	_ = v11.method            // v11::Const
-	_ = (*struct{ J }).method // J::nil
+	_ = v11.method            //@ ssa(v11,"Const")
+	_ = (*struct{ J }).method //@ ssa(J,"nil")
 
 	// These vars are not optimised away.
 	if false {
-		v13 := 0     // v13::Const
-		println(v13) // v13::Const
+		v13 := 0     //@ ssa(v13,"Const")
+		println(v13) //@ ssa(v13,"Const")
 	}
 
-	switch x := 1; x { // x::Const
-	case v0: // v0::Phi
+	switch x := 1; x { //@ ssa(x,"Const")
+	case v0: //@ ssa(v0,"Phi")
 	}
 
-	for k, v := range m { // k::Extract v::Extract m::MakeMap
-		_ = k // k::Extract
-		v++   // v::BinOp
+	for k, v := range m { //@ ssa(k,"Extract"), ssa(v,"Extract"), ssa(m,"MakeMap")
+		_ = k //@ ssa(k,"Extract")
+		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)
-	i = 1                  // i::MakeInterface
-	switch i := i.(type) { // i::MakeInterface i::MakeInterface
+	var i interface{}      //@ ssa(i,"Const") // nil interface
+	i = 1                  //@ ssa(i,"MakeInterface")
+	switch i := i.(type) { //@ ssa(i,"MakeInterface"), ssa(i,"MakeInterface")
 	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 {
-	case x := <-ch: // x::UnOp (receive) ch::MakeChan
-		_ = x // x::UnOp
+	case x := <-ch: //@ ssa(x,"UnOp") /*receive*/, ssa(ch,"MakeChan")
+		_ = x //@ ssa(x,"UnOp")
 	}
 
 	// .Op is an inter-package FieldVal-selection.
-	var err os.PathError // &err::Alloc
-	_ = err.Op           // &err::Alloc &Op::FieldAddr
-	_ = &err.Op          // &err::Alloc &Op::FieldAddr
+	var err os.PathError //@ ssa(err,"&Alloc")
+	_ = err.Op           //@ ssa(err,"&Alloc"), ssa(Op,"&FieldAddr")
+	_ = &err.Op          //@ ssa(err,"&Alloc"), ssa(Op,"&FieldAddr")
 
 	// Exercise corner-cases of lvalues vs rvalues.
 	// (Guessing IsAddr from the 'pointerness' won't cut it here.)
 	type N *N
-	var n N    // n::Const
-	n1 := n    // n1::Const n::Const
-	n2 := &n1  // n2::Alloc &n1::Alloc
-	n3 := *n2  // n3::UnOp n2::Alloc
-	n4 := **n3 // n4::UnOp n3::UnOp
-	_ = n4     // n4::UnOp
+	var n N    //@ ssa(n,"Const")
+	n1 := n    //@ ssa(n1,"Const"), ssa(n,"Const")
+	n2 := &n1  //@ ssa(n2,"Alloc"), ssa(n1,"&Alloc")
+	n3 := *n2  //@ ssa(n3,"UnOp"), ssa(n2,"Alloc")
+	n4 := **n3 //@ ssa(n4,"UnOp"), ssa(n3,"UnOp")
+	_ = n4     //@ ssa(n4,"UnOp")
 }