@@ -2009,32 +2009,39 @@ impl CodeGenerator for CompInfo {
2009
2009
let mut needs_default_impl = false ;
2010
2010
let mut needs_debug_impl = false ;
2011
2011
let mut needs_partialeq_impl = false ;
2012
+ let mut needs_packed_wrapper = false ;
2012
2013
if let Some ( comment) = item. comment ( ctx) {
2013
2014
attributes. push ( attributes:: doc ( comment) ) ;
2014
2015
}
2016
+
2017
+ // We can't specify both packed(N) and align(N), but the packed()
2018
+ // should be redundant in this case.
2015
2019
if packed && !is_opaque {
2016
2020
let n = layout. map_or ( 1 , |l| l. align ) ;
2017
2021
assert ! ( ctx. options( ) . rust_features( ) . repr_packed_n || n == 1 ) ;
2018
- let packed_repr = if n == 1 {
2022
+ if ctx. options ( ) . rust_features ( ) . repr_align &&
2023
+ explicit_align. is_some ( )
2024
+ {
2025
+ needs_packed_wrapper = true ;
2026
+ }
2027
+ let packed_repr = if n == 1 || needs_packed_wrapper {
2019
2028
"packed" . to_string ( )
2020
2029
} else {
2021
2030
format ! ( "packed({})" , n)
2022
2031
} ;
2023
2032
attributes. push ( attributes:: repr_list ( & [ "C" , & packed_repr] ) ) ;
2024
2033
} else {
2025
2034
attributes. push ( attributes:: repr ( "C" ) ) ;
2026
- }
2027
2035
2028
- if ctx. options ( ) . rust_features ( ) . repr_align && !packed {
2029
- // We can't specify both packed(N) and align(N), but the align()
2030
- // should be redundant in this case.
2031
- if let Some ( explicit) = explicit_align {
2032
- // Ensure that the struct has the correct alignment even in
2033
- // presence of alignas.
2034
- let explicit = helpers:: ast_ty:: int_expr ( explicit as i64 ) ;
2035
- attributes. push ( quote ! {
2036
- #[ repr( align( #explicit) ) ]
2037
- } ) ;
2036
+ if ctx. options ( ) . rust_features ( ) . repr_align {
2037
+ if let Some ( explicit) = explicit_align {
2038
+ // Ensure that the struct has the correct alignment even in
2039
+ // presence of alignas.
2040
+ let explicit = helpers:: ast_ty:: int_expr ( explicit as i64 ) ;
2041
+ attributes. push ( quote ! {
2042
+ #[ repr( align( #explicit) ) ]
2043
+ } ) ;
2044
+ }
2038
2045
}
2039
2046
}
2040
2047
@@ -2088,15 +2095,21 @@ impl CodeGenerator for CompInfo {
2088
2095
attributes. push ( attributes:: must_use ( ) ) ;
2089
2096
}
2090
2097
2098
+ let layout_ident = if needs_packed_wrapper {
2099
+ ctx. rust_ident ( canonical_name. to_owned ( ) + "__packed" )
2100
+ } else {
2101
+ canonical_ident. clone ( )
2102
+ } ;
2103
+
2091
2104
let mut tokens = if is_union && struct_layout. is_rust_union ( ) {
2092
2105
quote ! {
2093
2106
#( #attributes ) *
2094
- pub union #canonical_ident
2107
+ pub union #layout_ident
2095
2108
}
2096
2109
} else {
2097
2110
quote ! {
2098
2111
#( #attributes ) *
2099
- pub struct #canonical_ident
2112
+ pub struct #layout_ident
2100
2113
}
2101
2114
} ;
2102
2115
@@ -2107,6 +2120,19 @@ impl CodeGenerator for CompInfo {
2107
2120
} ) ;
2108
2121
result. push ( tokens) ;
2109
2122
2123
+ if needs_packed_wrapper {
2124
+ let attributes = attributes:: derives ( & derives) ;
2125
+ let align = proc_macro2:: TokenStream :: from_str (
2126
+ & explicit_align. unwrap ( ) . to_string ( ) ,
2127
+ )
2128
+ . unwrap ( ) ;
2129
+ result. push ( quote ! {
2130
+ #attributes
2131
+ #[ repr( C , align( #align) ) ]
2132
+ pub struct #canonical_ident( pub #layout_ident) ;
2133
+ } ) ;
2134
+ }
2135
+
2110
2136
// Generate the inner types and all that stuff.
2111
2137
//
2112
2138
// TODO: In the future we might want to be smart, and use nested
@@ -2206,12 +2232,17 @@ impl CodeGenerator for CompInfo {
2206
2232
let uninit_decl = if !check_field_offset. is_empty ( ) {
2207
2233
// FIXME: When MSRV >= 1.59.0, we can use
2208
2234
// > const PTR: *const #canonical_ident = ::#prefix::mem::MaybeUninit::uninit().as_ptr();
2235
+ let layout_cast = if needs_packed_wrapper {
2236
+ Some ( quote ! ( as * const #layout_ident) )
2237
+ } else {
2238
+ None
2239
+ } ;
2209
2240
Some ( quote ! {
2210
2241
// Use a shared MaybeUninit so that rustc with
2211
2242
// opt-level=0 doesn't take too much stack space,
2212
2243
// see #2218.
2213
2244
const UNINIT : :: #prefix:: mem:: MaybeUninit <#canonical_ident> = :: #prefix:: mem:: MaybeUninit :: uninit( ) ;
2214
- let ptr = UNINIT . as_ptr( ) ;
2245
+ let ptr = UNINIT . as_ptr( ) #layout_cast ;
2215
2246
} )
2216
2247
} else {
2217
2248
None
0 commit comments