@@ -7,7 +7,7 @@ use std::iter::FromIterator as _;
7
7
use std:: mem;
8
8
9
9
use crate :: bindgen:: ir:: {
10
- Documentation , Enum , Field , GenericArgument , GenericPath , Item , ItemContainer , OpaqueItem ,
10
+ Cfg , Documentation , Enum , Field , GenericArgument , GenericPath , Item , ItemContainer , OpaqueItem ,
11
11
Path , Struct , Type , Typedef , Union ,
12
12
} ;
13
13
use crate :: bindgen:: library:: Library ;
@@ -152,30 +152,53 @@ impl Monomorphs {
152
152
/// functions that can lead to compilation warnings/errors if not explicitly instantiated.
153
153
pub struct ReturnValueMonomorphs < ' a > {
154
154
library : & ' a Library ,
155
- monomorphs : HashSet < GenericPath > ,
155
+ monomorphs : HashSet < ( GenericPath , Option < Cfg > ) > ,
156
+ active_cfgs : Vec < Cfg > ,
156
157
}
157
158
158
159
impl < ' a > ReturnValueMonomorphs < ' a > {
159
160
pub fn new ( library : & ' a Library ) -> Self {
160
161
Self {
161
162
library,
162
163
monomorphs : HashSet :: new ( ) ,
164
+ active_cfgs : Vec :: new ( ) ,
163
165
}
164
166
}
165
167
166
- /// Resolve a typedef that is a function return value, specializing it first if needed.
167
- fn handle_return_value_typedef ( & mut self , typedef : Typedef , generic : & GenericPath ) {
168
- if typedef. is_generic ( ) {
169
- let args = generic. generics ( ) ;
170
- let aliased = & typedef. aliased ;
171
- let mappings = typedef. generic_params . call ( typedef. path . name ( ) , args) ;
172
- let aliased = aliased. specialize ( & mappings) ;
173
- aliased. find_return_value_monomorphs ( self , true ) ;
168
+ fn insert ( & mut self , generic : & GenericPath , cfg : Option < Cfg > ) {
169
+ if !generic. generics ( ) . is_empty ( ) {
170
+ self . with_active_cfg ( cfg, |m| {
171
+ let cfg = Cfg :: join ( & m. active_cfgs ) ;
172
+ m. monomorphs . insert ( ( generic. clone ( ) , cfg) ) ;
173
+ } ) ;
174
+ }
175
+ }
176
+
177
+ pub fn with_active_cfg ( & mut self , cfg : Option < Cfg > , thunk : impl FnOnce ( & mut Self ) ) {
178
+ if let Some ( cfg) = cfg {
179
+ self . active_cfgs . push ( cfg) ;
180
+ thunk ( self ) ;
181
+ self . active_cfgs . pop ( ) ;
174
182
} else {
175
- typedef . find_return_value_monomorphs ( self , true ) ;
183
+ thunk ( self ) ;
176
184
}
177
185
}
178
186
187
+ /// Resolve a typedef that is a function return value, specializing it first if needed.
188
+ fn handle_return_value_typedef ( & mut self , typedef : Typedef , generic : & GenericPath ) {
189
+ self . with_active_cfg ( typedef. cfg . clone ( ) , |m| {
190
+ if typedef. is_generic ( ) {
191
+ let args = generic. generics ( ) ;
192
+ let aliased = & typedef. aliased ;
193
+ let mappings = typedef. generic_params . call ( typedef. path . name ( ) , args) ;
194
+ let aliased = aliased. specialize ( & mappings) ;
195
+ aliased. find_return_value_monomorphs ( m, true ) ;
196
+ } else {
197
+ typedef. find_return_value_monomorphs ( m, true ) ;
198
+ }
199
+ } ) ;
200
+ }
201
+
179
202
/// Once we find a function return type, what we do with it depends on the type of item it
180
203
/// resolves to. Typedefs need to be resolved recursively, while generic structs, unions, and
181
204
/// enums are captured in the set of return value monomorphs.
@@ -191,16 +214,13 @@ impl<'a> ReturnValueMonomorphs<'a> {
191
214
// Opaque items cannot be instantiated (doomed to compilation failure)
192
215
ItemContainer :: OpaqueItem ( _) => { }
193
216
ItemContainer :: Typedef ( t) => self . handle_return_value_typedef ( t, generic) ,
194
- ItemContainer :: Union ( _) | ItemContainer :: Enum ( _) => {
195
- if !generic. generics ( ) . is_empty ( ) {
196
- self . monomorphs . insert ( generic. clone ( ) ) ;
197
- }
198
- }
217
+ ItemContainer :: Union ( u) => self . insert ( generic, u. cfg ) ,
218
+ ItemContainer :: Enum ( e) => self . insert ( generic, e. cfg ) ,
199
219
ItemContainer :: Struct ( s) => {
200
220
if let Some ( t) = s. as_typedef ( ) {
201
221
self . handle_return_value_typedef ( t, generic) ;
202
- } else if !generic . generics ( ) . is_empty ( ) {
203
- self . monomorphs . insert ( generic. clone ( ) ) ;
222
+ } else {
223
+ self . insert ( generic, s . cfg ) ;
204
224
}
205
225
}
206
226
}
@@ -225,11 +245,15 @@ impl<'a> ReturnValueMonomorphs<'a> {
225
245
226
246
// Sort the output so that the struct remains stable across runs (tests want that).
227
247
let mut monomorphs = Vec :: from_iter ( self . monomorphs ) ;
228
- monomorphs. sort ( ) ;
248
+ monomorphs. sort_by ( | ( k1 , _ ) , ( k2 , _ ) | k1 . cmp ( k2 ) ) ;
229
249
let fields = monomorphs
230
250
. into_iter ( )
231
251
. enumerate ( )
232
- . map ( |( i, path) | Field :: from_name_and_type ( format ! ( "field{}" , i) , Type :: Path ( path) ) )
252
+ . map ( |( i, ( path, cfg) ) | {
253
+ let mut f = Field :: from_name_and_type ( format ! ( "field{}" , i) , Type :: Path ( path) ) ;
254
+ f. cfg = cfg;
255
+ f
256
+ } )
233
257
. collect ( ) ;
234
258
let doc_comment = vec ! [
235
259
" Dummy struct emitted by cbindgen to avoid compiler warnings/errors about" ,
0 commit comments