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  }