1// +build ignore
2
3package main
4
5// Test of arrays & slices with reflection.
6
7import "reflect"
8
9var a, b int
10
11type S string
12
13func reflectValueSlice() {
14	// reflect.Value contains a slice.
15	slice := make([]*int, 10) // @line slice
16	slice[0] = &a
17	rvsl := reflect.ValueOf(slice).Slice(0, 0)
18	print(rvsl.Interface())              // @types []*int
19	print(rvsl.Interface().([]*int))     // @pointsto makeslice@slice:15
20	print(rvsl.Interface().([]*int)[42]) // @pointsto main.a
21
22	// reflect.Value contains an array (non-addressable).
23	array := [10]*int{&a} // @line array
24	rvarray := reflect.ValueOf(array).Slice(0, 0)
25	print(rvarray.Interface())              // @types
26	print(rvarray.Interface().([]*int))     // @pointsto
27	print(rvarray.Interface().([]*int)[42]) // @pointsto
28
29	// reflect.Value contains a pointer-to-array
30	rvparray := reflect.ValueOf(&array).Slice(0, 0)
31	print(rvparray.Interface())              // @types []*int
32	print(rvparray.Interface().([]*int))     // @pointsto array@array:2
33	print(rvparray.Interface().([]*int)[42]) // @pointsto main.a
34
35	// reflect.Value contains a string.
36	rvstring := reflect.ValueOf("hi").Slice(0, 0)
37	print(rvstring.Interface()) // @types string
38
39	// reflect.Value contains a (named) string type.
40	rvS := reflect.ValueOf(S("hi")).Slice(0, 0)
41	print(rvS.Interface()) // @types S
42
43	// reflect.Value contains a non-array pointer.
44	rvptr := reflect.ValueOf(new(int)).Slice(0, 0)
45	print(rvptr.Interface()) // @types
46
47	// reflect.Value contains a non-string basic type.
48	rvint := reflect.ValueOf(3).Slice(0, 0)
49	print(rvint.Interface()) // @types
50}
51
52func reflectValueBytes() {
53	sl1 := make([]byte, 0) // @line ar5sl1
54	sl2 := make([]byte, 0) // @line ar5sl2
55
56	rvsl1 := reflect.ValueOf(sl1)
57	print(rvsl1.Interface())          // @types []byte
58	print(rvsl1.Interface().([]byte)) // @pointsto makeslice@ar5sl1:13
59	print(rvsl1.Bytes())              // @pointsto makeslice@ar5sl1:13
60
61	rvsl2 := reflect.ValueOf(123)
62	rvsl2.SetBytes(sl2)
63	print(rvsl2.Interface())          // @types int
64	print(rvsl2.Interface().([]byte)) // @pointsto
65	print(rvsl2.Bytes())              // @pointsto
66
67	rvsl3 := reflect.ValueOf([]byte(nil))
68	rvsl3.SetBytes(sl2)
69	print(rvsl3.Interface())          // @types []byte
70	print(rvsl3.Interface().([]byte)) // @pointsto makeslice@ar5sl2:13
71	print(rvsl3.Bytes())              // @pointsto makeslice@ar5sl2:13
72}
73
74func reflectValueIndex() {
75	slice := []*int{&a} // @line ar6slice
76	rv1 := reflect.ValueOf(slice)
77	print(rv1.Index(42).Interface())        // @types *int
78	print(rv1.Index(42).Interface().(*int)) // @pointsto main.a
79
80	array := [10]*int{&a}
81	rv2 := reflect.ValueOf(array)
82	print(rv2.Index(42).Interface())        // @types *int
83	print(rv2.Index(42).Interface().(*int)) // @pointsto main.a
84
85	rv3 := reflect.ValueOf("string")
86	print(rv3.Index(42).Interface()) // @types rune
87
88	rv4 := reflect.ValueOf(&array)
89	print(rv4.Index(42).Interface()) // @types
90
91	rv5 := reflect.ValueOf(3)
92	print(rv5.Index(42).Interface()) // @types
93}
94
95func reflectValueElem() {
96	// Interface.
97	var iface interface{} = &a
98	rv1 := reflect.ValueOf(&iface).Elem()
99	print(rv1.Interface())               // @types *int
100	print(rv1.Interface().(*int))        // @pointsto main.a
101	print(rv1.Elem().Interface())        // @types *int
102	print(rv1.Elem().Interface().(*int)) // @pointsto main.a
103
104	print(reflect.ValueOf(new(interface{})).Elem().Elem()) // @types
105
106	// Pointer.
107	ptr := &a
108	rv2 := reflect.ValueOf(&ptr)
109	print(rv2.Elem().Interface())        // @types *int
110	print(rv2.Elem().Interface().(*int)) // @pointsto main.a
111
112	// No other type works with (rV).Elem, not even those that
113	// work with (rT).Elem: slice, array, map, chan.
114
115	rv3 := reflect.ValueOf([]*int{&a})
116	print(rv3.Elem().Interface()) // @types
117
118	rv4 := reflect.ValueOf([10]*int{&a})
119	print(rv4.Elem().Interface()) // @types
120
121	rv5 := reflect.ValueOf(map[*int]*int{&a: &b})
122	print(rv5.Elem().Interface()) // @types
123
124	ch := make(chan *int)
125	ch <- &a
126	rv6 := reflect.ValueOf(ch)
127	print(rv6.Elem().Interface()) // @types
128
129	rv7 := reflect.ValueOf(3)
130	print(rv7.Elem().Interface()) // @types
131}
132
133func reflectTypeElem() {
134	rt1 := reflect.TypeOf(make([]*int, 0))
135	print(reflect.Zero(rt1.Elem())) // @types *int
136
137	rt2 := reflect.TypeOf([10]*int{})
138	print(reflect.Zero(rt2.Elem())) // @types *int
139
140	rt3 := reflect.TypeOf(map[*int]*int{})
141	print(reflect.Zero(rt3.Elem())) // @types *int
142
143	rt4 := reflect.TypeOf(make(chan *int))
144	print(reflect.Zero(rt4.Elem())) // @types *int
145
146	ptr := &a
147	rt5 := reflect.TypeOf(&ptr)
148	print(reflect.Zero(rt5.Elem())) // @types *int
149
150	rt6 := reflect.TypeOf(3)
151	print(reflect.Zero(rt6.Elem())) // @types
152}
153
154func reflectPtrTo() {
155	tInt := reflect.TypeOf(3)
156	tPtrInt := reflect.PtrTo(tInt)
157	print(reflect.Zero(tPtrInt)) // @types *int
158	tPtrPtrInt := reflect.PtrTo(tPtrInt)
159	print(reflect.Zero(tPtrPtrInt)) // @types **int
160}
161
162func reflectSliceOf() {
163	tInt := reflect.TypeOf(3)
164	tSliceInt := reflect.SliceOf(tInt)
165	print(reflect.Zero(tSliceInt)) // @types []int
166}
167
168type T struct{ x int }
169
170func reflectMakeSlice() {
171	rt := []reflect.Type{
172		reflect.TypeOf(3),
173		reflect.TypeOf([]int{}),
174		reflect.TypeOf([]T{}),
175	}[0]
176	sl := reflect.MakeSlice(rt, 0, 0)
177	print(sl)                         // @types []int | []T
178	print(sl)                         // @pointsto <alloc in reflect.MakeSlice> | <alloc in reflect.MakeSlice>
179	print(&sl.Interface().([]T)[0].x) // @pointsto <alloc in reflect.MakeSlice>[*].x
180}
181
182func main() {
183	reflectValueSlice()
184	reflectValueBytes()
185	reflectValueIndex()
186	reflectValueElem()
187	reflectTypeElem()
188	reflectPtrTo()
189	reflectSliceOf()
190	reflectMakeSlice()
191}
192