librustc: Don't create &[T] slices with NULL as the ptr.

This commit is contained in:
Luqman Aden 2014-07-03 22:24:33 -07:00
parent e646188f66
commit 31570cb22e
2 changed files with 17 additions and 19 deletions

View File

@ -27,6 +27,10 @@
use slice::{MutableOrdVector, MutableVectorAllocating, CloneableVector};
use slice::{Items, MutItems};
#[doc(hidden)]
pub static PTR_MARKER: u8 = 0;
/// An owned, growable vector.
///
/// # Examples
@ -71,7 +75,13 @@ impl<T> Vec<T> {
/// ```
#[inline]
pub fn new() -> Vec<T> {
Vec { len: 0, cap: 0, ptr: 0 as *mut T }
// If we have a 0-sized vector, then the base pointer should not be NULL
// because an iterator over the slice will attempt to yield the base
// pointer as the first element in the vector, but this will end up
// being Some(NULL) which is optimized to None. So instead we set ptr
// to some arbitrary non-null value which is fine since we never call
// deallocate on the ptr if cap is 0.
Vec { len: 0, cap: 0, ptr: &PTR_MARKER as *const _ as *mut T }
}
/// Constructs a new, empty `Vec` with the specified capacity.
@ -88,7 +98,7 @@ pub fn new() -> Vec<T> {
#[inline]
pub fn with_capacity(capacity: uint) -> Vec<T> {
if mem::size_of::<T>() == 0 {
Vec { len: 0, cap: uint::MAX, ptr: 0 as *mut T }
Vec { len: 0, cap: uint::MAX, ptr: &PTR_MARKER as *const _ as *mut T }
} else if capacity == 0 {
Vec::new()
} else {
@ -1206,16 +1216,8 @@ pub fn init<'a>(&'a self) -> &'a [T] {
/// would also make any pointers to it invalid.
#[inline]
pub fn as_ptr(&self) -> *const T {
// If we have a 0-sized vector, then the base pointer should not be NULL
// because an iterator over the slice will attempt to yield the base
// pointer as the first element in the vector, but this will end up
// being Some(NULL) which is optimized to None.
if mem::size_of::<T>() == 0 {
1 as *const T
} else {
self.ptr as *const T
}
}
/// Returns a mutable unsafe pointer to the vector's buffer.
///
@ -1226,13 +1228,8 @@ pub fn as_ptr(&self) -> *const T {
/// would also make any pointers to it invalid.
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
// see above for the 0-size check
if mem::size_of::<T>() == 0 {
1 as *mut T
} else {
self.ptr
}
}
/// Retains only the elements specified by the predicate.
///

View File

@ -155,8 +155,9 @@ pub fn trans_slice_vstore<'a>(
let llcount = C_uint(ccx, count);
let llfixed;
if count == 0 {
// Zero-length array: just use NULL as the data pointer
llfixed = C_null(vt.llunit_ty.ptr_to());
// Just create a zero-sized alloca to preserve
// the non-null invariant of the inner slice ptr
llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
} else {
// Make a fixed-length backing array and allocate it on the stack.
llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);