1// run
2
3// Copyright 2011 The Go Authors.  All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7package main
8
9import "unsafe"
10
11type T struct {
12	X int
13}
14
15var t T
16
17func isUintptr(uintptr) {}
18
19type T2 struct {
20	A int32
21	U2
22}
23
24type U2 struct {
25	B int32
26	C int32
27}
28
29var t2 T2
30var p2 *T2
31
32func main() {
33	// Test unsafe.Sizeof, unsafe.Alignof, and unsafe.Offsetof all return uintptr.
34	isUintptr(unsafe.Sizeof(t))
35	isUintptr(unsafe.Alignof(t))
36	isUintptr(unsafe.Offsetof(t.X))
37
38	// Test correctness of Offsetof with respect to embedded fields (issue 4909).
39	if unsafe.Offsetof(t2.C) != 8 {
40		println(unsafe.Offsetof(t2.C), "!= 8")
41		panic("unsafe.Offsetof(t2.C) != 8")
42	}
43	if unsafe.Offsetof(p2.C) != 8 {
44		println(unsafe.Offsetof(p2.C), "!= 8")
45		panic("unsafe.Offsetof(p2.C) != 8")
46	}
47	if unsafe.Offsetof(t2.U2.C) != 4 {
48		println(unsafe.Offsetof(t2.U2.C), "!= 4")
49		panic("unsafe.Offsetof(t2.U2.C) != 4")
50	}
51	if unsafe.Offsetof(p2.U2.C) != 4 {
52		println(unsafe.Offsetof(p2.U2.C), "!= 4")
53		panic("unsafe.Offsetof(p2.U2.C) != 4")
54	}
55	testDeep()
56	testNotEmbedded()
57}
58
59type (
60	S1 struct {
61		A int64
62		S2
63	}
64	S2 struct {
65		B int64
66		S3
67	}
68	S3 struct {
69		C int64
70		S4
71	}
72	S4 struct {
73		D int64
74		S5
75	}
76	S5 struct {
77		E int64
78		S6
79	}
80	S6 struct {
81		F int64
82		S7
83	}
84	S7 struct {
85		G int64
86		S8
87	}
88	S8 struct {
89		H int64
90		*S1
91	}
92)
93
94func testDeep() {
95	var s1 S1
96	switch {
97	case unsafe.Offsetof(s1.A) != 0:
98		panic("unsafe.Offsetof(s1.A) != 0")
99	case unsafe.Offsetof(s1.B) != 8:
100		panic("unsafe.Offsetof(s1.B) != 8")
101	case unsafe.Offsetof(s1.C) != 16:
102		panic("unsafe.Offsetof(s1.C) != 16")
103	case unsafe.Offsetof(s1.D) != 24:
104		panic("unsafe.Offsetof(s1.D) != 24")
105	case unsafe.Offsetof(s1.E) != 32:
106		panic("unsafe.Offsetof(s1.E) != 32")
107	case unsafe.Offsetof(s1.F) != 40:
108		panic("unsafe.Offsetof(s1.F) != 40")
109	case unsafe.Offsetof(s1.G) != 48:
110		panic("unsafe.Offsetof(s1.G) != 48")
111	case unsafe.Offsetof(s1.H) != 56:
112		panic("unsafe.Offsetof(s1.H) != 56")
113	case unsafe.Offsetof(s1.S1) != 64:
114		panic("unsafe.Offsetof(s1.S1) != 64")
115	case unsafe.Offsetof(s1.S1.S2.S3.S4.S5.S6.S7.S8.S1.S2) != 8:
116		panic("unsafe.Offsetof(s1.S1.S2.S3.S4.S5.S6.S7.S8.S1.S2) != 8")
117	}
118}
119
120func testNotEmbedded() {
121	type T2 struct {
122		B int32
123		C int32
124	}
125	type T1 struct {
126		A int32
127		T2
128	}
129	type T struct {
130		Dummy int32
131		F     T1
132		P     *T1
133	}
134
135	var t T
136	var p *T
137	switch {
138	case unsafe.Offsetof(t.F.B) != 4:
139		panic("unsafe.Offsetof(t.F.B) != 4")
140	case unsafe.Offsetof(t.F.C) != 8:
141		panic("unsafe.Offsetof(t.F.C) != 8")
142
143	case unsafe.Offsetof(t.P.B) != 4:
144		panic("unsafe.Offsetof(t.P.B) != 4")
145	case unsafe.Offsetof(t.P.C) != 8:
146		panic("unsafe.Offsetof(t.P.C) != 8")
147
148	case unsafe.Offsetof(p.F.B) != 4:
149		panic("unsafe.Offsetof(p.F.B) != 4")
150	case unsafe.Offsetof(p.F.C) != 8:
151		panic("unsafe.Offsetof(p.F.C) != 8")
152
153	case unsafe.Offsetof(p.P.B) != 4:
154		panic("unsafe.Offsetof(p.P.B) != 4")
155	case unsafe.Offsetof(p.P.C) != 8:
156		panic("unsafe.Offsetof(p.P.C) != 8")
157	}
158}
159