mirror of
https://github.com/golang/go
synced 2024-11-19 06:24:41 -07:00
be2647ec01
Before, VarValue looked for the ssa.Value for the 'var' object in the same package as the object was defined, but this is (obviously) wrong for a cross-package FieldVal selection, expr.f. The caller must provide the package containing the reference. + test. Also: - add 2 TODOs. - split builder.expr into two functions so we don't need defer, which makes panic dumps harder to read. R=golang-dev, crawshaw CC=golang-dev https://golang.org/cl/13257045
141 lines
3.5 KiB
Go
141 lines
3.5 KiB
Go
//+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() {
|
|
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::UnOp (load from Alloc)
|
|
v7.x = 1 // &v7::Alloc x::Const
|
|
print(v7.x) // v7::UnOp x::Field
|
|
|
|
var v8 [1]int // v8::UnOp (load from Alloc)
|
|
v8[0] = 0 // &v8::Alloc
|
|
print(v8[:]) // &v8::Alloc
|
|
_ = v8[0] // v8::UnOp (load from Alloc)
|
|
_ = v8[:][0] // &v8::Alloc
|
|
v8ptr := &v8 // v8ptr::Alloc &v8::Alloc
|
|
_ = v8ptr[0] // v8ptr::Alloc
|
|
_ = *v8ptr // v8ptr::Alloc
|
|
|
|
v9 := S{} // &v9::Alloc
|
|
|
|
v10 := &v9 // v10::Alloc &v9::Alloc
|
|
|
|
var v11 *J = nil // v11::Const
|
|
v11.method() // v11::Const
|
|
|
|
var v12 J // v12::UnOp (load from 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
|
|
|
|
// These vars are optimised away.
|
|
if false {
|
|
v13 := 0 // v13::nil
|
|
println(v13) // v13::nil
|
|
}
|
|
|
|
switch x := 1; x { // x::Const
|
|
case v0: // v0::Phi
|
|
}
|
|
|
|
for k, v := range m { // k::Extract v::Extract m::MakeMap
|
|
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
|
|
}
|
|
|
|
// .Op is an inter-package FieldVal-selection.
|
|
var err os.PathError // err::UnOp
|
|
_ = err.Op // err::UnOp Op::Field
|
|
_ = &err.Op // &err::Alloc &Op::FieldAddr
|
|
}
|