1// errorcheckoutput
2
3package main
4
5import "fmt"
6
7// We are going to define 256 types T(n),
8// such that T(n) embeds T(2n) and *T(2n+1).
9
10func main() {
11	fmt.Printf("// errorcheck\n\n")
12	fmt.Printf("package p\n\n")
13	fmt.Println(`import "unsafe"`)
14
15	// Dump types.
16	for n := 1; n < 256; n++ {
17		writeStruct(n)
18	}
19	// Dump leaves
20	for n := 256; n < 512; n++ {
21		fmt.Printf("type T%d int\n", n)
22	}
23
24	fmt.Printf("var t T1\n")
25	fmt.Printf("var p *T1\n")
26
27	// Simple selectors
28	for n := 2; n < 256; n++ {
29		writeDot(n)
30	}
31
32	// Double selectors
33	for n := 128; n < 256; n++ {
34		writeDot(n/16, n)
35	}
36
37	// Triple selectors
38	for n := 128; n < 256; n++ {
39		writeDot(n/64, n/8, n)
40	}
41}
42
43const structTpl = `
44type T%d struct {
45	A%d int
46	T%d
47	*T%d
48}
49`
50
51func writeStruct(n int) {
52	fmt.Printf(structTpl, n, n, 2*n, 2*n+1)
53}
54
55func writeDot(ns ...int) {
56	for _, root := range []string{"t", "p"} {
57		fmt.Printf("const _ = unsafe.Offsetof(%s", root)
58		for _, n := range ns {
59			fmt.Printf(".T%d", n)
60		}
61		// Does it involve an indirection?
62		nlast := ns[len(ns)-1]
63		nprev := 1
64		if len(ns) > 1 {
65			nprev = ns[len(ns)-2]
66		}
67		isIndirect := false
68		for n := nlast / 2; n > nprev; n /= 2 {
69			if n%2 == 1 {
70				isIndirect = true
71				break
72			}
73		}
74		fmt.Print(")")
75		if isIndirect {
76			fmt.Print(` // ERROR "indirection"`)
77		}
78		fmt.Print("\n")
79	}
80}
81