diff options
Diffstat (limited to 'src/test/ui/allocator')
26 files changed, 632 insertions, 0 deletions
diff --git a/src/test/ui/allocator/allocator-args.rs b/src/test/ui/allocator/allocator-args.rs new file mode 100644 index 000000000..1033f947c --- /dev/null +++ b/src/test/ui/allocator/allocator-args.rs @@ -0,0 +1,13 @@ +use std::alloc::{GlobalAlloc, Layout}; + +struct A; + +unsafe impl GlobalAlloc for A { + unsafe fn alloc(&self, _: Layout) -> *mut u8 { panic!() } + unsafe fn dealloc(&self, _: *mut u8, _: Layout) { panic!() } +} + +#[global_allocator(malloc)] //~ ERROR malformed `global_allocator` attribute input +static S: A = A; + +fn main() {} diff --git a/src/test/ui/allocator/allocator-args.stderr b/src/test/ui/allocator/allocator-args.stderr new file mode 100644 index 000000000..dfff2a7e7 --- /dev/null +++ b/src/test/ui/allocator/allocator-args.stderr @@ -0,0 +1,8 @@ +error: malformed `global_allocator` attribute input + --> $DIR/allocator-args.rs:10:1 + | +LL | #[global_allocator(malloc)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[global_allocator]` + +error: aborting due to previous error + diff --git a/src/test/ui/allocator/auxiliary/custom-as-global.rs b/src/test/ui/allocator/auxiliary/custom-as-global.rs new file mode 100644 index 000000000..a5e96e775 --- /dev/null +++ b/src/test/ui/allocator/auxiliary/custom-as-global.rs @@ -0,0 +1,16 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +extern crate custom; + +use std::sync::atomic::{AtomicUsize, Ordering}; + +use custom::A; + +#[global_allocator] +static ALLOCATOR: A = A(AtomicUsize::new(0)); + +pub fn get() -> usize { + ALLOCATOR.0.load(Ordering::SeqCst) +} diff --git a/src/test/ui/allocator/auxiliary/custom.rs b/src/test/ui/allocator/auxiliary/custom.rs new file mode 100644 index 000000000..b0ec9ab09 --- /dev/null +++ b/src/test/ui/allocator/auxiliary/custom.rs @@ -0,0 +1,21 @@ +// no-prefer-dynamic + +#![feature(allocator_api)] +#![crate_type = "rlib"] + +use std::alloc::{GlobalAlloc, System, Layout}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +pub struct A(pub AtomicUsize); + +unsafe impl GlobalAlloc for A { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + self.0.fetch_add(1, Ordering::SeqCst); + System.alloc(layout) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + self.0.fetch_add(1, Ordering::SeqCst); + System.dealloc(ptr, layout) + } +} diff --git a/src/test/ui/allocator/auxiliary/helper.rs b/src/test/ui/allocator/auxiliary/helper.rs new file mode 100644 index 000000000..008fb3501 --- /dev/null +++ b/src/test/ui/allocator/auxiliary/helper.rs @@ -0,0 +1,11 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] +#![no_std] + +extern crate alloc; +use alloc::fmt; + +pub fn work_with(p: &fmt::Debug) { + drop(p); +} diff --git a/src/test/ui/allocator/auxiliary/system-allocator.rs b/src/test/ui/allocator/auxiliary/system-allocator.rs new file mode 100644 index 000000000..97b86bbc9 --- /dev/null +++ b/src/test/ui/allocator/auxiliary/system-allocator.rs @@ -0,0 +1,8 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +use std::alloc::System; + +#[global_allocator] +static A: System = System; diff --git a/src/test/ui/allocator/auxiliary/system-allocator2.rs b/src/test/ui/allocator/auxiliary/system-allocator2.rs new file mode 100644 index 000000000..97b86bbc9 --- /dev/null +++ b/src/test/ui/allocator/auxiliary/system-allocator2.rs @@ -0,0 +1,8 @@ +// no-prefer-dynamic + +#![crate_type = "rlib"] + +use std::alloc::System; + +#[global_allocator] +static A: System = System; diff --git a/src/test/ui/allocator/custom-in-block.rs b/src/test/ui/allocator/custom-in-block.rs new file mode 100644 index 000000000..12813a1fc --- /dev/null +++ b/src/test/ui/allocator/custom-in-block.rs @@ -0,0 +1,22 @@ +// run-pass +// no-prefer-dynamic +// aux-build:custom.rs +// aux-build:helper.rs + +extern crate custom; +extern crate helper; + +use custom::A; +use std::sync::atomic::{AtomicUsize, Ordering}; + +fn main() { + #[global_allocator] + pub static GLOBAL: A = A(AtomicUsize::new(0)); + + let n = GLOBAL.0.load(Ordering::SeqCst); + let s = Box::new(0); + helper::work_with(&s); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); + drop(s); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); +} diff --git a/src/test/ui/allocator/custom-in-submodule.rs b/src/test/ui/allocator/custom-in-submodule.rs new file mode 100644 index 000000000..ea341b1ac --- /dev/null +++ b/src/test/ui/allocator/custom-in-submodule.rs @@ -0,0 +1,26 @@ +// run-pass +// no-prefer-dynamic +// aux-build:custom.rs +// aux-build:helper.rs + +extern crate custom; +extern crate helper; + +use custom::A; +use std::sync::atomic::{AtomicUsize, Ordering}; + +mod submodule { + use super::*; + + #[global_allocator] + pub static GLOBAL: A = A(AtomicUsize::new(0)); +} + +fn main() { + let n = submodule::GLOBAL.0.load(Ordering::SeqCst); + let s = Box::new(0); + helper::work_with(&s); + assert_eq!(submodule::GLOBAL.0.load(Ordering::SeqCst), n + 1); + drop(s); + assert_eq!(submodule::GLOBAL.0.load(Ordering::SeqCst), n + 2); +} diff --git a/src/test/ui/allocator/custom.rs b/src/test/ui/allocator/custom.rs new file mode 100644 index 000000000..10cbc23c4 --- /dev/null +++ b/src/test/ui/allocator/custom.rs @@ -0,0 +1,59 @@ +// run-pass + +// aux-build:helper.rs +// no-prefer-dynamic + +#![feature(allocator_api)] +#![feature(slice_ptr_get)] + +extern crate helper; + +use std::alloc::{self, Allocator, Global, Layout, System}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static HITS: AtomicUsize = AtomicUsize::new(0); + +struct A; + +unsafe impl alloc::GlobalAlloc for A { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + HITS.fetch_add(1, Ordering::SeqCst); + alloc::GlobalAlloc::alloc(&System, layout) + } + + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + HITS.fetch_add(1, Ordering::SeqCst); + alloc::GlobalAlloc::dealloc(&System, ptr, layout) + } +} + +#[global_allocator] +static GLOBAL: A = A; + +fn main() { + println!("hello!"); + + let n = HITS.load(Ordering::SeqCst); + assert!(n > 0); + unsafe { + let layout = Layout::from_size_align(4, 2).unwrap(); + + let memory = Global.allocate(layout.clone()).unwrap(); + helper::work_with(&memory); + assert_eq!(HITS.load(Ordering::SeqCst), n + 1); + Global.deallocate(memory.as_non_null_ptr(), layout); + assert_eq!(HITS.load(Ordering::SeqCst), n + 2); + + let s = String::with_capacity(10); + helper::work_with(&s); + assert_eq!(HITS.load(Ordering::SeqCst), n + 3); + drop(s); + assert_eq!(HITS.load(Ordering::SeqCst), n + 4); + + let memory = System.allocate(layout.clone()).unwrap(); + helper::work_with(&memory); + assert_eq!(HITS.load(Ordering::SeqCst), n + 4); + System.deallocate(memory.as_non_null_ptr(), layout); + assert_eq!(HITS.load(Ordering::SeqCst), n + 4); + } +} diff --git a/src/test/ui/allocator/function-allocator.rs b/src/test/ui/allocator/function-allocator.rs new file mode 100644 index 000000000..d53f6e9b7 --- /dev/null +++ b/src/test/ui/allocator/function-allocator.rs @@ -0,0 +1,4 @@ +#[global_allocator] +fn foo() {} //~ ERROR: allocators must be statics + +fn main() {} diff --git a/src/test/ui/allocator/function-allocator.stderr b/src/test/ui/allocator/function-allocator.stderr new file mode 100644 index 000000000..5e47b0f0c --- /dev/null +++ b/src/test/ui/allocator/function-allocator.stderr @@ -0,0 +1,8 @@ +error: allocators must be statics + --> $DIR/function-allocator.rs:2:1 + | +LL | fn foo() {} + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/allocator/hygiene.rs b/src/test/ui/allocator/hygiene.rs new file mode 100644 index 000000000..9bd8406a2 --- /dev/null +++ b/src/test/ui/allocator/hygiene.rs @@ -0,0 +1,31 @@ +// run-pass +// no-prefer-dynamic +// aux-build:custom.rs +// aux-build:helper.rs + +#![allow(nonstandard_style)] + +extern crate custom; +extern crate helper; + +use custom::A; +use std::sync::atomic::{AtomicUsize, Ordering}; + +#[allow(dead_code)] +struct u8; +#[allow(dead_code)] +struct usize; +#[allow(dead_code)] +static arg0: () = (); + +#[global_allocator] +pub static GLOBAL: A = A(AtomicUsize::new(0)); + +fn main() { + let n = GLOBAL.0.load(Ordering::SeqCst); + let s = Box::new(0); + helper::work_with(&s); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); + drop(s); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); +} diff --git a/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs b/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs new file mode 100644 index 000000000..54b7c8bb9 --- /dev/null +++ b/src/test/ui/allocator/no_std-alloc-error-handler-custom.rs @@ -0,0 +1,103 @@ +// run-pass +// ignore-android no libc +// ignore-emscripten no libc +// ignore-sgx no libc +// ignore-wasm32 no libc +// only-linux +// compile-flags:-C panic=abort +// aux-build:helper.rs + +#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)] +#![feature(alloc_error_handler)] +#![no_std] + +extern crate alloc; +extern crate libc; + +// ARM targets need these symbols +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr0() {} + +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr1() {} + +use core::ptr::null_mut; +use core::alloc::{GlobalAlloc, Layout}; +use alloc::boxed::Box; + +extern crate helper; + +struct MyAllocator; + +#[alloc_error_handler] +fn my_oom(layout: Layout) -> ! +{ + use alloc::fmt::write; + unsafe { + let size = layout.size(); + let mut s = alloc::string::String::new(); + write(&mut s, format_args!("My OOM: failed to allocate {} bytes!\n", size)).unwrap(); + let s = s.as_str(); + libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len()); + libc::exit(0) + } +} + +unsafe impl GlobalAlloc for MyAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.size() < 4096 { + libc::malloc(layout.size()) as _ + } else { + null_mut() + } + } + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +} + +#[global_allocator] +static A: MyAllocator = MyAllocator; + +#[panic_handler] +fn panic(panic_info: &core::panic::PanicInfo) -> ! { + unsafe { + if let Some(s) = panic_info.payload().downcast_ref::<&str>() { + const PSTR: &str = "panic occurred: "; + const CR: &str = "\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len()); + libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len()); + } + if let Some(args) = panic_info.message() { + let mut s = alloc::string::String::new(); + alloc::fmt::write(&mut s, *args).unwrap(); + let s = s.as_str(); + const PSTR: &str = "panic occurred: "; + const CR: &str = "\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len()); + libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len()); + } else { + const PSTR: &str = "panic occurred\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + } + libc::exit(1) + } +} + +// Because we are compiling this code with `-C panic=abort`, this wouldn't normally be needed. +// However, `core` and `alloc` are both compiled with `-C panic=unwind`, which means that functions +// in these libaries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't +// unwind. So, for this test case we will define the symbol. +#[lang = "eh_personality"] +extern fn rust_eh_personality() {} + +#[derive(Debug)] +struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]); + +#[start] +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { + let zero = Box::<Page>::new_zeroed(); + let zero = unsafe { zero.assume_init() }; + helper::work_with(&zero); + 1 +} diff --git a/src/test/ui/allocator/no_std-alloc-error-handler-default.rs b/src/test/ui/allocator/no_std-alloc-error-handler-default.rs new file mode 100644 index 000000000..ffa331a99 --- /dev/null +++ b/src/test/ui/allocator/no_std-alloc-error-handler-default.rs @@ -0,0 +1,90 @@ +// run-pass +// ignore-android no libc +// ignore-emscripten no libc +// ignore-sgx no libc +// ignore-wasm32 no libc +// only-linux +// compile-flags:-C panic=abort +// aux-build:helper.rs +// gate-test-default_alloc_error_handler + +#![feature(start, rustc_private, new_uninit, panic_info_message, lang_items)] +#![feature(default_alloc_error_handler)] +#![no_std] + +extern crate alloc; +extern crate libc; + +// ARM targets need these symbols +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr0() {} + +#[no_mangle] +pub fn __aeabi_unwind_cpp_pr1() {} + +use alloc::boxed::Box; +use core::alloc::{GlobalAlloc, Layout}; +use core::ptr::null_mut; + +extern crate helper; + +struct MyAllocator; + +unsafe impl GlobalAlloc for MyAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.size() < 4096 { + libc::malloc(layout.size()) as _ + } else { + null_mut() + } + } + unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {} +} + +#[global_allocator] +static A: MyAllocator = MyAllocator; + +#[panic_handler] +fn panic(panic_info: &core::panic::PanicInfo) -> ! { + unsafe { + if let Some(s) = panic_info.payload().downcast_ref::<&str>() { + const PSTR: &str = "panic occurred: "; + const CR: &str = "\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len()); + libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len()); + } + if let Some(args) = panic_info.message() { + let mut s = alloc::string::String::new(); + alloc::fmt::write(&mut s, *args).unwrap(); + let s = s.as_str(); + const PSTR: &str = "panic occurred: "; + const CR: &str = "\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + libc::write(libc::STDERR_FILENO, s as *const _ as _, s.len()); + libc::write(libc::STDERR_FILENO, CR as *const _ as _, CR.len()); + } else { + const PSTR: &str = "panic occurred\n"; + libc::write(libc::STDERR_FILENO, PSTR as *const _ as _, PSTR.len()); + } + libc::exit(0) + } +} + +// Because we are compiling this code with `-C panic=abort`, this wouldn't normally be needed. +// However, `core` and `alloc` are both compiled with `-C panic=unwind`, which means that functions +// in these libaries will refer to `rust_eh_personality` if LLVM can not *prove* the contents won't +// unwind. So, for this test case we will define the symbol. +#[lang = "eh_personality"] +extern fn rust_eh_personality() {} + +#[derive(Debug)] +struct Page(#[allow(unused_tuple_struct_fields)] [[u64; 32]; 16]); + +#[start] +pub fn main(_argc: isize, _argv: *const *const u8) -> isize { + let zero = Box::<Page>::new_zeroed(); + let zero = unsafe { zero.assume_init() }; + helper::work_with(&zero); + 1 +} diff --git a/src/test/ui/allocator/not-an-allocator.rs b/src/test/ui/allocator/not-an-allocator.rs new file mode 100644 index 000000000..4a538d4d0 --- /dev/null +++ b/src/test/ui/allocator/not-an-allocator.rs @@ -0,0 +1,8 @@ +#[global_allocator] +static A: usize = 0; +//~^ ERROR E0277 +//~| ERROR E0277 +//~| ERROR E0277 +//~| ERROR E0277 + +fn main() {} diff --git a/src/test/ui/allocator/not-an-allocator.stderr b/src/test/ui/allocator/not-an-allocator.stderr new file mode 100644 index 000000000..62bb0679f --- /dev/null +++ b/src/test/ui/allocator/not-an-allocator.stderr @@ -0,0 +1,47 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion +LL | static A: usize = 0; + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | + = help: the trait `GlobalAlloc` is implemented for `System` + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion +LL | static A: usize = 0; + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | + = help: the trait `GlobalAlloc` is implemented for `System` + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion +LL | static A: usize = 0; + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | + = help: the trait `GlobalAlloc` is implemented for `System` + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/not-an-allocator.rs:2:11 + | +LL | #[global_allocator] + | ------------------- in this procedural macro expansion +LL | static A: usize = 0; + | ^^^^^ the trait `GlobalAlloc` is not implemented for `usize` + | + = help: the trait `GlobalAlloc` is implemented for `System` + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/allocator/object-safe.rs b/src/test/ui/allocator/object-safe.rs new file mode 100644 index 000000000..fae7ab7fe --- /dev/null +++ b/src/test/ui/allocator/object-safe.rs @@ -0,0 +1,13 @@ +// run-pass + +// Check that `Allocator` is object safe, this allows for polymorphic allocators + +#![feature(allocator_api)] + +use std::alloc::{Allocator, System}; + +fn ensure_object_safe(_: &dyn Allocator) {} + +fn main() { + ensure_object_safe(&System); +} diff --git a/src/test/ui/allocator/two-allocators.rs b/src/test/ui/allocator/two-allocators.rs new file mode 100644 index 000000000..aa1291e77 --- /dev/null +++ b/src/test/ui/allocator/two-allocators.rs @@ -0,0 +1,9 @@ +use std::alloc::System; + +#[global_allocator] +static A: System = System; +#[global_allocator] +static B: System = System; +//~^ ERROR: cannot define multiple global allocators + +fn main() {} diff --git a/src/test/ui/allocator/two-allocators.stderr b/src/test/ui/allocator/two-allocators.stderr new file mode 100644 index 000000000..7a914c2a3 --- /dev/null +++ b/src/test/ui/allocator/two-allocators.stderr @@ -0,0 +1,14 @@ +error: cannot define multiple global allocators + --> $DIR/two-allocators.rs:6:1 + | +LL | static A: System = System; + | -------------------------- previous global allocator defined here +LL | #[global_allocator] + | ------------------- in this procedural macro expansion +LL | static B: System = System; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot define a new global allocator + | + = note: this error originates in the attribute macro `global_allocator` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/allocator/two-allocators2.rs b/src/test/ui/allocator/two-allocators2.rs new file mode 100644 index 000000000..6dfefe19c --- /dev/null +++ b/src/test/ui/allocator/two-allocators2.rs @@ -0,0 +1,12 @@ +// aux-build:system-allocator.rs +// no-prefer-dynamic +// error-pattern: the `#[global_allocator]` in + +extern crate system_allocator; + +use std::alloc::System; + +#[global_allocator] +static A: System = System; + +fn main() {} diff --git a/src/test/ui/allocator/two-allocators2.stderr b/src/test/ui/allocator/two-allocators2.stderr new file mode 100644 index 000000000..b1fb4421e --- /dev/null +++ b/src/test/ui/allocator/two-allocators2.stderr @@ -0,0 +1,4 @@ +error: the `#[global_allocator]` in this crate conflicts with global allocator in: system_allocator + +error: aborting due to previous error + diff --git a/src/test/ui/allocator/two-allocators3.rs b/src/test/ui/allocator/two-allocators3.rs new file mode 100644 index 000000000..31dea2d44 --- /dev/null +++ b/src/test/ui/allocator/two-allocators3.rs @@ -0,0 +1,10 @@ +// aux-build:system-allocator.rs +// aux-build:system-allocator2.rs +// no-prefer-dynamic +// error-pattern: the `#[global_allocator]` in + + +extern crate system_allocator; +extern crate system_allocator2; + +fn main() {} diff --git a/src/test/ui/allocator/two-allocators3.stderr b/src/test/ui/allocator/two-allocators3.stderr new file mode 100644 index 000000000..a3079113d --- /dev/null +++ b/src/test/ui/allocator/two-allocators3.stderr @@ -0,0 +1,4 @@ +error: the `#[global_allocator]` in system_allocator conflicts with global allocator in: system_allocator2 + +error: aborting due to previous error + diff --git a/src/test/ui/allocator/xcrate-use.rs b/src/test/ui/allocator/xcrate-use.rs new file mode 100644 index 000000000..edd4df75e --- /dev/null +++ b/src/test/ui/allocator/xcrate-use.rs @@ -0,0 +1,36 @@ +// run-pass + +// aux-build:custom.rs +// aux-build:helper.rs +// no-prefer-dynamic + +#![feature(allocator_api)] +#![feature(slice_ptr_get)] + +extern crate custom; +extern crate helper; + +use std::alloc::{Allocator, Global, Layout, System}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +#[global_allocator] +static GLOBAL: custom::A = custom::A(AtomicUsize::new(0)); + +fn main() { + unsafe { + let n = GLOBAL.0.load(Ordering::SeqCst); + let layout = Layout::from_size_align(4, 2).unwrap(); + + let memory = Global.allocate(layout.clone()).unwrap(); + helper::work_with(&memory); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); + Global.deallocate(memory.as_non_null_ptr(), layout); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); + + let memory = System.allocate(layout.clone()).unwrap(); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); + helper::work_with(&memory); + System.deallocate(memory.as_non_null_ptr(), layout); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); + } +} diff --git a/src/test/ui/allocator/xcrate-use2.rs b/src/test/ui/allocator/xcrate-use2.rs new file mode 100644 index 000000000..d8478fb5e --- /dev/null +++ b/src/test/ui/allocator/xcrate-use2.rs @@ -0,0 +1,47 @@ +// run-pass + +// aux-build:custom.rs +// aux-build:custom-as-global.rs +// aux-build:helper.rs +// no-prefer-dynamic + +#![feature(allocator_api)] + +extern crate custom; +extern crate custom_as_global; +extern crate helper; + +use std::alloc::{alloc, dealloc, GlobalAlloc, System, Layout}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +static GLOBAL: custom::A = custom::A(AtomicUsize::new(0)); + +fn main() { + unsafe { + let n = custom_as_global::get(); + let layout = Layout::from_size_align(4, 2).unwrap(); + + // Global allocator routes to the `custom_as_global` global + let ptr = alloc(layout.clone()); + helper::work_with(&ptr); + assert_eq!(custom_as_global::get(), n + 1); + dealloc(ptr, layout.clone()); + assert_eq!(custom_as_global::get(), n + 2); + + // Usage of the system allocator avoids all globals + let ptr = System.alloc(layout.clone()); + helper::work_with(&ptr); + assert_eq!(custom_as_global::get(), n + 2); + System.dealloc(ptr, layout.clone()); + assert_eq!(custom_as_global::get(), n + 2); + + // Usage of our personal allocator doesn't affect other instances + let ptr = GLOBAL.alloc(layout.clone()); + helper::work_with(&ptr); + assert_eq!(custom_as_global::get(), n + 2); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 1); + GLOBAL.dealloc(ptr, layout); + assert_eq!(custom_as_global::get(), n + 2); + assert_eq!(GLOBAL.0.load(Ordering::SeqCst), 2); + } +} |