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 |
90 |
Members