diff --git a/src/cmd/gc/order.c b/src/cmd/gc/order.c index 9e64eb7759..3027ed27d4 100644 --- a/src/cmd/gc/order.c +++ b/src/cmd/gc/order.c @@ -1028,11 +1028,21 @@ orderexpr(Node **np, Order *order) orderexprinplace(&n->right, order); break; - case OCALLFUNC: - case OCALLMETH: - case OCALLINTER: case OAPPEND: + case OCALLFUNC: + case OCALLINTER: + case OCALLMETH: + case OCAP: case OCOMPLEX: + case OCOPY: + case OIMAG: + case OLEN: + case OMAKECHAN: + case OMAKEMAP: + case OMAKESLICE: + case ONEW: + case OREAL: + case ORECOVER: ordercall(n, order); n = ordercopyexpr(n, n->type, order, 0); break; diff --git a/test/fixedbugs/bug491.go b/test/fixedbugs/bug491.go new file mode 100644 index 0000000000..f4b58af1e6 --- /dev/null +++ b/test/fixedbugs/bug491.go @@ -0,0 +1,110 @@ +// run + +// Copyright 2014 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. + +// Test order of calls to builtin functions. +// Discovered during CL 144530045 review. + +package main + +func main() { + // append + { + x := make([]int, 0) + f := func() int { x = make([]int, 2); return 2 } + a, b, c := append(x, 1), f(), append(x, 1) + if len(a) != 1 || len(c) != 3 { + bug() + println("append call not ordered:", len(a), b, len(c)) + } + } + + // cap + { + x := make([]int, 1) + f := func() int { x = make([]int, 3); return 2 } + a, b, c := cap(x), f(), cap(x) + if a != 1 || c != 3 { + bug() + println("cap call not ordered:", a, b, c) + } + } + + // complex + { + x := 1.0 + f := func() int { x = 3; return 2 } + a, b, c := complex(x, 0), f(), complex(x, 0) + if real(a) != 1 || real(c) != 3 { + bug() + println("complex call not ordered:", a, b, c) + } + } + + // copy + { + tmp := make([]int, 100) + x := make([]int, 1) + f := func() int { x = make([]int, 3); return 2 } + a, b, c := copy(tmp, x), f(), copy(tmp, x) + if a != 1 || c != 3 { + bug() + println("copy call not ordered:", a, b, c) + } + } + + // imag + { + x := 1i + f := func() int { x = 3i; return 2 } + a, b, c := imag(x), f(), imag(x) + if a != 1 || c != 3 { + bug() + println("imag call not ordered:", a, b, c) + } + } + + // len + { + x := make([]int, 1) + f := func() int { x = make([]int, 3); return 2 } + a, b, c := len(x), f(), len(x) + if a != 1 || c != 3 { + bug() + println("len call not ordered:", a, b, c) + } + } + + // make + { + x := 1 + f := func() int { x = 3; return 2 } + a, b, c := make([]int, x), f(), make([]int, x) + if len(a) != 1 || len(c) != 3 { + bug() + println("make call not ordered:", len(a), b, len(c)) + } + } + + // real + { + x := 1 + 0i + f := func() int { x = 3; return 2 } + a, b, c := real(x), f(), real(x) + if a != 1 || c != 3 { + bug() + println("real call not ordered:", a, b, c) + } + } +} + +var bugged = false + +func bug() { + if !bugged { + println("BUG") + bugged = true + } +} \ No newline at end of file diff --git a/test/fixedbugs/issue8761.go b/test/fixedbugs/issue8761.go new file mode 100644 index 0000000000..badf639fcc --- /dev/null +++ b/test/fixedbugs/issue8761.go @@ -0,0 +1,26 @@ +// compile + +// Copyright 2014 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. + +// issue 8761 +// used to confuse code generator into using temporary before initialization. +// caused 'variable live at entry' error in liveness analysis. + +package p + +func _() { + type C chan int + _ = [1][]C{[]C{make(chan int)}} +} + +func _() { + type C interface{} + _ = [1][]C{[]C{recover()}} +} + +func _() { + type C *int + _ = [1][]C{[]C{new(int)}} +} diff --git a/test/live.go b/test/live.go index ad2db27fa9..f15bb74ba1 100644 --- a/test/live.go +++ b/test/live.go @@ -586,14 +586,16 @@ func f39a() (x []int) { } func f39b() (x [10]*int) { - x = [10]*int{new(int)} // ERROR "live at call to newobject: x" - println() // ERROR "live at call to printnl: x" + x = [10]*int{} + x[0] = new(int) // ERROR "live at call to newobject: x" + println() // ERROR "live at call to printnl: x" return x } func f39c() (x [10]*int) { - x = [10]*int{new(int)} // ERROR "live at call to newobject: x" - println() // ERROR "live at call to printnl: x" + x = [10]*int{} + x[0] = new(int) // ERROR "live at call to newobject: x" + println() // ERROR "live at call to printnl: x" return } @@ -605,9 +607,8 @@ type T40 struct { } func newT40() *T40 { - ret := T40{ // ERROR "live at call to makemap: &ret" - make(map[int]int), - } + ret := T40{} + ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret" return &ret } @@ -618,9 +619,8 @@ func bad40() { } func good40() { - ret := T40{ // ERROR "live at call to makemap: ret" - make(map[int]int), - } + ret := T40{} + ret.m = make(map[int]int) // ERROR "live at call to makemap: ret" t := &ret println() // ERROR "live at call to printnl: ret" _ = t diff --git a/test/live2.go b/test/live2.go index 5762b2e289..ef6ad994cc 100644 --- a/test/live2.go +++ b/test/live2.go @@ -17,9 +17,8 @@ type T40 struct { } func newT40() *T40 { - ret := T40{ // ERROR "live at call to makemap: &ret" - make(map[int]int), - } + ret := T40{} + ret.m = make(map[int]int) // ERROR "live at call to makemap: &ret" return &ret } @@ -30,9 +29,8 @@ func bad40() { } func good40() { - ret := T40{ // ERROR "live at call to makemap: ret" - make(map[int]int), - } + ret := T40{} + ret.m = make(map[int]int) // ERROR "live at call to makemap: ret" t := &ret println() // ERROR "live at call to printnl: ret" _ = t