summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2014-10-22 11:21:16 -0400
committerAustin Clements <austin@google.com>2014-10-22 11:21:16 -0400
commit2c586384223e980fd3303625ea6b02ed5d9fb9c0 (patch)
tree54aa72cd9d5eb1566f682d3b0770141a11b54fc2 /test
parentebe8a09fb603d9510cb982a6c11a3e1638f7f8fb (diff)
parent45fcda1dc8d9b4d4a9b642faf8e78941873f508d (diff)
downloadgo-2c586384223e980fd3303625ea6b02ed5d9fb9c0.tar.gz
[dev.power64] build: merge default into dev.power64
LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/160200044
Diffstat (limited to 'test')
-rw-r--r--test/fixedbugs/bug490.go16
-rw-r--r--test/fixedbugs/issue4388.go6
-rw-r--r--test/fixedbugs/issue5856.go2
-rw-r--r--test/fixedbugs/issue7760.go25
-rw-r--r--test/fixedbugs/issue8325.go31
-rw-r--r--test/fixedbugs/issue8336.go29
-rw-r--r--test/fixedbugs/issue8475.go25
-rw-r--r--test/fixedbugs/issue8612.go34
-rw-r--r--test/live.go53
-rw-r--r--test/map.go2
-rw-r--r--test/maplinear.go143
-rw-r--r--test/mapnan.go56
-rw-r--r--test/named1.go8
-rw-r--r--test/nosplit.go10
-rw-r--r--test/recover.go48
-rw-r--r--test/slice3.go18
-rw-r--r--test/slicecap.go90
17 files changed, 496 insertions, 100 deletions
diff --git a/test/fixedbugs/bug490.go b/test/fixedbugs/bug490.go
new file mode 100644
index 000000000..7d05f3945
--- /dev/null
+++ b/test/fixedbugs/bug490.go
@@ -0,0 +1,16 @@
+// 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.
+
+// The gccgo compiler used to crash building a comparison between an
+// interface and an empty struct literal.
+
+package p
+
+type S struct{}
+
+func F(v interface{}) bool {
+ return v == S{}
+}
diff --git a/test/fixedbugs/issue4388.go b/test/fixedbugs/issue4388.go
index 2e052e138..b18c98bac 100644
--- a/test/fixedbugs/issue4388.go
+++ b/test/fixedbugs/issue4388.go
@@ -17,18 +17,18 @@ type T struct {
}
func f1() {
- // The 4 here and below depends on the number of internal runtime frames
+ // The 5 here and below depends on the number of internal runtime frames
// that sit between a deferred function called during panic and
// the original frame. If that changes, this test will start failing and
// the number here will need to be updated.
- defer checkLine(4)
+ defer checkLine(5)
var t *T
var c io.Closer = t
c.Close()
}
func f2() {
- defer checkLine(4)
+ defer checkLine(5)
var t T
var c io.Closer = t
c.Close()
diff --git a/test/fixedbugs/issue5856.go b/test/fixedbugs/issue5856.go
index 35cadf8c9..78ca3b9f6 100644
--- a/test/fixedbugs/issue5856.go
+++ b/test/fixedbugs/issue5856.go
@@ -29,7 +29,7 @@ func f() {
}
func g() {
- _, file, line, _ := runtime.Caller(2)
+ _, file, line, _ := runtime.Caller(3)
if !strings.HasSuffix(file, "issue5856.go") || line != 28 {
fmt.Printf("BUG: defer called from %s:%d, want issue5856.go:28\n", file, line)
os.Exit(1)
diff --git a/test/fixedbugs/issue7760.go b/test/fixedbugs/issue7760.go
new file mode 100644
index 000000000..cccae4891
--- /dev/null
+++ b/test/fixedbugs/issue7760.go
@@ -0,0 +1,25 @@
+// errorcheck
+
+// 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.
+
+// Verify that pointers can't be used as constants.
+
+package main
+
+import "unsafe"
+
+type myPointer unsafe.Pointer
+
+const _ = unsafe.Pointer(uintptr(1)) // ERROR "is not (a )?constant"
+const _ = myPointer(uintptr(1)) // ERROR "is not (a )?constant"
+
+const _ = (*int)(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant"
+const _ = (*int)(myPointer(uintptr(1))) // ERROR "is not (a )?constant"
+
+const _ = uintptr(unsafe.Pointer(uintptr(1))) // ERROR "is not (a )?constant"
+const _ = uintptr(myPointer(uintptr(1))) // ERROR "is not (a )?constant"
+
+const _ = []byte("") // ERROR "is not (a )?constant"
+const _ = []rune("") // ERROR "is not (a )?constant"
diff --git a/test/fixedbugs/issue8325.go b/test/fixedbugs/issue8325.go
new file mode 100644
index 000000000..e22fd319d
--- /dev/null
+++ b/test/fixedbugs/issue8325.go
@@ -0,0 +1,31 @@
+// 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.
+
+// Issue 8325: corrupted byte operations during optimization
+// pass.
+
+package main
+
+const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+func main() {
+ var bytes = []byte{10, 20, 30, 40, 50}
+
+ for i, b := range bytes {
+ bytes[i] = alphanum[b%byte(len(alphanum))]
+ }
+
+ for _, b := range bytes {
+ switch {
+ case '0' <= b && b <= '9',
+ 'A' <= b && b <= 'Z':
+ default:
+ println("found a bad character", string(b))
+ panic("BUG")
+ }
+
+ }
+}
diff --git a/test/fixedbugs/issue8336.go b/test/fixedbugs/issue8336.go
new file mode 100644
index 000000000..26bdeabb2
--- /dev/null
+++ b/test/fixedbugs/issue8336.go
@@ -0,0 +1,29 @@
+// 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.
+
+// Issue 8336. Order of evaluation of receive channels in select.
+
+package main
+
+type X struct {
+ c chan int
+}
+
+func main() {
+ defer func() {
+ recover()
+ }()
+ var x *X
+ select {
+ case <-x.c: // should fault and panic before foo is called
+ case <-foo():
+ }
+}
+
+func foo() chan int {
+ println("BUG: foo must not be called")
+ return make(chan int)
+}
diff --git a/test/fixedbugs/issue8475.go b/test/fixedbugs/issue8475.go
new file mode 100644
index 000000000..e69794534
--- /dev/null
+++ b/test/fixedbugs/issue8475.go
@@ -0,0 +1,25 @@
+// build
+
+// 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 8745: comma-ok assignments should produce untyped bool as 2nd result.
+
+package main
+
+type mybool bool
+
+func main() {
+ var ok mybool
+ _ = ok
+
+ var i interface{}
+ _, ok = i.(int)
+
+ var m map[int]int
+ _, ok = m[0]
+
+ var c chan int
+ _, ok = <-c
+}
diff --git a/test/fixedbugs/issue8612.go b/test/fixedbugs/issue8612.go
new file mode 100644
index 000000000..93370cf66
--- /dev/null
+++ b/test/fixedbugs/issue8612.go
@@ -0,0 +1,34 @@
+//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.
+
+// Gccgo had a bug comparing a struct or array value with an interface
+// values, when the struct or array was not addressable.
+
+package p
+
+type A [10]int
+
+type S struct {
+ i int
+}
+
+func F1() S {
+ return S{0}
+}
+
+func F2() A {
+ return A{}
+}
+
+func Cmp(v interface{}) bool {
+ if F1() == v {
+ return true
+ }
+ if F2() == v {
+ return true
+ }
+ return false
+}
diff --git a/test/live.go b/test/live.go
index 6ac1d6a46..35099d18b 100644
--- a/test/live.go
+++ b/test/live.go
@@ -118,7 +118,10 @@ var i9 interface{}
func f9() bool {
g8()
x := i9
- return x != 99
+ // using complex number in comparison so that
+ // there is always a convT2E, no matter what the
+ // interface rules are.
+ return x != 99.0i // ERROR "live at call to convT2E: x"
}
// liveness formerly confused by UNDEF followed by RET,
@@ -184,7 +187,7 @@ func f11c() *int {
func f12() *int {
if b {
- select{}
+ select {}
} else {
return nil
}
@@ -215,7 +218,7 @@ func f15() {
var x string
_ = &x
x = g15() // ERROR "live at call to g15: x"
- print(x) // ERROR "live at call to printstring: x"
+ print(x) // ERROR "live at call to printstring: x"
}
func g15() string
@@ -287,7 +290,7 @@ var ch chan *byte
func f19() {
// dest temporary for channel receive.
var z *byte
-
+
if b {
z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
}
@@ -348,21 +351,21 @@ func f25(b bool) {
var x string
_ = &x
x = g15() // ERROR "live at call to g15: x"
- print(x) // ERROR "live at call to printstring: x"
+ print(x) // ERROR "live at call to printstring: x"
} // ERROR "live at call to deferreturn: x"
func g25()
-
+
// non-escaping ... slices passed to function call should die on return,
// so that the temporaries do not stack and do not cause ambiguously
// live variables.
func f26(b bool) {
if b {
- print26(1,2,3) // ERROR "live at call to print26: autotmp_[0-9]+$"
+ print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
}
- print26(4,5,6) // ERROR "live at call to print26: autotmp_[0-9]+$"
- print26(7,8,9) // ERROR "live at call to print26: autotmp_[0-9]+$"
+ print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
+ print26((*int)(nil), (*int)(nil), (*int)(nil)) // ERROR "live at call to print26: autotmp_[0-9]+$"
println()
}
@@ -374,10 +377,10 @@ func print26(...interface{})
func f27(b bool) {
x := 0
if b {
- call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$"
+ call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
}
- call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$"
- call27(func() {x++}) // ERROR "live at call to call27: autotmp_[0-9]+$"
+ call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
+ call27(func() { x++ }) // ERROR "live at call to call27: autotmp_[0-9]+$"
println()
}
@@ -386,10 +389,10 @@ func f27(b bool) {
func f27defer(b bool) {
x := 0
if b {
- defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$"
+ defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+$"
}
- defer call27(func() {x++}) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live"
- println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
+ defer call27(func() { x++ }) // ERROR "live at call to deferproc: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$" "ambiguously live"
+ println() // ERROR "live at call to printnl: autotmp_[0-9]+ autotmp_[0-9]+$"
} // ERROR "live at call to deferreturn: autotmp_[0-9]+ autotmp_[0-9]+$"
// and newproc (go) escapes to the heap
@@ -397,9 +400,9 @@ func f27defer(b bool) {
func f27go(b bool) {
x := 0
if b {
- go call27(func() {x++}) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$"
+ go call27(func() { x++ }) // ERROR "live at call to newobject: &x" "live at call to newproc: &x$"
}
- go call27(func() {x++}) // ERROR "live at call to newobject: &x"
+ go call27(func() { x++ }) // ERROR "live at call to newobject: &x"
println()
}
@@ -412,11 +415,11 @@ var s1, s2, s3, s4, s5, s6, s7, s8, s9, s10 string
func f28(b bool) {
if b {
- print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+ print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
}
- print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
- print(s1+s2+s3+s4+s5+s6+s7+s8+s9+s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
-}
+ print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+ print(s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10) // ERROR "live at call to concatstrings: autotmp_[0-9]+$" "live at call to printstring: autotmp_[0-9]+$"
+}
// map iterator should die on end of range loop
@@ -464,7 +467,7 @@ func f31(b1, b2, b3 bool) {
h31("b") // ERROR "live at call to newobject: autotmp_[0-9]+$" "live at call to convT2E: autotmp_[0-9]+ autotmp_[0-9]+$" "live at call to h31: autotmp_[0-9]+$"
}
if b3 {
- panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to panic: autotmp_[0-9]+$"
+ panic("asdf") // ERROR "live at call to convT2E: autotmp_[0-9]+$" "live at call to gopanic: autotmp_[0-9]+$"
}
print(b3)
}
@@ -584,13 +587,13 @@ 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"
+ 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"
+ println() // ERROR "live at call to printnl: x"
return
}
@@ -603,7 +606,7 @@ type T40 struct {
func newT40() *T40 {
ret := T40{ // ERROR "live at call to makemap: &ret"
- make(map[int]int),
+ make(map[int]int),
}
return &ret
}
diff --git a/test/map.go b/test/map.go
index 485e743fe..2c1cf8a14 100644
--- a/test/map.go
+++ b/test/map.go
@@ -5,7 +5,7 @@
// license that can be found in the LICENSE file.
// Test maps, almost exhaustively.
-// NaN complexity test is in mapnan.go.
+// Complexity (linearity) test is in maplinear.go.
package main
diff --git a/test/maplinear.go b/test/maplinear.go
new file mode 100644
index 000000000..56e50951a
--- /dev/null
+++ b/test/maplinear.go
@@ -0,0 +1,143 @@
+// +build darwin linux
+// run
+
+// Copyright 2013 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 that maps don't go quadratic for NaNs and other values.
+
+package main
+
+import (
+ "fmt"
+ "math"
+ "time"
+)
+
+// checkLinear asserts that the running time of f(n) is in O(n).
+// tries is the initial number of iterations.
+func checkLinear(typ string, tries int, f func(n int)) {
+ // Depending on the machine and OS, this test might be too fast
+ // to measure with accurate enough granularity. On failure,
+ // make it run longer, hoping that the timing granularity
+ // is eventually sufficient.
+
+ timeF := func(n int) time.Duration {
+ t1 := time.Now()
+ f(n)
+ return time.Since(t1)
+ }
+
+ t0 := time.Now()
+
+ n := tries
+ fails := 0
+ for {
+ t1 := timeF(n)
+ t2 := timeF(2 * n)
+
+ // should be 2x (linear); allow up to 3x
+ if t2 < 3*t1 {
+ if false {
+ fmt.Println(typ, "\t", time.Since(t0))
+ }
+ return
+ }
+ fails++
+ if fails == 6 {
+ panic(fmt.Sprintf("%s: too slow: %d inserts: %v; %d inserts: %v\n",
+ typ, n, t1, 2*n, t2))
+ }
+ if fails < 4 {
+ n *= 2
+ }
+ }
+}
+
+type I interface {
+ f()
+}
+
+type C int
+
+func (C) f() {}
+
+func main() {
+ // NaNs. ~31ms on a 1.6GHz Zeon.
+ checkLinear("NaN", 30000, func(n int) {
+ m := map[float64]int{}
+ nan := math.NaN()
+ for i := 0; i < n; i++ {
+ m[nan] = 1
+ }
+ if len(m) != n {
+ panic("wrong size map after nan insertion")
+ }
+ })
+
+ // ~6ms on a 1.6GHz Zeon.
+ checkLinear("eface", 10000, func(n int) {
+ m := map[interface{}]int{}
+ for i := 0; i < n; i++ {
+ m[i] = 1
+ }
+ })
+
+ // ~7ms on a 1.6GHz Zeon.
+ // Regression test for CL 119360043.
+ checkLinear("iface", 10000, func(n int) {
+ m := map[I]int{}
+ for i := 0; i < n; i++ {
+ m[C(i)] = 1
+ }
+ })
+
+ // ~6ms on a 1.6GHz Zeon.
+ checkLinear("int", 10000, func(n int) {
+ m := map[int]int{}
+ for i := 0; i < n; i++ {
+ m[i] = 1
+ }
+ })
+
+ // ~18ms on a 1.6GHz Zeon.
+ checkLinear("string", 10000, func(n int) {
+ m := map[string]int{}
+ for i := 0; i < n; i++ {
+ m[fmt.Sprint(i)] = 1
+ }
+ })
+
+ // ~6ms on a 1.6GHz Zeon.
+ checkLinear("float32", 10000, func(n int) {
+ m := map[float32]int{}
+ for i := 0; i < n; i++ {
+ m[float32(i)] = 1
+ }
+ })
+
+ // ~6ms on a 1.6GHz Zeon.
+ checkLinear("float64", 10000, func(n int) {
+ m := map[float64]int{}
+ for i := 0; i < n; i++ {
+ m[float64(i)] = 1
+ }
+ })
+
+ // ~22ms on a 1.6GHz Zeon.
+ checkLinear("complex64", 10000, func(n int) {
+ m := map[complex64]int{}
+ for i := 0; i < n; i++ {
+ m[complex(float32(i), float32(i))] = 1
+ }
+ })
+
+ // ~32ms on a 1.6GHz Zeon.
+ checkLinear("complex128", 10000, func(n int) {
+ m := map[complex128]int{}
+ for i := 0; i < n; i++ {
+ m[complex(float64(i), float64(i))] = 1
+ }
+ })
+}
diff --git a/test/mapnan.go b/test/mapnan.go
deleted file mode 100644
index f081cab01..000000000
--- a/test/mapnan.go
+++ /dev/null
@@ -1,56 +0,0 @@
-// +build darwin linux
-// run
-
-// Copyright 2013 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 that NaNs in maps don't go quadratic.
-
-package main
-
-import (
- "fmt"
- "math"
- "time"
-)
-
-func main() {
-
- // Test that NaNs in maps don't go quadratic.
- t := func(n int) time.Duration {
- t1 := time.Now()
- m := map[float64]int{}
- nan := math.NaN()
- for i := 0; i < n; i++ {
- m[nan] = 1
- }
- if len(m) != n {
- panic("wrong size map after nan insertion")
- }
- return time.Since(t1)
- }
-
- // Depending on the machine and OS, this test might be too fast
- // to measure with accurate enough granularity. On failure,
- // make it run longer, hoping that the timing granularity
- // is eventually sufficient.
-
- n := 30000 // ~8ms user time on a Mid 2011 MacBook Air (1.8 GHz Core i7)
- fails := 0
- for {
- t1 := t(n)
- t2 := t(2 * n)
- // should be 2x (linear); allow up to 3x
- if t2 < 3*t1 {
- return
- }
- fails++
- if fails == 6 {
- panic(fmt.Sprintf("too slow: %d inserts: %v; %d inserts: %v\n", n, t1, 2*n, t2))
- }
- if fails < 4 {
- n *= 2
- }
- }
-}
diff --git a/test/named1.go b/test/named1.go
index 62b874c5c..febad64ec 100644
--- a/test/named1.go
+++ b/test/named1.go
@@ -41,21 +41,21 @@ func main() {
asBool(1 != 2) // ok now
asBool(i < j) // ok now
- _, b = m[2] // ERROR "cannot .* bool.*type Bool"
+ _, b = m[2] // ok now
var inter interface{}
- _, b = inter.(Map) // ERROR "cannot .* bool.*type Bool"
+ _, b = inter.(Map) // ok now
_ = b
var minter interface {
M()
}
- _, b = minter.(Map) // ERROR "cannot .* bool.*type Bool"
+ _, b = minter.(Map) // ok now
_ = b
_, bb := <-c
asBool(bb) // ERROR "cannot use.*type bool.*as type Bool"
- _, b = <-c // ERROR "cannot .* bool.*type Bool"
+ _, b = <-c // ok now
_ = b
asString(String(slice)) // ok
diff --git a/test/nosplit.go b/test/nosplit.go
index b5399ad38..8dab2fc7a 100644
--- a/test/nosplit.go
+++ b/test/nosplit.go
@@ -251,7 +251,7 @@ TestCases:
if line == "" {
continue
}
- for _, subline := range strings.Split(line, ";") {
+ for i, subline := range strings.Split(line, ";") {
subline = strings.TrimSpace(subline)
if subline == "" {
continue
@@ -264,6 +264,14 @@ TestCases:
}
name := m[1]
size, _ := strconv.Atoi(m[2])
+
+ // The limit was originally 128 but is now 384.
+ // Instead of rewriting the test cases above, adjust
+ // the first stack frame to use up the extra 32 bytes.
+ if i == 0 {
+ size += 384 - 128
+ }
+
if size%ptrSize == 4 {
continue TestCases
}
diff --git a/test/recover.go b/test/recover.go
index 071be6667..6287d6507 100644
--- a/test/recover.go
+++ b/test/recover.go
@@ -47,6 +47,7 @@ func main() {
test11reflect1()
test11reflect2()
}
+ test111()
test12()
if !interp {
test12reflect1()
@@ -77,7 +78,7 @@ func mustRecoverBody(v1, v2, v3, x interface{}) {
}
v = v2
if v == nil {
- println("missing recover")
+ println("missing recover", x.(int))
die() // panic is useless here
}
if v != x {
@@ -137,7 +138,7 @@ func test1WithClosures() {
mustNotRecover()
v := recover()
if v == nil {
- println("missing recover")
+ println("missing recover", x.(int))
die()
}
if v != x {
@@ -406,6 +407,49 @@ func test11reflect2() {
panic(11)
}
+// tiny receiver, so basic wrapper in i.M()
+type T3deeper struct{}
+
+func (T3deeper) M() {
+ badstate() // difference from T3
+ mustRecoverBody(doubleRecover(), recover(), recover(), 111)
+}
+
+func test111() {
+ var i I = T3deeper{}
+ defer i.M()
+ panic(111)
+}
+
+type Tiny struct{}
+
+func (Tiny) M() {
+ panic(112)
+}
+
+// i.M is a wrapper, and i.M panics.
+//
+// This is a torture test for an old implementation of recover that
+// tried to deal with wrapper functions by doing some argument
+// positioning math on both entry and exit. Doing anything on exit
+// is a problem because sometimes functions exit via panic instead
+// of an ordinary return, so panic would have to know to do the
+// same math when unwinding the stack. It gets complicated fast.
+// This particular test never worked with the old scheme, because
+// panic never did the right unwinding math.
+//
+// The new scheme adjusts Panic.argp on entry to a wrapper.
+// It has no exit work, so if a wrapper is interrupted by a panic,
+// there's no cleanup that panic itself must do.
+// This test just works now.
+func badstate() {
+ defer func() {
+ recover()
+ }()
+ var i I = Tiny{}
+ i.M()
+}
+
// large receiver, so basic wrapper in i.M()
type T4 [2]string
diff --git a/test/slice3.go b/test/slice3.go
index 3cf34b57e..857eaf3a0 100644
--- a/test/slice3.go
+++ b/test/slice3.go
@@ -19,10 +19,10 @@ var bout *bufio.Writer
func main() {
bout = bufio.NewWriter(os.Stdout)
-
+
fmt.Fprintf(bout, "%s", programTop)
fmt.Fprintf(bout, "func main() {\n")
-
+
index := []string{
"0",
"1",
@@ -38,7 +38,7 @@ func main() {
"v10",
"v20",
}
-
+
parse := func(s string) (n int, isconst bool) {
if s == "vminus1" {
return -1, false
@@ -69,7 +69,7 @@ func main() {
iconst && kconst && iv > kv,
iconst && base == "array" && iv > Cap,
jconst && base == "array" && jv > Cap,
- kconst && base == "array" && kv > Cap:
+ kconst && base == "array" && kv > Cap:
continue
}
@@ -82,7 +82,7 @@ func main() {
xlen = jv - iv
xcap = kv - iv
}
- fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap)
+ fmt.Fprintf(bout, "\tcheckSlice(%q, func() []byte { return %s }, %d, %d, %d)\n", expr, expr, xbase, xlen, xcap)
}
}
}
@@ -147,9 +147,13 @@ func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) {
println(desc, "=", base, len, cap, "want panic")
return
}
- if base != uintptr(xbase) || len != uintptr(xlen) || cap != uintptr(xcap) {
+ if cap != 0 && base != uintptr(xbase) || base >= 10 || len != uintptr(xlen) || cap != uintptr(xcap) {
notOK()
- println(desc, "=", base, len, cap, "want", xbase, xlen, xcap)
+ if cap == 0 {
+ println(desc, "=", base, len, cap, "want", "0-9", xlen, xcap)
+ } else {
+ println(desc, "=", base, len, cap, "want", xbase, xlen, xcap)
+ }
}
}
diff --git a/test/slicecap.go b/test/slicecap.go
new file mode 100644
index 000000000..dceb7e2cc
--- /dev/null
+++ b/test/slicecap.go
@@ -0,0 +1,90 @@
+// 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.
+
+package main
+
+import "unsafe"
+
+var (
+ hello = "hello"
+ bytes = []byte{1, 2, 3, 4, 5}
+ ints = []int32{1, 2, 3, 4, 5}
+
+ five = 5
+
+ ok = true
+)
+
+func notOK() {
+ if ok {
+ println("BUG:")
+ ok = false
+ }
+}
+
+func checkString(desc, s string) {
+ p1 := *(*uintptr)(unsafe.Pointer(&s))
+ p2 := *(*uintptr)(unsafe.Pointer(&hello))
+ if p1-p2 >= 5 {
+ notOK()
+ println("string", desc, "has invalid base")
+ }
+}
+
+func checkBytes(desc string, s []byte) {
+ p1 := *(*uintptr)(unsafe.Pointer(&s))
+ p2 := *(*uintptr)(unsafe.Pointer(&bytes))
+ if p1-p2 >= 5 {
+ println("byte slice", desc, "has invalid base")
+ }
+}
+
+func checkInts(desc string, s []int32) {
+ p1 := *(*uintptr)(unsafe.Pointer(&s))
+ p2 := *(*uintptr)(unsafe.Pointer(&ints))
+ if p1-p2 >= 5*4 {
+ println("int slice", desc, "has invalid base")
+ }
+}
+
+func main() {
+ {
+ x := hello
+ checkString("x", x)
+ checkString("x[5:]", x[5:])
+ checkString("x[five:]", x[five:])
+ checkString("x[5:five]", x[5:five])
+ checkString("x[five:5]", x[five:5])
+ checkString("x[five:five]", x[five:five])
+ checkString("x[1:][2:][2:]", x[1:][2:][2:])
+ y := x[4:]
+ checkString("y[1:]", y[1:])
+ }
+ {
+ x := bytes
+ checkBytes("x", x)
+ checkBytes("x[5:]", x[5:])
+ checkBytes("x[five:]", x[five:])
+ checkBytes("x[5:five]", x[5:five])
+ checkBytes("x[five:5]", x[five:5])
+ checkBytes("x[five:five]", x[five:five])
+ checkBytes("x[1:][2:][2:]", x[1:][2:][2:])
+ y := x[4:]
+ checkBytes("y[1:]", y[1:])
+ }
+ {
+ x := ints
+ checkInts("x", x)
+ checkInts("x[5:]", x[5:])
+ checkInts("x[five:]", x[five:])
+ checkInts("x[5:five]", x[5:five])
+ checkInts("x[five:5]", x[five:5])
+ checkInts("x[five:five]", x[five:five])
+ checkInts("x[1:][2:][2:]", x[1:][2:][2:])
+ y := x[4:]
+ checkInts("y[1:]", y[1:])
+ }
+}