@@ -8,6 +8,8 @@ use syn::ext::IdentExt;
88use syn:: fold:: Fold ;
99use syn:: parse:: { Parse , ParseStream , Parser , Result as ParseResult } ;
1010
11+ use crate :: bindgen:: ir:: { Repr , ReprStyle } ;
12+
1113// $(#[$outer:meta])*
1214// ($($vis:tt)*) $BitFlags:ident: $T:ty {
1315// $(
@@ -52,7 +54,17 @@ pub enum Bitflags {
5254}
5355
5456impl Bitflags {
55- pub fn expand ( & self ) -> ( Option < syn:: ItemStruct > , syn:: ItemImpl ) {
57+ pub fn self_ty_name ( & self ) -> & syn:: Ident {
58+ match self {
59+ Bitflags :: Struct ( s) => & s. name ,
60+ Bitflags :: Impl ( i) => & i. name ,
61+ }
62+ }
63+
64+ pub fn expand (
65+ & self ,
66+ out_of_line_transparent : bool ,
67+ ) -> ( Option < syn:: ItemStruct > , syn:: ItemImpl ) {
5668 match self {
5769 Bitflags :: Struct ( BitflagsStruct {
5870 attrs,
@@ -69,7 +81,13 @@ impl Bitflags {
6981 }
7082 } ;
7183
72- let consts = flags. expand ( name, repr, false ) ;
84+ let is_transparent = if let Ok ( repr) = Repr :: load ( attrs) {
85+ matches ! ( repr. style, ReprStyle :: Transparent )
86+ } else {
87+ false
88+ } ;
89+
90+ let consts = flags. expand ( name, repr, false , is_transparent) ;
7391 let impl_ = parse_quote ! {
7492 impl #name {
7593 #consts
@@ -81,7 +99,7 @@ impl Bitflags {
8199 Bitflags :: Impl ( BitflagsImpl {
82100 name, repr, flags, ..
83101 } ) => {
84- let consts = flags. expand ( name, repr, true ) ;
102+ let consts = flags. expand ( name, repr, true , out_of_line_transparent ) ;
85103 let impl_: syn:: ItemImpl = parse_quote ! {
86104 impl #name {
87105 #consts
@@ -136,6 +154,7 @@ struct FlagValueFold<'a> {
136154 struct_name : & ' a syn:: Ident ,
137155 flag_names : & ' a HashSet < String > ,
138156 out_of_line : bool ,
157+ is_transparent : bool ,
139158}
140159
141160impl FlagValueFold < ' _ > {
@@ -192,6 +211,12 @@ impl Fold for FlagValueFold<'_> {
192211 . flag_names
193212 . contains( & path. segments. last( ) . unwrap( ) . ident. to_string( ) ) ) =>
194213 {
214+ // In the transparent case the struct is rendered as a plain typedef to the
215+ // underlying integer (e.g. `typedef uint8_t Flags;`), so there is no field
216+ // to access, so we keep just the receiver.
217+ if self . is_transparent {
218+ return * receiver;
219+ }
195220 return syn:: Expr :: Field ( syn:: ExprField {
196221 attrs,
197222 base : receiver,
@@ -216,6 +241,7 @@ impl Flag {
216241 repr : & syn:: Type ,
217242 flag_names : & HashSet < String > ,
218243 out_of_line : bool ,
244+ is_transparent : bool ,
219245 ) -> TokenStream {
220246 let Flag {
221247 ref attrs,
@@ -227,9 +253,10 @@ impl Flag {
227253 struct_name,
228254 flag_names,
229255 out_of_line,
256+ is_transparent,
230257 }
231258 . fold_expr ( value. clone ( ) ) ;
232- let value = if out_of_line {
259+ let value = if out_of_line || is_transparent {
233260 quote ! { ( ( #folded_value) as #repr) }
234261 } else {
235262 quote ! { { bits: ( #folded_value) as #repr } }
@@ -275,15 +302,21 @@ impl Parse for Flags {
275302}
276303
277304impl Flags {
278- fn expand ( & self , struct_name : & syn:: Ident , repr : & syn:: Type , out_of_line : bool ) -> TokenStream {
305+ fn expand (
306+ & self ,
307+ struct_name : & syn:: Ident ,
308+ repr : & syn:: Type ,
309+ out_of_line : bool ,
310+ is_transparent : bool ,
311+ ) -> TokenStream {
279312 let mut ts = quote ! { } ;
280313 let flag_names = self
281314 . 0
282315 . iter ( )
283316 . map ( |flag| flag. name . to_string ( ) )
284317 . collect :: < HashSet < _ > > ( ) ;
285318 for flag in & self . 0 {
286- ts. extend ( flag. expand ( struct_name, repr, & flag_names, out_of_line) ) ;
319+ ts. extend ( flag. expand ( struct_name, repr, & flag_names, out_of_line, is_transparent ) ) ;
287320 }
288321 ts
289322 }
0 commit comments