Skip to content

Commit b99b321

Browse files
committed
respect conditional cfg
1 parent fe40e24 commit b99b321

18 files changed

+356
-47
lines changed

src/bindgen/ir/cfg.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl<'a> DefineKey<'a> {
4242
}
4343
}
4444

45-
#[derive(Debug, Clone)]
45+
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
4646
pub enum Cfg {
4747
Boolean(String),
4848
Named(String, String),
@@ -129,10 +129,10 @@ impl syn::parse::Parse for Cfg {
129129

130130
impl Cfg {
131131
pub fn join(cfgs: &[Cfg]) -> Option<Cfg> {
132-
if cfgs.is_empty() {
133-
None
134-
} else {
135-
Some(Cfg::All(cfgs.to_owned()))
132+
match cfgs {
133+
[] => None,
134+
[cfg] => Some(cfg.clone()),
135+
_ => Some(Cfg::All(cfgs.to_owned())),
136136
}
137137
}
138138

src/bindgen/ir/enumeration.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -318,11 +318,13 @@ impl Enum {
318318
}
319319

320320
pub fn find_return_value_monomorphs(&self, monomorphs: &mut ReturnValueMonomorphs<'_>) {
321-
for v in &self.variants {
322-
if let VariantBody::Body { ref body, .. } = v.body {
323-
body.find_return_value_monomorphs(monomorphs);
321+
monomorphs.with_active_cfg(self.cfg.clone(), |m| {
322+
for v in &self.variants {
323+
if let VariantBody::Body { ref body, .. } = v.body {
324+
body.find_return_value_monomorphs(m);
325+
}
324326
}
325-
}
327+
});
326328
}
327329

328330
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {

src/bindgen/ir/function.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,9 @@ impl Function {
137137
}
138138

139139
pub fn find_return_value_monomorphs(&self, monomorphs: &mut ReturnValueMonomorphs<'_>) {
140-
monomorphs.handle_function(&self.ret, self.args.iter().map(|arg| &arg.ty));
140+
monomorphs.with_active_cfg(self.cfg.clone(), |m| {
141+
m.handle_function(&self.ret, self.args.iter().map(|arg| &arg.ty));
142+
});
141143
}
142144
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
143145
self.ret.add_monomorphs(library, out);

src/bindgen/ir/structure.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,11 @@ impl Struct {
174174
}
175175

176176
pub fn find_return_value_monomorphs(&self, monomorphs: &mut ReturnValueMonomorphs<'_>) {
177-
for field in &self.fields {
178-
field.ty.find_return_value_monomorphs(monomorphs, false);
179-
}
177+
monomorphs.with_active_cfg(self.cfg.clone(), |m| {
178+
for field in &self.fields {
179+
field.ty.find_return_value_monomorphs(m, false);
180+
}
181+
});
180182
}
181183

182184
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {

src/bindgen/ir/typedef.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,10 @@ impl Typedef {
107107
monomorphs: &mut ReturnValueMonomorphs<'_>,
108108
is_return_value: bool,
109109
) {
110-
self.aliased
111-
.find_return_value_monomorphs(monomorphs, is_return_value);
110+
monomorphs.with_active_cfg(self.cfg.clone(), |m| {
111+
self.aliased
112+
.find_return_value_monomorphs(m, is_return_value);
113+
});
112114
}
113115

114116
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {

src/bindgen/ir/union.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,11 @@ impl Union {
101101
}
102102

103103
pub fn find_return_value_monomorphs(&self, monomorphs: &mut ReturnValueMonomorphs<'_>) {
104-
for field in &self.fields {
105-
field.ty.find_return_value_monomorphs(monomorphs, false);
106-
}
104+
monomorphs.with_active_cfg(self.cfg.clone(), |m| {
105+
for field in &self.fields {
106+
field.ty.find_return_value_monomorphs(m, false);
107+
}
108+
});
107109
}
108110

109111
pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {

src/bindgen/monomorph.rs

+44-20
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::iter::FromIterator as _;
77
use std::mem;
88

99
use crate::bindgen::ir::{
10-
Documentation, Enum, Field, GenericArgument, GenericPath, Item, ItemContainer, OpaqueItem,
10+
Cfg, Documentation, Enum, Field, GenericArgument, GenericPath, Item, ItemContainer, OpaqueItem,
1111
Path, Struct, Type, Typedef, Union,
1212
};
1313
use crate::bindgen::library::Library;
@@ -152,30 +152,53 @@ impl Monomorphs {
152152
/// functions that can lead to compilation warnings/errors if not explicitly instantiated.
153153
pub struct ReturnValueMonomorphs<'a> {
154154
library: &'a Library,
155-
monomorphs: HashSet<GenericPath>,
155+
monomorphs: HashSet<(GenericPath, Option<Cfg>)>,
156+
active_cfgs: Vec<Cfg>,
156157
}
157158

158159
impl<'a> ReturnValueMonomorphs<'a> {
159160
pub fn new(library: &'a Library) -> Self {
160161
Self {
161162
library,
162163
monomorphs: HashSet::new(),
164+
active_cfgs: Vec::new(),
163165
}
164166
}
165167

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();
174182
} else {
175-
typedef.find_return_value_monomorphs(self, true);
183+
thunk(self);
176184
}
177185
}
178186

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+
179202
/// Once we find a function return type, what we do with it depends on the type of item it
180203
/// resolves to. Typedefs need to be resolved recursively, while generic structs, unions, and
181204
/// enums are captured in the set of return value monomorphs.
@@ -191,16 +214,13 @@ impl<'a> ReturnValueMonomorphs<'a> {
191214
// Opaque items cannot be instantiated (doomed to compilation failure)
192215
ItemContainer::OpaqueItem(_) => {}
193216
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),
199219
ItemContainer::Struct(s) => {
200220
if let Some(t) = s.as_typedef() {
201221
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);
204224
}
205225
}
206226
}
@@ -225,11 +245,15 @@ impl<'a> ReturnValueMonomorphs<'a> {
225245

226246
// Sort the output so that the struct remains stable across runs (tests want that).
227247
let mut monomorphs = Vec::from_iter(self.monomorphs);
228-
monomorphs.sort();
248+
monomorphs.sort_by(|(k1, _), (k2, _)| k1.cmp(k2));
229249
let fields = monomorphs
230250
.into_iter()
231251
.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+
})
233257
.collect();
234258
let doc_comment = vec![
235259
" Dummy struct emitted by cbindgen to avoid compiler warnings/errors about",

tests/expectations/return_value_monomorphs.c

+28
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
1+
#if 0
2+
DEF DEFINE_FEATURE_1 = 0
3+
DEF DEFINE_FEATURE_2 = 0
4+
#endif
5+
6+
17
#include <stdarg.h>
28
#include <stdbool.h>
39
#include <stdint.h>
410
#include <stdlib.h>
511

12+
typedef struct {
13+
uint16_t x;
14+
} Foo_u16;
15+
16+
#if defined(DEFINE_FEATURE_1)
17+
typedef Foo_u16 FooConditional_u16;
18+
#endif
19+
620
typedef struct {
721
int16_t x;
822
} Foo_i16;
@@ -68,6 +82,14 @@ typedef struct {
6882

6983
typedef Foo_i64 Transparent;
7084

85+
typedef struct {
86+
uint8_t x;
87+
} Foo_u8;
88+
89+
#if defined(DEFINE_FEATURE_2)
90+
FooConditional_u16 double_feature(void);
91+
#endif
92+
7193
int32_t fnA(void);
7294

7395
int16_t fnB(void);
@@ -91,3 +113,9 @@ Foo_bool fnL(void);
91113
WrapNonZeroInt fnM(void);
92114

93115
Transparent fnN(void);
116+
117+
#if defined(DEFINE_FEATURE_1)
118+
Foo_u8 fnO(void);
119+
#endif
120+
121+
Foo_u8 fnP(void);

tests/expectations/return_value_monomorphs.compat.c

+28
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,22 @@
1+
#if 0
2+
DEF DEFINE_FEATURE_1 = 0
3+
DEF DEFINE_FEATURE_2 = 0
4+
#endif
5+
6+
17
#include <stdarg.h>
28
#include <stdbool.h>
39
#include <stdint.h>
410
#include <stdlib.h>
511

12+
typedef struct {
13+
uint16_t x;
14+
} Foo_u16;
15+
16+
#if defined(DEFINE_FEATURE_1)
17+
typedef Foo_u16 FooConditional_u16;
18+
#endif
19+
620
typedef struct {
721
int16_t x;
822
} Foo_i16;
@@ -68,10 +82,18 @@ typedef struct {
6882

6983
typedef Foo_i64 Transparent;
7084

85+
typedef struct {
86+
uint8_t x;
87+
} Foo_u8;
88+
7189
#ifdef __cplusplus
7290
extern "C" {
7391
#endif // __cplusplus
7492

93+
#if defined(DEFINE_FEATURE_2)
94+
FooConditional_u16 double_feature(void);
95+
#endif
96+
7597
int32_t fnA(void);
7698

7799
int16_t fnB(void);
@@ -96,6 +118,12 @@ WrapNonZeroInt fnM(void);
96118

97119
Transparent fnN(void);
98120

121+
#if defined(DEFINE_FEATURE_1)
122+
Foo_u8 fnO(void);
123+
#endif
124+
125+
Foo_u8 fnP(void);
126+
99127
#ifdef __cplusplus
100128
} // extern "C"
101129
#endif // __cplusplus

tests/expectations/return_value_monomorphs.cpp

+34-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#if 0
2+
DEF DEFINE_FEATURE_1 = 0
3+
DEF DEFINE_FEATURE_2 = 0
4+
#endif
5+
6+
17
#include <cstdarg>
28
#include <cstdint>
39
#include <cstdlib>
@@ -23,12 +29,26 @@ struct __cbindgen_return_value_monomorphs {
2329
Bar<int8_t, int32_t> field2;
2430
Bar<int16_t, int16_t> field3;
2531
Foo<bool> field4;
26-
Foo<int8_t> field5;
27-
Foo<int16_t> field6;
28-
Foo<int32_t> field7;
29-
Foo<int64_t> field8;
32+
#if defined(DEFINE_FEATURE_1)
33+
Foo<uint8_t> field5
34+
#endif
35+
;
36+
Foo<uint8_t> field6;
37+
#if (defined(DEFINE_FEATURE_2) && defined(DEFINE_FEATURE_1))
38+
Foo<uint16_t> field7
39+
#endif
40+
;
41+
Foo<int8_t> field8;
42+
Foo<int16_t> field9;
43+
Foo<int32_t> field10;
44+
Foo<int64_t> field11;
3045
};
3146

47+
#if defined(DEFINE_FEATURE_1)
48+
template<typename T>
49+
using FooConditional = Foo<T>;
50+
#endif
51+
3252
template<typename T>
3353
struct NotReturnValue {
3454
T x;
@@ -57,6 +77,10 @@ using Transparent = Foo<int64_t>;
5777

5878
extern "C" {
5979

80+
#if defined(DEFINE_FEATURE_2)
81+
FooConditional<uint16_t> double_feature();
82+
#endif
83+
6084
int32_t fnA();
6185

6286
int16_t fnB();
@@ -81,4 +105,10 @@ WrapNonZeroInt fnM();
81105

82106
Transparent fnN();
83107

108+
#if defined(DEFINE_FEATURE_1)
109+
Foo<uint8_t> fnO();
110+
#endif
111+
112+
Foo<uint8_t> fnP();
113+
84114
} // extern "C"

0 commit comments

Comments
 (0)