131 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			Go
		
	
	
	
| // +build ignore
 | |
| 
 | |
| package main
 | |
| 
 | |
| import "reflect"
 | |
| 
 | |
| var zero, a, b int
 | |
| var false2 bool
 | |
| 
 | |
| func f(p *int, q hasF) *int {
 | |
| 	print(p)      // @pointsto main.a
 | |
| 	print(q)      // @types *T
 | |
| 	print(q.(*T)) // @pointsto new@newT1:22
 | |
| 	return &b
 | |
| }
 | |
| 
 | |
| func g(p *bool) (*int, *bool, hasF) {
 | |
| 	return &b, p, new(T) // @line newT2
 | |
| }
 | |
| 
 | |
| func reflectValueCall() {
 | |
| 	rvf := reflect.ValueOf(f)
 | |
| 	res := rvf.Call([]reflect.Value{
 | |
| 		// argument order is not significant:
 | |
| 		reflect.ValueOf(new(T)), // @line newT1
 | |
| 		reflect.ValueOf(&a),
 | |
| 	})
 | |
| 	print(res[0].Interface())        // @types *int
 | |
| 	print(res[0].Interface().(*int)) // @pointsto main.b
 | |
| }
 | |
| 
 | |
| // @calls main.reflectValueCall -> main.f
 | |
| 
 | |
| func reflectValueCallIndirect() {
 | |
| 	rvf := reflect.ValueOf(g)
 | |
| 	call := rvf.Call // kids, don't try this at home
 | |
| 
 | |
| 	// Indirect call uses shared contour.
 | |
| 	//
 | |
| 	// Also notice that argument position doesn't matter, and args
 | |
| 	// of inappropriate type (e.g. 'a') are ignored.
 | |
| 	res := call([]reflect.Value{
 | |
| 		reflect.ValueOf(&a),
 | |
| 		reflect.ValueOf(&false2),
 | |
| 	})
 | |
| 	res0 := res[0].Interface()
 | |
| 	print(res0)         // @types *int | *bool | *T
 | |
| 	print(res0.(*int))  // @pointsto main.b
 | |
| 	print(res0.(*bool)) // @pointsto main.false2
 | |
| 	print(res0.(hasF))  // @types *T
 | |
| 	print(res0.(*T))    // @pointsto new@newT2:19
 | |
| }
 | |
| 
 | |
| // @calls main.reflectValueCallIndirect -> (reflect.Value).Call$bound
 | |
| // @calls (reflect.Value).Call$bound -> main.g
 | |
| 
 | |
| func reflectTypeInOut() {
 | |
| 	var f func(float64, bool) (string, int)
 | |
| 	print(reflect.Zero(reflect.TypeOf(f).In(0)).Interface())    // @types float64
 | |
| 	print(reflect.Zero(reflect.TypeOf(f).In(1)).Interface())    // @types bool
 | |
| 	print(reflect.Zero(reflect.TypeOf(f).In(-1)).Interface())   // @types float64 | bool
 | |
| 	print(reflect.Zero(reflect.TypeOf(f).In(zero)).Interface()) // @types float64 | bool
 | |
| 
 | |
| 	print(reflect.Zero(reflect.TypeOf(f).Out(0)).Interface()) // @types string
 | |
| 	print(reflect.Zero(reflect.TypeOf(f).Out(1)).Interface()) // @types int
 | |
| 	print(reflect.Zero(reflect.TypeOf(f).Out(2)).Interface()) // @types
 | |
| 
 | |
| 	print(reflect.Zero(reflect.TypeOf(3).Out(0)).Interface()) // @types
 | |
| }
 | |
| 
 | |
| type hasF interface {
 | |
| 	F()
 | |
| }
 | |
| 
 | |
| type T struct{}
 | |
| 
 | |
| func (T) F()    {}
 | |
| func (T) g(int) {}
 | |
| 
 | |
| type U struct{}
 | |
| 
 | |
| func (U) F(int)    {}
 | |
| func (U) g(string) {}
 | |
| 
 | |
| type I interface {
 | |
| 	f()
 | |
| }
 | |
| 
 | |
| var nonconst string
 | |
| 
 | |
| func reflectTypeMethodByName() {
 | |
| 	TU := reflect.TypeOf([]interface{}{T{}, U{}}[0])
 | |
| 	print(reflect.Zero(TU)) // @types T | U
 | |
| 
 | |
| 	F, _ := TU.MethodByName("F")
 | |
| 	print(reflect.Zero(F.Type)) // @types func(T) | func(U, int)
 | |
| 	print(F.Func)               // @pointsto (main.T).F | (main.U).F
 | |
| 
 | |
| 	g, _ := TU.MethodByName("g")
 | |
| 	print(reflect.Zero(g.Type)) // @types func(T, int) | func(U, string)
 | |
| 	print(g.Func)               // @pointsto (main.T).g | (main.U).g
 | |
| 
 | |
| 	// Non-literal method names are treated less precisely.
 | |
| 	U := reflect.TypeOf(U{})
 | |
| 	X, _ := U.MethodByName(nonconst)
 | |
| 	print(reflect.Zero(X.Type)) // @types func(U, int) | func(U, string)
 | |
| 	print(X.Func)               // @pointsto (main.U).F | (main.U).g
 | |
| 
 | |
| 	// Interface methods.
 | |
| 	rThasF := reflect.TypeOf(new(hasF)).Elem()
 | |
| 	print(reflect.Zero(rThasF)) // @types hasF
 | |
| 	F2, _ := rThasF.MethodByName("F")
 | |
| 	print(reflect.Zero(F2.Type)) // @types func()
 | |
| 	print(F2.Func)               // @pointsto
 | |
| 
 | |
| }
 | |
| 
 | |
| func reflectTypeMethod() {
 | |
| 	m := reflect.TypeOf(T{}).Method(0)
 | |
| 	print(reflect.Zero(m.Type)) // @types func(T) | func(T, int)
 | |
| 	print(m.Func)               // @pointsto (main.T).F | (main.T).g
 | |
| }
 | |
| 
 | |
| func main() {
 | |
| 	reflectValueCall()
 | |
| 	reflectValueCallIndirect()
 | |
| 	reflectTypeInOut()
 | |
| 	reflectTypeMethodByName()
 | |
| 	reflectTypeMethod()
 | |
| }
 |