interpret: fix align_of_val on packed types
This commit is contained in:
parent
33b530e040
commit
d366471e58
@ -598,7 +598,7 @@ pub(super) fn size_and_align_of(
|
||||
// the last field). Can't have foreign types here, how would we
|
||||
// adjust alignment and size for them?
|
||||
let field = layout.field(self, layout.fields.count() - 1);
|
||||
let Some((unsized_size, unsized_align)) = self.size_and_align_of(metadata, &field)? else {
|
||||
let Some((unsized_size, mut unsized_align)) = self.size_and_align_of(metadata, &field)? else {
|
||||
// A field with an extern type. We don't know the actual dynamic size
|
||||
// or the alignment.
|
||||
return Ok(None);
|
||||
@ -614,6 +614,13 @@ pub(super) fn size_and_align_of(
|
||||
// Return the sum of sizes and max of aligns.
|
||||
let size = sized_size + unsized_size; // `Size` addition
|
||||
|
||||
// Packed types ignore the alignment of their fields.
|
||||
if let ty::Adt(def, _) = layout.ty.kind() {
|
||||
if def.repr().packed() {
|
||||
unsized_align = sized_align;
|
||||
}
|
||||
}
|
||||
|
||||
// Choose max of two known alignments (combined value must
|
||||
// be aligned according to more restrictive of the two).
|
||||
let align = sized_align.max(unsized_align);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#![feature(bigint_helper_methods)]
|
||||
#![feature(cell_update)]
|
||||
#![feature(const_assume)]
|
||||
#![feature(const_align_of_val_raw)]
|
||||
#![feature(const_black_box)]
|
||||
#![feature(const_bool_to_option)]
|
||||
#![feature(const_caller_location)]
|
||||
@ -42,6 +43,7 @@
|
||||
#![feature(try_find)]
|
||||
#![feature(inline_const)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(layout_for_ptr)]
|
||||
#![feature(pattern)]
|
||||
#![feature(pin_macro)]
|
||||
#![feature(sort_internals)]
|
||||
|
@ -1,4 +1,5 @@
|
||||
use core::mem::*;
|
||||
use core::ptr;
|
||||
|
||||
#[cfg(panic = "unwind")]
|
||||
use std::rc::Rc;
|
||||
@ -75,6 +76,25 @@ fn align_of_val_basic() {
|
||||
assert_eq!(align_of_val(&1u32), 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(bootstrap))] // stage 0 doesn't have the fix yet, so the test fails
|
||||
fn align_of_val_raw_packed() {
|
||||
#[repr(C, packed)]
|
||||
struct B {
|
||||
f: [u32],
|
||||
}
|
||||
let storage = [0u8; 4];
|
||||
let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1);
|
||||
assert_eq!(unsafe { align_of_val_raw(b) }, 1);
|
||||
|
||||
const ALIGN_OF_VAL_RAW: usize = {
|
||||
let storage = [0u8; 4];
|
||||
let b: *const B = ptr::from_raw_parts(storage.as_ptr().cast(), 1);
|
||||
unsafe { align_of_val_raw(b) }
|
||||
};
|
||||
assert_eq!(ALIGN_OF_VAL_RAW, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_swap() {
|
||||
let mut x = 31337;
|
||||
|
Loading…
Reference in New Issue
Block a user