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