diff options
Diffstat (limited to 'tests/run-pass-valgrind')
17 files changed, 506 insertions, 0 deletions
diff --git a/tests/run-pass-valgrind/cast-enum-with-dtor.rs b/tests/run-pass-valgrind/cast-enum-with-dtor.rs new file mode 100644 index 000000000..f7ef92df8 --- /dev/null +++ b/tests/run-pass-valgrind/cast-enum-with-dtor.rs @@ -0,0 +1,34 @@ +#![allow(dead_code, cenum_impl_drop_cast)] + +// check dtor calling order when casting enums. + +use std::sync::atomic; +use std::sync::atomic::Ordering; +use std::mem; + +enum E { + A = 0, + B = 1, + C = 2 +} + +static FLAG: atomic::AtomicUsize = atomic::AtomicUsize::new(0); + +impl Drop for E { + fn drop(&mut self) { + // avoid dtor loop + unsafe { mem::forget(mem::replace(self, E::B)) }; + + FLAG.store(FLAG.load(Ordering::SeqCst)+1, Ordering::SeqCst); + } +} + +fn main() { + assert_eq!(FLAG.load(Ordering::SeqCst), 0); + { + let e = E::C; + assert_eq!(e as u32, 2); + assert_eq!(FLAG.load(Ordering::SeqCst), 1); + } + assert_eq!(FLAG.load(Ordering::SeqCst), 1); +} diff --git a/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs new file mode 100644 index 000000000..dfc094abe --- /dev/null +++ b/tests/run-pass-valgrind/cleanup-auto-borrow-obj.rs @@ -0,0 +1,25 @@ +// This would previously leak the Box<Trait> because we wouldn't +// schedule cleanups when auto borrowing trait objects. +// This program should be valgrind clean. + +static mut DROP_RAN: bool = false; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN = true; } + } +} + + +trait Trait { fn dummy(&self) { } } +impl Trait for Foo {} + +pub fn main() { + { + let _x: &Trait = &*(Box::new(Foo) as Box<Trait>); + } + unsafe { + assert!(DROP_RAN); + } +} diff --git a/tests/run-pass-valgrind/cleanup-stdin.rs b/tests/run-pass-valgrind/cleanup-stdin.rs new file mode 100644 index 000000000..cf8f81cf5 --- /dev/null +++ b/tests/run-pass-valgrind/cleanup-stdin.rs @@ -0,0 +1,5 @@ +fn main() { + let _ = std::io::stdin(); + let _ = std::io::stdout(); + let _ = std::io::stderr(); +} diff --git a/tests/run-pass-valgrind/coerce-match-calls.rs b/tests/run-pass-valgrind/coerce-match-calls.rs new file mode 100644 index 000000000..60943aad8 --- /dev/null +++ b/tests/run-pass-valgrind/coerce-match-calls.rs @@ -0,0 +1,15 @@ +// Check that coercions are propagated through match and if expressions. + +// pretty-expanded FIXME #23616 + +use std::boxed::Box; + +pub fn main() { + let _: Box<[isize]> = if true { Box::new([1, 2, 3]) } else { Box::new([1]) }; + + let _: Box<[isize]> = match true { true => Box::new([1, 2, 3]), false => Box::new([1]) }; + + // Check we don't get over-keen at propagating coercions in the case of casts. + let x = if true { 42 } else { 42u8 } as u16; + let x = match true { true => 42, false => 42u8 } as u16; +} diff --git a/tests/run-pass-valgrind/coerce-match.rs b/tests/run-pass-valgrind/coerce-match.rs new file mode 100644 index 000000000..5b78f1ec7 --- /dev/null +++ b/tests/run-pass-valgrind/coerce-match.rs @@ -0,0 +1,22 @@ +// Check that coercions are propagated through match and if expressions. + +// pretty-expanded FIXME #23616 + +pub fn main() { + let _: Box<[isize]> = if true { + let b: Box<_> = Box::new([1, 2, 3]); + b + } else { + let b: Box<_> = Box::new([1]); + b + }; + + let _: Box<[isize]> = match true { + true => { let b: Box<_> = Box::new([1, 2, 3]); b } + false => { let b: Box<_> = Box::new([1]); b } + }; + + // Check we don't get over-keen at propagating coercions in the case of casts. + let x = if true { 42 } else { 42u8 } as u16; + let x = match true { true => 42, false => 42u8 } as u16; +} diff --git a/tests/run-pass-valgrind/down-with-thread-dtors.rs b/tests/run-pass-valgrind/down-with-thread-dtors.rs new file mode 100644 index 000000000..8531b8d83 --- /dev/null +++ b/tests/run-pass-valgrind/down-with-thread-dtors.rs @@ -0,0 +1,39 @@ +// ignore-emscripten + +thread_local!(static FOO: Foo = Foo); +thread_local!(static BAR: Bar = Bar(1)); +thread_local!(static BAZ: Baz = Baz); + +static mut HIT: bool = false; + +struct Foo; +struct Bar(i32); +struct Baz; + +impl Drop for Foo { + fn drop(&mut self) { + BAR.with(|_| {}); + } +} + +impl Drop for Bar { + fn drop(&mut self) { + assert_eq!(self.0, 1); + self.0 = 2; + BAZ.with(|_| {}); + assert_eq!(self.0, 2); + } +} + +impl Drop for Baz { + fn drop(&mut self) { + unsafe { HIT = true; } + } +} + +fn main() { + std::thread::spawn(|| { + FOO.with(|_| {}); + }).join().unwrap(); + assert!(unsafe { HIT }); +} diff --git a/tests/run-pass-valgrind/dst-dtor-1.rs b/tests/run-pass-valgrind/dst-dtor-1.rs new file mode 100644 index 000000000..5b8433f61 --- /dev/null +++ b/tests/run-pass-valgrind/dst-dtor-1.rs @@ -0,0 +1,24 @@ +static mut DROP_RAN: bool = false; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN = true; } + } +} + +trait Trait { fn dummy(&self) { } } +impl Trait for Foo {} + +struct Fat<T: ?Sized> { + f: T +} + +pub fn main() { + { + let _x: Box<Fat<Trait>> = Box::<Fat<Foo>>::new(Fat { f: Foo }); + } + unsafe { + assert!(DROP_RAN); + } +} diff --git a/tests/run-pass-valgrind/dst-dtor-2.rs b/tests/run-pass-valgrind/dst-dtor-2.rs new file mode 100644 index 000000000..991fe0095 --- /dev/null +++ b/tests/run-pass-valgrind/dst-dtor-2.rs @@ -0,0 +1,21 @@ +static mut DROP_RAN: isize = 0; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN += 1; } + } +} + +struct Fat<T: ?Sized> { + f: T +} + +pub fn main() { + { + let _x: Box<Fat<[Foo]>> = Box::<Fat<[Foo; 3]>>::new(Fat { f: [Foo, Foo, Foo] }); + } + unsafe { + assert_eq!(DROP_RAN, 3); + } +} diff --git a/tests/run-pass-valgrind/dst-dtor-3.rs b/tests/run-pass-valgrind/dst-dtor-3.rs new file mode 100644 index 000000000..f0c2dda5a --- /dev/null +++ b/tests/run-pass-valgrind/dst-dtor-3.rs @@ -0,0 +1,22 @@ +#![feature(unsized_tuple_coercion)] + +static mut DROP_RAN: bool = false; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN = true; } + } +} + +trait Trait { fn dummy(&self) { } } +impl Trait for Foo {} + +pub fn main() { + { + let _x: Box<(i32, Trait)> = Box::<(i32, Foo)>::new((42, Foo)); + } + unsafe { + assert!(DROP_RAN); + } +} diff --git a/tests/run-pass-valgrind/dst-dtor-4.rs b/tests/run-pass-valgrind/dst-dtor-4.rs new file mode 100644 index 000000000..ad6d46f7c --- /dev/null +++ b/tests/run-pass-valgrind/dst-dtor-4.rs @@ -0,0 +1,19 @@ +#![feature(unsized_tuple_coercion)] + +static mut DROP_RAN: isize = 0; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN += 1; } + } +} + +pub fn main() { + { + let _x: Box<(i32, [Foo])> = Box::<(i32, [Foo; 3])>::new((42, [Foo, Foo, Foo])); + } + unsafe { + assert_eq!(DROP_RAN, 3); + } +} diff --git a/tests/run-pass-valgrind/exit-flushes.rs b/tests/run-pass-valgrind/exit-flushes.rs new file mode 100644 index 000000000..9daf487d3 --- /dev/null +++ b/tests/run-pass-valgrind/exit-flushes.rs @@ -0,0 +1,20 @@ +// ignore-emscripten +// ignore-sgx no processes +// ignore-macos this needs valgrind 3.11 or higher; see +// https://github.com/rust-lang/rust/pull/30365#issuecomment-165763679 + +use std::env; +use std::process::{exit, Command}; + +fn main() { + if env::args().len() > 1 { + print!("hello!"); + exit(0); + } else { + let out = Command::new(env::args().next().unwrap()).arg("foo") + .output().unwrap(); + assert!(out.status.success()); + assert_eq!(String::from_utf8(out.stdout).unwrap(), "hello!"); + assert_eq!(String::from_utf8(out.stderr).unwrap(), ""); + } +} diff --git a/tests/run-pass-valgrind/issue-44800.rs b/tests/run-pass-valgrind/issue-44800.rs new file mode 100644 index 000000000..f76657ca7 --- /dev/null +++ b/tests/run-pass-valgrind/issue-44800.rs @@ -0,0 +1,12 @@ +use std::alloc::System; +use std::collections::VecDeque; + +#[global_allocator] +static ALLOCATOR: System = System; + +fn main() { + let mut deque = VecDeque::with_capacity(32); + deque.push_front(0); + deque.reserve(31); + deque.push_back(0); +} diff --git a/tests/run-pass-valgrind/osx-frameworks.rs b/tests/run-pass-valgrind/osx-frameworks.rs new file mode 100644 index 000000000..571621c1d --- /dev/null +++ b/tests/run-pass-valgrind/osx-frameworks.rs @@ -0,0 +1,21 @@ +// pretty-expanded FIXME #23616 + +#![feature(rustc_private)] + +extern crate libc; + +#[cfg(target_os = "macos")] +#[link(name = "CoreFoundation", kind = "framework")] +extern "C" { + fn CFRunLoopGetTypeID() -> libc::c_ulong; +} + +#[cfg(target_os = "macos")] +pub fn main() { + unsafe { + CFRunLoopGetTypeID(); + } +} + +#[cfg(not(target_os = "macos"))] +pub fn main() {} diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs new file mode 100644 index 000000000..ece4dea9a --- /dev/null +++ b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call.rs @@ -0,0 +1,56 @@ +#![feature(unsized_locals)] +#![feature(unboxed_closures)] +#![feature(tuple_trait)] + +pub trait FnOnce<Args: std::marker::Tuple> { + type Output; + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct A; + +impl FnOnce<()> for A { + type Output = String; + extern "rust-call" fn call_once(self, (): ()) -> Self::Output { + format!("hello") + } +} + +struct B(i32); + +impl FnOnce<()> for B { + type Output = String; + extern "rust-call" fn call_once(self, (): ()) -> Self::Output { + format!("{}", self.0) + } +} + +struct C(String); + +impl FnOnce<()> for C { + type Output = String; + extern "rust-call" fn call_once(self, (): ()) -> Self::Output { + self.0 + } +} + +struct D(Box<String>); + +impl FnOnce<()> for D { + type Output = String; + extern "rust-call" fn call_once(self, (): ()) -> Self::Output { + *self.0 + } +} + + +fn main() { + let x = *(Box::new(A) as Box<dyn FnOnce<(), Output = String>>); + assert_eq!(x.call_once(()), format!("hello")); + let x = *(Box::new(B(42)) as Box<dyn FnOnce<(), Output = String>>); + assert_eq!(x.call_once(()), format!("42")); + let x = *(Box::new(C(format!("jumping fox"))) as Box<dyn FnOnce<(), Output = String>>); + assert_eq!(x.call_once(()), format!("jumping fox")); + let x = *(Box::new(D(Box::new(format!("lazy dog")))) as Box<dyn FnOnce<(), Output = String>>); + assert_eq!(x.call_once(()), format!("lazy dog")); +} diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs new file mode 100644 index 000000000..94df2b0b8 --- /dev/null +++ b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects-rust-call2.rs @@ -0,0 +1,70 @@ +#![feature(unsized_locals)] +#![feature(unboxed_closures)] +#![feature(tuple_trait)] + +pub trait FnOnce<Args: std::marker::Tuple> { + type Output; + extern "rust-call" fn call_once(self, args: Args) -> Self::Output; +} + +struct A; + +impl FnOnce<(String, Box<str>)> for A { + type Output = String; + extern "rust-call" fn call_once(self, (s1, s2): (String, Box<str>)) -> Self::Output { + assert_eq!(&s1 as &str, "s1"); + assert_eq!(&s2 as &str, "s2"); + format!("hello") + } +} + +struct B(i32); + +impl FnOnce<(String, Box<str>)> for B { + type Output = String; + extern "rust-call" fn call_once(self, (s1, s2): (String, Box<str>)) -> Self::Output { + assert_eq!(&s1 as &str, "s1"); + assert_eq!(&s2 as &str, "s2"); + format!("{}", self.0) + } +} + +struct C(String); + +impl FnOnce<(String, Box<str>)> for C { + type Output = String; + extern "rust-call" fn call_once(self, (s1, s2): (String, Box<str>)) -> Self::Output { + assert_eq!(&s1 as &str, "s1"); + assert_eq!(&s2 as &str, "s2"); + self.0 + } +} + +struct D(Box<String>); + +impl FnOnce<(String, Box<str>)> for D { + type Output = String; + extern "rust-call" fn call_once(self, (s1, s2): (String, Box<str>)) -> Self::Output { + assert_eq!(&s1 as &str, "s1"); + assert_eq!(&s2 as &str, "s2"); + *self.0 + } +} + + +fn main() { + let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); + let x = *(Box::new(A) as Box<dyn FnOnce<(String, Box<str>), Output = String>>); + assert_eq!(x.call_once((s1, s2)), format!("hello")); + let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); + let x = *(Box::new(B(42)) as Box<dyn FnOnce<(String, Box<str>), Output = String>>); + assert_eq!(x.call_once((s1, s2)), format!("42")); + let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); + let x = *(Box::new(C(format!("jumping fox"))) + as Box<dyn FnOnce<(String, Box<str>), Output = String>>); + assert_eq!(x.call_once((s1, s2)), format!("jumping fox")); + let (s1, s2) = (format!("s1"), format!("s2").into_boxed_str()); + let x = *(Box::new(D(Box::new(format!("lazy dog")))) + as Box<dyn FnOnce<(String, Box<str>), Output = String>>); + assert_eq!(x.call_once((s1, s2)), format!("lazy dog")); +} diff --git a/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs new file mode 100644 index 000000000..3d67101e7 --- /dev/null +++ b/tests/run-pass-valgrind/unsized-locals/by-value-trait-objects.rs @@ -0,0 +1,49 @@ +#![feature(unsized_locals)] + +pub trait Foo { + fn foo(self) -> String; +} + +struct A; + +impl Foo for A { + fn foo(self) -> String { + format!("hello") + } +} + +struct B(i32); + +impl Foo for B { + fn foo(self) -> String { + format!("{}", self.0) + } +} + +struct C(String); + +impl Foo for C { + fn foo(self) -> String { + self.0 + } +} + +struct D(Box<String>); + +impl Foo for D { + fn foo(self) -> String { + *self.0 + } +} + + +fn main() { + let x = *(Box::new(A) as Box<dyn Foo>); + assert_eq!(x.foo(), format!("hello")); + let x = *(Box::new(B(42)) as Box<dyn Foo>); + assert_eq!(x.foo(), format!("42")); + let x = *(Box::new(C(format!("jumping fox"))) as Box<dyn Foo>); + assert_eq!(x.foo(), format!("jumping fox")); + let x = *(Box::new(D(Box::new(format!("lazy dog")))) as Box<dyn Foo>); + assert_eq!(x.foo(), format!("lazy dog")); +} diff --git a/tests/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs b/tests/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs new file mode 100644 index 000000000..a7b905261 --- /dev/null +++ b/tests/run-pass-valgrind/unsized-locals/long-live-the-unsized-temporary.rs @@ -0,0 +1,52 @@ +#![allow(incomplete_features)] +#![feature(unsized_locals, unsized_fn_params)] + +use std::fmt; + +fn gen_foo() -> Box<fmt::Display> { + Box::new(Box::new("foo")) +} + +fn foo(x: fmt::Display) { + assert_eq!(x.to_string(), "foo"); +} + +fn foo_indirect(x: fmt::Display) { + foo(x); +} + +fn main() { + foo(*gen_foo()); + foo_indirect(*gen_foo()); + + { + let x: fmt::Display = *gen_foo(); + foo(x); + } + + { + let x: fmt::Display = *gen_foo(); + let y: fmt::Display = *gen_foo(); + foo(x); + foo(y); + } + + { + let mut cnt: usize = 3; + let x = loop { + let x: fmt::Display = *gen_foo(); + if cnt == 0 { + break x; + } else { + cnt -= 1; + } + }; + foo(x); + } + + { + let x: fmt::Display = *gen_foo(); + let x = if true { x } else { *gen_foo() }; + foo(x); + } +} |