diff options
-rw-r--r-- | src/ir/analysis/derive_hash.rs | 4 | ||||
-rw-r--r-- | src/ir/context.rs | 6 | ||||
-rw-r--r-- | src/lib.rs | 26 | ||||
-rw-r--r-- | src/options.rs | 13 | ||||
-rw-r--r-- | tests/expectations/tests/no-hash-opaque.rs | 24 | ||||
-rw-r--r-- | tests/expectations/tests/no-hash-whitelisted.rs | 34 | ||||
-rw-r--r-- | tests/expectations/tests/whitelisted-item-references-no-hash.rs | 52 | ||||
-rw-r--r-- | tests/headers/no-hash-opaque.hpp | 5 | ||||
-rw-r--r-- | tests/headers/no-hash-whitelisted.hpp | 5 | ||||
-rw-r--r-- | tests/headers/whitelisted-item-references-no-hash.hpp | 7 |
10 files changed, 176 insertions, 0 deletions
diff --git a/src/ir/analysis/derive_hash.rs b/src/ir/analysis/derive_hash.rs index d2eac677..46790232 100644 --- a/src/ir/analysis/derive_hash.rs +++ b/src/ir/analysis/derive_hash.rs @@ -127,6 +127,10 @@ impl<'ctx> MonotoneFramework for CannotDeriveHash<'ctx> { } }; + if self.ctx.no_hash_by_name(&item) { + return self.insert(id) + } + if item.is_opaque(self.ctx, &()) { let layout_can_derive = ty.layout(self.ctx).map_or(true, |l| { l.opaque().can_trivially_derive_hash() diff --git a/src/ir/context.rs b/src/ir/context.rs index 0acf8d41..138a69b9 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -2495,6 +2495,12 @@ impl BindgenContext { let name = item.canonical_path(self)[1..].join("::"); self.options().no_copy_types.matches(&name) } + + /// Chech if `--no-hash` flag is enabled for this item. + pub fn no_hash_by_name(&self, item: &Item) -> bool { + let name = item.canonical_path(self)[1..].join("::"); + self.options().no_hash_types.matches(&name) + } } /// A builder struct for configuring item resolution options. @@ -536,6 +536,20 @@ impl Builder { }) .count(); + self.options + .no_hash_types + .get_items() + .iter() + .map(|item| { + output_vector.push("--no-hash".into()); + output_vector.push( + item.trim_left_matches("^") + .trim_right_matches("$") + .into(), + ); + }) + .count(); + output_vector } @@ -1179,6 +1193,13 @@ impl Builder { self.options.no_copy_types.insert(arg); self } + + /// Don't derive `Hash` for a given type. Regular + /// expressions are supported. + pub fn no_hash(mut self, arg: String) -> Builder { + self.options.no_hash_types.insert(arg); + self + } } /// Configuration options for generated bindings. @@ -1369,6 +1390,9 @@ struct BindgenOptions { /// The set of types that we should not derive `Copy` for. no_copy_types: RegexSet, + + /// The set of types that we should not derive `Hash` for. + no_hash_types: RegexSet, } /// TODO(emilio): This is sort of a lie (see the error message that results from @@ -1388,6 +1412,7 @@ impl BindgenOptions { self.rustified_enums.build(); self.no_partialeq_types.build(); self.no_copy_types.build(); + self.no_hash_types.build(); } /// Update rust target version @@ -1460,6 +1485,7 @@ impl Default for BindgenOptions { rustfmt_configuration_file: None, no_partialeq_types: Default::default(), no_copy_types: Default::default(), + no_hash_types: Default::default(), } } } diff --git a/src/options.rs b/src/options.rs index 38b47b6a..d06fb6a2 100644 --- a/src/options.rs +++ b/src/options.rs @@ -292,6 +292,13 @@ where .takes_value(true) .multiple(true) .number_of_values(1), + Arg::with_name("no-hash") + .long("no-hash") + .help("Avoid deriving Hash for types matching <regex>.") + .value_name("regex") + .takes_value(true) + .multiple(true) + .number_of_values(1), ]) // .args() .get_matches_from(args); @@ -592,6 +599,12 @@ where } } + if let Some(no_hash) = matches.values_of("no-hash") { + for regex in no_hash { + builder = builder.no_hash(String::from(regex)); + } + } + let verbose = matches.is_present("verbose"); Ok((builder, output, verbose)) diff --git a/tests/expectations/tests/no-hash-opaque.rs b/tests/expectations/tests/no-hash-opaque.rs new file mode 100644 index 00000000..c4211c71 --- /dev/null +++ b/tests/expectations/tests/no-hash-opaque.rs @@ -0,0 +1,24 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct NoHash { + pub _bindgen_opaque_blob: u32, +} +#[test] +fn bindgen_test_layout_NoHash() { + assert_eq!( + ::std::mem::size_of::<NoHash>(), + 4usize, + concat!("Size of: ", stringify!(NoHash)) + ); + assert_eq!( + ::std::mem::align_of::<NoHash>(), + 4usize, + concat!("Alignment of ", stringify!(NoHash)) + ); +} diff --git a/tests/expectations/tests/no-hash-whitelisted.rs b/tests/expectations/tests/no-hash-whitelisted.rs new file mode 100644 index 00000000..9997d062 --- /dev/null +++ b/tests/expectations/tests/no-hash-whitelisted.rs @@ -0,0 +1,34 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct NoHash { + pub i: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_NoHash() { + assert_eq!( + ::std::mem::size_of::<NoHash>(), + 4usize, + concat!("Size of: ", stringify!(NoHash)) + ); + assert_eq!( + ::std::mem::align_of::<NoHash>(), + 4usize, + concat!("Alignment of ", stringify!(NoHash)) + ); + assert_eq!( + unsafe { &(*(0 as *const NoHash)).i as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(NoHash), + "::", + stringify!(i) + ) + ); +} diff --git a/tests/expectations/tests/whitelisted-item-references-no-hash.rs b/tests/expectations/tests/whitelisted-item-references-no-hash.rs new file mode 100644 index 00000000..5a77ff75 --- /dev/null +++ b/tests/expectations/tests/whitelisted-item-references-no-hash.rs @@ -0,0 +1,52 @@ +/* automatically generated by rust-bindgen */ + + +#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)] + + +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct NoHash { + pub _address: u8, +} +#[test] +fn bindgen_test_layout_NoHash() { + assert_eq!( + ::std::mem::size_of::<NoHash>(), + 1usize, + concat!("Size of: ", stringify!(NoHash)) + ); + assert_eq!( + ::std::mem::align_of::<NoHash>(), + 1usize, + concat!("Alignment of ", stringify!(NoHash)) + ); +} +#[repr(C)] +#[derive(Debug, Default, Copy, Clone)] +pub struct WhitelistMe { + pub a: NoHash, +} +#[test] +fn bindgen_test_layout_WhitelistMe() { + assert_eq!( + ::std::mem::size_of::<WhitelistMe>(), + 1usize, + concat!("Size of: ", stringify!(WhitelistMe)) + ); + assert_eq!( + ::std::mem::align_of::<WhitelistMe>(), + 1usize, + concat!("Alignment of ", stringify!(WhitelistMe)) + ); + assert_eq!( + unsafe { &(*(0 as *const WhitelistMe)).a as *const _ as usize }, + 0usize, + concat!( + "Alignment of field: ", + stringify!(WhitelistMe), + "::", + stringify!(a) + ) + ); +} diff --git a/tests/headers/no-hash-opaque.hpp b/tests/headers/no-hash-opaque.hpp new file mode 100644 index 00000000..c1db2cd1 --- /dev/null +++ b/tests/headers/no-hash-opaque.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --with-derive-hash --opaque-type "NoHash" --no-hash "NoHash" + +class NoHash { + int i; +}; diff --git a/tests/headers/no-hash-whitelisted.hpp b/tests/headers/no-hash-whitelisted.hpp new file mode 100644 index 00000000..77c90864 --- /dev/null +++ b/tests/headers/no-hash-whitelisted.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --with-derive-hash --whitelist-type "NoHash" --no-hash "NoHash" + +class NoHash { + int i; +}; diff --git a/tests/headers/whitelisted-item-references-no-hash.hpp b/tests/headers/whitelisted-item-references-no-hash.hpp new file mode 100644 index 00000000..e656d32d --- /dev/null +++ b/tests/headers/whitelisted-item-references-no-hash.hpp @@ -0,0 +1,7 @@ +// bindgen-flags: --with-derive-hash --whitelist-type "WhitelistMe" --no-hash "NoHash" + +struct NoHash {}; + +class WhitelistMe { + NoHash a; +}; |