| 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 | } |
| 132 |
Members