1package main 2 3import "runtime" 4 5func final1a(x *int) int { 6 print(x) // @pointsto new@newint:10 7 return *x 8} 9 10func final1b(x *bool) { 11 print(x) // @pointsto 12} 13 14func 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 main.runtimeSetFinalizer1 -> main.final1a 21// @calls main.runtimeSetFinalizer1 -> main.final1b 22 23func final2a(x *bool) { 24 print(x) // @pointsto new@newbool1:10 | new@newbool2:10 25} 26 27func final2b(x *bool) { 28 print(x) // @pointsto new@newbool1:10 | new@newbool2:10 29} 30 31func 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 main.runtimeSetFinalizer2 -> main.final2a 42// @calls main.runtimeSetFinalizer2 -> main.final2b 43 44type T int 45 46func (t *T) finalize() { 47 print(t) // @pointsto new@final3:10 48} 49 50func runtimeSetFinalizer3() { 51 x := new(T) // @line final3 52 runtime.SetFinalizer(x, (*T).finalize) 53} 54 55// @calls main.runtimeSetFinalizer3 -> (*main.T).finalize$thunk 56 57// I hope I never live to see this code in the wild. 58var setFinalizer = runtime.SetFinalizer 59 60func final4(x *int) { 61 print(x) // @pointsto new@finalIndirect:10 62} 63 64func 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. 73func 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 main.runtimeSetFinalizerIndirect -> runtime.SetFinalizer 79// @calls runtime.SetFinalizer -> main.final4 80 81func main() { 82 runtimeSetFinalizer1() 83 runtimeSetFinalizer2() 84 runtimeSetFinalizer3() 85 runtimeSetFinalizerIndirect() 86 runtimeSetFinalizerNonpointer() 87} 88 89var unknown bool // defeat dead-code elimination 90