Skip to content

Commit 7c3c70c

Browse files
committed
Add option to avoid wrapping function pointer fields or arguments
1 parent c17c292 commit 7c3c70c

File tree

10 files changed

+415
-11
lines changed

10 files changed

+415
-11
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@
152152
# Unreleased
153153

154154
## Added
155+
* Do not wrap function pointer fields or arguments in `Option` if the new
156+
`--skip-fn-ptr-wrapping` option is enabled.
155157

156158
## Changed
157159
* Fixed name collisions when having a C `enum` and a `typedef` with the same

bindgen-cli/options.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,12 @@ where
565565
Arg::new("wrap-unsafe-ops")
566566
.long("wrap-unsafe-ops")
567567
.help("Wrap unsafe operations in unsafe blocks."),
568+
Arg::new("skip-fn-ptr-wrapping")
569+
.long("skip-fn-ptr-wrapping")
570+
.help("Do not wrap function pointers in `Option` if they are used as fields/arguments matching <regex>.")
571+
.value_name("regex")
572+
.multiple_occurrences(true)
573+
.number_of_values(1),
568574
Arg::new("V")
569575
.long("version")
570576
.help("Prints the version, and exits"),
@@ -1092,5 +1098,11 @@ where
10921098
builder = builder.wrap_unsafe_ops(true);
10931099
}
10941100

1101+
if let Some(must_use_type) = matches.values_of("skip-fn-ptr-wrapping") {
1102+
for regex in must_use_type {
1103+
builder = builder.skip_fn_ptr_wrapping(regex);
1104+
}
1105+
}
1106+
10951107
Ok((builder, output, verbose))
10961108
}

bindgen-tests/tests/expectations/tests/skip-fn-ptr-wrapping.rs

Lines changed: 177 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// bindgen-flags: --skip-fn-ptr-wrapping=".*foo::.*" --no-default=".*foo"
2+
3+
typedef struct foo {
4+
int (*bar)();
5+
} foo;
6+
7+
foo new_foo(int (*arg)());
8+
9+
typedef struct baz {
10+
int (*foo)();
11+
} baz;
12+
13+
baz new_baz(int (*foo)());
14+
15+
typedef union union_foo {
16+
int (*fst)();
17+
float (*snd)();
18+
} union_foo;
19+
20+
union_foo new_union_foo(int (*arg)());
21+
22+
typedef union union_baz {
23+
int (*foo)();
24+
float (*bar)();
25+
} union_baz;
26+
27+
union_baz new_union_baz(int (*foo)());

bindgen/codegen/mod.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3746,11 +3746,8 @@ impl TryToRustTy for Type {
37463746
// they aren't NonZero), so don't *ever* use an or_opaque
37473747
// variant here.
37483748
let ty = fs.try_to_rust_ty(ctx, &())?;
3749-
37503749
let prefix = ctx.trait_prefix();
3751-
Ok(quote! {
3752-
::#prefix::option::Option<#ty>
3753-
})
3750+
Ok(quote!(::#prefix::option::Option<#ty>))
37543751
}
37553752
TypeKind::Array(item, len) | TypeKind::Vector(item, len) => {
37563753
let ty = item.try_to_rust_ty(ctx, &())?;

bindgen/codegen/postprocessing/merge_extern_blocks.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@ use syn::{
33
Item, ItemForeignMod, ItemMod,
44
};
55

6-
pub(super) fn merge_extern_blocks(item_mod: &mut ItemMod) {
6+
use crate::BindgenOptions;
7+
8+
pub(super) fn merge_extern_blocks(
9+
item_mod: &mut ItemMod,
10+
_options: &BindgenOptions,
11+
) {
712
Visitor.visit_item_mod_mut(item_mod)
813
}
914

bindgen/codegen/postprocessing/mod.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@ use syn::{parse2, ItemMod};
55
use crate::BindgenOptions;
66

77
mod merge_extern_blocks;
8+
mod skip_fn_ptr_wrapping;
89
mod sort_semantically;
910

1011
use merge_extern_blocks::merge_extern_blocks;
12+
use skip_fn_ptr_wrapping::skip_fn_ptr_wrapping;
1113
use sort_semantically::sort_semantically;
1214

1315
struct PostProcessingPass {
1416
should_run: fn(&BindgenOptions) -> bool,
15-
run: fn(&mut ItemMod),
17+
run: fn(&mut ItemMod, &BindgenOptions),
1618
}
1719

1820
// TODO: This can be a const fn when mutable references are allowed in const
@@ -21,13 +23,19 @@ macro_rules! pass {
2123
($pass:ident) => {
2224
PostProcessingPass {
2325
should_run: |options| options.$pass,
24-
run: |item_mod| $pass(item_mod),
26+
run: |item_mod, options| $pass(item_mod, options),
2527
}
2628
};
2729
}
2830

29-
const PASSES: &[PostProcessingPass] =
30-
&[pass!(merge_extern_blocks), pass!(sort_semantically)];
31+
const PASSES: &[PostProcessingPass] = &[
32+
pass!(merge_extern_blocks),
33+
pass!(sort_semantically),
34+
PostProcessingPass {
35+
should_run: |options| !options.skip_fn_ptr_wrapping.is_empty(),
36+
run: skip_fn_ptr_wrapping,
37+
},
38+
];
3139

3240
pub(crate) fn postprocessing(
3341
items: Vec<TokenStream>,
@@ -51,7 +59,7 @@ pub(crate) fn postprocessing(
5159

5260
for pass in PASSES {
5361
if (pass.should_run)(options) {
54-
(pass.run)(&mut item_mod);
62+
(pass.run)(&mut item_mod, options);
5563
}
5664
}
5765

0 commit comments

Comments
 (0)