diff --git a/bindgen-cli/options.rs b/bindgen-cli/options.rs index 5c3960e92b..3e4b3f224c 100644 --- a/bindgen-cli/options.rs +++ b/bindgen-cli/options.rs @@ -568,6 +568,12 @@ where Arg::new("merge-extern-blocks") .long("merge-extern-blocks") .help("Deduplicates extern blocks."), + Arg::new("remove-alias") + .long("remove-alias") + .help("Remove type aliases matching .") + .value_name("regex") + .multiple_occurrences(true) + .number_of_values(1), Arg::new("V") .long("version") .help("Prints the version, and exits"), @@ -1088,5 +1094,11 @@ where builder = builder.merge_extern_blocks(true); } + if let Some(remove_alias) = matches.values_of("remove-alias") { + for regex in remove_alias { + builder = builder.remove_alias(regex); + } + } + Ok((builder, output, verbose)) } diff --git a/bindgen-tests/tests/expectations/tests/remove_alias.rs b/bindgen-tests/tests/expectations/tests/remove_alias.rs new file mode 100644 index 0000000000..bae0fd07f3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/remove_alias.rs @@ -0,0 +1,51 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +pub type i32_ = ::std::os::raw::c_int; +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct int32_ { + pub inner: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_int32_() { + const UNINIT: ::std::mem::MaybeUninit = + ::std::mem::MaybeUninit::uninit(); + let ptr = UNINIT.as_ptr(); + assert_eq!( + ::std::mem::size_of::(), + 4usize, + concat!("Size of: ", stringify!(int32_)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(int32_)) + ); + assert_eq!( + unsafe { ::std::ptr::addr_of!((*ptr).inner) as usize - ptr as usize }, + 0usize, + concat!( + "Offset of field: ", + stringify!(int32_), + "::", + stringify!(inner) + ) + ); +} +extern "C" { + pub fn foo() -> ::std::os::raw::c_longlong; +} +extern "C" { + pub fn bar() -> ::std::os::raw::c_int; +} +extern "C" { + pub fn baz() -> i32_; +} +extern "C" { + pub fn qux() -> int32_; +} diff --git a/bindgen-tests/tests/expectations/tests/remove_template_alias.rs b/bindgen-tests/tests/expectations/tests/remove_template_alias.rs new file mode 100644 index 0000000000..e06ffadab3 --- /dev/null +++ b/bindgen-tests/tests/expectations/tests/remove_template_alias.rs @@ -0,0 +1,8 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +pub type Wrapped = T; diff --git a/bindgen-tests/tests/headers/remove_alias.h b/bindgen-tests/tests/headers/remove_alias.h new file mode 100644 index 0000000000..1b83396c25 --- /dev/null +++ b/bindgen-tests/tests/headers/remove_alias.h @@ -0,0 +1,14 @@ +// bindgen-flags: --remove-alias "int.*" + +typedef long long int64; +typedef int int32; +typedef int32 i32; + +struct int32_ { + int32 inner; +}; + +int64 foo(); +int32 bar(); +i32 baz(); +struct int32_ qux(); diff --git a/bindgen-tests/tests/headers/remove_template_alias.hpp b/bindgen-tests/tests/headers/remove_template_alias.hpp new file mode 100644 index 0000000000..a77021f726 --- /dev/null +++ b/bindgen-tests/tests/headers/remove_template_alias.hpp @@ -0,0 +1,4 @@ +// bindgen-flags: --remove-alias "Wrapped" + +template +using Wrapped = T; diff --git a/bindgen/Cargo.toml b/bindgen/Cargo.toml index dca779bd0c..3965ad4d4c 100644 --- a/bindgen/Cargo.toml +++ b/bindgen/Cargo.toml @@ -45,7 +45,7 @@ lazycell = "1" lazy_static = "1" peeking_take_while = "0.1.2" quote = { version = "1", default-features = false } -syn = { version = "1.0.99", features = ["full", "extra-traits"]} +syn = { version = "1.0.99", features = ["full", "extra-traits", "visit-mut"]} regex = { version = "1.5", default-features = false , features = ["std", "unicode"] } which = { version = "4.2.1", optional = true, default-features = false } shlex = "1" diff --git a/bindgen/codegen/postprocessing/merge_extern_blocks.rs b/bindgen/codegen/postprocessing/merge_extern_blocks.rs index 2b7614941e..f0bf594271 100644 --- a/bindgen/codegen/postprocessing/merge_extern_blocks.rs +++ b/bindgen/codegen/postprocessing/merge_extern_blocks.rs @@ -1,6 +1,11 @@ use syn::{Item, ItemForeignMod}; -pub(super) fn merge_extern_blocks(items: &mut Vec) { +use crate::BindgenOptions; + +pub(super) fn merge_extern_blocks( + items: &mut Vec, + _options: &BindgenOptions, +) { // Keep all the extern blocks in a different `Vec` for faster search. let mut foreign_mods = Vec::::new(); diff --git a/bindgen/codegen/postprocessing/mod.rs b/bindgen/codegen/postprocessing/mod.rs index c6612f2b91..6969c7bfc7 100644 --- a/bindgen/codegen/postprocessing/mod.rs +++ b/bindgen/codegen/postprocessing/mod.rs @@ -5,14 +5,16 @@ use syn::Item; use crate::BindgenOptions; mod merge_extern_blocks; +mod remove_alias; mod sort_semantically; use merge_extern_blocks::merge_extern_blocks; +use remove_alias::remove_alias; use sort_semantically::sort_semantically; struct PostProcessingPass { should_run: fn(&BindgenOptions) -> bool, - run: fn(&mut Vec), + run: fn(&mut Vec, &BindgenOptions), } // TODO: This can be a const fn when mutable references are allowed in const @@ -21,13 +23,19 @@ macro_rules! pass { ($pass:ident) => { PostProcessingPass { should_run: |options| options.$pass, - run: |items| $pass(items), + run: |items, options| $pass(items, options), } }; } -const PASSES: &[PostProcessingPass] = - &[pass!(merge_extern_blocks), pass!(sort_semantically)]; +const PASSES: &[PostProcessingPass] = &[ + pass!(merge_extern_blocks), + pass!(sort_semantically), + PostProcessingPass { + should_run: |options| !options.remove_alias.is_empty(), + run: |items, options| remove_alias(items, options), + }, +]; pub(crate) fn postprocessing( items: Vec, @@ -56,7 +64,7 @@ pub(crate) fn postprocessing( for pass in PASSES { if (pass.should_run)(options) { - (pass.run)(&mut items); + (pass.run)(&mut items, options); } } diff --git a/bindgen/codegen/postprocessing/remove_alias.rs b/bindgen/codegen/postprocessing/remove_alias.rs new file mode 100644 index 0000000000..9312527e75 --- /dev/null +++ b/bindgen/codegen/postprocessing/remove_alias.rs @@ -0,0 +1,53 @@ +use syn::visit_mut::{visit_type_mut, VisitMut}; +use syn::{Item, Type}; + +use crate::BindgenOptions; + +pub(super) fn remove_alias(items: &mut Vec, options: &BindgenOptions) { + let visitors: Vec<_> = items + .iter() + .enumerate() + .rev() + .filter_map(|(index, item)| { + if let Item::Type(alias_item) = item { + if alias_item.generics.params.is_empty() { + let ident = alias_item.ident.to_string(); + if options.remove_alias.matches(&ident) { + return Some(( + index, + Visitor { + ident, + ty: alias_item.ty.clone(), + }, + )); + } + } + } + None + }) + .collect(); + + for (index, mut visitor) in visitors { + items.remove(index); + for item in items.iter_mut() { + visitor.visit_item_mut(item); + } + } +} + +struct Visitor { + ident: String, + ty: Box, +} + +impl VisitMut for Visitor { + fn visit_type_mut(&mut self, ty: &mut Type) { + if let Type::Path(type_path) = ty { + if type_path.path.is_ident(&self.ident) { + *ty = self.ty.as_ref().clone(); + } + } + + visit_type_mut::<_>(self, ty) + } +} diff --git a/bindgen/codegen/postprocessing/sort_semantically.rs b/bindgen/codegen/postprocessing/sort_semantically.rs index 96596cb01e..019c7ad478 100644 --- a/bindgen/codegen/postprocessing/sort_semantically.rs +++ b/bindgen/codegen/postprocessing/sort_semantically.rs @@ -1,6 +1,8 @@ use syn::Item; -pub(super) fn sort_semantically(items: &mut [Item]) { +use crate::BindgenOptions; + +pub(super) fn sort_semantically(items: &mut [Item], _options: &BindgenOptions) { items.sort_by_key(|item| match item { Item::Type(_) => 0, Item::Struct(_) => 1, diff --git a/bindgen/lib.rs b/bindgen/lib.rs index 6e6fa225d6..878a6935b6 100644 --- a/bindgen/lib.rs +++ b/bindgen/lib.rs @@ -358,6 +358,7 @@ impl Builder { (&self.options.no_default_types, "--no-default"), (&self.options.no_hash_types, "--no-hash"), (&self.options.must_use_types, "--must-use-type"), + (&self.options.remove_alias, "--remove-alias"), ]; for (set, flag) in regex_sets { @@ -1770,6 +1771,13 @@ impl Builder { self.options.c_naming = doit; self } + + /// Remove a type alias that matches the provided argument. Regular + /// expressions are supported. + pub fn remove_alias>(mut self, arg: T) -> Self { + self.options.remove_alias.insert(arg.into()); + self + } } /// Configuration options for generated bindings. @@ -2105,6 +2113,9 @@ struct BindgenOptions { /// Deduplicate `extern` blocks. merge_extern_blocks: bool, + + /// The set of type aliases that should be removed. + remove_alias: RegexSet, } /// TODO(emilio): This is sort of a lie (see the error message that results from @@ -2142,6 +2153,7 @@ impl BindgenOptions { &mut self.no_default_types, &mut self.no_hash_types, &mut self.must_use_types, + &mut self.remove_alias, ]; let record_matches = self.record_matches; for regex_set in &mut regex_sets { @@ -2261,6 +2273,7 @@ impl Default for BindgenOptions { vtable_generation: false, sort_semantically: false, merge_extern_blocks: false, + remove_alias: Default::default(), } } }