github.com/powerman/golang-tools@v0.1.11-0.20220410185822-5ad214d8d803/go/pointer/testdata/finalizer.go (about)

     1  package main
     2  
     3  import "runtime"
     4  
     5  func final1a(x *int) int {
     6  	print(x) // @pointsto new@newint:10
     7  	return *x
     8  }
     9  
    10  func final1b(x *bool) {
    11  	print(x) // @pointsto
    12  }
    13  
    14  func runtimeSetFinalizer1() {
    15  	x := new(int)                    // @line newint
    16  	runtime.SetFinalizer(x, final1a) // ok: final1a's result is ignored
    17  	runtime.SetFinalizer(x, final1b) // param type mismatch: no effect
    18  }
    19  
    20  // @calls command-line-arguments.runtimeSetFinalizer1 -> command-line-arguments.final1a
    21  // @calls command-line-arguments.runtimeSetFinalizer1 -> command-line-arguments.final1b
    22  
    23  func final2a(x *bool) {
    24  	print(x) // @pointsto new@newbool1:10 | new@newbool2:10
    25  }
    26  
    27  func final2b(x *bool) {
    28  	print(x) // @pointsto new@newbool1:10 | new@newbool2:10
    29  }
    30  
    31  func runtimeSetFinalizer2() {
    32  	x := new(bool) // @line newbool1
    33  	f := final2a
    34  	if unknown {
    35  		x = new(bool) // @line newbool2
    36  		f = final2b
    37  	}
    38  	runtime.SetFinalizer(x, f)
    39  }
    40  
    41  // @calls command-line-arguments.runtimeSetFinalizer2 -> command-line-arguments.final2a
    42  // @calls command-line-arguments.runtimeSetFinalizer2 -> command-line-arguments.final2b
    43  
    44  type T int
    45  
    46  func (t *T) finalize() {
    47  	print(t) // @pointsto new@final3:10
    48  }
    49  
    50  func runtimeSetFinalizer3() {
    51  	x := new(T) // @line final3
    52  	runtime.SetFinalizer(x, (*T).finalize)
    53  }
    54  
    55  // @calls command-line-arguments.runtimeSetFinalizer3 -> (*command-line-arguments.T).finalize$thunk
    56  
    57  // I hope I never live to see this code in the wild.
    58  var setFinalizer = runtime.SetFinalizer
    59  
    60  func final4(x *int) {
    61  	print(x) // @pointsto new@finalIndirect:10
    62  }
    63  
    64  func runtimeSetFinalizerIndirect() {
    65  	// In an indirect call, the shared contour for SetFinalizer is
    66  	// used, i.e. the call is not inlined and appears in the call graph.
    67  	x := new(int) // @line finalIndirect
    68  	setFinalizer(x, final4)
    69  }
    70  
    71  // Exercise the elimination of SetFinalizer
    72  // constraints with non-pointer operands.
    73  func runtimeSetFinalizerNonpointer() {
    74  	runtime.SetFinalizer(nil, (*T).finalize) // x is a non-pointer
    75  	runtime.SetFinalizer((*T).finalize, nil) // f is a non-pointer
    76  }
    77  
    78  // @calls command-line-arguments.runtimeSetFinalizerIndirect -> runtime.SetFinalizer
    79  // @calls runtime.SetFinalizer -> command-line-arguments.final4
    80  
    81  func main() {
    82  	runtimeSetFinalizer1()
    83  	runtimeSetFinalizer2()
    84  	runtimeSetFinalizer3()
    85  	runtimeSetFinalizerIndirect()
    86  	runtimeSetFinalizerNonpointer()
    87  }
    88  
    89  var unknown bool // defeat dead-code elimination