// 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) } } `