1// run
2
3// Copyright 2014 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7// The liveness code used to say that, in func g, s was live
8// starting at its declaration, because it appears to have its
9// address taken by the closure (different s, but the parser
10// gets slightly confused, a separate bug). The liveness analysis
11// saw s as having its address taken but the register optimizer
12// did not. This mismatch meant that s would be marked live
13// (and therefore initialized) at the call to f, but the register optimizer
14// would optimize away the initialization of s before f, causing the
15// garbage collector to use unused data.
16// The register optimizer has been changed to respect the
17// same "address taken" flag that the liveness analysis uses,
18// even if it cannot see any address being taken in the actual
19// machine code. This is conservative but keeps the two consistent,
20// which is the most important thing.
21
22package main
23
24import "runtime"
25
26//go:noinline
27func f() interface{} {
28	runtime.GC()
29	return nil
30}
31
32//go:noinline
33func g() {
34	var s interface{}
35	_ = func() {
36		s := f()
37		_ = s
38	}
39	s = f()
40	useiface(s)
41	useiface(s)
42}
43
44//go:noinline
45func useiface(x interface{}) {
46}
47
48//go:noinline
49func h() {
50	var x [16]uintptr
51	for i := range x {
52		x[i] = 1
53	}
54
55	useint(x[0])
56	useint(x[1])
57	useint(x[2])
58	useint(x[3])
59}
60
61//go:noinline
62func useint(x uintptr) {
63}
64
65func main() {
66	// scribble non-zero values on stack
67	h()
68	// call function that used to let the garbage collector
69	// see uninitialized stack values; it will see the
70	// nonzero values.
71	g()
72}
73
74func big(x int) {
75	if x >= 0 {
76		big(x - 1)
77	}
78}
79