From 3d67fd4cf4dfcdfb93e880a09ed7d41d95170226 Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Fri, 22 Nov 2024 19:32:02 -0500 Subject: [PATCH] Add language tests for aggregate types --- .../ui/layout/aggregate-lang/struct-align.rs | 31 +++++++ .../layout/aggregate-lang/struct-offsets.rs | 93 +++++++++++++++++++ tests/ui/layout/aggregate-lang/struct-size.rs | 57 ++++++++++++ tests/ui/layout/aggregate-lang/union-align.rs | 31 +++++++ .../ui/layout/aggregate-lang/union-offsets.rs | 46 +++++++++ tests/ui/layout/aggregate-lang/union-size.rs | 54 +++++++++++ 6 files changed, 312 insertions(+) create mode 100644 tests/ui/layout/aggregate-lang/struct-align.rs create mode 100644 tests/ui/layout/aggregate-lang/struct-offsets.rs create mode 100644 tests/ui/layout/aggregate-lang/struct-size.rs create mode 100644 tests/ui/layout/aggregate-lang/union-align.rs create mode 100644 tests/ui/layout/aggregate-lang/union-offsets.rs create mode 100644 tests/ui/layout/aggregate-lang/union-size.rs diff --git a/tests/ui/layout/aggregate-lang/struct-align.rs b/tests/ui/layout/aggregate-lang/struct-align.rs new file mode 100644 index 0000000000000..931d686798daa --- /dev/null +++ b/tests/ui/layout/aggregate-lang/struct-align.rs @@ -0,0 +1,31 @@ +//@ run-pass +//@ reference: layout.aggregate.struct-size-align +//@ edition: 2018 + +#[repr(align(64))] +#[derive(Copy, Clone)] +#[allow(dead_code)] +pub struct Overaligned(u8); + +#[allow(dead_code)] +struct ReprRustStruct { + x: i32, + y: [u32; 4], + z: f32, + a: u128, + b: Overaligned, +} + +#[cfg_attr(test, test)] +fn test_alignment_contains_all_fields() { + assert!(core::mem::align_of::() >= core::mem::align_of::()); + assert!(core::mem::align_of::() >= core::mem::align_of::<[u32; 4]>()); + assert!(core::mem::align_of::() >= core::mem::align_of::()); + assert!(core::mem::align_of::() >= core::mem::align_of::()); + assert!(core::mem::align_of::() >= core::mem::align_of::()); +} + +#[cfg(not(test))] +fn main() { + test_alignment_contains_all_fields(); +} diff --git a/tests/ui/layout/aggregate-lang/struct-offsets.rs b/tests/ui/layout/aggregate-lang/struct-offsets.rs new file mode 100644 index 0000000000000..62e16e6d8434e --- /dev/null +++ b/tests/ui/layout/aggregate-lang/struct-offsets.rs @@ -0,0 +1,93 @@ +//@ run-pass +//@ reference: layout.aggregate.struct-offsets +//@ edition: 2018 + +#[repr(align(64))] +#[derive(Copy, Clone)] +#[allow(dead_code)] +pub struct Overaligned(u8); + +#[allow(dead_code)] +struct ReprRustStruct { + x: i32, + y: [u32; 4], + z: f32, + a: u128, + b: Overaligned, +} + +macro_rules! span_of { + ($ty:ty , $field:tt) => {{ + let __field = unsafe { ::core::mem::zeroed::<$ty>() }; + + ( + core::mem::offset_of!($ty, $field), + core::mem::offset_of!($ty, $field) + core::mem::size_of_val(&__field.$field), + ) + }}; +} + +fn test_fields_make_sense(a: &(usize, usize)) { + assert!(a.0 <= a.1); +} + +// order is `begin, end` +fn test_non_overlapping(a: &(usize, usize), b: &(usize, usize)) { + assert!((a.1 <= b.0) || (b.1 <= a.0)); +} + +#[cfg_attr(test, test)] +fn test_fields_non_overlapping() { + let fields = [ + span_of!(ReprRustStruct, x), + span_of!(ReprRustStruct, y), + span_of!(ReprRustStruct, z), + span_of!(ReprRustStruct, a), + span_of!(ReprRustStruct, b), + ]; + + test_fields_make_sense(&fields[0]); + test_fields_make_sense(&fields[1]); + test_fields_make_sense(&fields[2]); + test_fields_make_sense(&fields[3]); + test_fields_make_sense(&fields[4]); + + test_non_overlapping(&fields[0], &fields[1]); + test_non_overlapping(&fields[0], &fields[2]); + test_non_overlapping(&fields[0], &fields[3]); + test_non_overlapping(&fields[0], &fields[4]); + test_non_overlapping(&fields[1], &fields[2]); + test_non_overlapping(&fields[2], &fields[3]); + test_non_overlapping(&fields[2], &fields[4]); + test_non_overlapping(&fields[3], &fields[4]); +} + +#[cfg_attr(test, test)] +fn test_fields_aligned() { + assert_eq!( + (core::mem::offset_of!(ReprRustStruct, x) % (core::mem::align_of::())), + 0 + ); + assert_eq!( + (core::mem::offset_of!(ReprRustStruct, y) % (core::mem::align_of::<[u32; 4]>())), + 0 + ); + assert_eq!( + (core::mem::offset_of!(ReprRustStruct, z) % (core::mem::align_of::())), + 0 + ); + assert_eq!( + (core::mem::offset_of!(ReprRustStruct, a) % (core::mem::align_of::())), + 0 + ); + assert_eq!( + (core::mem::offset_of!(ReprRustStruct, b) % (core::mem::align_of::())), + 0 + ); +} + +#[cfg(not(test))] +fn main() { + test_fields_non_overlapping(); + test_fields_aligned(); +} diff --git a/tests/ui/layout/aggregate-lang/struct-size.rs b/tests/ui/layout/aggregate-lang/struct-size.rs new file mode 100644 index 0000000000000..3d93a8dca3487 --- /dev/null +++ b/tests/ui/layout/aggregate-lang/struct-size.rs @@ -0,0 +1,57 @@ +//@ run-pass +//@ reference: layout.aggregate.struct-size-align +//@ edition: 2018 + +#[allow(dead_code)] +struct ReprRustStruct { + x: i32, + y: [u32; 4], + z: f32, + a: u128, +} + +#[cfg_attr(test, test)] +fn test_size_contains_all_types() { + assert!( + core::mem::size_of::() + >= (core::mem::size_of::() + + core::mem::size_of::<[u32; 4]>() + + core::mem::size_of::() + + core::mem::size_of::()) + ); +} + +#[cfg_attr(test, test)] +fn test_size_contains_all_fields() { + assert!( + (core::mem::offset_of!(ReprRustStruct, x) + core::mem::size_of::()) + <= core::mem::size_of::() + ); + assert!( + (core::mem::offset_of!(ReprRustStruct, y) + core::mem::size_of::<[u32; 4]>()) + <= core::mem::size_of::() + ); + assert!( + (core::mem::offset_of!(ReprRustStruct, z) + core::mem::size_of::()) + <= core::mem::size_of::() + ); + assert!( + (core::mem::offset_of!(ReprRustStruct, a) + core::mem::size_of::()) + <= core::mem::size_of::() + ); +} + +#[cfg_attr(test, test)] +fn test_size_modulo_align() { + assert_eq!( + core::mem::size_of::() % core::mem::align_of::(), + 0 + ); +} + +#[cfg(not(test))] +fn main() { + test_size_contains_all_fields(); + test_size_contains_all_types(); + test_size_modulo_align(); +} diff --git a/tests/ui/layout/aggregate-lang/union-align.rs b/tests/ui/layout/aggregate-lang/union-align.rs new file mode 100644 index 0000000000000..a37d94abfa832 --- /dev/null +++ b/tests/ui/layout/aggregate-lang/union-align.rs @@ -0,0 +1,31 @@ +//@ run-pass +//@ reference: layout.aggregate.struct-size-align +//@ edition: 2018 + +#[repr(align(64))] +#[derive(Copy, Clone)] +#[allow(dead_code)] +pub struct Overaligned(u8); + +#[allow(dead_code)] +union ReprRustUnion { + x: i32, + y: [u32; 4], + z: f32, + a: u128, + b: Overaligned, +} + +#[cfg_attr(test, test)] +fn test_alignment_contains_all_fields() { + assert!(core::mem::align_of::() >= core::mem::align_of::()); + assert!(core::mem::align_of::() >= core::mem::align_of::<[u32; 4]>()); + assert!(core::mem::align_of::() >= core::mem::align_of::()); + assert!(core::mem::align_of::() >= core::mem::align_of::()); + assert!(core::mem::align_of::() >= core::mem::align_of::()); +} + +#[cfg(not(test))] +fn main() { + test_alignment_contains_all_fields(); +} diff --git a/tests/ui/layout/aggregate-lang/union-offsets.rs b/tests/ui/layout/aggregate-lang/union-offsets.rs new file mode 100644 index 0000000000000..2a2f7d9c790b7 --- /dev/null +++ b/tests/ui/layout/aggregate-lang/union-offsets.rs @@ -0,0 +1,46 @@ +//@ run-pass +//@ reference: layout.aggregate.struct-offsets +//@ edition: 2018 + +#[repr(align(64))] +#[derive(Copy, Clone)] +#[allow(dead_code)] +pub struct Overaligned(u8); + +#[allow(dead_code)] +union ReprRustUnion { + x: i32, + y: [u32; 4], + z: f32, + a: u128, + b: Overaligned, +} + +#[cfg_attr(test, test)] +fn test_fields_aligned() { + assert_eq!( + (core::mem::offset_of!(ReprRustUnion, x) % (core::mem::align_of::())), + 0 + ); + assert_eq!( + (core::mem::offset_of!(ReprRustUnion, y) % (core::mem::align_of::<[u32; 4]>())), + 0 + ); + assert_eq!( + (core::mem::offset_of!(ReprRustUnion, z) % (core::mem::align_of::())), + 0 + ); + assert_eq!( + (core::mem::offset_of!(ReprRustUnion, a) % (core::mem::align_of::())), + 0 + ); + assert_eq!( + (core::mem::offset_of!(ReprRustUnion, b) % (core::mem::align_of::())), + 0 + ); +} + +#[cfg(not(test))] +fn main() { + test_fields_aligned(); +} diff --git a/tests/ui/layout/aggregate-lang/union-size.rs b/tests/ui/layout/aggregate-lang/union-size.rs new file mode 100644 index 0000000000000..f82412f50899a --- /dev/null +++ b/tests/ui/layout/aggregate-lang/union-size.rs @@ -0,0 +1,54 @@ +//@ run-pass +//@ reference: layout.aggregate.struct-size-align +//@ edition: 2018 + +#[allow(dead_code)] +union ReprRustUnion { + x: i32, + y: [u32; 4], + z: f32, + a: u128, +} + +#[cfg_attr(test, test)] +fn test_size_contains_each_type() { + assert!(core::mem::size_of::() <= core::mem::size_of::()); + assert!(core::mem::size_of::<[u32; 4]>() <= core::mem::size_of::()); + assert!(core::mem::size_of::() <= core::mem::size_of::()); + assert!(core::mem::size_of::() <= core::mem::size_of::()); +} + +#[cfg_attr(test, test)] +fn test_size_contains_all_fields() { + assert!( + (core::mem::offset_of!(ReprRustUnion, x) + core::mem::size_of::()) + <= core::mem::size_of::() + ); + assert!( + (core::mem::offset_of!(ReprRustUnion, y) + core::mem::size_of::<[u32; 4]>()) + <= core::mem::size_of::() + ); + assert!( + (core::mem::offset_of!(ReprRustUnion, z) + core::mem::size_of::()) + <= core::mem::size_of::() + ); + assert!( + (core::mem::offset_of!(ReprRustUnion, a) + core::mem::size_of::()) + <= core::mem::size_of::() + ); +} + +#[cfg_attr(test, test)] +fn test_size_modulo_align() { + assert_eq!( + core::mem::size_of::() % core::mem::align_of::(), + 0 + ); +} + +#[cfg(not(test))] +fn main() { + test_size_contains_each_type(); + test_size_contains_all_fields(); + test_size_modulo_align(); +}