1// +build ignore 2 3package main 4 5import "reflect" 6 7var zero, a, b int 8var false2 bool 9 10func f(p *int, q hasF) *int { 11 print(p) // @pointsto main.a 12 print(q) // @types *T 13 print(q.(*T)) // @pointsto new@newT1:22 14 return &b 15} 16 17func g(p *bool) (*int, *bool, hasF) { 18 return &b, p, new(T) // @line newT2 19} 20 21func reflectValueCall() { 22 rvf := reflect.ValueOf(f) 23 res := rvf.Call([]reflect.Value{ 24 // argument order is not significant: 25 reflect.ValueOf(new(T)), // @line newT1 26 reflect.ValueOf(&a), 27 }) 28 print(res[0].Interface()) // @types *int 29 print(res[0].Interface().(*int)) // @pointsto main.b 30} 31 32// @calls main.reflectValueCall -> main.f 33 34func reflectValueCallIndirect() { 35 rvf := reflect.ValueOf(g) 36 call := rvf.Call // kids, don't try this at home 37 38 // Indirect call uses shared contour. 39 // 40 // Also notice that argument position doesn't matter, and args 41 // of inappropriate type (e.g. 'a') are ignored. 42 res := call([]reflect.Value{ 43 reflect.ValueOf(&a), 44 reflect.ValueOf(&false2), 45 }) 46 res0 := res[0].Interface() 47 print(res0) // @types *int | *bool | *T 48 print(res0.(*int)) // @pointsto main.b 49 print(res0.(*bool)) // @pointsto main.false2 50 print(res0.(hasF)) // @types *T 51 print(res0.(*T)) // @pointsto new@newT2:19 52} 53 54// @calls main.reflectValueCallIndirect -> (reflect.Value).Call$bound 55// @calls (reflect.Value).Call$bound -> main.g 56 57func reflectTypeInOut() { 58 var f func(float64, bool) (string, int) 59 print(reflect.Zero(reflect.TypeOf(f).In(0)).Interface()) // @types float64 60 print(reflect.Zero(reflect.TypeOf(f).In(1)).Interface()) // @types bool 61 print(reflect.Zero(reflect.TypeOf(f).In(-1)).Interface()) // @types float64 | bool 62 print(reflect.Zero(reflect.TypeOf(f).In(zero)).Interface()) // @types float64 | bool 63 64 print(reflect.Zero(reflect.TypeOf(f).Out(0)).Interface()) // @types string 65 print(reflect.Zero(reflect.TypeOf(f).Out(1)).Interface()) // @types int 66 print(reflect.Zero(reflect.TypeOf(f).Out(2)).Interface()) // @types 67 68 print(reflect.Zero(reflect.TypeOf(3).Out(0)).Interface()) // @types 69} 70 71type hasF interface { 72 F() 73} 74 75type T struct{} 76 77func (T) F() {} 78func (T) g(int) {} 79 80type U struct{} 81 82func (U) F(int) {} 83func (U) g(string) {} 84 85type I interface { 86 f() 87} 88 89var nonconst string 90 91func reflectTypeMethodByName() { 92 TU := reflect.TypeOf([]interface{}{T{}, U{}}[0]) 93 print(reflect.Zero(TU)) // @types T | U 94 95 F, _ := TU.MethodByName("F") 96 print(reflect.Zero(F.Type)) // @types func(T) | func(U, int) 97 print(F.Func) // @pointsto (main.T).F | (main.U).F 98 99 g, _ := TU.MethodByName("g") 100 print(reflect.Zero(g.Type)) // @types func(T, int) | func(U, string) 101 print(g.Func) // @pointsto (main.T).g | (main.U).g 102 103 // Non-literal method names are treated less precisely. 104 U := reflect.TypeOf(U{}) 105 X, _ := U.MethodByName(nonconst) 106 print(reflect.Zero(X.Type)) // @types func(U, int) | func(U, string) 107 print(X.Func) // @pointsto (main.U).F | (main.U).g 108 109 // Interface methods. 110 rThasF := reflect.TypeOf(new(hasF)).Elem() 111 print(reflect.Zero(rThasF)) // @types hasF 112 F2, _ := rThasF.MethodByName("F") 113 print(reflect.Zero(F2.Type)) // @types func() 114 print(F2.Func) // @pointsto 115 116} 117 118func reflectTypeMethod() { 119 m := reflect.TypeOf(T{}).Method(0) 120 print(reflect.Zero(m.Type)) // @types func(T) | func(T, int) 121 print(m.Func) // @pointsto (main.T).F | (main.T).g 122} 123 124func main() { 125 reflectValueCall() 126 reflectValueCallIndirect() 127 reflectTypeInOut() 128 reflectTypeMethodByName() 129 reflectTypeMethod() 130} 131