1
Fork 0

reject projecting to fields whose offset we cannot compute

This commit is contained in:
Ralf Jung 2023-12-02 12:43:56 +01:00
parent b1613ebc43
commit 9ef1e35166
7 changed files with 85 additions and 75 deletions

View file

@ -99,6 +99,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
let offset = self.layout.fields.offset(ix);
let effective_field_align = self.align.restrict_for_offset(offset);
// `simple` is called when we don't need to adjust the offset to
// the dynamic alignment of the field.
let mut simple = || {
let llval = match self.layout.abi {
_ if offset.bytes() == 0 => {
@ -141,28 +143,21 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
};
// Simple cases, which don't need DST adjustment:
// * no metadata available - just log the case
// * known alignment - sized types, `[T]`, `str` or a foreign type
// * known alignment - sized types, `[T]`, `str`
// * offset 0 -- rounding up to alignment cannot change the offset
// Note that looking at `field.align` is incorrect since that is not necessarily equal
// to the dynamic alignment of the type.
match field.ty.kind() {
_ if self.llextra.is_none() => {
debug!(
"unsized field `{}`, of `{:?}` has no metadata for adjustment",
ix, self.llval
);
return simple();
}
_ if field.is_sized() => return simple(),
ty::Slice(..) | ty::Str | ty::Foreign(..) => return simple(),
ty::Slice(..) | ty::Str => return simple(),
_ if offset.bytes() == 0 => return simple(),
_ => {}
}
// We need to get the pointer manually now.
// We do this by casting to a `*i8`, then offsetting it by the appropriate amount.
// We do this instead of, say, simply adjusting the pointer from the result of a GEP
// because the field may have an arbitrary alignment in the LLVM representation
// anyway.
// because the field may have an arbitrary alignment in the LLVM representation.
//
// To demonstrate:
//