1
0
mirror of https://github.com/golang/go synced 2024-10-01 13:28:37 -06:00
go/pointer/testdata/reflect.go
Alan Donovan 94c387c610 go.tools/pointer: implement (reflect.Value).Call.
The implementation follows the basic pattern of an indirect
function call (genDynamicCall).

We use the same trick as SetFinalizer so that direct calls to
(r.V).Call, which are overwhelmingly the norm, are inlined.

Bug fix (and simplification): calling untag() to unbox a
reflect.Value is wrong for reflect.Values containing interfaces
(rare).  Now, we call untag for concrete types and typeFilter
for interface types, and we can use this pattern in all cases.
It corresponds to the ssa.TypeAssert operator, so we call
it typeAssert.  Added tests to cover this.

We also specialize reflect.{In,Out} when the operand is an int
literal.

+ Tests.

Also:
- make taggedValue() panic, not return nil, eliminating many checks.
  We call isTaggedValue for the one place that cares.
- pointer_test: recover from panics in Analyze() and dump the log.

R=crawshaw
CC=golang-dev
https://golang.org/cl/14426050
2013-10-29 21:57:53 -04:00

88 lines
3.3 KiB
Go

// +build ignore
package main
import "reflect"
import "unsafe"
var a, b int
var unknown bool
func reflectIndirect() {
ptr := &a
// Pointer:
print(reflect.Indirect(reflect.ValueOf(&ptr)).Interface().(*int)) // @pointsto main.a
// Non-pointer:
print(reflect.Indirect(reflect.ValueOf([]*int{ptr})).Interface().([]*int)[0]) // @pointsto main.a
}
func reflectNewAt() {
var x [8]byte
print(reflect.NewAt(reflect.TypeOf(3), unsafe.Pointer(&x)).Interface()) // @types *int
}
// @warning "unsound: main.reflectNewAt contains a reflect.NewAt.. call"
func reflectTypeOf() {
t := reflect.TypeOf(3)
if unknown {
t = reflect.TypeOf("foo")
}
// TODO(adonovan): make types.Eval let us refer to unexported types.
print(t) // #@types *reflect.rtype
print(reflect.Zero(t).Interface()) // @types int | string
newint := reflect.New(t).Interface() // @line rtonew
print(newint) // @types *int | *string
print(newint.(*int)) // @pointsto <alloc in reflect.New>
print(newint.(*string)) // @pointsto <alloc in reflect.New>
}
func reflectTypeElem() {
print(reflect.Zero(reflect.TypeOf(&a).Elem()).Interface()) // @types int
print(reflect.Zero(reflect.TypeOf([]string{}).Elem()).Interface()) // @types string
print(reflect.Zero(reflect.TypeOf(make(chan bool)).Elem()).Interface()) // @types bool
print(reflect.Zero(reflect.TypeOf(make(map[string]float64)).Elem()).Interface()) // @types float64
print(reflect.Zero(reflect.TypeOf([3]complex64{}).Elem()).Interface()) // @types complex64
print(reflect.Zero(reflect.TypeOf(3).Elem()).Interface()) // @types
print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem())) // @types interface{}
print(reflect.Zero(reflect.TypeOf(new(interface{})).Elem()).Interface()) // @types
}
// reflect.Values within reflect.Values.
func metareflection() {
// "box" a *int twice, unbox it twice.
v0 := reflect.ValueOf(&a)
print(v0) // @types *int
v1 := reflect.ValueOf(v0) // box
print(v1) // @types reflect.Value
v2 := reflect.ValueOf(v1) // box
print(v2) // @types reflect.Value
v1a := v2.Interface().(reflect.Value) // unbox
print(v1a) // @types reflect.Value
v0a := v1a.Interface().(reflect.Value) // unbox
print(v0a) // @types *int
print(v0a.Interface().(*int)) // @pointsto main.a
// "box" an interface{} lvalue twice, unbox it twice.
var iface interface{} = 3
x0 := reflect.ValueOf(&iface).Elem()
print(x0) // @types interface{}
x1 := reflect.ValueOf(x0) // box
print(x1) // @types reflect.Value
x2 := reflect.ValueOf(x1) // box
print(x2) // @types reflect.Value
x1a := x2.Interface().(reflect.Value) // unbox
print(x1a) // @types reflect.Value
x0a := x1a.Interface().(reflect.Value) // unbox
print(x0a) // @types interface{}
print(x0a.Interface()) // @types int
}
func main() {
reflectIndirect()
reflectNewAt()
reflectTypeOf()
reflectTypeElem()
metareflection()
}