mirror of
https://github.com/golang/go
synced 2024-11-26 06:38:00 -07:00
cmd/compile: fix x=x assignments
No point in doing anything for x=x assignments. In addition, skipping these assignments prevents generating: VARDEF x COPY x -> x which is bad because x is incorrectly considered dead before the vardef. Fixes #14904 Change-Id: I6817055ec20bcc34a9648617e0439505ee355f82 Reviewed-on: https://go-review.googlesource.com/21470 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Dave Cheney <dave@cheney.net>
This commit is contained in:
parent
5c7ae10f66
commit
309144b7f1
@ -661,6 +661,17 @@ func (s *state) stmt(n *Node) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if n.Left == n.Right && n.Left.Op == ONAME {
|
||||||
|
// An x=x assignment. No point in doing anything
|
||||||
|
// here. In addition, skipping this assignment
|
||||||
|
// prevents generating:
|
||||||
|
// VARDEF x
|
||||||
|
// COPY x -> x
|
||||||
|
// which is bad because x is incorrectly considered
|
||||||
|
// dead before the vardef. See issue #14904.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
var t *Type
|
var t *Type
|
||||||
if n.Right != nil {
|
if n.Right != nil {
|
||||||
t = n.Right.Type
|
t = n.Right.Type
|
||||||
|
@ -99,3 +99,5 @@ func TestUnsafe(t *testing.T) { runTest(t, "unsafe_ssa.go") }
|
|||||||
func TestPhi(t *testing.T) { runTest(t, "phi_ssa.go") }
|
func TestPhi(t *testing.T) { runTest(t, "phi_ssa.go") }
|
||||||
|
|
||||||
func TestSlice(t *testing.T) { runTest(t, "slice.go") }
|
func TestSlice(t *testing.T) { runTest(t, "slice.go") }
|
||||||
|
|
||||||
|
func TestNamedReturn(t *testing.T) { runTest(t, "namedReturn.go") }
|
||||||
|
101
src/cmd/compile/internal/gc/testdata/namedReturn.go
vendored
Normal file
101
src/cmd/compile/internal/gc/testdata/namedReturn.go
vendored
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// run
|
||||||
|
|
||||||
|
// This test makes sure that naming named
|
||||||
|
// return variables in a return statement works.
|
||||||
|
// See issue #14904.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Our heap-allocated object that will be GC'd incorrectly.
|
||||||
|
// Note that we always check the second word because that's
|
||||||
|
// where 0xdeaddeaddeaddead is written.
|
||||||
|
type B [4]int
|
||||||
|
|
||||||
|
// small (SSAable) array
|
||||||
|
type T1 [3]*B
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func f1() (t T1) {
|
||||||
|
t[0] = &B{91, 92, 93, 94}
|
||||||
|
runtime.GC()
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// large (non-SSAable) array
|
||||||
|
type T2 [8]*B
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func f2() (t T2) {
|
||||||
|
t[0] = &B{91, 92, 93, 94}
|
||||||
|
runtime.GC()
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// small (SSAable) struct
|
||||||
|
type T3 struct {
|
||||||
|
a, b, c *B
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func f3() (t T3) {
|
||||||
|
t.a = &B{91, 92, 93, 94}
|
||||||
|
runtime.GC()
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// large (non-SSAable) struct
|
||||||
|
type T4 struct {
|
||||||
|
a, b, c, d, e, f *B
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func f4() (t T4) {
|
||||||
|
t.a = &B{91, 92, 93, 94}
|
||||||
|
runtime.GC()
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
var sink *B
|
||||||
|
|
||||||
|
func f5() int {
|
||||||
|
b := &B{91, 92, 93, 94}
|
||||||
|
t := T4{b, nil, nil, nil, nil, nil}
|
||||||
|
sink = b // make sure b is heap allocated ...
|
||||||
|
sink = nil // ... but not live
|
||||||
|
runtime.GC()
|
||||||
|
t = t
|
||||||
|
return t.a[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
failed := false
|
||||||
|
|
||||||
|
if v := f1()[0][1]; v != 92 {
|
||||||
|
fmt.Printf("f1()[0][1]=%d, want 92\n", v)
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
if v := f2()[0][1]; v != 92 {
|
||||||
|
fmt.Printf("f2()[0][1]=%d, want 92\n", v)
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
if v := f3().a[1]; v != 92 {
|
||||||
|
fmt.Printf("f3().a[1]=%d, want 92\n", v)
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
if v := f4().a[1]; v != 92 {
|
||||||
|
fmt.Printf("f4().a[1]=%d, want 92\n", v)
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
if v := f5(); v != 92 {
|
||||||
|
fmt.Printf("f5()=%d, want 92\n", v)
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
if failed {
|
||||||
|
panic("bad")
|
||||||
|
}
|
||||||
|
}
|
@ -606,13 +606,12 @@ func f39a() (x []int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Reenable after #14904 is fixed.
|
func f39b() (x [10]*int) {
|
||||||
//func f39b() (x [10]*int) {
|
x = [10]*int{}
|
||||||
// x = [10]*int{}
|
x[0] = new(int) // ERROR "live at call to newobject: x$"
|
||||||
// x[0] = new(int) // E.R.R.O.R. "live at call to newobject: x$"
|
printnl() // ERROR "live at call to printnl: x$"
|
||||||
// printnl() // E.R.R.O.R. "live at call to printnl: x$"
|
return x
|
||||||
// return x
|
}
|
||||||
//}
|
|
||||||
|
|
||||||
func f39c() (x [10]*int) {
|
func f39c() (x [10]*int) {
|
||||||
x = [10]*int{}
|
x = [10]*int{}
|
||||||
|
Loading…
Reference in New Issue
Block a user