]> git.lizzy.rs Git - rust.git/blob - src/test/run-pass/align-struct.rs
Auto merge of #41433 - estebank:constructor, r=michaelwoerister
[rust.git] / src / test / run-pass / align-struct.rs
1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 #![feature(attr_literals)]
11 #![feature(repr_align)]
12
13 use std::mem;
14
15 // Raising alignment
16 #[repr(align(16))]
17 struct Align16(i32);
18
19 // Lowering has no effect
20 #[repr(align(1))]
21 struct Align1(i32);
22
23 // Multiple attributes take the max
24 #[repr(align(4))]
25 #[repr(align(16))]
26 #[repr(align(8))]
27 struct AlignMany(i32);
28
29 // Raising alignment may not alter size.
30 #[repr(align(8))]
31 #[allow(dead_code)]
32 struct Align8Many {
33     a: i32,
34     b: i32,
35     c: i32,
36     d: u8,
37 }
38
39 enum Enum {
40     #[allow(dead_code)]
41     A(i32),
42     B(Align16)
43 }
44
45 // Nested alignment - use `#[repr(C)]` to suppress field reordering for sizeof test
46 #[repr(C)]
47 struct Nested {
48     a: i32,
49     b: i32,
50     c: Align16,
51     d: i8,
52 }
53
54 #[repr(packed)]
55 struct Packed(i32);
56
57 #[repr(align(16))]
58 struct AlignContainsPacked {
59     a: Packed,
60     b: Packed,
61 }
62
63 impl Align16 {
64     // return aligned type
65     pub fn new(i: i32) -> Align16 {
66         Align16(i)
67     }
68     // pass aligned type
69     pub fn consume(a: Align16) -> i32 {
70         a.0
71     }
72 }
73
74 const CONST_ALIGN16: Align16 = Align16(7);
75 static STATIC_ALIGN16: Align16 = Align16(8);
76
77 // Check the actual address is aligned
78 fn is_aligned_to<T>(p: &T, align: usize) -> bool {
79     let addr = p as *const T as usize;
80     (addr & (align - 1)) == 0
81 }
82
83 pub fn main() {
84     // check alignment and size by type and value
85     assert_eq!(mem::align_of::<Align16>(), 16);
86     assert_eq!(mem::size_of::<Align16>(), 16);
87
88     let a = Align16(7);
89     assert_eq!(a.0, 7);
90     assert_eq!(mem::align_of_val(&a), 16);
91     assert_eq!(mem::size_of_val(&a), 16);
92
93     assert!(is_aligned_to(&a, 16));
94
95     // lowering should have no effect
96     assert_eq!(mem::align_of::<Align1>(), 4);
97     assert_eq!(mem::size_of::<Align1>(), 4);
98     let a = Align1(7);
99     assert_eq!(a.0, 7);
100     assert_eq!(mem::align_of_val(&a), 4);
101     assert_eq!(mem::size_of_val(&a), 4);
102     assert!(is_aligned_to(&a, 4));
103
104     // when multiple attributes are specified the max should be used
105     assert_eq!(mem::align_of::<AlignMany>(), 16);
106     assert_eq!(mem::size_of::<AlignMany>(), 16);
107     let a = AlignMany(7);
108     assert_eq!(a.0, 7);
109     assert_eq!(mem::align_of_val(&a), 16);
110     assert_eq!(mem::size_of_val(&a), 16);
111     assert!(is_aligned_to(&a, 16));
112
113     // raising alignment should not reduce size
114     assert_eq!(mem::align_of::<Align8Many>(), 8);
115     assert_eq!(mem::size_of::<Align8Many>(), 16);
116     let a = Align8Many { a: 1, b: 2, c: 3, d: 4 };
117     assert_eq!(a.a, 1);
118     assert_eq!(mem::align_of_val(&a), 8);
119     assert_eq!(mem::size_of_val(&a), 16);
120     assert!(is_aligned_to(&a, 8));
121
122     // return type
123     let a = Align16::new(1);
124     assert_eq!(mem::align_of_val(&a), 16);
125     assert_eq!(mem::size_of_val(&a), 16);
126     assert_eq!(a.0, 1);
127     assert!(is_aligned_to(&a, 16));
128     assert_eq!(Align16::consume(a), 1);
129
130     // check const alignment, size and value
131     assert_eq!(mem::align_of_val(&CONST_ALIGN16), 16);
132     assert_eq!(mem::size_of_val(&CONST_ALIGN16), 16);
133     assert_eq!(CONST_ALIGN16.0, 7);
134     assert!(is_aligned_to(&CONST_ALIGN16, 16));
135
136     // check global static alignment, size and value
137     assert_eq!(mem::align_of_val(&STATIC_ALIGN16), 16);
138     assert_eq!(mem::size_of_val(&STATIC_ALIGN16), 16);
139     assert_eq!(STATIC_ALIGN16.0, 8);
140     assert!(is_aligned_to(&STATIC_ALIGN16, 16));
141
142     // Note that the size of Nested may change if struct field re-ordering is enabled
143     assert_eq!(mem::align_of::<Nested>(), 16);
144     assert_eq!(mem::size_of::<Nested>(), 48);
145     let a = Nested{ a: 1, b: 2, c: Align16(3), d: 4};
146     assert_eq!(mem::align_of_val(&a), 16);
147     assert_eq!(mem::align_of_val(&a.b), 4);
148     assert_eq!(mem::align_of_val(&a.c), 16);
149     assert_eq!(mem::size_of_val(&a), 48);
150     assert!(is_aligned_to(&a, 16));
151     // check the correct fields are indexed
152     assert_eq!(a.a, 1);
153     assert_eq!(a.b, 2);
154     assert_eq!(a.c.0, 3);
155     assert_eq!(a.d, 4);
156
157     // enum should be aligned to max alignment
158     assert_eq!(mem::align_of::<Enum>(), 16);
159     assert_eq!(mem::align_of_val(&Enum::B(Align16(0))), 16);
160     let e = Enum::B(Align16(15));
161     match e {
162         Enum::B(ref a) => {
163             assert_eq!(a.0, 15);
164             assert_eq!(mem::align_of_val(a), 16);
165             assert_eq!(mem::size_of_val(a), 16);
166         },
167         _ => ()
168     }
169     assert!(is_aligned_to(&e, 16));
170
171     // arrays of aligned elements should also be aligned
172     assert_eq!(mem::align_of::<[Align16;2]>(), 16);
173     assert_eq!(mem::size_of::<[Align16;2]>(), 32);
174
175     let a = [Align16(0), Align16(1)];
176     assert_eq!(mem::align_of_val(&a[0]), 16);
177     assert_eq!(mem::align_of_val(&a[1]), 16);
178     assert!(is_aligned_to(&a, 16));
179
180     // check heap value is aligned
181     assert_eq!(mem::align_of_val(Box::new(Align16(0)).as_ref()), 16);
182
183     // check heap array is aligned
184     let a = vec!(Align16(0), Align16(1));
185     assert_eq!(mem::align_of_val(&a[0]), 16);
186     assert_eq!(mem::align_of_val(&a[1]), 16);
187
188     assert_eq!(mem::align_of::<AlignContainsPacked>(), 16);
189     assert_eq!(mem::size_of::<AlignContainsPacked>(), 16);
190     let a = AlignContainsPacked { a: Packed(1), b: Packed(2) };
191     assert_eq!(mem::align_of_val(&a), 16);
192     assert_eq!(mem::align_of_val(&a.a), 1);
193     assert_eq!(mem::align_of_val(&a.b), 1);
194     assert_eq!(mem::size_of_val(&a), 16);
195     assert!(is_aligned_to(&a, 16));
196 }