+++ /dev/null
-// +build ignore
-
-package main
-
-import "reflect"
-
-var zero, a, b int
-var false2 bool
-
-func f(p *int, q hasF) *int {
- print(p) // @pointsto main.a
- print(q) // @types *T
- print(q.(*T)) // @pointsto new@newT1:22
- return &b
-}
-
-func g(p *bool) (*int, *bool, hasF) {
- return &b, p, new(T) // @line newT2
-}
-
-func reflectValueCall() {
- rvf := reflect.ValueOf(f)
- res := rvf.Call([]reflect.Value{
- // argument order is not significant:
- reflect.ValueOf(new(T)), // @line newT1
- reflect.ValueOf(&a),
- })
- print(res[0].Interface()) // @types *int
- print(res[0].Interface().(*int)) // @pointsto main.b
-}
-
-// @calls main.reflectValueCall -> main.f
-
-func reflectValueCallIndirect() {
- rvf := reflect.ValueOf(g)
- call := rvf.Call // kids, don't try this at home
-
- // Indirect call uses shared contour.
- //
- // Also notice that argument position doesn't matter, and args
- // of inappropriate type (e.g. 'a') are ignored.
- res := call([]reflect.Value{
- reflect.ValueOf(&a),
- reflect.ValueOf(&false2),
- })
- res0 := res[0].Interface()
- print(res0) // @types *int | *bool | *T
- print(res0.(*int)) // @pointsto main.b
- print(res0.(*bool)) // @pointsto main.false2
- print(res0.(hasF)) // @types *T
- print(res0.(*T)) // @pointsto new@newT2:19
-}
-
-// @calls main.reflectValueCallIndirect -> (reflect.Value).Call$bound
-// @calls (reflect.Value).Call$bound -> main.g
-
-func reflectTypeInOut() {
- var f func(float64, bool) (string, int)
- print(reflect.Zero(reflect.TypeOf(f).In(0)).Interface()) // @types float64
- print(reflect.Zero(reflect.TypeOf(f).In(1)).Interface()) // @types bool
- print(reflect.Zero(reflect.TypeOf(f).In(-1)).Interface()) // @types float64 | bool
- print(reflect.Zero(reflect.TypeOf(f).In(zero)).Interface()) // @types float64 | bool
-
- print(reflect.Zero(reflect.TypeOf(f).Out(0)).Interface()) // @types string
- print(reflect.Zero(reflect.TypeOf(f).Out(1)).Interface()) // @types int
- print(reflect.Zero(reflect.TypeOf(f).Out(2)).Interface()) // @types
-
- print(reflect.Zero(reflect.TypeOf(3).Out(0)).Interface()) // @types
-}
-
-type hasF interface {
- F()
-}
-
-type T struct{}
-
-func (T) F() {}
-func (T) g(int) {}
-
-type U struct{}
-
-func (U) F(int) {}
-func (U) g(string) {}
-
-type I interface {
- f()
-}
-
-var nonconst string
-
-func reflectTypeMethodByName() {
- TU := reflect.TypeOf([]interface{}{T{}, U{}}[0])
- print(reflect.Zero(TU)) // @types T | U
-
- F, _ := TU.MethodByName("F")
- print(reflect.Zero(F.Type)) // @types func(T) | func(U, int)
- print(F.Func) // @pointsto (main.T).F | (main.U).F
-
- g, _ := TU.MethodByName("g")
- print(reflect.Zero(g.Type)) // @types func(T, int) | func(U, string)
- print(g.Func) // @pointsto (main.T).g | (main.U).g
-
- // Non-literal method names are treated less precisely.
- U := reflect.TypeOf(U{})
- X, _ := U.MethodByName(nonconst)
- print(reflect.Zero(X.Type)) // @types func(U, int) | func(U, string)
- print(X.Func) // @pointsto (main.U).F | (main.U).g
-
- // Interface methods.
- rThasF := reflect.TypeOf(new(hasF)).Elem()
- print(reflect.Zero(rThasF)) // @types hasF
- F2, _ := rThasF.MethodByName("F")
- print(reflect.Zero(F2.Type)) // @types func()
- print(F2.Func) // @pointsto
-
-}
-
-func reflectTypeMethod() {
- m := reflect.TypeOf(T{}).Method(0)
- print(reflect.Zero(m.Type)) // @types func(T) | func(T, int)
- print(m.Func) // @pointsto (main.T).F | (main.T).g
-}
-
-func main() {
- reflectValueCall()
- reflectValueCallIndirect()
- reflectTypeInOut()
- reflectTypeMethodByName()
- reflectTypeMethod()
-}