90 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
| package main
 | |
| 
 | |
| import "runtime"
 | |
| 
 | |
| func final1a(x *int) int {
 | |
| 	print(x) // @pointsto new@newint:10
 | |
| 	return *x
 | |
| }
 | |
| 
 | |
| func final1b(x *bool) {
 | |
| 	print(x) // @pointsto
 | |
| }
 | |
| 
 | |
| func runtimeSetFinalizer1() {
 | |
| 	x := new(int)                    // @line newint
 | |
| 	runtime.SetFinalizer(x, final1a) // ok: final1a's result is ignored
 | |
| 	runtime.SetFinalizer(x, final1b) // param type mismatch: no effect
 | |
| }
 | |
| 
 | |
| // @calls main.runtimeSetFinalizer1 -> main.final1a
 | |
| // @calls main.runtimeSetFinalizer1 -> main.final1b
 | |
| 
 | |
| func final2a(x *bool) {
 | |
| 	print(x) // @pointsto new@newbool1:10 | new@newbool2:10
 | |
| }
 | |
| 
 | |
| func final2b(x *bool) {
 | |
| 	print(x) // @pointsto new@newbool1:10 | new@newbool2:10
 | |
| }
 | |
| 
 | |
| func runtimeSetFinalizer2() {
 | |
| 	x := new(bool) // @line newbool1
 | |
| 	f := final2a
 | |
| 	if unknown {
 | |
| 		x = new(bool) // @line newbool2
 | |
| 		f = final2b
 | |
| 	}
 | |
| 	runtime.SetFinalizer(x, f)
 | |
| }
 | |
| 
 | |
| // @calls main.runtimeSetFinalizer2 -> main.final2a
 | |
| // @calls main.runtimeSetFinalizer2 -> main.final2b
 | |
| 
 | |
| type T int
 | |
| 
 | |
| func (t *T) finalize() {
 | |
| 	print(t) // @pointsto new@final3:10
 | |
| }
 | |
| 
 | |
| func runtimeSetFinalizer3() {
 | |
| 	x := new(T) // @line final3
 | |
| 	runtime.SetFinalizer(x, (*T).finalize)
 | |
| }
 | |
| 
 | |
| // @calls main.runtimeSetFinalizer3 -> (*main.T).finalize$thunk
 | |
| 
 | |
| // I hope I never live to see this code in the wild.
 | |
| var setFinalizer = runtime.SetFinalizer
 | |
| 
 | |
| func final4(x *int) {
 | |
| 	print(x) // @pointsto new@finalIndirect:10
 | |
| }
 | |
| 
 | |
| func runtimeSetFinalizerIndirect() {
 | |
| 	// In an indirect call, the shared contour for SetFinalizer is
 | |
| 	// used, i.e. the call is not inlined and appears in the call graph.
 | |
| 	x := new(int) // @line finalIndirect
 | |
| 	setFinalizer(x, final4)
 | |
| }
 | |
| 
 | |
| // Exercise the elimination of SetFinalizer
 | |
| // constraints with non-pointer operands.
 | |
| func runtimeSetFinalizerNonpointer() {
 | |
| 	runtime.SetFinalizer(nil, (*T).finalize) // x is a non-pointer
 | |
| 	runtime.SetFinalizer((*T).finalize, nil) // f is a non-pointer
 | |
| }
 | |
| 
 | |
| // @calls main.runtimeSetFinalizerIndirect -> runtime.SetFinalizer
 | |
| // @calls runtime.SetFinalizer -> main.final4
 | |
| 
 | |
| func main() {
 | |
| 	runtimeSetFinalizer1()
 | |
| 	runtimeSetFinalizer2()
 | |
| 	runtimeSetFinalizer3()
 | |
| 	runtimeSetFinalizerIndirect()
 | |
| 	runtimeSetFinalizerNonpointer()
 | |
| }
 | |
| 
 | |
| var unknown bool // defeat dead-code elimination
 |