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