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