finalizer.go
2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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