//@ run-pass //@ compile-flags: --cfg FOURTY_TWO="42" --cfg TRUE --check-cfg=cfg(FOURTY_TWO,values("42")) --check-cfg=cfg(TRUE) #![feature(static_align)] #![deny(non_upper_case_globals)] use std::cell::Cell; #[rustc_align_static(64)] static A: u8 = 0; #[rustc_align_static(4096)] static B: u8 = 0; #[rustc_align_static(128)] #[no_mangle] static EXPORTED: u64 = 0; unsafe extern "C" { #[rustc_align_static(128)] #[link_name = "EXPORTED"] static C: u64; } struct HasDrop(*const HasDrop); impl Drop for HasDrop { fn drop(&mut self) { assert_eq!(core::ptr::from_mut(self).cast_const(), self.0); } } thread_local! { #[rustc_align_static(4096)] static LOCAL: u64 = 0; #[allow(unused_mut, reason = "test attribute handling")] #[cfg_attr(true, rustc_align_static(4096))] static CONST_LOCAL: u64 = const { 0 }; #[cfg_attr(any(true), cfg_attr(true, rustc_align_static(4096)))] #[allow(unused_mut, reason = "test attribute handling")] static HASDROP_LOCAL: Cell = Cell::new(HasDrop(core::ptr::null())); /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. #[allow(unused_mut, reason = "test attribute handling")] #[cfg_attr(TRUE, cfg_attr(FOURTY_TWO = "42", cfg_attr(all(), cfg_attr(any(true), cfg_attr(true, rustc_align_static(4096))))))] #[allow(unused_mut, reason = "test attribute handling")] /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. /// I love doc comments. static HASDROP_CONST_LOCAL: Cell = const { Cell::new(HasDrop(core::ptr::null())) }; #[cfg_attr(TRUE,)] #[cfg_attr(true,)] #[cfg_attr(false,)] #[cfg_attr( TRUE, rustc_align_static(32), cfg_attr(true, allow(non_upper_case_globals, reason = "test attribute handling")), cfg_attr(false,) )] #[cfg_attr(false, rustc_align_static(0))] static more_attr_testing: u64 = 0; } fn thread_local_ptr(key: &'static std::thread::LocalKey) -> *const T { key.with(|local| core::ptr::from_ref::(local)) } fn main() { assert!(core::ptr::from_ref(&A).addr().is_multiple_of(64)); assert!(core::ptr::from_ref(&B).addr().is_multiple_of(4096)); assert!(core::ptr::from_ref(&EXPORTED).addr().is_multiple_of(128)); unsafe { assert!(core::ptr::from_ref(&C).addr().is_multiple_of(128)) }; assert!(thread_local_ptr(&LOCAL).addr().is_multiple_of(4096)); assert!(thread_local_ptr(&CONST_LOCAL).addr().is_multiple_of(4096)); assert!(thread_local_ptr(&HASDROP_LOCAL).addr().is_multiple_of(4096)); assert!(thread_local_ptr(&HASDROP_CONST_LOCAL).addr().is_multiple_of(4096)); assert!(thread_local_ptr(&more_attr_testing).addr().is_multiple_of(32)); // Test that address (and therefore alignment) is maintained during drop let hasdrop_ptr = thread_local_ptr(&HASDROP_LOCAL); core::mem::forget(HASDROP_LOCAL.replace(HasDrop(hasdrop_ptr.cast()))); let hasdrop_const_ptr = thread_local_ptr(&HASDROP_CONST_LOCAL); core::mem::forget(HASDROP_CONST_LOCAL.replace(HasDrop(hasdrop_const_ptr.cast()))); }