@@ -57,26 +57,57 @@ pub mod access;
57
57
/// let field_2 = map_field!(volatile.field_2);
58
58
/// assert_eq!(field_2.read(), 255);
59
59
/// ```
60
+ ///
61
+ /// Creating `VolatilePtr`s to unaligned field in packed structs is not allowed:
62
+ /// ```compile_fail
63
+ /// # extern crate core;
64
+ /// use volatile::{VolatilePtr, map_field};
65
+ /// use core::ptr::NonNull;
66
+ ///
67
+ /// #[repr(packed)]
68
+ /// struct Example { field_1: u8, field_2: usize, }
69
+ /// let mut value = Example { field_1: 15, field_2: 255 };
70
+ /// let mut volatile = unsafe { VolatilePtr::new_read_write(NonNull::from(&mut value)) };
71
+ ///
72
+ /// // Constructing a volatile reference to an unaligned field doesn't compile.
73
+ /// let field_2 = map_field!(volatile.field_2);
74
+ /// ```
60
75
#[ macro_export]
61
76
macro_rules! map_field {
62
- ( $volatile: ident. $place: ident) => {
77
+ ( $volatile: ident. $place: ident) => { {
78
+ // Simulate creating a reference to the field. This is done to make
79
+ // sure that the field is not potentially unaligned. The body of the
80
+ // if statement will never be executed, so it can never cause any UB.
81
+ if false {
82
+ #[ deny( unaligned_references) ]
83
+ let _ref_to_field = & ( unsafe { & * $volatile. as_ptr( ) . as_ptr( ) } ) . $place;
84
+ }
85
+
63
86
unsafe {
64
87
$volatile. map( |ptr| {
65
88
core:: ptr:: NonNull :: new( core:: ptr:: addr_of_mut!( ( * ptr. as_ptr( ) ) . $place) ) . unwrap( )
66
89
} )
67
90
}
68
- } ;
91
+ } } ;
69
92
}
70
93
71
94
#[ macro_export]
72
95
macro_rules! map_field_mut {
73
- ( $volatile: ident. $place: ident) => {
96
+ ( $volatile: ident. $place: ident) => { {
97
+ // Simulate creating a reference to the field. This is done to make
98
+ // sure that the field is not potentially unaligned. The body of the
99
+ // if statement will never be executed, so it can never cause any UB.
100
+ if false {
101
+ #[ deny( unaligned_references) ]
102
+ let _ref_to_field = & ( unsafe { & * $volatile. as_ptr( ) . as_ptr( ) } ) . $place;
103
+ }
104
+
74
105
unsafe {
75
106
$volatile. map_mut( |ptr| {
76
107
core:: ptr:: NonNull :: new( core:: ptr:: addr_of_mut!( ( * ptr. as_ptr( ) ) . $place) ) . unwrap( )
77
108
} )
78
109
}
79
- } ;
110
+ } } ;
80
111
}
81
112
82
113
// this must be defined after the `map_field` macros
0 commit comments