mirror of
https://github.com/golang/go
synced 2024-11-26 03:57:57 -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
|
||||
}
|
||||
|
||||
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
|
||||
if n.Right != nil {
|
||||
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 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
|
||||
}
|
||||
|
||||
// TODO: Reenable after #14904 is fixed.
|
||||
//func f39b() (x [10]*int) {
|
||||
// x = [10]*int{}
|
||||
// x[0] = new(int) // E.R.R.O.R. "live at call to newobject: x$"
|
||||
// printnl() // E.R.R.O.R. "live at call to printnl: x$"
|
||||
// return x
|
||||
//}
|
||||
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{}
|
||||
|
Loading…
Reference in New Issue
Block a user