Merge pull request #488 from RalfJung/start-fn
Automatically use start-fn if we have all the MIR
This commit is contained in:
commit
53dc505592
44 changed files with 108 additions and 153 deletions
|
|
@ -50,9 +50,9 @@ script:
|
|||
# test `cargo miri`
|
||||
cd cargo-miri-test &&
|
||||
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
cargo miri -q -- -Zmiri-start-fn
|
||||
cargo miri -q
|
||||
else
|
||||
cargo miri -q -- -Zmiri-start-fn >stdout.real 2>stderr.real &&
|
||||
cargo miri -q >stdout.real 2>stderr.real &&
|
||||
cat stdout.real stderr.real &&
|
||||
# Test `cargo miri` output. Not on mac because output redirecting doesn't
|
||||
# work. There is no error. It just stops CI.
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
|
|||
if i.attrs.iter().any(|attr| attr.name() == "test") {
|
||||
let did = self.0.hir.body_owner_def_id(body_id);
|
||||
println!("running test: {}", self.0.def_path_debug_str(did));
|
||||
miri::eval_main(self.0, did, None, /*validate*/true);
|
||||
miri::eval_main(self.0, did, /*validate*/true);
|
||||
self.1.session.abort_if_errors();
|
||||
}
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) {
|
|||
state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(tcx, state));
|
||||
} else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
|
||||
let entry_def_id = tcx.hir.local_def_id(entry_node_id);
|
||||
miri::eval_main(tcx, entry_def_id, None, /*validate*/true);
|
||||
miri::eval_main(tcx, entry_def_id, /*validate*/true);
|
||||
|
||||
state.session.abort_if_errors();
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -26,11 +26,6 @@ use std::path::PathBuf;
|
|||
struct MiriCompilerCalls {
|
||||
default: Box<RustcDefaultCalls>,
|
||||
|
||||
/// Whether to begin interpretation at the start_fn lang item or not.
|
||||
///
|
||||
/// If false, the interpretation begins at the `main` function.
|
||||
start_fn: bool,
|
||||
|
||||
/// Whether to enforce the validity invariant.
|
||||
validate: bool,
|
||||
}
|
||||
|
|
@ -90,10 +85,9 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
|
|||
let this = *self;
|
||||
let mut control = this.default.build_controller(sess, matches);
|
||||
control.after_hir_lowering.callback = Box::new(after_hir_lowering);
|
||||
let start_fn = this.start_fn;
|
||||
let validate = this.validate;
|
||||
control.after_analysis.callback =
|
||||
Box::new(move |state| after_analysis(state, start_fn, validate));
|
||||
Box::new(move |state| after_analysis(state, validate));
|
||||
control.after_analysis.stop = Compilation::Stop;
|
||||
control
|
||||
}
|
||||
|
|
@ -109,7 +103,6 @@ fn after_hir_lowering(state: &mut CompileState) {
|
|||
|
||||
fn after_analysis<'a, 'tcx>(
|
||||
state: &mut CompileState<'a, 'tcx>,
|
||||
use_start_fn: bool,
|
||||
validate: bool,
|
||||
) {
|
||||
state.session.abort_if_errors();
|
||||
|
|
@ -134,7 +127,7 @@ fn after_analysis<'a, 'tcx>(
|
|||
"running test: {}",
|
||||
self.tcx.def_path_debug_str(did),
|
||||
);
|
||||
miri::eval_main(self.tcx, did, None, self.validate);
|
||||
miri::eval_main(self.tcx, did, self.validate);
|
||||
self.state.session.abort_if_errors();
|
||||
}
|
||||
}
|
||||
|
|
@ -147,13 +140,7 @@ fn after_analysis<'a, 'tcx>(
|
|||
);
|
||||
} else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() {
|
||||
let entry_def_id = tcx.hir.local_def_id(entry_node_id);
|
||||
// Use start_fn lang item if we have -Zmiri-start-fn set
|
||||
let start_wrapper = if use_start_fn {
|
||||
Some(tcx.lang_items().start_fn().unwrap())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
miri::eval_main(tcx, entry_def_id, start_wrapper, validate);
|
||||
miri::eval_main(tcx, entry_def_id, validate);
|
||||
|
||||
state.session.abort_if_errors();
|
||||
} else {
|
||||
|
|
@ -231,14 +218,9 @@ fn main() {
|
|||
args.push(find_sysroot());
|
||||
}
|
||||
|
||||
let mut start_fn = false;
|
||||
let mut validate = true;
|
||||
args.retain(|arg| {
|
||||
match arg.as_str() {
|
||||
"-Zmiri-start-fn" => {
|
||||
start_fn = true;
|
||||
false
|
||||
},
|
||||
"-Zmiri-disable-validation" => {
|
||||
validate = false;
|
||||
false
|
||||
|
|
@ -251,7 +233,6 @@ fn main() {
|
|||
let result = rustc_driver::run(move || {
|
||||
rustc_driver::run_compiler(&args, Box::new(MiriCompilerCalls {
|
||||
default: Box::new(RustcDefaultCalls),
|
||||
start_fn,
|
||||
validate,
|
||||
}), None, None)
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
use rustc::ty;
|
||||
use rustc::ty::layout::{Align, LayoutOf, Size};
|
||||
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir;
|
||||
use syntax::attr;
|
||||
|
||||
use std::mem;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub trait EvalContextExt<'tcx, 'mir> {
|
||||
|
|
@ -19,8 +17,6 @@ pub trait EvalContextExt<'tcx, 'mir> {
|
|||
ret: mir::BasicBlock,
|
||||
) -> EvalResult<'tcx>;
|
||||
|
||||
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>>;
|
||||
|
||||
/// Emulate a function that should have MIR but does not.
|
||||
/// This is solely to support execution without full MIR.
|
||||
/// Fail if emulating this function is not supported.
|
||||
|
|
@ -638,40 +634,6 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for EvalContext<'a, '
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Get an instance for a path.
|
||||
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>> {
|
||||
self.tcx
|
||||
.crates()
|
||||
.iter()
|
||||
.find(|&&krate| self.tcx.original_crate_name(krate) == path[0])
|
||||
.and_then(|krate| {
|
||||
let krate = DefId {
|
||||
krate: *krate,
|
||||
index: CRATE_DEF_INDEX,
|
||||
};
|
||||
let mut items = self.tcx.item_children(krate);
|
||||
let mut path_it = path.iter().skip(1).peekable();
|
||||
|
||||
while let Some(segment) = path_it.next() {
|
||||
for item in mem::replace(&mut items, Default::default()).iter() {
|
||||
if item.ident.name == *segment {
|
||||
if path_it.peek().is_none() {
|
||||
return Some(ty::Instance::mono(self.tcx.tcx, item.def.def_id()));
|
||||
}
|
||||
|
||||
items = self.tcx.item_children(item.def.def_id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
let path = path.iter().map(|&s| s.to_owned()).collect();
|
||||
EvalErrorKind::PathNotFound(path).into()
|
||||
})
|
||||
}
|
||||
|
||||
fn emulate_missing_fn(
|
||||
&mut self,
|
||||
path: String,
|
||||
|
|
@ -699,7 +661,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for EvalContext<'a, '
|
|||
"std::io::_print" |
|
||||
"std::io::_eprint" => {
|
||||
warn!(
|
||||
"Ignoring output. To run programs that print, make sure you have a libstd with full MIR."
|
||||
"Ignoring output. To run programs that prints, make sure you have a libstd with full MIR."
|
||||
);
|
||||
}
|
||||
"std::thread::Builder::new" => {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
use super::{Scalar, ScalarMaybeUndef, EvalResult};
|
||||
use std::mem;
|
||||
|
||||
pub trait FalibleScalarExt {
|
||||
use rustc::ty;
|
||||
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
|
||||
|
||||
use super::*;
|
||||
|
||||
pub trait ScalarExt {
|
||||
/// HACK: this function just extracts all bits if `defined != 0`
|
||||
/// Mainly used for args of C-functions and we should totally correctly fetch the size
|
||||
/// of their arguments
|
||||
fn to_bytes(self) -> EvalResult<'static, u128>;
|
||||
}
|
||||
|
||||
impl FalibleScalarExt for Scalar {
|
||||
impl ScalarExt for Scalar {
|
||||
fn to_bytes(self) -> EvalResult<'static, u128> {
|
||||
match self {
|
||||
Scalar::Bits { bits, size } => {
|
||||
|
|
@ -19,8 +24,49 @@ impl FalibleScalarExt for Scalar {
|
|||
}
|
||||
}
|
||||
|
||||
impl FalibleScalarExt for ScalarMaybeUndef {
|
||||
impl ScalarExt for ScalarMaybeUndef {
|
||||
fn to_bytes(self) -> EvalResult<'static, u128> {
|
||||
self.not_undef()?.to_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait EvalContextExt<'tcx> {
|
||||
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>>;
|
||||
}
|
||||
|
||||
|
||||
impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> {
|
||||
/// Get an instance for a path.
|
||||
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>> {
|
||||
self.tcx
|
||||
.crates()
|
||||
.iter()
|
||||
.find(|&&krate| self.tcx.original_crate_name(krate) == path[0])
|
||||
.and_then(|krate| {
|
||||
let krate = DefId {
|
||||
krate: *krate,
|
||||
index: CRATE_DEF_INDEX,
|
||||
};
|
||||
let mut items = self.tcx.item_children(krate);
|
||||
let mut path_it = path.iter().skip(1).peekable();
|
||||
|
||||
while let Some(segment) = path_it.next() {
|
||||
for item in mem::replace(&mut items, Default::default()).iter() {
|
||||
if item.ident.name == *segment {
|
||||
if path_it.peek().is_none() {
|
||||
return Some(ty::Instance::mono(self.tcx.tcx, item.def.def_id()));
|
||||
}
|
||||
|
||||
items = self.tcx.item_children(item.def.def_id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
let path = path.iter().map(|&s| s.to_owned()).collect();
|
||||
EvalErrorKind::PathNotFound(path).into()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ use rustc_mir::interpret::{EvalContext, PlaceTy, OpTy};
|
|||
|
||||
use super::{
|
||||
Value, Scalar, ScalarMaybeUndef,
|
||||
FalibleScalarExt, OperatorEvalContextExt
|
||||
ScalarExt, OperatorEvalContextExt
|
||||
};
|
||||
|
||||
pub trait EvalContextExt<'tcx> {
|
||||
|
|
|
|||
17
src/lib.rs
17
src/lib.rs
|
|
@ -43,13 +43,13 @@ use operator::EvalContextExt as OperatorEvalContextExt;
|
|||
use intrinsic::EvalContextExt as IntrinsicEvalContextExt;
|
||||
use tls::{EvalContextExt as TlsEvalContextExt, TlsData};
|
||||
use range_map::RangeMap;
|
||||
use helpers::FalibleScalarExt;
|
||||
#[allow(unused_imports)] // FIXME rustc bug https://github.com/rust-lang/rust/issues/53682
|
||||
use helpers::{ScalarExt, EvalContextExt as HelpersEvalContextExt};
|
||||
use mono_hash_map::MonoHashMap;
|
||||
|
||||
pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
main_id: DefId,
|
||||
start_wrapper: Option<DefId>,
|
||||
validate: bool,
|
||||
) -> EvalResult<'tcx, EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>>> {
|
||||
let mut ecx = EvalContext::new(
|
||||
|
|
@ -69,8 +69,14 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
|||
));
|
||||
}
|
||||
|
||||
if let Some(start_id) = start_wrapper {
|
||||
let main_ret_ty = ecx.tcx.fn_sig(main_id).output();
|
||||
let libstd_has_mir = {
|
||||
let rustc_panic = ecx.resolve_path(&["std", "panicking", "rust_panic"])?;
|
||||
ecx.load_mir(rustc_panic.def).is_ok()
|
||||
};
|
||||
|
||||
if libstd_has_mir {
|
||||
let start_id = tcx.lang_items().start_fn().unwrap();
|
||||
let main_ret_ty = tcx.fn_sig(main_id).output();
|
||||
let main_ret_ty = main_ret_ty.no_late_bound_regions().unwrap();
|
||||
let start_instance = ty::Instance::resolve(
|
||||
ecx.tcx.tcx,
|
||||
|
|
@ -145,10 +151,9 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
|||
pub fn eval_main<'a, 'tcx: 'a>(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
main_id: DefId,
|
||||
start_wrapper: Option<DefId>,
|
||||
validate: bool,
|
||||
) {
|
||||
let mut ecx = create_ecx(tcx, main_id, start_wrapper, validate).expect("Couldn't create ecx");
|
||||
let mut ecx = create_ecx(tcx, main_id, validate).expect("Couldn't create ecx");
|
||||
|
||||
let res: EvalResult = (|| {
|
||||
ecx.run()?;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ fn main() {
|
|||
unsafe {
|
||||
let x = Global.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap();
|
||||
Global.realloc(x, Layout::from_size_align_unchecked(1, 1), 1).unwrap();
|
||||
let _z = *(x.as_ptr() as *mut u8); //~ ERROR constant evaluation error
|
||||
//~^ NOTE dangling pointer was dereferenced
|
||||
let _z = *(x.as_ptr() as *mut u8); //~ ERROR dangling pointer was dereferenced
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ fn main() {
|
|||
let x_ptr: *mut u8 = &mut x[0];
|
||||
let y_ptr = x_ptr as *mut u64;
|
||||
unsafe {
|
||||
*y_ptr = 42; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to access memory with alignment 1, but alignment
|
||||
*y_ptr = 42; //~ ERROR tried to access memory with alignment 1, but alignment
|
||||
}
|
||||
panic!("unreachable in miri");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ fn main() {
|
|||
unsafe {
|
||||
std::intrinsics::assume(x < 10);
|
||||
std::intrinsics::assume(x > 1);
|
||||
std::intrinsics::assume(x > 42); //~ ERROR constant evaluation error
|
||||
//~^ NOTE `assume` argument was false
|
||||
std::intrinsics::assume(x > 42); //~ `assume` argument was false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,11 +28,10 @@ fn mk_rec() -> Rec {
|
|||
fn is_u64_aligned(u: &Tag<u64>) -> bool {
|
||||
let p: usize = unsafe { mem::transmute(u) };
|
||||
let u64_align = std::mem::align_of::<u64>();
|
||||
return (p & (u64_align + 1)) == 0; //~ ERROR constant evaluation error
|
||||
//~^ NOTE a raw memory access tried to access part of a pointer value as raw bytes
|
||||
return (p & (u64_align + 1)) == 0; //~ ERROR a raw memory access tried to access part of a pointer value as raw bytes
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let x = mk_rec();
|
||||
assert!(is_u64_aligned(&x.t)); //~ NOTE inside call to `is_u64_aligned
|
||||
assert!(is_u64_aligned(&x.t));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,5 @@ fn main() {
|
|||
std::mem::transmute::<&usize, &fn(i32)>(&b)
|
||||
};
|
||||
|
||||
(*g)(42) //~ ERROR constant evaluation error
|
||||
//~^ NOTE a memory access tried to interpret some bytes as a pointer
|
||||
(*g)(42) //~ ERROR a memory access tried to interpret some bytes as a pointer
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,5 @@ fn main() {
|
|||
std::mem::transmute::<usize, fn(i32)>(42)
|
||||
};
|
||||
|
||||
g(42) //~ ERROR constant evaluation error
|
||||
//~^ NOTE a memory access tried to interpret some bytes as a pointer
|
||||
g(42) //~ ERROR a memory access tried to interpret some bytes as a pointer
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ fn main() {
|
|||
let b = Box::new(42);
|
||||
&*b as *const i32
|
||||
};
|
||||
let x = unsafe { *p }; //~ ERROR constant evaluation error
|
||||
//~^ NOTE dangling pointer was dereferenced
|
||||
let x = unsafe { *p }; //~ ERROR dangling pointer was dereferenced
|
||||
panic!("this should never print: {}", x);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,5 @@
|
|||
#![allow(const_err)]
|
||||
|
||||
fn main() {
|
||||
let _n = 1 / 0; //~ ERROR constant evaluation error
|
||||
//~^ NOTE attempt to divide by zero
|
||||
let _n = 1 / 0; //~ ERROR attempt to divide by zero
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ fn main() {
|
|||
let x = box 42;
|
||||
unsafe {
|
||||
let f = std::mem::transmute::<Box<i32>, fn()>(x);
|
||||
f() //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to treat a memory pointer as a function pointer
|
||||
f() //~ ERROR tried to treat a memory pointer as a function pointer
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,5 @@ fn main() {
|
|||
let y : *mut u8 = unsafe { mem::transmute(x) };
|
||||
let y = y.wrapping_offset(1);
|
||||
let x : fn() = unsafe { mem::transmute(y) };
|
||||
x(); //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to use a function pointer after offsetting it
|
||||
x(); //~ ERROR tried to use a function pointer after offsetting it
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
fn main() {
|
||||
let x = &1; // the `&1` is promoted to a constant, but it used to be that only the pointer is marked static, not the pointee
|
||||
let y = unsafe { &mut *(x as *const i32 as *mut i32) };
|
||||
*y = 42; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to modify constant memory
|
||||
*y = 42; //~ ERROR tried to modify constant memory
|
||||
assert_eq!(*x, 42);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@
|
|||
fn main() {
|
||||
let y = &5;
|
||||
let x: ! = unsafe {
|
||||
*(y as *const _ as *const !) //~ ERROR constant evaluation error
|
||||
//~^ NOTE entered unreachable code
|
||||
*(y as *const _ as *const !) //~ ERROR entered unreachable code
|
||||
};
|
||||
f(x)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@
|
|||
enum Void {}
|
||||
|
||||
fn f(v: Void) -> ! {
|
||||
match v {} //~ ERROR constant evaluation error
|
||||
//~^ NOTE entered unreachable code
|
||||
match v {} //~ ERROR entered unreachable code
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
fn main() {
|
||||
let v: Vec<u8> = vec![1, 2];
|
||||
let x = unsafe { *v.as_ptr().wrapping_offset(5) }; //~ ERROR constant evaluation error
|
||||
//~^ NOTE which has size 2
|
||||
let x = unsafe { *v.as_ptr().wrapping_offset(5) }; //~ ERROR outside bounds of allocation
|
||||
panic!("this should never print: {}", x);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
fn main() {
|
||||
let v: Vec<u8> = vec![1, 2];
|
||||
let x = unsafe { *v.as_ptr().wrapping_offset(5) }; //~ ERROR constant evaluation error
|
||||
//~^ NOTE outside bounds of allocation
|
||||
let x = unsafe { *v.as_ptr().wrapping_offset(5) }; //~ ERROR outside bounds of allocation
|
||||
panic!("this should never print: {}", x);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,5 @@
|
|||
#![allow(const_err)]
|
||||
|
||||
fn main() {
|
||||
let _n = 2i64 << -1; //~ ERROR constant evaluation error
|
||||
//~^ NOTE attempt to shift left with overflow
|
||||
let _n = 2i64 << -1; //~ ERROR attempt to shift left with overflow
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,5 @@
|
|||
|
||||
fn main() {
|
||||
// Make sure we catch overflows that would be hidden by first casting the RHS to u32
|
||||
let _n = 1i64 >> (u32::max_value() as i64 + 1); //~ ERROR constant evaluation error
|
||||
//~^ NOTE attempt to shift right with overflow
|
||||
let _n = 1i64 >> (u32::max_value() as i64 + 1); //~ ERROR attempt to shift right with overflow
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,5 @@
|
|||
#![allow(exceeding_bitshifts)]
|
||||
|
||||
fn main() {
|
||||
let _n = 1i64 >> 64; //~ ERROR constant evaluation error
|
||||
//~^ NOTE attempt to shift right with overflow
|
||||
let _n = 1i64 >> 64; //~ ERROR attempt to shift right with overflow
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ fn main() {
|
|||
// "attempted to interpret some raw bytes as a pointer address" instead of
|
||||
// "attempted to read undefined bytes"
|
||||
}
|
||||
let x = *p; //~ ERROR constant evaluation error
|
||||
//~^ NOTE attempted to read undefined bytes
|
||||
let x = *p; //~ ERROR attempted to read undefined bytes
|
||||
panic!("this should never print: {}", x);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,5 @@ fn main() {
|
|||
let y = &x;
|
||||
let z = &y as *const &i32 as *const u8;
|
||||
// the deref fails, because we are reading only a part of the pointer
|
||||
let _ = unsafe { *z }; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to access part of a pointer value as raw bytes
|
||||
let _ = unsafe { *z }; //~ ERROR tried to access part of a pointer value as raw bytes
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
fn main() {
|
||||
let x: *const u8 = &1;
|
||||
let y: *const u8 = &2;
|
||||
if x < y { //~ ERROR constant evaluation error
|
||||
//~^ NOTE attempted to do invalid arithmetic on pointers
|
||||
if x < y { //~ ERROR attempted to do invalid arithmetic on pointers
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ fn main() {
|
|||
let x = &1;
|
||||
// Casting down to u8 and back up to a pointer loses too much precision; this must not work.
|
||||
let x = x as *const i32;
|
||||
let x = x as u8; //~ ERROR constant evaluation error
|
||||
//~^ NOTE a raw memory access tried to access part of a pointer value as raw bytes
|
||||
let x = x as u8; //~ ERROR a raw memory access tried to access part of a pointer value as raw bytes
|
||||
let x = x as *const i32;
|
||||
let _ = unsafe { *x };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ fn main() {
|
|||
// starts 1 byte to the right, so using it would actually be wrong!
|
||||
let d_alias = &mut w.data as *mut _ as *mut *const u8;
|
||||
unsafe {
|
||||
let _x = *d_alias; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to access part of a pointer value as raw bytes
|
||||
let _x = *d_alias; //~ ERROR tried to access part of a pointer value as raw bytes
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,5 @@ fn main() {
|
|||
y: 99,
|
||||
};
|
||||
let p = unsafe { &foo.x };
|
||||
let i = *p; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to access memory with alignment 1, but alignment 4 is required
|
||||
let i = *p; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ static X: usize = 5;
|
|||
#[allow(mutable_transmutes)]
|
||||
fn main() {
|
||||
unsafe {
|
||||
*std::mem::transmute::<&usize, &mut usize>(&X) = 6; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to modify constant memory
|
||||
*std::mem::transmute::<&usize, &mut usize>(&X) = 6; //~ ERROR tried to modify constant memory
|
||||
assert_eq!(X, 6);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use std::mem::transmute;
|
|||
fn main() {
|
||||
unsafe {
|
||||
let s = "this is a test";
|
||||
transmute::<&[u8], &mut [u8]>(s.as_bytes())[4] = 42; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to modify constant memory
|
||||
transmute::<&[u8], &mut [u8]>(s.as_bytes())[4] = 42; //~ ERROR tried to modify constant memory
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ use std::mem::transmute;
|
|||
fn main() {
|
||||
unsafe {
|
||||
let bs = b"this is a test";
|
||||
transmute::<&[u8], &mut [u8]>(bs)[4] = 42; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to modify constant memory
|
||||
transmute::<&[u8], &mut [u8]>(bs)[4] = 42; //~ ERROR tried to modify constant memory
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,5 @@ fn main() {
|
|||
assert_eq!(byte, 0);
|
||||
}
|
||||
let v = unsafe { *z.offset(first_undef) };
|
||||
if v == 0 {} //~ ERROR constant evaluation error
|
||||
//~^ NOTE attempted to read undefined bytes
|
||||
if v == 0 {} //~ ERROR attempted to read undefined bytes
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,5 @@ fn main() {
|
|||
let bad = unsafe {
|
||||
std::mem::transmute::<&[u8], [u8; 8]>(&[1u8])
|
||||
};
|
||||
let _ = bad[0] + bad[bad.len()-1]; //~ ERROR constant evaluation error
|
||||
//~^ NOTE a raw memory access tried to access part of a pointer value as raw bytes
|
||||
let _ = bad[0] + bad[bad.len()-1]; //~ ERROR a raw memory access tried to access part of a pointer value as raw bytes
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,5 @@ fn main() {
|
|||
let bad = unsafe {
|
||||
std::mem::transmute::<u64, &[u8]>(42)
|
||||
};
|
||||
bad[0]; //~ ERROR constant evaluation error
|
||||
//~^ NOTE index out of bounds: the len is 0 but the index is 0
|
||||
bad[0]; //~ ERROR index out of bounds: the len is 0 but the index is 0
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,5 @@ fn main() {
|
|||
let x = &2u16;
|
||||
let x = x as *const _ as *const u32;
|
||||
// This must fail because alignment is violated
|
||||
let _x = unsafe { *x }; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to access memory with alignment 2, but alignment 4 is required
|
||||
let _x = unsafe { *x }; //~ ERROR tried to access memory with alignment 2, but alignment 4 is required
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,5 @@ fn main() {
|
|||
let x = x as *const _ as *const *const u8;
|
||||
// This must fail because alignment is violated. Test specifically for loading pointers, which have special code
|
||||
// in miri's memory.
|
||||
let _x = unsafe { *x }; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to access memory with alignment 2, but alignment
|
||||
let _x = unsafe { *x }; //~ ERROR tried to access memory with alignment 2, but alignment
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,5 @@ fn main() {
|
|||
let x = &2u16;
|
||||
let x = x as *const _ as *const [u32; 0];
|
||||
// This must fail because alignment is violated. Test specifically for loading ZST.
|
||||
let _x = unsafe { *x }; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to access memory with alignment 2, but alignment 4 is required
|
||||
let _x = unsafe { *x }; //~ ERROR tried to access memory with alignment 2, but alignment 4 is required
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
fn main() {
|
||||
let v: Vec<u8> = Vec::with_capacity(10);
|
||||
let undef = unsafe { *v.get_unchecked(5) };
|
||||
let x = undef + 1; //~ ERROR: error
|
||||
//~^ NOTE attempted to read undefined bytes
|
||||
let x = undef + 1; //~ ERROR attempted to read undefined bytes
|
||||
panic!("this should never print: {}", x);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
fn main() {
|
||||
let p = 44 as *const i32;
|
||||
let x = unsafe { *p }; //~ ERROR constant evaluation error
|
||||
//~^ NOTE a memory access tried to interpret some bytes as a pointer
|
||||
let x = unsafe { *p }; //~ ERROR a memory access tried to interpret some bytes as a pointer
|
||||
panic!("this should never print: {}", x);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
fn main() {
|
||||
let x = &() as *const () as *const i32;
|
||||
let _ = unsafe { *x }; //~ ERROR constant evaluation error
|
||||
//~^ NOTE tried to access memory with alignment 1, but alignment 4 is required
|
||||
let _ = unsafe { *x }; //~ ERROR tried to access memory with alignment 1, but alignment 4 is required
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,9 +100,6 @@ fn miri_pass(sysroot: &Path, path: &str, target: &str, host: &str, need_fullmir:
|
|||
let mut flags = Vec::new();
|
||||
flags.push(format!("--sysroot {}", sysroot.display()));
|
||||
flags.push("-Dwarnings -Dunused".to_owned()); // overwrite the -Aunused in compiletest-rs
|
||||
if have_fullmir() {
|
||||
flags.push("-Zmiri-start-fn".to_owned());
|
||||
}
|
||||
if opt {
|
||||
// FIXME: Using level 1 (instead of 3) for now, as the optimizer is pretty broken
|
||||
// and crashes...
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue