| // runoutput |
| |
| // 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 run-time behavior of 3-index slice expressions. |
| |
| package main |
| |
| import ( |
| "bufio" |
| "fmt" |
| "os" |
| "strconv" |
| ) |
| |
| 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", |
| "2", |
| "3", |
| "10", |
| "20", |
| "vminus1", |
| "v0", |
| "v1", |
| "v2", |
| "v3", |
| "v10", |
| "v20", |
| } |
| |
| parse := func(s string) (n int, isconst bool) { |
| if s == "vminus1" { |
| return -1, false |
| } |
| isconst = true |
| if s[0] == 'v' { |
| isconst = false |
| s = s[1:] |
| } |
| n, _ = strconv.Atoi(s) |
| return n, isconst |
| } |
| |
| const Cap = 10 // cap of slice, array |
| |
| for _, base := range []string{"array", "slice"} { |
| for _, i := range index { |
| iv, iconst := parse(i) |
| for _, j := range index { |
| jv, jconst := parse(j) |
| for _, k := range index { |
| kv, kconst := parse(k) |
| // Avoid errors that would make the program not compile. |
| // Those are tested by slice3err.go. |
| switch { |
| case iconst && jconst && iv > jv, |
| jconst && kconst && jv > kv, |
| iconst && kconst && iv > kv, |
| iconst && base == "array" && iv > Cap, |
| jconst && base == "array" && jv > Cap, |
| kconst && base == "array" && kv > Cap: |
| continue |
| } |
| |
| expr := base + "[" + i + ":" + j + ":" + k + "]" |
| var xbase, xlen, xcap int |
| if iv > jv || jv > kv || kv > Cap || iv < 0 || jv < 0 || kv < 0 { |
| xbase, xlen, xcap = -1, -1, -1 |
| } else { |
| xbase = iv |
| 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, "\tif !ok { os.Exit(1) }\n") |
| fmt.Fprintf(bout, "}\n") |
| bout.Flush() |
| } |
| |
| var programTop = ` |
| package main |
| |
| import ( |
| "fmt" |
| "os" |
| "unsafe" |
| ) |
| |
| var ok = true |
| |
| var ( |
| array = new([10]byte) |
| slice = array[:] |
| |
| vminus1 = -1 |
| v0 = 0 |
| v1 = 1 |
| v2 = 2 |
| v3 = 3 |
| v4 = 4 |
| v5 = 5 |
| v10 = 10 |
| v20 = 20 |
| ) |
| |
| func notOK() { |
| if ok { |
| println("BUG:") |
| ok = false |
| } |
| } |
| |
| func checkSlice(desc string, f func() []byte, xbase, xlen, xcap int) { |
| defer func() { |
| if err := recover(); err != nil { |
| if xbase >= 0 { |
| notOK() |
| println(desc, " unexpected panic: ", fmt.Sprint(err)) |
| } |
| } |
| // "no panic" is checked below |
| }() |
| |
| x := f() |
| |
| arrayBase := uintptr(unsafe.Pointer(array)) |
| raw := *(*[3]uintptr)(unsafe.Pointer(&x)) |
| base, len, cap := raw[0] - arrayBase, raw[1], raw[2] |
| if xbase < 0 { |
| notOK() |
| println(desc, "=", base, len, cap, "want panic") |
| return |
| } |
| if base != uintptr(xbase) || len != uintptr(xlen) || cap != uintptr(xcap) { |
| notOK() |
| println(desc, "=", base, len, cap, "want", xbase, xlen, xcap) |
| } |
| } |
| |
| ` |