]> git.proxmox.com Git - rustc.git/blame - src/test/ui/structs-enums/align-struct.rs
New upstream version 1.67.1+dfsg1
[rustc.git] / src / test / ui / structs-enums / align-struct.rs
CommitLineData
b7449926 1// run-pass
0bf4aa26 2#![allow(dead_code)]
cc61c64b
XL
3
4use std::mem;
5
6// Raising alignment
7#[repr(align(16))]
3b2f2976 8#[derive(Clone, Copy, Debug)]
cc61c64b
XL
9struct Align16(i32);
10
11// Lowering has no effect
12#[repr(align(1))]
13struct Align1(i32);
14
15// Multiple attributes take the max
16#[repr(align(4))]
17#[repr(align(16))]
18#[repr(align(8))]
19struct AlignMany(i32);
20
21// Raising alignment may not alter size.
22#[repr(align(8))]
23#[allow(dead_code)]
24struct Align8Many {
25 a: i32,
26 b: i32,
27 c: i32,
28 d: u8,
29}
30
31enum Enum {
32 #[allow(dead_code)]
33 A(i32),
34 B(Align16)
35}
36
37// Nested alignment - use `#[repr(C)]` to suppress field reordering for sizeof test
38#[repr(C)]
39struct Nested {
40 a: i32,
41 b: i32,
42 c: Align16,
43 d: i8,
44}
45
46#[repr(packed)]
47struct Packed(i32);
48
49#[repr(align(16))]
50struct AlignContainsPacked {
51 a: Packed,
52 b: Packed,
53}
54
83c7162d
XL
55#[repr(C, packed(4))]
56struct Packed4C {
57 a: u32,
58 b: u64,
59}
60
61#[repr(align(16))]
62struct AlignContainsPacked4C {
63 a: Packed4C,
64 b: u64,
65}
66
041b39d2
XL
67// The align limit was originally smaller (2^15).
68// Check that it works with big numbers.
69#[repr(align(0x10000))]
70struct AlignLarge {
71 stuff: [u8; 0x10000],
72}
73
3b2f2976
XL
74union UnionContainsAlign {
75 a: Align16,
76 b: f32
77}
78
cc61c64b
XL
79impl Align16 {
80 // return aligned type
81 pub fn new(i: i32) -> Align16 {
82 Align16(i)
83 }
84 // pass aligned type
85 pub fn consume(a: Align16) -> i32 {
86 a.0
87 }
88}
89
90const CONST_ALIGN16: Align16 = Align16(7);
91static STATIC_ALIGN16: Align16 = Align16(8);
92
93// Check the actual address is aligned
94fn is_aligned_to<T>(p: &T, align: usize) -> bool {
95 let addr = p as *const T as usize;
96 (addr & (align - 1)) == 0
97}
98
99pub fn main() {
100 // check alignment and size by type and value
101 assert_eq!(mem::align_of::<Align16>(), 16);
102 assert_eq!(mem::size_of::<Align16>(), 16);
103
104 let a = Align16(7);
105 assert_eq!(a.0, 7);
106 assert_eq!(mem::align_of_val(&a), 16);
107 assert_eq!(mem::size_of_val(&a), 16);
108
109 assert!(is_aligned_to(&a, 16));
110
111 // lowering should have no effect
112 assert_eq!(mem::align_of::<Align1>(), 4);
113 assert_eq!(mem::size_of::<Align1>(), 4);
114 let a = Align1(7);
115 assert_eq!(a.0, 7);
116 assert_eq!(mem::align_of_val(&a), 4);
117 assert_eq!(mem::size_of_val(&a), 4);
118 assert!(is_aligned_to(&a, 4));
119
120 // when multiple attributes are specified the max should be used
121 assert_eq!(mem::align_of::<AlignMany>(), 16);
122 assert_eq!(mem::size_of::<AlignMany>(), 16);
123 let a = AlignMany(7);
124 assert_eq!(a.0, 7);
125 assert_eq!(mem::align_of_val(&a), 16);
126 assert_eq!(mem::size_of_val(&a), 16);
127 assert!(is_aligned_to(&a, 16));
128
129 // raising alignment should not reduce size
130 assert_eq!(mem::align_of::<Align8Many>(), 8);
131 assert_eq!(mem::size_of::<Align8Many>(), 16);
132 let a = Align8Many { a: 1, b: 2, c: 3, d: 4 };
133 assert_eq!(a.a, 1);
134 assert_eq!(mem::align_of_val(&a), 8);
135 assert_eq!(mem::size_of_val(&a), 16);
136 assert!(is_aligned_to(&a, 8));
137
138 // return type
139 let a = Align16::new(1);
140 assert_eq!(mem::align_of_val(&a), 16);
141 assert_eq!(mem::size_of_val(&a), 16);
142 assert_eq!(a.0, 1);
143 assert!(is_aligned_to(&a, 16));
144 assert_eq!(Align16::consume(a), 1);
145
146 // check const alignment, size and value
147 assert_eq!(mem::align_of_val(&CONST_ALIGN16), 16);
148 assert_eq!(mem::size_of_val(&CONST_ALIGN16), 16);
149 assert_eq!(CONST_ALIGN16.0, 7);
150 assert!(is_aligned_to(&CONST_ALIGN16, 16));
151
152 // check global static alignment, size and value
153 assert_eq!(mem::align_of_val(&STATIC_ALIGN16), 16);
154 assert_eq!(mem::size_of_val(&STATIC_ALIGN16), 16);
155 assert_eq!(STATIC_ALIGN16.0, 8);
156 assert!(is_aligned_to(&STATIC_ALIGN16, 16));
157
158 // Note that the size of Nested may change if struct field re-ordering is enabled
159 assert_eq!(mem::align_of::<Nested>(), 16);
160 assert_eq!(mem::size_of::<Nested>(), 48);
161 let a = Nested{ a: 1, b: 2, c: Align16(3), d: 4};
162 assert_eq!(mem::align_of_val(&a), 16);
163 assert_eq!(mem::align_of_val(&a.b), 4);
164 assert_eq!(mem::align_of_val(&a.c), 16);
165 assert_eq!(mem::size_of_val(&a), 48);
166 assert!(is_aligned_to(&a, 16));
167 // check the correct fields are indexed
168 assert_eq!(a.a, 1);
169 assert_eq!(a.b, 2);
170 assert_eq!(a.c.0, 3);
171 assert_eq!(a.d, 4);
172
173 // enum should be aligned to max alignment
174 assert_eq!(mem::align_of::<Enum>(), 16);
175 assert_eq!(mem::align_of_val(&Enum::B(Align16(0))), 16);
176 let e = Enum::B(Align16(15));
177 match e {
178 Enum::B(ref a) => {
179 assert_eq!(a.0, 15);
180 assert_eq!(mem::align_of_val(a), 16);
181 assert_eq!(mem::size_of_val(a), 16);
182 },
183 _ => ()
184 }
185 assert!(is_aligned_to(&e, 16));
186
3b2f2976
XL
187 // check union alignment
188 assert_eq!(mem::align_of::<UnionContainsAlign>(), 16);
189 assert_eq!(mem::size_of::<UnionContainsAlign>(), 16);
190 let u = UnionContainsAlign { a: Align16(10) };
191 unsafe {
192 assert_eq!(mem::align_of_val(&u.a), 16);
193 assert_eq!(mem::size_of_val(&u.a), 16);
194 assert_eq!(u.a.0, 10);
195 let UnionContainsAlign { a } = u;
196 assert_eq!(a.0, 10);
197 }
198
cc61c64b
XL
199 // arrays of aligned elements should also be aligned
200 assert_eq!(mem::align_of::<[Align16;2]>(), 16);
201 assert_eq!(mem::size_of::<[Align16;2]>(), 32);
202
203 let a = [Align16(0), Align16(1)];
204 assert_eq!(mem::align_of_val(&a[0]), 16);
205 assert_eq!(mem::align_of_val(&a[1]), 16);
206 assert!(is_aligned_to(&a, 16));
207
208 // check heap value is aligned
209 assert_eq!(mem::align_of_val(Box::new(Align16(0)).as_ref()), 16);
210
211 // check heap array is aligned
212 let a = vec!(Align16(0), Align16(1));
213 assert_eq!(mem::align_of_val(&a[0]), 16);
214 assert_eq!(mem::align_of_val(&a[1]), 16);
215
216 assert_eq!(mem::align_of::<AlignContainsPacked>(), 16);
217 assert_eq!(mem::size_of::<AlignContainsPacked>(), 16);
218 let a = AlignContainsPacked { a: Packed(1), b: Packed(2) };
219 assert_eq!(mem::align_of_val(&a), 16);
220 assert_eq!(mem::align_of_val(&a.a), 1);
221 assert_eq!(mem::align_of_val(&a.b), 1);
222 assert_eq!(mem::size_of_val(&a), 16);
223 assert!(is_aligned_to(&a, 16));
041b39d2 224
83c7162d
XL
225 assert_eq!(mem::align_of::<AlignContainsPacked4C>(), 16);
226 assert_eq!(mem::size_of::<AlignContainsPacked4C>(), 32);
227 let a = AlignContainsPacked4C { a: Packed4C{ a: 1, b: 2 }, b: 3 };
228 assert_eq!(mem::align_of_val(&a), 16);
229 assert_eq!(mem::align_of_val(&a.a), 4);
230 assert_eq!(mem::align_of_val(&a.b), mem::align_of::<u64>());
231 assert_eq!(mem::size_of_val(&a), 32);
232 assert!(is_aligned_to(&a, 16));
233
f2b60f7d 234 let mut large = Box::new(AlignLarge {
041b39d2 235 stuff: [0; 0x10000],
f2b60f7d 236 });
041b39d2
XL
237 large.stuff[0] = 132;
238 *large.stuff.last_mut().unwrap() = 102;
239 assert_eq!(large.stuff[0], 132);
240 assert_eq!(large.stuff.last(), Some(&102));
241 assert_eq!(mem::align_of::<AlignLarge>(), 0x10000);
242 assert_eq!(mem::align_of_val(&*large), 0x10000);
243 assert!(is_aligned_to(&*large, 0x10000));
cc61c64b 244}