diff options
author | Varphone Wong <varphone@qq.com> | 2020-08-02 09:48:40 +0800 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2020-08-03 18:29:07 +0200 |
commit | ff3698189cb44f900e81d2b92131b1c191acf4de (patch) | |
tree | 89b8c03fe5f29b8afebf77ead0962f1f8b217d06 | |
parent | f56fbcef788098155a10ef455284e218fe15bc7a (diff) |
Add --no-debug <regex> flag
-rw-r--r-- | book/src/SUMMARY.md | 1 | ||||
-rw-r--r-- | book/src/nodebug.md | 40 | ||||
-rw-r--r-- | src/codegen/mod.rs | 8 | ||||
-rw-r--r-- | src/ir/analysis/derive.rs | 1 | ||||
-rw-r--r-- | src/ir/annotations.rs | 9 | ||||
-rw-r--r-- | src/ir/context.rs | 6 | ||||
-rw-r--r-- | src/lib.rs | 13 | ||||
-rw-r--r-- | src/options.rs | 13 | ||||
-rw-r--r-- | tests/expectations/tests/no_debug.rs | 13 | ||||
-rw-r--r-- | tests/expectations/tests/no_debug_bypass_impl_debug.rs | 32 | ||||
-rw-r--r-- | tests/expectations/tests/no_debug_opaque.rs | 26 | ||||
-rw-r--r-- | tests/expectations/tests/no_debug_whitelisted.rs | 30 | ||||
-rw-r--r-- | tests/headers/no_debug.hpp | 6 | ||||
-rw-r--r-- | tests/headers/no_debug_bypass_impl_debug.hpp | 11 | ||||
-rw-r--r-- | tests/headers/no_debug_opaque.hpp | 5 | ||||
-rw-r--r-- | tests/headers/no_debug_whitelisted.hpp | 5 |
16 files changed, 216 insertions, 3 deletions
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 1bd75cdd..e2347fb4 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -17,6 +17,7 @@ - [Treating a Type as an Opaque Blob of Bytes](./opaque.md) - [Replacing One Type with Another](./replacing-types.md) - [Preventing the Derivation of `Copy` and `Clone`](./nocopy.md) + - [Preventing the Derivation of `Debug`](./nodebug.md) - [Generating Bindings to C++](./cpp.md) - [Generating Bindings to Objective-c](./objc.md) - [Using Unions](./using-unions.md) diff --git a/book/src/nodebug.md b/book/src/nodebug.md new file mode 100644 index 00000000..251b792b --- /dev/null +++ b/book/src/nodebug.md @@ -0,0 +1,40 @@ +# Preventing the Derivation of `Debug` + +`bindgen` will attempt to derive the `Debug` traits on a best-effort +basis. Sometimes, it might not understand that although adding `#[derive(Debug)]` to a translated type definition will compile, it still shouldn't do +that for reasons it can't know. In these cases, the `nodebug` annotation can be +used to prevent bindgen to autoderive the `Debug` traits for a type. + +### Library + +* [`bindgen::Builder::no_debug`](https://docs.rs/bindgen/0.54.2/bindgen/struct.Builder.html#method.no_debug) + +### Command Line + +* `--no-debug <regex>` + +### Annotations + +```c +/** + * Although bindgen can't know, this enum is not safe to format the output. + * the value may be combined with multiple bits in many C/C++ cases, + * for example: + * + * <div rustbindgen nodebug></div> + */ +enum AVRounding { + AV_ROUND_ZERO = 0, + AV_ROUND_INF = 1, + AV_ROUND_DOWN = 2, + AV_ROUND_UP = 3, + AV_ROUND_NEAR_INF = 5, + AV_ROUND_PASS_MINMAX = 8192, +}; + +// Prototype +int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding) av_const; + +// Call +int64_t pts = av_rescale_rnd(40000, 3600, 90000, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); +``` diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 20bf54c4..00aa68f3 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -112,7 +112,7 @@ bitflags! { fn derives_of_item(item: &Item, ctx: &BindgenContext) -> DerivableTraits { let mut derivable_traits = DerivableTraits::empty(); - if item.can_derive_debug(ctx) { + if item.can_derive_debug(ctx) && !item.annotations().disallow_debug() { derivable_traits |= DerivableTraits::DEBUG; } @@ -1885,8 +1885,10 @@ impl CodeGenerator for CompInfo { let derivable_traits = derives_of_item(item, ctx); if !derivable_traits.contains(DerivableTraits::DEBUG) { - needs_debug_impl = - ctx.options().derive_debug && ctx.options().impl_debug + needs_debug_impl = ctx.options().derive_debug && + ctx.options().impl_debug && + !ctx.no_debug_by_name(item) && + !item.annotations().disallow_debug(); } if !derivable_traits.contains(DerivableTraits::DEFAULT) { diff --git a/src/ir/analysis/derive.rs b/src/ir/analysis/derive.rs index 6858d7f1..48c544f6 100644 --- a/src/ir/analysis/derive.rs +++ b/src/ir/analysis/derive.rs @@ -445,6 +445,7 @@ impl DeriveTrait { fn not_by_name(&self, ctx: &BindgenContext, item: &Item) -> bool { match self { DeriveTrait::Copy => ctx.no_copy_by_name(item), + DeriveTrait::Debug => ctx.no_debug_by_name(item), DeriveTrait::Hash => ctx.no_hash_by_name(item), DeriveTrait::PartialEqOrPartialOrd => { ctx.no_partialeq_by_name(item) diff --git a/src/ir/annotations.rs b/src/ir/annotations.rs index 98a0c042..da4ef4f7 100644 --- a/src/ir/annotations.rs +++ b/src/ir/annotations.rs @@ -38,6 +38,8 @@ pub struct Annotations { /// Manually disable deriving copy/clone on this type. Only applies to /// struct or union types. disallow_copy: bool, + /// Manually disable deriving debug on this type. + disallow_debug: bool, /// Whether fields should be marked as private or not. You can set this on /// structs (it will apply to all the fields), or individual fields. private_fields: Option<bool>, @@ -78,6 +80,7 @@ impl Default for Annotations { hide: false, use_instead_of: None, disallow_copy: false, + disallow_debug: false, private_fields: None, accessor_kind: None, constify_enum_variant: false, @@ -147,6 +150,11 @@ impl Annotations { self.disallow_copy } + /// Should we avoid implementing the `Debug` trait? + pub fn disallow_debug(&self) -> bool { + self.disallow_debug + } + /// Should the fields be private? pub fn private_fields(&self) -> Option<bool> { self.private_fields @@ -172,6 +180,7 @@ impl Annotations { "opaque" => self.opaque = true, "hide" => self.hide = true, "nocopy" => self.disallow_copy = true, + "nodebug" => self.disallow_debug = true, "replaces" => { self.use_instead_of = Some( attr.value.split("::").map(Into::into).collect(), diff --git a/src/ir/context.rs b/src/ir/context.rs index 38d73b7e..9513a41c 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -2635,6 +2635,12 @@ If you encounter an error missing from this list, please file an issue or a PR!" self.options().no_copy_types.matches(&name) } + /// Check if `--no-debug` flag is enabled for this item. + pub fn no_debug_by_name(&self, item: &Item) -> bool { + let name = item.path_for_whitelisting(self)[1..].join("::"); + self.options().no_debug_types.matches(&name) + } + /// Check if `--no-hash` flag is enabled for this item. pub fn no_hash_by_name(&self, item: &Item) -> bool { let name = item.path_for_whitelisting(self)[1..].join("::"); @@ -295,6 +295,7 @@ impl Builder { (&self.options.whitelisted_vars, "--whitelist-var"), (&self.options.no_partialeq_types, "--no-partialeq"), (&self.options.no_copy_types, "--no-copy"), + (&self.options.no_debug_types, "--no-debug"), (&self.options.no_hash_types, "--no-hash"), ]; @@ -1410,6 +1411,13 @@ impl Builder { self } + /// Don't derive `Debug` for a given type. Regular + /// expressions are supported. + pub fn no_debug<T: Into<String>>(mut self, arg: T) -> Self { + self.options.no_debug_types.insert(arg.into()); + self + } + /// Don't derive `Hash` for a given type. Regular /// expressions are supported. pub fn no_hash<T: Into<String>>(mut self, arg: T) -> Builder { @@ -1691,6 +1699,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 `Debug` for. + no_debug_types: RegexSet, + /// The set of types that we should not derive `Hash` for. no_hash_types: RegexSet, @@ -1727,6 +1738,7 @@ impl BindgenOptions { &mut self.new_type_alias_deref, &mut self.no_partialeq_types, &mut self.no_copy_types, + &mut self.no_debug_types, &mut self.no_hash_types, ]; let record_matches = self.record_matches; @@ -1824,6 +1836,7 @@ impl Default for BindgenOptions { rustfmt_configuration_file: None, no_partialeq_types: Default::default(), no_copy_types: Default::default(), + no_debug_types: Default::default(), no_hash_types: Default::default(), array_pointers_in_arguments: false, wasm_import_module_name: None, diff --git a/src/options.rs b/src/options.rs index 0add7b4c..13fbf7a4 100644 --- a/src/options.rs +++ b/src/options.rs @@ -430,6 +430,13 @@ where .takes_value(true) .multiple(true) .number_of_values(1), + Arg::with_name("no-debug") + .long("no-debug") + .help("Avoid deriving Debug for types matching <regex>.") + .value_name("regex") + .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>.") @@ -831,6 +838,12 @@ where } } + if let Some(no_debug) = matches.values_of("no-debug") { + for regex in no_debug { + builder = builder.no_debug(regex); + } + } + if let Some(no_hash) = matches.values_of("no-hash") { for regex in no_hash { builder = builder.no_hash(regex); diff --git a/tests/expectations/tests/no_debug.rs b/tests/expectations/tests/no_debug.rs new file mode 100644 index 00000000..21850ecb --- /dev/null +++ b/tests/expectations/tests/no_debug.rs @@ -0,0 +1,13 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +/// <div rustbindgen nodebug></div> +#[repr(C)] +#[derive(Default, Copy, Clone)] +pub struct DebugButWait { + pub whatever: ::std::os::raw::c_int, +} diff --git a/tests/expectations/tests/no_debug_bypass_impl_debug.rs b/tests/expectations/tests/no_debug_bypass_impl_debug.rs new file mode 100644 index 00000000..adb80eaa --- /dev/null +++ b/tests/expectations/tests/no_debug_bypass_impl_debug.rs @@ -0,0 +1,32 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +#[repr(C)] +pub struct Generic<T> { + pub t: [T; 40usize], + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>, +} +impl<T> Default for Generic<T> { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} +impl<T> ::std::fmt::Debug for Generic<T> { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + write!(f, "Generic {{ t: Array with length 40 }}") + } +} +#[repr(C)] +pub struct NoDebug<T> { + pub t: [T; 40usize], + pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>, +} +impl<T> Default for NoDebug<T> { + fn default() -> Self { + unsafe { ::std::mem::zeroed() } + } +} diff --git a/tests/expectations/tests/no_debug_opaque.rs b/tests/expectations/tests/no_debug_opaque.rs new file mode 100644 index 00000000..4b657481 --- /dev/null +++ b/tests/expectations/tests/no_debug_opaque.rs @@ -0,0 +1,26 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +#[repr(C)] +#[repr(align(4))] +#[derive(Default, Copy, Clone)] +pub struct NoDebug { + pub _bindgen_opaque_blob: u32, +} +#[test] +fn bindgen_test_layout_NoDebug() { + assert_eq!( + ::std::mem::size_of::<NoDebug>(), + 4usize, + concat!("Size of: ", stringify!(NoDebug)) + ); + assert_eq!( + ::std::mem::align_of::<NoDebug>(), + 4usize, + concat!("Alignment of ", stringify!(NoDebug)) + ); +} diff --git a/tests/expectations/tests/no_debug_whitelisted.rs b/tests/expectations/tests/no_debug_whitelisted.rs new file mode 100644 index 00000000..ac43e4ea --- /dev/null +++ b/tests/expectations/tests/no_debug_whitelisted.rs @@ -0,0 +1,30 @@ +#![allow( + dead_code, + non_snake_case, + non_camel_case_types, + non_upper_case_globals +)] + +#[repr(C)] +#[derive(Default, Copy, Clone)] +pub struct NoDebug { + pub i: ::std::os::raw::c_int, +} +#[test] +fn bindgen_test_layout_NoDebug() { + assert_eq!( + ::std::mem::size_of::<NoDebug>(), + 4usize, + concat!("Size of: ", stringify!(NoDebug)) + ); + assert_eq!( + ::std::mem::align_of::<NoDebug>(), + 4usize, + concat!("Alignment of ", stringify!(NoDebug)) + ); + assert_eq!( + unsafe { &(*(::std::ptr::null::<NoDebug>())).i as *const _ as usize }, + 0usize, + concat!("Offset of field: ", stringify!(NoDebug), "::", stringify!(i)) + ); +} diff --git a/tests/headers/no_debug.hpp b/tests/headers/no_debug.hpp new file mode 100644 index 00000000..2017f75d --- /dev/null +++ b/tests/headers/no_debug.hpp @@ -0,0 +1,6 @@ + +/** <div rustbindgen nodebug></div> */ +template<typename T> +class DebugButWait { + int whatever; +}; diff --git a/tests/headers/no_debug_bypass_impl_debug.hpp b/tests/headers/no_debug_bypass_impl_debug.hpp new file mode 100644 index 00000000..a5864410 --- /dev/null +++ b/tests/headers/no_debug_bypass_impl_debug.hpp @@ -0,0 +1,11 @@ +// bindgen-flags: --no-debug "NoDebug" --impl-debug + +template<typename T> +class Generic { + T t[40]; +}; + +template<typename T> +class NoDebug { + T t[40]; +}; diff --git a/tests/headers/no_debug_opaque.hpp b/tests/headers/no_debug_opaque.hpp new file mode 100644 index 00000000..d5dc18f7 --- /dev/null +++ b/tests/headers/no_debug_opaque.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --opaque-type "NoDebug" --no-debug "NoDebug" + +class NoDebug { + int i; +}; diff --git a/tests/headers/no_debug_whitelisted.hpp b/tests/headers/no_debug_whitelisted.hpp new file mode 100644 index 00000000..7a855e81 --- /dev/null +++ b/tests/headers/no_debug_whitelisted.hpp @@ -0,0 +1,5 @@ +// bindgen-flags: --whitelist-type "NoDebug" --no-debug "NoDebug" + +class NoDebug { + int i; +}; |