summaryrefslogtreecommitdiff
path: root/vendor/golang.org/x/tools/go/ssa/testdata
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/golang.org/x/tools/go/ssa/testdata')
-rw-r--r--vendor/golang.org/x/tools/go/ssa/testdata/objlookup.go160
-rw-r--r--vendor/golang.org/x/tools/go/ssa/testdata/structconv.go24
-rw-r--r--vendor/golang.org/x/tools/go/ssa/testdata/valueforexpr.go152
3 files changed, 336 insertions, 0 deletions
diff --git a/vendor/golang.org/x/tools/go/ssa/testdata/objlookup.go b/vendor/golang.org/x/tools/go/ssa/testdata/objlookup.go
new file mode 100644
index 0000000..1aaa417
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/ssa/testdata/objlookup.go
@@ -0,0 +1,160 @@
+//+build ignore
+
+package main
+
+// This file is the input to TestObjValueLookup in source_test.go,
+// which ensures that each occurrence of an ident defining or
+// referring to a func, var or const object can be mapped to its
+// corresponding SSA Value.
+//
+// For every reference to a var object, we use annotations in comments
+// to denote both the expected SSA Value kind, and whether to expect
+// its value (x) or its address (&x).
+//
+// For const and func objects, the results don't vary by reference and
+// are always values not addresses, so no annotations are needed. The
+// declaration is enough.
+
+import "fmt"
+import "os"
+
+type J int
+
+func (*J) method() {}
+
+const globalConst = 0
+
+var globalVar int // &globalVar::Global
+
+func globalFunc() {}
+
+type I interface {
+ interfaceMethod()
+}
+
+type S struct {
+ x int // x::nil
+}
+
+func main() {
+ print(globalVar) // globalVar::UnOp
+ globalVar = 1 // globalVar::Const
+
+ var v0 int = 1 // v0::Const (simple local value spec)
+ if v0 > 0 { // v0::Const
+ v0 = 2 // v0::Const
+ }
+ print(v0) // 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
+ }
+ param = 2 // param::Const
+ println(param) // param::Const
+ }
+
+ f(0) // f::MakeClosure
+
+ var v2 int // v2::Const (implicitly zero-initialized local value spec)
+ print(v2) // v2::Const
+
+ m := make(map[string]int) // 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
+
+ v3++ // v3::BinOp (assign with op)
+ v3 += 2 // v3::BinOp (assign with op)
+
+ v5, v6 := false, "" // v5::Const v6::Const (defining assignment)
+ print(v5) // v5::Const
+ print(v6) // v6::Const
+
+ var v7 S // &v7::Alloc
+ v7.x = 1 // &v7::Alloc &x::FieldAddr
+ print(v7.x) // &v7::Alloc &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
+
+ v8a := make([]int, 1) // v8a::Slice
+ v8a[0] = 0 // v8a::Slice
+ print(v8a[:]) // v8a::Slice
+
+ v9 := S{} // &v9::Alloc
+
+ v10 := &v9 // v10::Alloc &v9::Alloc
+ _ = v10 // v10::Alloc
+
+ var v11 *J = nil // v11::Const
+ v11.method() // v11::Const
+
+ var v12 J // &v12::Alloc
+ v12.method() // &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
+
+ // These vars are not optimised away.
+ if false {
+ v13 := 0 // v13::Const
+ println(v13) // v13::Const
+ }
+
+ switch x := 1; x { // x::Const
+ case v0: // v0::Phi
+ }
+
+ for k, v := range m { // k::Extract v::Extract m::MakeMap
+ _ = k // k::Extract
+ v++ // v::BinOp
+ }
+
+ if y := 0; y > 1 { // y::Const y::Const
+ }
+
+ var i interface{} // i::Const (nil interface)
+ i = 1 // i::MakeInterface
+ switch i := i.(type) { // i::MakeInterface i::MakeInterface
+ case int:
+ println(i) // i::Extract
+ }
+
+ ch := make(chan int) // ch::MakeChan
+ select {
+ case x := <-ch: // x::UnOp (receive) ch::MakeChan
+ _ = x // 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
+
+ // 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
+}
diff --git a/vendor/golang.org/x/tools/go/ssa/testdata/structconv.go b/vendor/golang.org/x/tools/go/ssa/testdata/structconv.go
new file mode 100644
index 0000000..3126469
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/ssa/testdata/structconv.go
@@ -0,0 +1,24 @@
+//+build ignore
+
+// This file is the input to TestValueForExprStructConv in identical_test.go,
+// which uses the same framework as TestValueForExpr does in source_test.go.
+//
+// In Go 1.8, struct conversions are permitted even when the struct types have
+// different tags. This wasn't permitted in earlier versions of Go, so this file
+// exists separately from valueforexpr.go to just test this behavior in Go 1.8
+// and later.
+
+package main
+
+type t1 struct {
+ x int
+}
+type t2 struct {
+ x int `tag`
+}
+
+func main() {
+ var tv1 t1
+ var tv2 t2 = /*@ChangeType*/ (t2(tv1))
+ _ = tv2
+}
diff --git a/vendor/golang.org/x/tools/go/ssa/testdata/valueforexpr.go b/vendor/golang.org/x/tools/go/ssa/testdata/valueforexpr.go
new file mode 100644
index 0000000..4a2cb85
--- /dev/null
+++ b/vendor/golang.org/x/tools/go/ssa/testdata/valueforexpr.go
@@ -0,0 +1,152 @@
+//+build ignore
+
+package main
+
+// This file is the input to TestValueForExpr in source_test.go, which
+// ensures that each expression e immediately following a /*@kind*/(x)
+// annotation, when passed to Function.ValueForExpr(e), returns a
+// non-nil Value of the same type as e and of kind 'kind'.
+
+func f(spilled, unspilled int) {
+ _ = /*@UnOp*/ (spilled)
+ _ = /*@Parameter*/ (unspilled)
+ _ = /*@<nil>*/ (1 + 2) // (constant)
+ i := 0
+
+ f := func() (int, int) { return 0, 0 }
+
+ /*@Call*/ (print( /*@BinOp*/ (i + 1)))
+ _, _ = /*@Call*/ (f())
+ ch := /*@MakeChan*/ (make(chan int))
+ /*@UnOp*/ (<-ch)
+ x := /*@UnOp*/ (<-ch)
+ _ = x
+ select {
+ case /*@Extract*/ (<-ch):
+ case x := /*@Extract*/ (<-ch):
+ _ = x
+ }
+ defer /*@Function*/ (func() {
+ })()
+ go /*@Function*/ (func() {
+ })()
+ y := 0
+ if true && /*@BinOp*/ (bool(y > 0)) {
+ y = 1
+ }
+ _ = /*@Phi*/ (y)
+ map1 := /*@MakeMap*/ (make(map[string]string))
+ _ = map1
+ _ = /*@Slice*/ (make([]int, 0))
+ _ = /*@MakeClosure*/ (func() { print(spilled) })
+
+ sl := []int{}
+ _ = /*@Slice*/ (sl[:0])
+
+ _ = /*@<nil>*/ (new(int)) // optimized away
+ tmp := /*@Alloc*/ (new(int))
+ _ = tmp
+ var iface interface{}
+ _ = /*@TypeAssert*/ (iface.(int))
+ _ = /*@UnOp*/ (sl[0])
+ _ = /*@IndexAddr*/ (&sl[0])
+ _ = /*@Index*/ ([2]int{}[0])
+ var p *int
+ _ = /*@UnOp*/ (*p)
+
+ _ = /*@UnOp*/ (global)
+ /*@UnOp*/ (global)[""] = ""
+ /*@Global*/ (global) = map[string]string{}
+
+ var local t
+ /*UnOp*/ (local.x) = 1
+
+ // Exercise corner-cases of lvalues vs rvalues.
+ type N *N
+ var n N
+ /*@UnOp*/ (n) = /*@UnOp*/ (n)
+ /*@ChangeType*/ (n) = /*@Alloc*/ (&n)
+ /*@UnOp*/ (n) = /*@UnOp*/ (*n)
+ /*@UnOp*/ (n) = /*@UnOp*/ (**n)
+}
+
+func complit() {
+ // Composite literals.
+ // We get different results for
+ // - composite literal as value (e.g. operand to print)
+ // - composite literal initializer for addressable value
+ // - composite literal value assigned to blank var
+
+ // 1. Slices
+ print( /*@Slice*/ ([]int{}))
+ print( /*@Alloc*/ (&[]int{}))
+ print(& /*@Slice*/ ([]int{}))
+
+ sl1 := /*@Slice*/ ([]int{})
+ sl2 := /*@Alloc*/ (&[]int{})
+ sl3 := & /*@Slice*/ ([]int{})
+ _, _, _ = sl1, sl2, sl3
+
+ _ = /*@Slice*/ ([]int{})
+ _ = /*@<nil>*/ (& /*@Slice*/ ([]int{})) // & optimized away
+ _ = & /*@Slice*/ ([]int{})
+
+ // 2. Arrays
+ print( /*@UnOp*/ ([1]int{}))
+ print( /*@Alloc*/ (&[1]int{}))
+ print(& /*@Alloc*/ ([1]int{}))
+
+ arr1 := /*@Alloc*/ ([1]int{})
+ arr2 := /*@Alloc*/ (&[1]int{})
+ arr3 := & /*@Alloc*/ ([1]int{})
+ _, _, _ = arr1, arr2, arr3
+
+ _ = /*@UnOp*/ ([1]int{})
+ _ = /*@Alloc*/ (& /*@Alloc*/ ([1]int{}))
+ _ = & /*@Alloc*/ ([1]int{})
+
+ // 3. Maps
+ type M map[int]int
+ print( /*@MakeMap*/ (M{}))
+ print( /*@Alloc*/ (&M{}))
+ print(& /*@MakeMap*/ (M{}))
+
+ m1 := /*@MakeMap*/ (M{})
+ m2 := /*@Alloc*/ (&M{})
+ m3 := & /*@MakeMap*/ (M{})
+ _, _, _ = m1, m2, m3
+
+ _ = /*@MakeMap*/ (M{})
+ _ = /*@<nil>*/ (& /*@MakeMap*/ (M{})) // & optimized away
+ _ = & /*@MakeMap*/ (M{})
+
+ // 4. Structs
+ print( /*@UnOp*/ (struct{}{}))
+ print( /*@Alloc*/ (&struct{}{}))
+ print(& /*@Alloc*/ (struct{}{}))
+
+ s1 := /*@Alloc*/ (struct{}{})
+ s2 := /*@Alloc*/ (&struct{}{})
+ s3 := & /*@Alloc*/ (struct{}{})
+ _, _, _ = s1, s2, s3
+
+ _ = /*@UnOp*/ (struct{}{})
+ _ = /*@Alloc*/ (& /*@Alloc*/ (struct{}{}))
+ _ = & /*@Alloc*/ (struct{}{})
+}
+
+type t struct{ x int }
+
+// Ensure we can locate methods of named types.
+func (t) f(param int) {
+ _ = /*@Parameter*/ (param)
+}
+
+// Ensure we can locate init functions.
+func init() {
+ m := /*@MakeMap*/ (make(map[string]string))
+ _ = m
+}
+
+// Ensure we can locate variables in initializer expressions.
+var global = /*@MakeMap*/ (make(map[string]string))