From 74d084bd6c56256c496dab2fdadeb212efa1faa0 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Thu, 24 Nov 2022 10:14:27 -0500 Subject: [PATCH 1/2] Add option to avoid wrapping function pointer fields --- CHANGELOG.md | 2 ++ bindgen-cli/options.rs | 7 ++++ .../tests/dont-wrap-fn-ptr-fields.rs | 33 +++++++++++++++++++ .../tests/headers/dont-wrap-fn-ptr-fields.h | 5 +++ bindgen/codegen/mod.rs | 10 +++--- bindgen/lib.rs | 14 ++++++++ 6 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 bindgen-tests/tests/expectations/tests/dont-wrap-fn-ptr-fields.rs create mode 100644 bindgen-tests/tests/headers/dont-wrap-fn-ptr-fields.h diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cac405a60..68135875ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -152,6 +152,8 @@ # Unreleased ## Added + * Do not wrap function pointer fields in `Option` if the new + `--dont-wrap-fn-ptr-fields` option is enabled. ## Changed diff --git a/bindgen-cli/options.rs b/bindgen-cli/options.rs index f7fccc4ff4..a1ad398143 100644 --- a/bindgen-cli/options.rs +++ b/bindgen-cli/options.rs @@ -565,6 +565,9 @@ where Arg::new("wrap-unsafe-ops") .long("wrap-unsafe-ops") .help("Wrap unsafe operations in unsafe blocks."), + Arg::new("dont-wrap-fn-ptr-fields") + .long("dont-wrap-fn-ptr-fields") + .help("Do not wrap function pointer fields in `Option`."), Arg::new("V") .long("version") .help("Prints the version, and exits"), @@ -1092,5 +1095,9 @@ where builder = builder.wrap_unsafe_ops(true); } + if matches.is_present("dont-wrap-fn-ptr-fields") { + builder = builder.wrap_fn_ptr_fields(false); + } + Ok((builder, output, verbose)) } diff --git a/bindgen-tests/tests/expectations/tests/dont-wrap-fn-ptr-fields.rs b/bindgen-tests/tests/expectations/tests/dont-wrap-fn-ptr-fields.rs new file mode 100644 index 0000000000..209ece51ce --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/dont-wrap-fn-ptr-fields.rs @@ -0,0 +1,33 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct foo { + pub bar: unsafe extern "C" fn() -> ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_foo() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 8usize, + concat!("Size of: ", stringify!(foo)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(foo)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).bar) as usize - ptr as usize }, + 0usize, + concat!("Offset of field: ", stringify!(foo), "::", stringify!(bar)) + ); +} diff --git a/bindgen-tests/tests/headers/dont-wrap-fn-ptr-fields.h b/bindgen-tests/tests/headers/dont-wrap-fn-ptr-fields.h new file mode 100644 index 0000000000..7cdb226163 --- /dev/null +++ b/bindgen-tests/tests/headers/dont-wrap-fn-ptr-fields.h @@ -0,0 +1,5 @@ +// bindgen-flags: --dont-wrap-fn-ptr-fields + +typedef struct foo { + int (*bar)(); +} foo; diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index e537242710..55270e563c 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -3762,10 +3762,12 @@ impl TryToRustTy for Type { // variant here. let ty = fs.try_to_rust_ty(ctx, &())?; - let prefix = ctx.trait_prefix(); - Ok(quote! { - ::#prefix::option::Option<#ty> - }) + if ctx.options().wrap_fn_ptr_fields { + let prefix = ctx.trait_prefix(); + Ok(quote!(::#prefix::option::Option<#ty>)) + } else { + Ok(quote!(#ty)) + } } TypeKind::Array(item, len) | TypeKind::Vector(item, len) => { let ty = item.try_to_rust_ty(ctx, &())?; diff --git a/bindgen/lib.rs b/bindgen/lib.rs index 4b71fb97ce..a3c4e80ed6 100644 --- a/bindgen/lib.rs +++ b/bindgen/lib.rs @@ -649,6 +649,10 @@ impl Builder { output_vector.push("--wrap-unsafe-ops".into()); } + if !self.options.wrap_fn_ptr_fields { + output_vector.push("--dont-wrap-fn-ptr-fields".into()); + } + // Add clang arguments output_vector.push("--".into()); @@ -1787,6 +1791,12 @@ impl Builder { self.options.wrap_unsafe_ops = doit; self } + + /// If true, wraps function pointer fields in `Option`. + pub fn wrap_fn_ptr_fields(mut self, doit: bool) -> Self { + self.options.wrap_fn_ptr_fields = doit; + self + } } /// Configuration options for generated bindings. @@ -2127,6 +2137,9 @@ struct BindgenOptions { /// Whether to wrap unsafe operations in unsafe blocks or not. wrap_unsafe_ops: bool, + + /// Whether to wrap function pointer fields in `Option` or not. + wrap_fn_ptr_fields: bool, } impl BindgenOptions { @@ -2238,6 +2251,7 @@ impl Default for BindgenOptions { record_matches: true, rustfmt_bindings: true, size_t_is_usize: true, + wrap_fn_ptr_fields: true, --default-fields-- blocklisted_types, From 9973a70f2a4cb80934a57ca07f43033c1e0c556e Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Thu, 24 Nov 2022 10:56:11 -0500 Subject: [PATCH 2/2] fix test --- .../tests/expectations/tests/dont-wrap-fn-ptr-fields.rs | 2 +- bindgen-tests/tests/headers/dont-wrap-fn-ptr-fields.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bindgen-tests/tests/expectations/tests/dont-wrap-fn-ptr-fields.rs b/bindgen-tests/tests/expectations/tests/dont-wrap-fn-ptr-fields.rs index 209ece51ce..348f1d4583 100644 --- a/bindgen-tests/tests/expectations/tests/dont-wrap-fn-ptr-fields.rs +++ b/bindgen-tests/tests/expectations/tests/dont-wrap-fn-ptr-fields.rs @@ -6,7 +6,7 @@ )] #[repr(C)] -#[derive(Debug, Default, Copy, Clone)] +#[derive(Debug, Copy, Clone)] pub struct foo { pub bar: unsafe extern "C" fn() -> ::std::os::raw::c_int, } diff --git a/bindgen-tests/tests/headers/dont-wrap-fn-ptr-fields.h b/bindgen-tests/tests/headers/dont-wrap-fn-ptr-fields.h index 7cdb226163..e77ef35a76 100644 --- a/bindgen-tests/tests/headers/dont-wrap-fn-ptr-fields.h +++ b/bindgen-tests/tests/headers/dont-wrap-fn-ptr-fields.h @@ -1,4 +1,4 @@ -// bindgen-flags: --dont-wrap-fn-ptr-fields +// bindgen-flags: --dont-wrap-fn-ptr-fields --no-default="foo" typedef struct foo { int (*bar)();