mirror of
https://github.com/golang/go
synced 2024-11-11 19:51:37 -07:00
cmd/compile: s.f aliases itself
The change in 20907 fixed varexpr but broke aliased. After that change, a reference to a field in a struct would not be seen as aliasing itself. Before that change, it would, but only because all fields in a struct aliased everything. This CL changes the compiler to consider all references to a field as aliasing all other fields in that struct. This is imperfect--a reference to one field does not alias another field--but is a simple fix for the immediate problem. A better fix would require tracking the specific fields as well. Fixes #15042. Change-Id: I5c95c0dd7b0699e53022fce9bae2e8f50d6d1d04 Reviewed-on: https://go-review.googlesource.com/21390 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
1bf779a44a
commit
92bb694a49
@ -2335,6 +2335,12 @@ func aliased(n *Node, all []*Node, i int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Treat all fields of a struct as referring to the whole struct.
|
||||
// We could do better but we would have to keep track of the fields.
|
||||
for n.Op == ODOT {
|
||||
n = n.Left
|
||||
}
|
||||
|
||||
// Look for obvious aliasing: a variable being assigned
|
||||
// during the all list and appearing in n.
|
||||
// Also record whether there are any writes to main memory.
|
||||
@ -2346,6 +2352,11 @@ func aliased(n *Node, all []*Node, i int) bool {
|
||||
var a *Node
|
||||
for _, an := range all[:i] {
|
||||
a = outervalue(an.Left)
|
||||
|
||||
for a.Op == ODOT {
|
||||
a = a.Left
|
||||
}
|
||||
|
||||
if a.Op != ONAME {
|
||||
memwrite = 1
|
||||
continue
|
||||
@ -2436,7 +2447,8 @@ func varexpr(n *Node) bool {
|
||||
return varexpr(n.Left) && varexpr(n.Right)
|
||||
|
||||
case ODOT: // but not ODOTPTR
|
||||
return varexpr(n.Left)
|
||||
// Should have been handled in aliased.
|
||||
Fatalf("varexpr unexpected ODOT")
|
||||
}
|
||||
|
||||
// Be conservative.
|
||||
|
27
test/fixedbugs/issue15042.go
Normal file
27
test/fixedbugs/issue15042.go
Normal file
@ -0,0 +1,27 @@
|
||||
// run
|
||||
|
||||
// Copyright 2016 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.
|
||||
|
||||
// Exchanging two struct fields was compiled incorrectly.
|
||||
|
||||
package main
|
||||
|
||||
type S struct {
|
||||
i int
|
||||
}
|
||||
|
||||
func F(c bool, s1, s2 S) (int, int) {
|
||||
if c {
|
||||
s1.i, s2.i = s2.i, s1.i
|
||||
}
|
||||
return s1.i, s2.i
|
||||
}
|
||||
|
||||
func main() {
|
||||
i, j := F(true, S{1}, S{20})
|
||||
if i != 20 || j != 1 {
|
||||
panic(i+j)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user