1// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// This test makes sure that naming named
6// return variables in a return statement works.
7// See issue #14904.
8
9package main
10
11import (
12	"runtime"
13	"testing"
14)
15
16// Our heap-allocated object that will be GC'd incorrectly.
17// Note that we always check the second word because that's
18// where 0xdeaddeaddeaddead is written.
19type B [4]int
20
21// small (SSAable) array
22type A1 [3]*B
23
24//go:noinline
25func f1() (t A1) {
26	t[0] = &B{91, 92, 93, 94}
27	runtime.GC()
28	return t
29}
30
31// large (non-SSAable) array
32type A2 [8]*B
33
34//go:noinline
35func f2() (t A2) {
36	t[0] = &B{91, 92, 93, 94}
37	runtime.GC()
38	return t
39}
40
41// small (SSAable) struct
42type A3 struct {
43	a, b, c *B
44}
45
46//go:noinline
47func f3() (t A3) {
48	t.a = &B{91, 92, 93, 94}
49	runtime.GC()
50	return t
51}
52
53// large (non-SSAable) struct
54type A4 struct {
55	a, b, c, d, e, f *B
56}
57
58//go:noinline
59func f4() (t A4) {
60	t.a = &B{91, 92, 93, 94}
61	runtime.GC()
62	return t
63}
64
65var sink *B
66
67func f5() int {
68	b := &B{91, 92, 93, 94}
69	t := A4{b, nil, nil, nil, nil, nil}
70	sink = b   // make sure b is heap allocated ...
71	sink = nil // ... but not live
72	runtime.GC()
73	t = t
74	return t.a[1]
75}
76
77func TestNamedReturn(t *testing.T) {
78	if v := f1()[0][1]; v != 92 {
79		t.Errorf("f1()[0][1]=%d, want 92\n", v)
80	}
81	if v := f2()[0][1]; v != 92 {
82		t.Errorf("f2()[0][1]=%d, want 92\n", v)
83	}
84	if v := f3().a[1]; v != 92 {
85		t.Errorf("f3().a[1]=%d, want 92\n", v)
86	}
87	if v := f4().a[1]; v != 92 {
88		t.Errorf("f4().a[1]=%d, want 92\n", v)
89	}
90	if v := f5(); v != 92 {
91		t.Errorf("f5()=%d, want 92\n", v)
92	}
93}
94