mirror of
https://github.com/golang/go
synced 2024-11-26 08:38:01 -07:00
cmd/compile: fix "append outside assignment" ICE
Some special-case code paths in order.go didn't expect OCALLFUNC to have Ninit; in particular, OAS2FUNC and ODEFER/OGO failed to call o.init on their child OCALLFUNC node. This resulted in not all of the AST being properly ordered. This was noticed because order is responsible for introducing an invariant around how OAPPEND is used, which is enforced by walk. However, there were perhaps simpler cases (e.g., simple order of evaluation) that were being silently miscompiled. Fixes #31010. Change-Id: Ib928890ab5ec2aebd8e30a030bc2b404387f9123 Reviewed-on: https://go-review.googlesource.com/c/go/+/169257 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
270de1c110
commit
c4f87ed26f
@ -383,6 +383,10 @@ func (o *Order) init(n *Node) {
|
|||||||
// call orders the call expression n.
|
// call orders the call expression n.
|
||||||
// n.Op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
|
// n.Op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
|
||||||
func (o *Order) call(n *Node) {
|
func (o *Order) call(n *Node) {
|
||||||
|
if n.Ninit.Len() > 0 {
|
||||||
|
// Caller should have already called o.init(n).
|
||||||
|
Fatalf("%v with unexpected ninit", n.Op)
|
||||||
|
}
|
||||||
n.Left = o.expr(n.Left, nil)
|
n.Left = o.expr(n.Left, nil)
|
||||||
n.Right = o.expr(n.Right, nil) // ODDDARG temp
|
n.Right = o.expr(n.Right, nil) // ODDDARG temp
|
||||||
o.exprList(n.List)
|
o.exprList(n.List)
|
||||||
@ -578,6 +582,7 @@ func (o *Order) stmt(n *Node) {
|
|||||||
case OAS2FUNC:
|
case OAS2FUNC:
|
||||||
t := o.markTemp()
|
t := o.markTemp()
|
||||||
o.exprList(n.List)
|
o.exprList(n.List)
|
||||||
|
o.init(n.Rlist.First())
|
||||||
o.call(n.Rlist.First())
|
o.call(n.Rlist.First())
|
||||||
o.as2(n)
|
o.as2(n)
|
||||||
o.cleanTemp(t)
|
o.cleanTemp(t)
|
||||||
@ -637,6 +642,7 @@ func (o *Order) stmt(n *Node) {
|
|||||||
// Special: order arguments to inner call but not call itself.
|
// Special: order arguments to inner call but not call itself.
|
||||||
case ODEFER, OGO:
|
case ODEFER, OGO:
|
||||||
t := o.markTemp()
|
t := o.markTemp()
|
||||||
|
o.init(n.Left)
|
||||||
o.call(n.Left)
|
o.call(n.Left)
|
||||||
o.out = append(o.out, n)
|
o.out = append(o.out, n)
|
||||||
o.cleanTemp(t)
|
o.cleanTemp(t)
|
||||||
|
24
test/fixedbugs/issue31010.go
Normal file
24
test/fixedbugs/issue31010.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// compile
|
||||||
|
|
||||||
|
// Copyright 2019 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.
|
||||||
|
|
||||||
|
package p
|
||||||
|
|
||||||
|
var (
|
||||||
|
x int
|
||||||
|
xs []int
|
||||||
|
)
|
||||||
|
|
||||||
|
func a([]int) (int, error)
|
||||||
|
|
||||||
|
func b() (int, error) {
|
||||||
|
return a(append(xs, x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func c(int, error) (int, error)
|
||||||
|
|
||||||
|
func d() (int, error) {
|
||||||
|
return c(b())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user