| // errorcheckoutput |
| |
| package main |
| |
| import "fmt" |
| |
| // We are going to define 256 types T(n), |
| // such that T(n) embeds T(2n) and *T(2n+1). |
| |
| func main() { |
| fmt.Printf("// errorcheck\n\n") |
| fmt.Printf("package p\n\n") |
| fmt.Println(`import "unsafe"`) |
| |
| // Dump types. |
| for n := 1; n < 256; n++ { |
| writeStruct(n) |
| } |
| // Dump leaves |
| for n := 256; n < 512; n++ { |
| fmt.Printf("type T%d int\n", n) |
| } |
| |
| fmt.Printf("var t T1\n") |
| fmt.Printf("var p *T1\n") |
| |
| // Simple selectors |
| for n := 2; n < 256; n++ { |
| writeDot(n) |
| } |
| |
| // Double selectors |
| for n := 128; n < 256; n++ { |
| writeDot(n/16, n) |
| } |
| |
| // Triple selectors |
| for n := 128; n < 256; n++ { |
| writeDot(n/64, n/8, n) |
| } |
| } |
| |
| const structTpl = ` |
| type T%d struct { |
| A%d int |
| T%d |
| *T%d |
| } |
| ` |
| |
| func writeStruct(n int) { |
| fmt.Printf(structTpl, n, n, 2*n, 2*n+1) |
| } |
| |
| func writeDot(ns ...int) { |
| for _, root := range []string{"t", "p"} { |
| fmt.Printf("const _ = unsafe.Offsetof(%s", root) |
| for _, n := range ns { |
| fmt.Printf(".T%d", n) |
| } |
| // Does it involve an indirection? |
| nlast := ns[len(ns)-1] |
| nprev := 1 |
| if len(ns) > 1 { |
| nprev = ns[len(ns)-2] |
| } |
| isIndirect := false |
| for n := nlast / 2; n > nprev; n /= 2 { |
| if n%2 == 1 { |
| isIndirect = true |
| break |
| } |
| } |
| fmt.Print(")") |
| if isIndirect { |
| fmt.Print(` // ERROR "indirection|embedded via a pointer"`) |
| } |
| fmt.Print("\n") |
| } |
| } |