aboutsummaryrefslogtreecommitdiff
path: root/test/live.go
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2016-09-15 13:29:17 -0700
committerKeith Randall <khr@golang.org>2016-09-15 20:47:01 +0000
commitb265d51789ea7ccf68787ebb30a2cdf03cc9d4fe (patch)
tree546044076992ff11e106325fe7bf7d8a08dd5c91 /test/live.go
parentf13701bf2f32fe48f6dcf9149b35b9ce3effe022 (diff)
downloadgo-b265d51789ea7ccf68787ebb30a2cdf03cc9d4fe.tar.gz
go-b265d51789ea7ccf68787ebb30a2cdf03cc9d4fe.zip
test,cmd/compile: remove _ssa file suffix
Everything is SSA now. Update #16357 Change-Id: I436dbe367b863ee81a3695a7d653ba4bfc5b0f6c Reviewed-on: https://go-review.googlesource.com/29232 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
Diffstat (limited to 'test/live.go')
-rw-r--r--test/live.go656
1 files changed, 656 insertions, 0 deletions
diff --git a/test/live.go b/test/live.go
new file mode 100644
index 0000000000..373b4e9c2f
--- /dev/null
+++ b/test/live.go
@@ -0,0 +1,656 @@
+// errorcheck -0 -l -live -wb=0
+
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// liveness tests with inlining disabled.
+// see also live2.go.
+
+package main
+
+func printnl()
+
+//go:noescape
+func printpointer(**int)
+
+//go:noescape
+func printintpointer(*int)
+
+//go:noescape
+func printstringpointer(*string)
+
+//go:noescape
+func printstring(string)
+
+//go:noescape
+func printbytepointer(*byte)
+
+func printint(int)
+
+func f1() {
+ var x *int
+ printpointer(&x) // ERROR "live at call to printpointer: x$"
+ printpointer(&x) // ERROR "live at call to printpointer: x$"
+}
+
+func f2(b bool) {
+ if b {
+ printint(0) // nothing live here
+ return
+ }
+ var x *int
+ printpointer(&x) // ERROR "live at call to printpointer: x$"
+ printpointer(&x) // ERROR "live at call to printpointer: x$"
+}
+
+func f3(b1, b2 bool) {
+ // Because x and y are ambiguously live, they appear
+ // live throughout the function, to avoid being poisoned
+ // in GODEBUG=gcdead=1 mode.
+
+ printint(0) // ERROR "live at call to printint: x y$"
+ if b1 == false {
+ printint(0) // ERROR "live at call to printint: x y$"
+ return
+ }
+
+ if b2 {
+ var x *int
+ printpointer(&x) // ERROR "live at call to printpointer: x y$"
+ printpointer(&x) // ERROR "live at call to printpointer: x y$"
+ } else {
+ var y *int
+ printpointer(&y) // ERROR "live at call to printpointer: x y$"
+ printpointer(&y) // ERROR "live at call to printpointer: x y$"
+ }
+ printint(0) // ERROR "f3: x \(type \*int\) is ambiguously live$" "f3: y \(type \*int\) is ambiguously live$" "live at call to printint: x y$"
+}
+
+// The old algorithm treated x as live on all code that
+// could flow to a return statement, so it included the
+// function entry and code above the declaration of x
+// but would not include an indirect use of x in an infinite loop.
+// Check that these cases are handled correctly.
+
+func f4(b1, b2 bool) { // x not live here
+ if b2 {
+ printint(0) // x not live here
+ return
+ }
+ var z **int
+ x := new(int)
+ *x = 42
+ z = &x
+ printint(**z) // ERROR "live at call to printint: x$"
+ if b2 {
+ printint(1) // x not live here
+ return
+ }
+ for {
+ printint(**z) // ERROR "live at call to printint: x$"
+ }
+}
+
+func f5(b1 bool) {
+ var z **int
+ if b1 {
+ x := new(int)
+ *x = 42
+ z = &x
+ } else {
+ y := new(int)
+ *y = 54
+ z = &y
+ }
+ printint(**z) // ERROR "f5: x \(type \*int\) is ambiguously live$" "f5: y \(type \*int\) is ambiguously live$" "live at call to printint: x y$"
+}
+
+// confusion about the _ result used to cause spurious "live at entry to f6: _".
+
+func f6() (_, y string) {
+ y = "hello"
+ return
+}
+
+// confusion about addressed results used to cause "live at entry to f7: x".
+
+func f7() (x string) {
+ _ = &x
+ x = "hello"
+ return
+}
+
+// ignoring block returns used to cause "live at entry to f8: x, y".
+
+func f8() (x, y string) {
+ return g8()
+}
+
+func g8() (string, string)
+
+// ignoring block assignments used to cause "live at entry to f9: x"
+// issue 7205
+
+var i9 interface{}
+
+func f9() bool {
+ g8()
+ x := i9
+ return x != interface{}(99.0i) // ERROR "live at call to convT2E: x.data x.type$"
+}
+
+// liveness formerly confused by UNDEF followed by RET,
+// leading to "live at entry to f10: ~r1" (unnamed result).
+
+func f10() string {
+ panic(1)
+}
+
+// liveness formerly confused by select, thinking runtime.selectgo
+// can return to next instruction; it always jumps elsewhere.
+// note that you have to use at least two cases in the select
+// to get a true select; smaller selects compile to optimized helper functions.
+
+var c chan *int
+var b bool
+
+// this used to have a spurious "live at entry to f11a: ~r0"
+func f11a() *int {
+ select { // ERROR "live at call to newselect: autotmp_[0-9]+$" "live at call to selectgo: autotmp_[0-9]+$"
+ case <-c: // ERROR "live at call to selectrecv: autotmp_[0-9]+$"
+ return nil
+ case <-c: // ERROR "live at call to selectrecv: autotmp_[0-9]+$"
+ return nil
+ }
+}
+
+func f11b() *int {
+ p := new(int)
+ if b {
+ // At this point p is dead: the code here cannot
+ // get to the bottom of the function.
+ // This used to have a spurious "live at call to printint: p".
+ printint(1) // nothing live here!
+ select { // ERROR "live at call to newselect: autotmp_[0-9]+$" "live at call to selectgo: autotmp_[0-9]+$"
+ case <-c: // ERROR "live at call to selectrecv: autotmp_[0-9]+$"
+ return nil
+ case <-c: // ERROR "live at call to selectrecv: autotmp_[0-9]+$"
+ return nil
+ }
+ }
+ println(*p)
+ return nil
+}
+
+var sink *int
+
+func f11c() *int {
+ p := new(int)
+ sink = p // prevent stack allocation, otherwise p is rematerializeable
+ if b {
+ // Unlike previous, the cases in this select fall through,
+ // so we can get to the println, so p is not dead.
+ printint(1) // ERROR "live at call to printint: p$"
+ select { // ERROR "live at call to newselect: autotmp_[0-9]+ p$" "live at call to selectgo: autotmp_[0-9]+ p$"
+ case <-c: // ERROR "live at call to selectrecv: autotmp_[0-9]+ p$"
+ case <-c: // ERROR "live at call to selectrecv: autotmp_[0-9]+ p$"
+ }
+ }
+ println(*p)
+ return nil
+}
+
+// similarly, select{} does not fall through.
+// this used to have a spurious "live at entry to f12: ~r0".
+
+func f12() *int {
+ if b {
+ select {}
+ } else {
+ return nil
+ }
+}
+
+// incorrectly placed VARDEF annotations can cause missing liveness annotations.
+// this used to be missing the fact that s is live during the call to g13 (because it is
+// needed for the call to h13).
+
+func f13() {
+ s := g14()
+ s = h13(s, g13(s)) // ERROR "live at call to g13: s.ptr$"
+}
+
+func g13(string) string
+func h13(string, string) string
+
+// more incorrectly placed VARDEF.
+
+func f14() {
+ x := g14()
+ printstringpointer(&x) // ERROR "live at call to printstringpointer: x$"
+}
+
+func g14() string
+
+func f15() {
+ var x string
+ _ = &x
+ x = g15() // ERROR "live at call to g15: x$"
+ printstring(x) // ERROR "live at call to printstring: x$"
+}
+
+func g15() string
+
+// Checking that various temporaries do not persist or cause
+// ambiguously live values that must be zeroed.
+// The exact temporary names are inconsequential but we are
+// trying to check that there is only one at any given site,
+// and also that none show up in "ambiguously live" messages.
+
+var m map[string]int
+
+func f16() {
+ if b {
+ delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$"
+ }
+ delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$"
+ delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$"
+}
+
+var m2s map[string]*byte
+var m2 map[[2]string]*byte
+var x2 [2]string
+var bp *byte
+
+func f17a() {
+ // value temporary only
+ if b {
+ m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+ }
+ m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+ m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+}
+
+func f17b() {
+ // key temporary only
+ if b {
+ m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+ }
+ m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+ m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+}
+
+func f17c() {
+ // key and value temporaries
+ if b {
+ m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+ }
+ m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+ m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+}
+
+func g18() [2]string
+
+func f18() {
+ // key temporary for mapaccess.
+ // temporary introduced by orderexpr.
+ var z *byte
+ if b {
+ z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ }
+ z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ printbytepointer(z)
+}
+
+var ch chan *byte
+
+func f19() {
+ // dest temporary for channel receive.
+ var z *byte
+
+ if b {
+ z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
+ }
+ z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
+ z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
+ printbytepointer(z)
+}
+
+func f20() {
+ // src temporary for channel send
+ if b {
+ ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$"
+ }
+ ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$"
+ ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$"
+}
+
+func f21() {
+ // key temporary for mapaccess using array literal key.
+ var z *byte
+ if b {
+ z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ }
+ z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ printbytepointer(z)
+}
+
+func f23() {
+ // key temporary for two-result map access using array literal key.
+ var z *byte
+ var ok bool
+ if b {
+ z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
+ }
+ z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
+ z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
+ printbytepointer(z)
+ print(ok)
+}
+
+func f24() {
+ // key temporary for map access using array literal key.
+ // value temporary too.
+ if b {
+ m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+ }
+ m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+ m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+}
+
+// defer should not cause spurious ambiguously live variables
+
+func f25(b bool) {
+ defer g25()
+ if b {
+ return
+ }
+ var x string
+ _ = &x
+ x = g15() // ERROR "live at call to g15: x$"
+ printstring(x) // ERROR "live at call to printstring: x$"
+} // ERROR "live at call to deferreturn: x$"
+
+func g25()
+
+// non-escaping ... slices passed to function call should die on return,
+// so that the temporaries do not stack and do not cause ambiguously
+// live variables.
+
+func f26(b bool) {
+ if b {
+ print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
+ }
+ print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
+ print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
+ printnl()
+}
+
+//go:noescape
+func print26(...interface{})
+
+// non-escaping closures passed to function call should die on return
+
+func f27(b bool) {
+ x := 0
+ if b {
+ call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
+ }
+ call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
+ call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
+ printnl()
+}
+
+// but defer does escape to later execution in the function
+
+func f27defer(b bool) {
+ x := 0
+ if b {
+ defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$"
+ }
+ defer call27(func() { x++ }) // ERROR "f27defer: autotmp_[0-9]+ \(type struct { F uintptr; x \*int }\) is ambiguously live$" "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$"
+ printnl() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
+} // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$"
+
+// and newproc (go) escapes to the heap
+
+func f27go(b bool) {
+ x := 0
+ if b {
+ go call27(func() { x++ }) // ERROR "live at call to newobject: &x$" "live at call to newproc: &x$"
+ }
+ go call27(func() { x++ }) // ERROR "live at call to newobject: &x$"
+ printnl()
+}
+
+//go:noescape
+func call27(func())
+
+// concatstring slice should die on return
+
+var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string
+
+func f28(b bool) {
+ if b {
+ printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+ }
+ printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+ printstring(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+}
+
+// map iterator should die on end of range loop
+
+func f29(b bool) {
+ if b {
+ for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
+ printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
+ }
+ }
+ for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
+ printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
+ }
+ for k := range m { // ERROR "live at call to mapiterinit: autotmp_[0-9]+$" "live at call to mapiternext: autotmp_[0-9]+$"
+ printstring(k) // ERROR "live at call to printstring: autotmp_[0-9]+$"
+ }
+}
+
+// copy of array of pointers should die at end of range loop
+
+var ptrarr [10]*int
+
+func f30(b bool) {
+ // two live temps during print(p):
+ // the copy of ptrarr and the internal iterator pointer.
+ if b {
+ for _, p := range ptrarr {
+ printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
+ }
+ }
+ for _, p := range ptrarr {
+ printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
+ }
+ for _, p := range ptrarr {
+ printintpointer(p) // ERROR "live at call to printintpointer: autotmp_[0-9]+ autotmp_[0-9]+$"
+ }
+}
+
+// conversion to interface should not leave temporary behind
+
+func f31(b1, b2, b3 bool) {
+ if b1 {
+ g31("a") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to g31: autotmp_[0-9]+$"
+ }
+ if b2 {
+ h31("b") // ERROR "live at call to convT2E: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to h31: autotmp_[0-9]+$" "live at call to newobject: autotmp_[0-9]+$"
+ }
+ if b3 {
+ panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to gopanic: autotmp_[0-9]+$"
+ }
+ print(b3)
+}
+
+func g31(interface{})
+func h31(...interface{})
+
+// non-escaping partial functions passed to function call should die on return
+
+type T32 int
+
+func (t *T32) Inc() { // ERROR "live at entry to \(\*T32\).Inc: t$"
+ *t++
+}
+
+var t32 T32
+
+func f32(b bool) {
+ if b {
+ call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$"
+ }
+ call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$"
+ call32(t32.Inc) // ERROR "live at call to call32: autotmp_[0-9]+$"
+}
+
+//go:noescape
+func call32(func())
+
+// temporaries introduced during if conditions and && || expressions
+// should die once the condition has been acted upon.
+
+var m33 map[interface{}]int
+
+func f33() {
+ if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ printnl()
+ return
+ } else {
+ printnl()
+ }
+ printnl()
+}
+
+func f34() {
+ if m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ printnl()
+ return
+ }
+ printnl()
+}
+
+func f35() {
+ if m33[nil] == 0 && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ printnl()
+ return
+ }
+ printnl()
+}
+
+func f36() {
+ if m33[nil] == 0 || m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ printnl()
+ return
+ }
+ printnl()
+}
+
+func f37() {
+ if (m33[nil] == 0 || m33[nil] == 0) && m33[nil] == 0 { // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ printnl()
+ return
+ }
+ printnl()
+}
+
+// select temps should disappear in the case bodies
+
+var c38 chan string
+
+func fc38() chan string
+func fi38(int) *string
+func fb38() *bool
+
+func f38(b bool) {
+ // we don't care what temps are printed on the lines with output.
+ // we care that the println lines have no live variables
+ // and therefore no output.
+ if b {
+ select { // ERROR "live at call to newselect: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to selectgo: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$"
+ case <-fc38(): // ERROR "live at call to selectrecv: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$"
+ printnl()
+ case fc38() <- *fi38(1): // ERROR "live at call to fc38: autotmp_[0-9]+$" "live at call to fi38: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to selectsend: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$"
+ printnl()
+ case *fi38(2) = <-fc38(): // ERROR "live at call to fc38: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to fi38: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to selectrecv: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$"
+ printnl()
+ case *fi38(3), *fb38() = <-fc38(): // ERROR "live at call to fb38: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to fc38: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to fi38: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to selectrecv2: autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+ autotmp_[0-9]+$"
+ printnl()
+ }
+ printnl()
+ }
+ printnl()
+}
+
+// issue 8097: mishandling of x = x during return.
+
+func f39() (x []int) {
+ x = []int{1}
+ printnl() // ERROR "live at call to printnl: autotmp_[0-9]+$"
+ return x
+}
+
+func f39a() (x []int) {
+ x = []int{1}
+ printnl() // ERROR "live at call to printnl: autotmp_[0-9]+$"
+ return
+}
+
+func f39b() (x [10]*int) {
+ x = [10]*int{}
+ x[0] = new(int) // ERROR "live at call to newobject: x$"
+ printnl() // ERROR "live at call to printnl: x$"
+ return x
+}
+
+func f39c() (x [10]*int) {
+ x = [10]*int{}
+ x[0] = new(int) // ERROR "live at call to newobject: x$"
+ printnl() // ERROR "live at call to printnl: x$"
+ return
+}
+
+// issue 8142: lost 'addrtaken' bit on inlined variables.
+// no inlining in this test, so just checking that non-inlined works.
+
+type T40 struct {
+ m map[int]int
+}
+
+func newT40() *T40 {
+ ret := T40{}
+ ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret$"
+ return &ret
+}
+
+func bad40() {
+ t := newT40()
+ _ = t
+ printnl()
+}
+
+func good40() {
+ ret := T40{}
+ ret.m = make(map[int]int) // ERROR "live at call to makemap: autotmp_[0-9]+ ret$"
+ t := &ret
+ printnl() // ERROR "live at call to printnl: autotmp_[0-9]+ ret$"
+ _ = t
+}
+
+func ddd1(x, y *int) { // ERROR "live at entry to ddd1: x y$"
+ ddd2(x, y) // ERROR "live at call to ddd2: x y autotmp_[0-9]+$"
+ printnl() // ERROR "live at call to printnl: x y$"
+ // Note: no autotmp live at printnl. See issue 16996.
+}
+func ddd2(a ...*int) { // ERROR "live at entry to ddd2: a$"
+ sink = a[0]
+}