parent
1c40fb0da1
commit
d42a7d021d
@ -203,10 +203,6 @@ fn usize_primval(&self, n: u64) -> PrimVal {
|
||||
PrimVal::from_uint_with_size(n, self.memory.pointer_size())
|
||||
}
|
||||
|
||||
fn isize_primval(&self, n: i64) -> PrimVal {
|
||||
PrimVal::from_int_with_size(n, self.memory.pointer_size())
|
||||
}
|
||||
|
||||
fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
|
||||
// FIXME: cache these allocs
|
||||
let ptr = self.memory.allocate(s.len(), 1)?;
|
||||
@ -523,7 +519,8 @@ fn eval_rvalue_into_lvalue(
|
||||
self.write_value(value, dest, value_ty)?;
|
||||
} else {
|
||||
assert_eq!(operands.len(), 0);
|
||||
let zero = self.isize_primval(0);
|
||||
let value_size = self.type_size(dest_ty).expect("pointer types are sized");
|
||||
let zero = PrimVal::from_int_with_size(0, value_size);
|
||||
self.write_primval(dest, zero)?;
|
||||
}
|
||||
} else {
|
||||
@ -541,13 +538,14 @@ fn eval_rvalue_into_lvalue(
|
||||
let operand_ty = self.operand_ty(operand);
|
||||
assert_eq!(self.type_size(operand_ty), Some(0));
|
||||
}
|
||||
let offset = self.nonnull_offset(dest_ty, nndiscr, discrfield)?;
|
||||
let (offset, ty) = self.nonnull_offset_and_ty(dest_ty, nndiscr, discrfield)?;
|
||||
|
||||
// FIXME(solson)
|
||||
let dest = self.force_allocation(dest)?.to_ptr();
|
||||
|
||||
let dest = dest.offset(offset.bytes() as isize);
|
||||
try!(self.memory.write_isize(dest, 0));
|
||||
let dest_size = self.type_size(ty).unwrap_or(self.memory.pointer_size());
|
||||
try!(self.memory.write_int(dest, 0, dest_size));
|
||||
}
|
||||
} else {
|
||||
bug!("tried to assign {:?} to Layout::RawNullablePointer", kind);
|
||||
@ -694,7 +692,7 @@ fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn nonnull_offset(&self, ty: Ty<'tcx>, nndiscr: u64, discrfield: &[u32]) -> EvalResult<'tcx, Size> {
|
||||
fn nonnull_offset_and_ty(&self, ty: Ty<'tcx>, nndiscr: u64, discrfield: &[u32]) -> EvalResult<'tcx, (Size, Ty<'tcx>)> {
|
||||
// Skip the constant 0 at the start meant for LLVM GEP.
|
||||
let mut path = discrfield.iter().skip(1).map(|&i| i as usize);
|
||||
|
||||
@ -709,10 +707,10 @@ fn nonnull_offset(&self, ty: Ty<'tcx>, nndiscr: u64, discrfield: &[u32]) -> Eval
|
||||
_ => bug!("non-enum for StructWrappedNullablePointer: {}", ty),
|
||||
};
|
||||
|
||||
self.field_path_offset(inner_ty, path)
|
||||
self.field_path_offset_and_ty(inner_ty, path)
|
||||
}
|
||||
|
||||
fn field_path_offset<I: Iterator<Item = usize>>(&self, mut ty: Ty<'tcx>, path: I) -> EvalResult<'tcx, Size> {
|
||||
fn field_path_offset_and_ty<I: Iterator<Item = usize>>(&self, mut ty: Ty<'tcx>, path: I) -> EvalResult<'tcx, (Size, Ty<'tcx>)> {
|
||||
let mut offset = Size::from_bytes(0);
|
||||
|
||||
// Skip the initial 0 intended for LLVM GEP.
|
||||
@ -722,7 +720,7 @@ fn field_path_offset<I: Iterator<Item = usize>>(&self, mut ty: Ty<'tcx>, path: I
|
||||
offset = offset.checked_add(field_offset, &self.tcx.data_layout).unwrap();
|
||||
}
|
||||
|
||||
Ok(offset)
|
||||
Ok((offset, ty))
|
||||
}
|
||||
|
||||
fn get_field_ty(&self, ty: Ty<'tcx>, field_index: usize) -> EvalResult<'tcx, Ty<'tcx>> {
|
||||
|
@ -263,14 +263,17 @@ fn read_discriminant_value(&self, adt_ptr: Pointer, adt_ty: Ty<'tcx>) -> EvalRes
|
||||
self.memory.read_int(adt_ptr, discr_size as usize)? as u64
|
||||
}
|
||||
|
||||
RawNullablePointer { nndiscr, .. } => {
|
||||
self.read_nonnull_discriminant_value(adt_ptr, nndiscr)?
|
||||
RawNullablePointer { nndiscr, value } => {
|
||||
let discr_size = value.size(&self.tcx.data_layout).bytes() as usize;
|
||||
self.read_nonnull_discriminant_value(adt_ptr, nndiscr, discr_size)?
|
||||
}
|
||||
|
||||
StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
|
||||
let offset = self.nonnull_offset(adt_ty, nndiscr, discrfield)?;
|
||||
let (offset, ty) = self.nonnull_offset_and_ty(adt_ty, nndiscr, discrfield)?;
|
||||
let nonnull = adt_ptr.offset(offset.bytes() as isize);
|
||||
self.read_nonnull_discriminant_value(nonnull, nndiscr)?
|
||||
// only the pointer part of a fat pointer is used for this space optimization
|
||||
let discr_size = self.type_size(ty).unwrap_or(self.memory.pointer_size());
|
||||
self.read_nonnull_discriminant_value(nonnull, nndiscr, discr_size)?
|
||||
}
|
||||
|
||||
// The discriminant_value intrinsic returns 0 for non-sum types.
|
||||
@ -281,8 +284,8 @@ fn read_discriminant_value(&self, adt_ptr: Pointer, adt_ty: Ty<'tcx>) -> EvalRes
|
||||
Ok(discr_val)
|
||||
}
|
||||
|
||||
fn read_nonnull_discriminant_value(&self, ptr: Pointer, nndiscr: u64) -> EvalResult<'tcx, u64> {
|
||||
let not_null = match self.memory.read_usize(ptr) {
|
||||
fn read_nonnull_discriminant_value(&self, ptr: Pointer, nndiscr: u64, discr_size: usize) -> EvalResult<'tcx, u64> {
|
||||
let not_null = match self.memory.read_uint(ptr, discr_size) {
|
||||
Ok(0) => false,
|
||||
Ok(_) | Err(EvalError::ReadPointerAsBytes) => true,
|
||||
Err(e) => return Err(e),
|
||||
|
14
tests/run-pass/small_enum_size_bug.rs
Normal file
14
tests/run-pass/small_enum_size_bug.rs
Normal file
@ -0,0 +1,14 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
enum E {
|
||||
A = 1,
|
||||
B = 2,
|
||||
C = 3,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let enone = None::<E>;
|
||||
if let Some(..) = enone {
|
||||
panic!();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user