diff options
author | Joel Galenson <jgalenson@google.com> | 2021-04-19 15:47:23 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-04-19 15:47:23 +0000 |
commit | 0336a0dd1f2ad6c5e7edd70d95d1c6c6df213bc7 (patch) | |
tree | 194e88a2399cee0d737c1a4b2106ed6d8ca3a602 | |
parent | 9233a598d437106969ae7fb397c5628f4b5ccedc (diff) | |
parent | c1527f10f53365eb5c66eee3981825faf9f14429 (diff) | |
download | bindgen-android12-mainline-art-release.tar.gz |
Upgrade rust/crates/bindgen to 0.58.1 am: 64466033e1 am: cddef73ab2 am: 6bb386ebbc am: c1527f10f5android-mainline-12.0.0_r99android-mainline-12.0.0_r98android-mainline-12.0.0_r97android-mainline-12.0.0_r96android-mainline-12.0.0_r95android-mainline-12.0.0_r94android-mainline-12.0.0_r93android-mainline-12.0.0_r92android-mainline-12.0.0_r91android-mainline-12.0.0_r90android-mainline-12.0.0_r9android-mainline-12.0.0_r89android-mainline-12.0.0_r88android-mainline-12.0.0_r87android-mainline-12.0.0_r86android-mainline-12.0.0_r85android-mainline-12.0.0_r84android-mainline-12.0.0_r83android-mainline-12.0.0_r82android-mainline-12.0.0_r81android-mainline-12.0.0_r80android-mainline-12.0.0_r8android-mainline-12.0.0_r79android-mainline-12.0.0_r78android-mainline-12.0.0_r77android-mainline-12.0.0_r76android-mainline-12.0.0_r75android-mainline-12.0.0_r74android-mainline-12.0.0_r73android-mainline-12.0.0_r72android-mainline-12.0.0_r71android-mainline-12.0.0_r70android-mainline-12.0.0_r7android-mainline-12.0.0_r69android-mainline-12.0.0_r68android-mainline-12.0.0_r67android-mainline-12.0.0_r66android-mainline-12.0.0_r65android-mainline-12.0.0_r64android-mainline-12.0.0_r63android-mainline-12.0.0_r62android-mainline-12.0.0_r61android-mainline-12.0.0_r60android-mainline-12.0.0_r6android-mainline-12.0.0_r59android-mainline-12.0.0_r58android-mainline-12.0.0_r57android-mainline-12.0.0_r56android-mainline-12.0.0_r53android-mainline-12.0.0_r52android-mainline-12.0.0_r51android-mainline-12.0.0_r50android-mainline-12.0.0_r5android-mainline-12.0.0_r49android-mainline-12.0.0_r48android-mainline-12.0.0_r47android-mainline-12.0.0_r46android-mainline-12.0.0_r45android-mainline-12.0.0_r44android-mainline-12.0.0_r43android-mainline-12.0.0_r42android-mainline-12.0.0_r41android-mainline-12.0.0_r40android-mainline-12.0.0_r39android-mainline-12.0.0_r38android-mainline-12.0.0_r37android-mainline-12.0.0_r35android-mainline-12.0.0_r34android-mainline-12.0.0_r33android-mainline-12.0.0_r32android-mainline-12.0.0_r31android-mainline-12.0.0_r30android-mainline-12.0.0_r3android-mainline-12.0.0_r29android-mainline-12.0.0_r28android-mainline-12.0.0_r27android-mainline-12.0.0_r26android-mainline-12.0.0_r25android-mainline-12.0.0_r24android-mainline-12.0.0_r23android-mainline-12.0.0_r22android-mainline-12.0.0_r21android-mainline-12.0.0_r20android-mainline-12.0.0_r2android-mainline-12.0.0_r19android-mainline-12.0.0_r18android-mainline-12.0.0_r17android-mainline-12.0.0_r16android-mainline-12.0.0_r15android-mainline-12.0.0_r14android-mainline-12.0.0_r13android-mainline-12.0.0_r126android-mainline-12.0.0_r125android-mainline-12.0.0_r124android-mainline-12.0.0_r123android-mainline-12.0.0_r122android-mainline-12.0.0_r121android-mainline-12.0.0_r120android-mainline-12.0.0_r12android-mainline-12.0.0_r119android-mainline-12.0.0_r118android-mainline-12.0.0_r117android-mainline-12.0.0_r116android-mainline-12.0.0_r115android-mainline-12.0.0_r114android-mainline-12.0.0_r113android-mainline-12.0.0_r110android-mainline-12.0.0_r11android-mainline-12.0.0_r109android-mainline-12.0.0_r108android-mainline-12.0.0_r107android-mainline-12.0.0_r106android-mainline-12.0.0_r105android-mainline-12.0.0_r104android-mainline-12.0.0_r103android-mainline-12.0.0_r102android-mainline-12.0.0_r101android-mainline-12.0.0_r100android-mainline-12.0.0_r10android-mainline-12.0.0_r1aml_wif_311811030aml_tz3_311312010aml_tet_311811050aml_sdk_311710000aml_pco_311011000aml_mpr_311911090aml_doc_310851020android12-mainline-wifi-releaseandroid12-mainline-tethering-releaseandroid12-mainline-statsd-releaseandroid12-mainline-sdkext-releaseandroid12-mainline-resolv-releaseandroid12-mainline-permission-releaseandroid12-mainline-neuralnetworks-releaseandroid12-mainline-networkstack-releaseandroid12-mainline-mediaprovider-releaseandroid12-mainline-media-swcodec-releaseandroid12-mainline-media-releaseandroid12-mainline-ipsec-releaseandroid12-mainline-extservices-releaseandroid12-mainline-documentsui-releaseandroid12-mainline-conscrypt-releaseandroid12-mainline-cellbroadcast-releaseandroid12-mainline-captiveportallogin-releaseandroid12-mainline-art-releaseandroid12-mainline-adbd-release
Original change: https://android-review.googlesource.com/c/platform/external/rust/crates/bindgen/+/1678110
Change-Id: I9e8747da5c0813609f2b20ea77f8830bd691d734
-rw-r--r-- | .cargo_vcs_info.json | 2 | ||||
-rw-r--r-- | Android.bp | 19 | ||||
-rw-r--r-- | Cargo.lock | 8 | ||||
-rw-r--r-- | Cargo.toml | 6 | ||||
-rw-r--r-- | Cargo.toml.orig | 6 | ||||
-rw-r--r-- | METADATA | 8 | ||||
-rw-r--r-- | TEST_MAPPING | 5 | ||||
-rw-r--r-- | src/callbacks.rs | 19 | ||||
-rw-r--r-- | src/codegen/dyngen.rs | 56 | ||||
-rw-r--r-- | src/codegen/impl_debug.rs | 4 | ||||
-rw-r--r-- | src/codegen/mod.rs | 321 | ||||
-rw-r--r-- | src/codegen/struct_layout.rs | 39 | ||||
-rw-r--r-- | src/ir/analysis/derive.rs | 33 | ||||
-rw-r--r-- | src/ir/analysis/has_destructor.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/has_float.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/has_type_param_in_array.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/has_vtable.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/mod.rs | 4 | ||||
-rw-r--r-- | src/ir/analysis/sizedness.rs | 2 | ||||
-rw-r--r-- | src/ir/analysis/template_params.rs | 60 | ||||
-rw-r--r-- | src/ir/comp.rs | 21 | ||||
-rw-r--r-- | src/ir/context.rs | 178 | ||||
-rw-r--r-- | src/ir/dot.rs | 6 | ||||
-rw-r--r-- | src/ir/enum_ty.rs | 17 | ||||
-rw-r--r-- | src/ir/item.rs | 44 | ||||
-rw-r--r-- | src/ir/template.rs | 4 | ||||
-rw-r--r-- | src/ir/traversal.rs | 4 | ||||
-rw-r--r-- | src/lib.rs | 270 | ||||
-rw-r--r-- | src/options.rs | 99 |
29 files changed, 777 insertions, 466 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index d047a4d..2263767 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,5 @@ { "git": { - "sha1": "5ca2fc7a0221cacde41fd60b0ce485ee5ab8dac3" + "sha1": "696455d1c15e682b2b89f81f409315ea4964aef3" } } @@ -1,4 +1,5 @@ // This file is generated by cargo2android.py --run --dependencies --features=clap,runtime,which-rustfmt --host-first-multilib --copy-out. +// Do not modify this file as changes will be overridden on upgrade. package { default_applicable_licenses: ["external_rust_crates_bindgen_license"], @@ -111,26 +112,26 @@ rust_library_host { // bitflags-1.2.1 "default" // cexpr-0.4.0 // cfg-if-1.0.0 -// clang-sys-1.0.3 "clang_3_5,clang_3_6,clang_3_7,clang_3_8,clang_3_9,clang_4_0,clang_5_0,clang_6_0,libloading,runtime" +// clang-sys-1.2.0 "clang_3_5,clang_3_6,clang_3_7,clang_3_8,clang_3_9,clang_4_0,clang_5_0,clang_6_0,libloading,runtime" // clap-2.33.3 "ansi_term,atty,color,default,strsim,suggestions,vec_map" // glob-0.3.0 // lazy_static-1.4.0 // lazycell-1.3.0 -// libc-0.2.86 "default,std" -// libloading-0.6.7 +// libc-0.2.93 "default,std" +// libloading-0.7.0 // memchr-2.3.4 "std,use_std" // nom-5.1.2 "alloc,std" // peeking_take_while-0.1.2 -// proc-macro2-1.0.24 -// quote-1.0.8 -// regex-1.4.3 "std,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment" -// regex-syntax-0.6.22 "unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment" +// proc-macro2-1.0.26 +// quote-1.0.9 +// regex-1.4.5 "std,unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment" +// regex-syntax-0.6.23 "unicode,unicode-age,unicode-bool,unicode-case,unicode-gencat,unicode-perl,unicode-script,unicode-segment" // rustc-hash-1.1.0 "default,std" -// shlex-0.1.1 +// shlex-1.0.0 // strsim-0.8.0 // textwrap-0.11.0 // unicode-width-0.1.8 "default" // unicode-xid-0.2.1 "default" // vec_map-0.8.2 -// version_check-0.9.2 +// version_check-0.9.3 // which-3.1.1 @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" version = "0.7.15" @@ -31,7 +33,7 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.57.0" +version = "0.58.1" dependencies = [ "bitflags", "cexpr", @@ -247,9 +249,9 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "shlex" -version = "0.1.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" +checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d" [[package]] name = "strsim" @@ -13,7 +13,7 @@ [package] edition = "2018" name = "bindgen" -version = "0.57.0" +version = "0.58.1" authors = ["Jyun-Yan You <jyyou.tw@gmail.com>", "Emilio Cobos Álvarez <emilio@crisal.io>", "Nick Fitzgerald <fitzgen@gmail.com>", "The Servo project developers"] build = "build.rs" include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"] @@ -82,7 +82,7 @@ default-features = false version = "1.0.1" [dependencies.shlex] -version = "0.1" +version = "1" [dependencies.which] version = "3.0" @@ -95,7 +95,7 @@ version = "2" version = "0.1" [dev-dependencies.shlex] -version = "0.1" +version = "1" [features] default = ["logging", "clap", "runtime", "which-rustfmt"] diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 4f8ac75..dd30f09 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -14,7 +14,7 @@ readme = "README.md" repository = "https://github.com/rust-lang/rust-bindgen" documentation = "https://docs.rs/bindgen" homepage = "https://rust-lang.github.io/rust-bindgen/" -version = "0.57.0" +version = "0.58.1" edition = "2018" build = "build.rs" @@ -42,7 +42,7 @@ required-features = ["clap"] [dev-dependencies] diff = "0.1" clap = "2" -shlex = "0.1" +shlex = "1" [dependencies] bitflags = "1.0.3" @@ -56,7 +56,7 @@ peeking_take_while = "0.1.2" quote = { version = "1", default-features = false } regex = { version = "1.0", default-features = false , features = [ "std", "unicode"]} which = { version = "3.0", optional = true, default-features = false } -shlex = "0.1" +shlex = "1" rustc-hash = "1.0.1" # New validation in 0.3.6 breaks bindgen-integration: # https://github.com/alexcrichton/proc-macro2/commit/489c642. @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/bindgen/bindgen-0.57.0.crate" + value: "https://static.crates.io/crates/bindgen/bindgen-0.58.1.crate" } - version: "0.57.0" + version: "0.58.1" license_type: NOTICE last_upgrade_date { year: 2021 - month: 2 - day: 9 + month: 4 + day: 16 } } diff --git a/TEST_MAPPING b/TEST_MAPPING index 7de080a..a731acb 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -2,10 +2,13 @@ { "presubmit": [ { + "name": "keystore2_test" + }, + { "name": "libsqlite3-sys_device_test_src_lib" }, { - "name": "keystore2_test" + "name": "vpnprofilestore_test" } ] } diff --git a/src/callbacks.rs b/src/callbacks.rs index 1cd7f37..e288af4 100644 --- a/src/callbacks.rs +++ b/src/callbacks.rs @@ -1,5 +1,7 @@ //! A public API for more fine-grained customization of bindgen behavior. +pub use crate::ir::analysis::DeriveTrait; +pub use crate::ir::derive::CanDerive as ImplementsTrait; pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue}; pub use crate::ir::int::IntKind; use std::fmt; @@ -76,4 +78,21 @@ pub trait ParseCallbacks: fmt::Debug + UnwindSafe { /// This will be called on every file inclusion, with the full path of the included file. fn include_file(&self, _filename: &str) {} + + /// This will be called to determine whether a particular blocklisted type + /// implements a trait or not. This will be used to implement traits on + /// other types containing the blocklisted type. + /// + /// * `None`: use the default behavior + /// * `Some(ImplementsTrait::Yes)`: `_name` implements `_derive_trait` + /// * `Some(ImplementsTrait::Manually)`: any type including `_name` can't + /// derive `_derive_trait` but can implemented it manually + /// * `Some(ImplementsTrait::No)`: `_name` doesn't implement `_derive_trait` + fn blocklisted_type_implements_trait( + &self, + _name: &str, + _derive_trait: DeriveTrait, + ) -> Option<ImplementsTrait> { + None + } } diff --git a/src/codegen/dyngen.rs b/src/codegen/dyngen.rs index 94dd574..71c4dab 100644 --- a/src/codegen/dyngen.rs +++ b/src/codegen/dyngen.rs @@ -77,6 +77,7 @@ impl DynamicItems { let constructor_inits = &self.constructor_inits; let init_fields = &self.init_fields; let struct_implementation = &self.struct_implementation; + quote! { extern crate libloading; @@ -90,14 +91,20 @@ impl DynamicItems { path: P ) -> Result<Self, ::libloading::Error> where P: AsRef<::std::ffi::OsStr> { - let __library = ::libloading::Library::new(path)?; + let library = ::libloading::Library::new(path)?; + Self::from_library(library) + } + + pub unsafe fn from_library<L>( + library: L + ) -> Result<Self, ::libloading::Error> + where L: Into<::libloading::Library> { + let __library = library.into(); #( #constructor_inits )* - Ok( - #lib_ident { - __library, - #( #init_fields ),* - } - ) + Ok(#lib_ident { + __library, + #( #init_fields ),* + }) } #( #struct_implementation )* @@ -110,6 +117,7 @@ impl DynamicItems { ident: Ident, abi: Abi, is_variadic: bool, + is_required: bool, args: Vec<proc_macro2::TokenStream>, args_identifiers: Vec<proc_macro2::TokenStream>, ret: proc_macro2::TokenStream, @@ -119,24 +127,48 @@ impl DynamicItems { assert_eq!(args.len(), args_identifiers.len()); } + let signature = quote! { unsafe extern #abi fn ( #( #args),* ) #ret }; + let member = if is_required { + signature + } else { + quote! { Result<#signature, ::libloading::Error> } + }; + self.struct_members.push(quote! { - pub #ident: Result<unsafe extern #abi fn ( #( #args ),* ) #ret, ::libloading::Error>, + pub #ident: #member, }); + // N.B: If the signature was required, it won't be wrapped in a Result<...> + // and we can simply call it directly. + let fn_ = if is_required { + quote! { self.#ident } + } else { + quote! { self.#ident.as_ref().expect("Expected function, got error.") } + }; + let call_body = quote! { + (#fn_)(#( #args_identifiers ),*) + }; + // We can't implement variadic functions from C easily, so we allow to // access the function pointer so that the user can call it just fine. if !is_variadic { self.struct_implementation.push(quote! { pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty { - let sym = self.#ident.as_ref().expect("Expected function, got error."); - (sym)(#( #args_identifiers ),*) + #call_body } }); } + // N.B: Unwrap the signature upon construction if it is required to be resolved. let ident_str = codegen::helpers::ast_ty::cstr_expr(ident.to_string()); - self.constructor_inits.push(quote! { - let #ident = __library.get(#ident_str).map(|sym| *sym); + self.constructor_inits.push(if is_required { + quote! { + let #ident = __library.get(#ident_str).map(|sym| *sym)?; + } + } else { + quote! { + let #ident = __library.get(#ident_str).map(|sym| *sym); + } }); self.init_fields.push(quote! { diff --git a/src/codegen/impl_debug.rs b/src/codegen/impl_debug.rs index ed1a5e2..b8fdd0d 100644 --- a/src/codegen/impl_debug.rs +++ b/src/codegen/impl_debug.rs @@ -120,9 +120,9 @@ impl<'a> ImplDebug<'a> for Item { ) -> Option<(String, Vec<proc_macro2::TokenStream>)> { let name_ident = ctx.rust_ident(name); - // We don't know if blacklisted items `impl Debug` or not, so we can't + // We don't know if blocklisted items `impl Debug` or not, so we can't // add them to the format string we're building up. - if !ctx.whitelisted_items().contains(&self.id()) { + if !ctx.allowlisted_items().contains(&self.id()) { return None; } diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index cad2f47..e62b1a8 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -422,45 +422,62 @@ trait CodeGenerator { /// Extra information from the caller. type Extra; + /// Extra information returned to the caller. + type Return; + fn codegen<'a>( &self, ctx: &BindgenContext, result: &mut CodegenResult<'a>, extra: &Self::Extra, - ); + ) -> Self::Return; } -impl CodeGenerator for Item { - type Extra = (); - - fn codegen<'a>( +impl Item { + fn process_before_codegen( &self, ctx: &BindgenContext, - result: &mut CodegenResult<'a>, - _extra: &(), - ) { + result: &mut CodegenResult, + ) -> bool { if !self.is_enabled_for_codegen(ctx) { - return; + return false; } - if self.is_blacklisted(ctx) || result.seen(self.id()) { + if self.is_blocklisted(ctx) || result.seen(self.id()) { debug!( - "<Item as CodeGenerator>::codegen: Ignoring hidden or seen: \ + "<Item as CodeGenerator>::process_before_codegen: Ignoring hidden or seen: \ self = {:?}", self ); - return; + return false; } - debug!("<Item as CodeGenerator>::codegen: self = {:?}", self); if !ctx.codegen_items().contains(&self.id()) { // TODO(emilio, #453): Figure out what to do when this happens // legitimately, we could track the opaque stuff and disable the // assertion there I guess. - warn!("Found non-whitelisted item in code generation: {:?}", self); + warn!("Found non-allowlisted item in code generation: {:?}", self); } result.set_seen(self.id()); + true + } +} + +impl CodeGenerator for Item { + type Extra = (); + type Return = (); + + fn codegen<'a>( + &self, + ctx: &BindgenContext, + result: &mut CodegenResult<'a>, + _extra: &(), + ) { + debug!("<Item as CodeGenerator>::codegen: self = {:?}", self); + if !self.process_before_codegen(ctx, result) { + return; + } match *self.kind() { ItemKind::Module(ref module) => { @@ -481,6 +498,7 @@ impl CodeGenerator for Item { impl CodeGenerator for Module { type Extra = Item; + type Return = (); fn codegen<'a>( &self, @@ -572,6 +590,8 @@ impl CodeGenerator for Module { impl CodeGenerator for Var { type Extra = Item; + type Return = (); + fn codegen<'a>( &self, ctx: &BindgenContext, @@ -698,6 +718,7 @@ impl CodeGenerator for Var { impl CodeGenerator for Type { type Extra = Item; + type Return = (); fn codegen<'a>( &self, @@ -725,7 +746,7 @@ impl CodeGenerator for Type { // These items don't need code generation, they only need to be // converted to rust types in fields, arguments, and such. // NOTE(emilio): If you add to this list, make sure to also add - // it to BindgenContext::compute_whitelisted_and_codegen_items. + // it to BindgenContext::compute_allowlisted_and_codegen_items. return; } TypeKind::TemplateInstantiation(ref inst) => { @@ -1004,6 +1025,7 @@ impl<'a> Vtable<'a> { impl<'a> CodeGenerator for Vtable<'a> { type Extra = Item; + type Return = (); fn codegen<'b>( &self, @@ -1048,6 +1070,7 @@ impl<'a> TryToRustTy for Vtable<'a> { impl CodeGenerator for TemplateInstantiation { type Extra = Item; + type Return = (); fn codegen<'a>( &self, @@ -1219,7 +1242,7 @@ impl<'a> FieldCodegen<'a> for FieldData { ty.append_implicit_template_params(ctx, field_item); // NB: If supported, we use proper `union` types. - let ty = if parent.is_union() && !parent.can_be_rust_union(ctx) { + let ty = if parent.is_union() && !struct_layout.is_rust_union() { result.saw_bindgen_union(); if ctx.options().enable_cxx_namespaces { quote! { @@ -1263,12 +1286,10 @@ impl<'a> FieldCodegen<'a> for FieldData { .expect("Each field should have a name in codegen!"); let field_ident = ctx.rust_ident_raw(field_name.as_str()); - if !parent.is_union() { - if let Some(padding_field) = - struct_layout.pad_field(&field_name, field_ty, self.offset()) - { - fields.extend(Some(padding_field)); - } + if let Some(padding_field) = + struct_layout.saw_field(&field_name, field_ty, self.offset()) + { + fields.extend(Some(padding_field)); } let is_private = (!self.is_public() && @@ -1433,7 +1454,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit { let layout = self.layout(); let unit_field_ty = helpers::bitfield_unit(ctx, layout); let field_ty = { - if parent.is_union() && !parent.can_be_rust_union(ctx) { + if parent.is_union() && !struct_layout.is_rust_union() { result.saw_bindgen_union(); if ctx.options().enable_cxx_namespaces { quote! { @@ -1571,7 +1592,7 @@ impl<'a> FieldCodegen<'a> for Bitfield { _accessor_kind: FieldAccessorKind, parent: &CompInfo, _result: &mut CodegenResult, - _struct_layout: &mut StructLayoutTracker, + struct_layout: &mut StructLayoutTracker, _fields: &mut F, methods: &mut M, (unit_field_name, bitfield_representable_as_int): (&'a str, &mut bool), @@ -1612,7 +1633,7 @@ impl<'a> FieldCodegen<'a> for Bitfield { self.is_public() && !fields_should_be_private, ); - if parent.is_union() && !parent.can_be_rust_union(ctx) { + if parent.is_union() && !struct_layout.is_rust_union() { methods.extend(Some(quote! { #[inline] #access_spec fn #getter_name(&self) -> #bitfield_ty { @@ -1666,6 +1687,7 @@ impl<'a> FieldCodegen<'a> for Bitfield { impl CodeGenerator for CompInfo { type Extra = Item; + type Return = (); fn codegen<'a>( &self, @@ -1768,15 +1790,53 @@ impl CodeGenerator for CompInfo { } } - let is_union = self.kind() == CompKind::Union; - let layout = item.kind().expect_type().layout(ctx); - - let mut explicit_align = None; if is_opaque { // Opaque item should not have generated methods, fields. debug_assert!(fields.is_empty()); debug_assert!(methods.is_empty()); + } + + let is_union = self.kind() == CompKind::Union; + let layout = item.kind().expect_type().layout(ctx); + let zero_sized = item.is_zero_sized(ctx); + let forward_decl = self.is_forward_declaration(); + + let mut explicit_align = None; + // C++ requires every struct to be addressable, so what C++ compilers do + // is making the struct 1-byte sized. + // + // This is apparently not the case for C, see: + // https://github.com/rust-lang/rust-bindgen/issues/551 + // + // Just get the layout, and assume C++ if not. + // + // NOTE: This check is conveniently here to avoid the dummy fields we + // may add for unused template parameters. + if !forward_decl && zero_sized { + let has_address = if is_opaque { + // Generate the address field if it's an opaque type and + // couldn't determine the layout of the blob. + layout.is_none() + } else { + layout.map_or(true, |l| l.size != 0) + }; + + if has_address { + let layout = Layout::new(1, 1); + let ty = helpers::blob(ctx, Layout::new(1, 1)); + struct_layout.saw_field_with_layout( + "_address", + layout, + /* offset = */ Some(0), + ); + fields.push(quote! { + pub _address: #ty, + }); + } + } + + if is_opaque { match layout { Some(l) => { explicit_align = Some(l.align); @@ -1790,7 +1850,7 @@ impl CodeGenerator for CompInfo { warn!("Opaque type without layout! Expect dragons!"); } } - } else if !is_union && !item.is_zero_sized(ctx) { + } else if !is_union && !zero_sized { if let Some(padding_field) = layout.and_then(|layout| struct_layout.pad_struct(layout)) { @@ -1815,57 +1875,26 @@ impl CodeGenerator for CompInfo { } } } - } else if is_union && !self.is_forward_declaration() { + } else if is_union && !forward_decl { // TODO(emilio): It'd be nice to unify this with the struct path // above somehow. let layout = layout.expect("Unable to get layout information?"); - struct_layout.saw_union(layout); - if struct_layout.requires_explicit_align(layout) { explicit_align = Some(layout.align); } - let ty = helpers::blob(ctx, layout); - fields.push(if self.can_be_rust_union(ctx) { - quote! { - _bindgen_union_align: #ty , - } - } else { - quote! { + if !struct_layout.is_rust_union() { + let ty = helpers::blob(ctx, layout); + fields.push(quote! { pub bindgen_union_field: #ty , - } - }); + }) + } } - // C++ requires every struct to be addressable, so what C++ compilers do - // is making the struct 1-byte sized. - // - // This is apparently not the case for C, see: - // https://github.com/rust-lang/rust-bindgen/issues/551 - // - // Just get the layout, and assume C++ if not. - // - // NOTE: This check is conveniently here to avoid the dummy fields we - // may add for unused template parameters. - if self.is_forward_declaration() { + if forward_decl { fields.push(quote! { _unused: [u8; 0], }); - } else if item.is_zero_sized(ctx) { - let has_address = if is_opaque { - // Generate the address field if it's an opaque type and - // couldn't determine the layout of the blob. - layout.is_none() - } else { - layout.map_or(true, |l| l.size != 0) - }; - - if has_address { - let ty = helpers::blob(ctx, Layout::new(1, 1)); - fields.push(quote! { - pub _address: #ty, - }); - } } let mut generic_param_names = vec![]; @@ -1963,7 +1992,7 @@ impl CodeGenerator for CompInfo { attributes.push(attributes::derives(&derives)) } - let mut tokens = if is_union && self.can_be_rust_union(ctx) { + let mut tokens = if is_union && struct_layout.is_rust_union() { quote! { #( #attributes )* pub union #canonical_ident @@ -2256,13 +2285,15 @@ impl MethodCodegen for Method { // First of all, output the actual function. let function_item = ctx.resolve_item(self.signature()); - if function_item.is_blacklisted(ctx) { - // We shouldn't emit a method declaration if the function is blacklisted + if !function_item.process_before_codegen(ctx, result) { return; } - function_item.codegen(ctx, result, &()); - let function = function_item.expect_function(); + let times_seen = function.codegen(ctx, result, &function_item); + let times_seen = match times_seen { + Some(seen) => seen, + None => return, + }; let signature_item = ctx.resolve_item(function.signature()); let mut name = match self.kind() { MethodKind::Constructor => "new".into(), @@ -2297,7 +2328,11 @@ impl MethodCodegen for Method { name.push_str(&count.to_string()); } - let function_name = ctx.rust_ident(function_item.canonical_name(ctx)); + let mut function_name = function_item.canonical_name(ctx); + if times_seen > 0 { + write!(&mut function_name, "{}", times_seen).unwrap(); + } + let function_name = ctx.rust_ident(function_name); let mut args = utils::fnsig_arguments(ctx, signature); let mut ret = utils::fnsig_return_ty(ctx, signature); @@ -2519,7 +2554,7 @@ impl<'a> EnumBuilder<'a> { /// the representation, and which variation it should be generated as. fn new( name: &'a str, - attrs: Vec<proc_macro2::TokenStream>, + mut attrs: Vec<proc_macro2::TokenStream>, repr: proc_macro2::TokenStream, enum_variation: EnumVariation, enum_codegen_depth: usize, @@ -2538,6 +2573,8 @@ impl<'a> EnumBuilder<'a> { }, EnumVariation::Rust { .. } => { + // `repr` is guaranteed to be Rustified in Enum::codegen + attrs.insert(0, quote! { #[repr( #repr )] }); let tokens = quote!(); EnumBuilder::Rust { codegen_depth: enum_codegen_depth + 1, @@ -2801,6 +2838,7 @@ impl<'a> EnumBuilder<'a> { impl CodeGenerator for Enum { type Extra = Item; + type Return = (); fn codegen<'a>( &self, @@ -2815,51 +2853,73 @@ impl CodeGenerator for Enum { let ident = ctx.rust_ident(&name); let enum_ty = item.expect_type(); let layout = enum_ty.layout(ctx); + let variation = self.computed_enum_variation(ctx, item); - let repr = self.repr().map(|repr| ctx.resolve_type(repr)); - let repr = match repr { - Some(repr) => match *repr.canonical_type(ctx).kind() { - TypeKind::Int(int_kind) => int_kind, - _ => panic!("Unexpected type as enum repr"), - }, - None => { - warn!( - "Guessing type of enum! Forward declarations of enums \ - shouldn't be legal!" - ); - IntKind::Int + let repr_translated; + let repr = match self.repr().map(|repr| ctx.resolve_type(repr)) { + Some(repr) + if !ctx.options().translate_enum_integer_types && + !variation.is_rust() => + { + repr } - }; + repr => { + // An enum's integer type is translated to a native Rust + // integer type in 3 cases: + // * the enum is Rustified and we need a translated type for + // the repr attribute + // * the representation couldn't be determined from the C source + // * it was explicitly requested as a bindgen option + + let kind = match repr { + Some(repr) => match *repr.canonical_type(ctx).kind() { + TypeKind::Int(int_kind) => int_kind, + _ => panic!("Unexpected type as enum repr"), + }, + None => { + warn!( + "Guessing type of enum! Forward declarations of enums \ + shouldn't be legal!" + ); + IntKind::Int + } + }; + + let signed = kind.is_signed(); + let size = layout + .map(|l| l.size) + .or_else(|| kind.known_size()) + .unwrap_or(0); + + let translated = match (signed, size) { + (true, 1) => IntKind::I8, + (false, 1) => IntKind::U8, + (true, 2) => IntKind::I16, + (false, 2) => IntKind::U16, + (true, 4) => IntKind::I32, + (false, 4) => IntKind::U32, + (true, 8) => IntKind::I64, + (false, 8) => IntKind::U64, + _ => { + warn!( + "invalid enum decl: signed: {}, size: {}", + signed, size + ); + IntKind::I32 + } + }; - let signed = repr.is_signed(); - let size = layout - .map(|l| l.size) - .or_else(|| repr.known_size()) - .unwrap_or(0); - - let repr_name = match (signed, size) { - (true, 1) => "i8", - (false, 1) => "u8", - (true, 2) => "i16", - (false, 2) => "u16", - (true, 4) => "i32", - (false, 4) => "u32", - (true, 8) => "i64", - (false, 8) => "u64", - _ => { - warn!("invalid enum decl: signed: {}, size: {}", signed, size); - "i32" + repr_translated = + Type::new(None, None, TypeKind::Int(translated), false); + &repr_translated } }; let mut attrs = vec![]; - let variation = self.computed_enum_variation(ctx, item); - // TODO(emilio): Delegate this to the builders? match variation { EnumVariation::Rust { non_exhaustive } => { - attrs.push(attributes::repr(repr_name)); if non_exhaustive && ctx.options().rust_features().non_exhaustive { @@ -2929,13 +2989,7 @@ impl CodeGenerator for Enum { }); } - let repr = match self.repr() { - Some(ty) => ty.to_rust_ty_or_opaque(ctx, &()), - None => { - let repr_name = ctx.rust_ident_raw(repr_name); - quote! { #repr_name } - } - }; + let repr = repr.to_rust_ty_or_opaque(ctx, item); let mut builder = EnumBuilder::new( &name, @@ -3708,19 +3762,23 @@ impl TryToRustTy for FunctionSig { impl CodeGenerator for Function { type Extra = Item; + /// If we've actually generated the symbol, the number of times we've seen + /// it. + type Return = Option<u32>; + fn codegen<'a>( &self, ctx: &BindgenContext, result: &mut CodegenResult<'a>, item: &Item, - ) { + ) -> Self::Return { debug!("<Function as CodeGenerator>::codegen: item = {:?}", item); debug_assert!(item.is_enabled_for_codegen(ctx)); // We can't currently do anything with Internal functions so just // avoid generating anything for them. match self.linkage() { - Linkage::Internal => return, + Linkage::Internal => return None, Linkage::External => {} } @@ -3730,7 +3788,7 @@ impl CodeGenerator for Function { FunctionKind::Method(ref method_kind) if method_kind.is_pure_virtual() => { - return; + return None; } _ => {} } @@ -3740,7 +3798,7 @@ impl CodeGenerator for Function { // instantiations is open ended and we have no way of knowing which // monomorphizations actually exist. if !item.all_template_params(ctx).is_empty() { - return; + return None; } let name = self.name(); @@ -3753,7 +3811,7 @@ impl CodeGenerator for Function { // TODO: Maybe warn here if there's a type/argument mismatch, or // something? if result.seen_function(seen_symbol_name) { - return; + return None; } result.saw_function(seen_symbol_name); } @@ -3780,21 +3838,14 @@ impl CodeGenerator for Function { attributes.push(attributes::doc(comment)); } - // Handle overloaded functions by giving each overload its own unique - // suffix. - let times_seen = result.overload_number(&canonical_name); - if times_seen > 0 { - write!(&mut canonical_name, "{}", times_seen).unwrap(); - } - let abi = match signature.abi() { Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => { warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target"); - return; + return None; } Abi::Win64 if signature.is_variadic() => { warn!("Skipping variadic function with Win64 ABI that isn't supported"); - return; + return None; } Abi::Unknown(unknown_abi) => { panic!( @@ -3805,6 +3856,13 @@ impl CodeGenerator for Function { abi => abi, }; + // Handle overloaded functions by giving each overload its own unique + // suffix. + let times_seen = result.overload_number(&canonical_name); + if times_seen > 0 { + write!(&mut canonical_name, "{}", times_seen).unwrap(); + } + let link_name = mangled_name.unwrap_or(name); if !utils::names_will_be_identical_after_mangling( &canonical_name, @@ -3846,6 +3904,7 @@ impl CodeGenerator for Function { ident, abi, signature.is_variadic(), + ctx.options().dynamic_link_require_all, args, args_identifiers, ret, @@ -3854,6 +3913,7 @@ impl CodeGenerator for Function { } else { result.push(tokens); } + Some(times_seen) } } @@ -3909,6 +3969,7 @@ fn objc_method_codegen( impl CodeGenerator for ObjCInterface { type Extra = Item; + type Return = (); fn codegen<'a>( &self, diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs index 4536e88..2e4b973 100644 --- a/src/codegen/struct_layout.rs +++ b/src/codegen/struct_layout.rs @@ -19,6 +19,7 @@ pub struct StructLayoutTracker<'a> { comp: &'a CompInfo, is_packed: bool, known_type_layout: Option<Layout>, + is_rust_union: bool, latest_offset: usize, padding_count: usize, latest_field_layout: Option<Layout>, @@ -89,12 +90,15 @@ impl<'a> StructLayoutTracker<'a> { ) -> Self { let known_type_layout = ty.layout(ctx); let is_packed = comp.is_packed(ctx, known_type_layout.as_ref()); + let is_rust_union = comp.is_union() && + comp.can_be_rust_union(ctx, known_type_layout.as_ref()); StructLayoutTracker { name, ctx, comp, is_packed, known_type_layout, + is_rust_union, latest_offset: 0, padding_count: 0, latest_field_layout: None, @@ -103,6 +107,10 @@ impl<'a> StructLayoutTracker<'a> { } } + pub fn is_rust_union(&self) -> bool { + self.is_rust_union + } + pub fn saw_vtable(&mut self) { debug!("saw vtable for {}", self.name); @@ -143,18 +151,9 @@ impl<'a> StructLayoutTracker<'a> { // actually generate the dummy alignment. } - pub fn saw_union(&mut self, layout: Layout) { - debug!("saw union for {}: {:?}", self.name, layout); - self.align_to_latest_field(layout); - - self.latest_offset += self.padding_bytes(layout) + layout.size; - self.latest_field_layout = Some(layout); - self.max_field_align = cmp::max(self.max_field_align, layout.align); - } - - /// Add a padding field if necessary for a given new field _before_ adding - /// that field. - pub fn pad_field( + /// Returns a padding field if necessary for a given new field _before_ + /// adding that field. + pub fn saw_field( &mut self, field_name: &str, field_ty: &Type, @@ -181,15 +180,27 @@ impl<'a> StructLayoutTracker<'a> { } } } + self.saw_field_with_layout(field_name, field_layout, field_offset) + } + pub fn saw_field_with_layout( + &mut self, + field_name: &str, + field_layout: Layout, + field_offset: Option<usize>, + ) -> Option<proc_macro2::TokenStream> { let will_merge_with_bitfield = self.align_to_latest_field(field_layout); + let is_union = self.comp.is_union(); let padding_bytes = match field_offset { Some(offset) if offset / 8 > self.latest_offset => { offset / 8 - self.latest_offset } _ => { - if will_merge_with_bitfield || field_layout.align == 0 { + if will_merge_with_bitfield || + field_layout.align == 0 || + is_union + { 0 } else if !self.is_packed { self.padding_bytes(field_layout) @@ -203,7 +214,7 @@ impl<'a> StructLayoutTracker<'a> { self.latest_offset += padding_bytes; - let padding_layout = if self.is_packed { + let padding_layout = if self.is_packed || is_union { None } else { // Otherwise the padding is useless. diff --git a/src/ir/analysis/derive.rs b/src/ir/analysis/derive.rs index 6c50fa6..be62666 100644 --- a/src/ir/analysis/derive.rs +++ b/src/ir/analysis/derive.rs @@ -16,7 +16,7 @@ use crate::ir::ty::{Type, TypeKind}; use crate::{Entry, HashMap, HashSet}; /// Which trait to consider when doing the `CannotDerive` analysis. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub enum DeriveTrait { /// The `Copy` trait. Copy, @@ -138,12 +138,25 @@ impl<'ctx> CannotDerive<'ctx> { } fn constrain_type(&mut self, item: &Item, ty: &Type) -> CanDerive { - if !self.ctx.whitelisted_items().contains(&item.id()) { - trace!( - " cannot derive {} for blacklisted type", - self.derive_trait - ); - return CanDerive::No; + if !self.ctx.allowlisted_items().contains(&item.id()) { + let can_derive = self + .ctx + .blocklisted_type_implements_trait(item, self.derive_trait); + match can_derive { + CanDerive::Yes => trace!( + " blocklisted type explicitly implements {}", + self.derive_trait + ), + CanDerive::Manually => trace!( + " blocklisted type requires manual implementation of {}", + self.derive_trait + ), + CanDerive::No => trace!( + " cannot derive {} for blocklisted type", + self.derive_trait + ), + } + return can_derive; } if self.derive_trait.not_by_name(self.ctx, &item) { @@ -640,10 +653,10 @@ impl<'ctx> MonotoneFramework for CannotDerive<'ctx> { } fn initial_worklist(&self) -> Vec<ItemId> { - // The transitive closure of all whitelisted items, including explicitly - // blacklisted items. + // The transitive closure of all allowlisted items, including explicitly + // blocklisted items. self.ctx - .whitelisted_items() + .allowlisted_items() .iter() .cloned() .flat_map(|i| { diff --git a/src/ir/analysis/has_destructor.rs b/src/ir/analysis/has_destructor.rs index ca4f253..5fa22e3 100644 --- a/src/ir/analysis/has_destructor.rs +++ b/src/ir/analysis/has_destructor.rs @@ -83,7 +83,7 @@ impl<'ctx> MonotoneFramework for HasDestructorAnalysis<'ctx> { } fn initial_worklist(&self) -> Vec<ItemId> { - self.ctx.whitelisted_items().iter().cloned().collect() + self.ctx.allowlisted_items().iter().cloned().collect() } fn constrain(&mut self, id: ItemId) -> ConstrainResult { diff --git a/src/ir/analysis/has_float.rs b/src/ir/analysis/has_float.rs index d21e651..bbf2126 100644 --- a/src/ir/analysis/has_float.rs +++ b/src/ir/analysis/has_float.rs @@ -94,7 +94,7 @@ impl<'ctx> MonotoneFramework for HasFloat<'ctx> { } fn initial_worklist(&self) -> Vec<ItemId> { - self.ctx.whitelisted_items().iter().cloned().collect() + self.ctx.allowlisted_items().iter().cloned().collect() } fn constrain(&mut self, id: ItemId) -> ConstrainResult { diff --git a/src/ir/analysis/has_type_param_in_array.rs b/src/ir/analysis/has_type_param_in_array.rs index ebdb7e3..aa52304 100644 --- a/src/ir/analysis/has_type_param_in_array.rs +++ b/src/ir/analysis/has_type_param_in_array.rs @@ -100,7 +100,7 @@ impl<'ctx> MonotoneFramework for HasTypeParameterInArray<'ctx> { } fn initial_worklist(&self) -> Vec<ItemId> { - self.ctx.whitelisted_items().iter().cloned().collect() + self.ctx.allowlisted_items().iter().cloned().collect() } fn constrain(&mut self, id: ItemId) -> ConstrainResult { diff --git a/src/ir/analysis/has_vtable.rs b/src/ir/analysis/has_vtable.rs index d2a57d5..7f5f911 100644 --- a/src/ir/analysis/has_vtable.rs +++ b/src/ir/analysis/has_vtable.rs @@ -147,7 +147,7 @@ impl<'ctx> MonotoneFramework for HasVtableAnalysis<'ctx> { } fn initial_worklist(&self) -> Vec<ItemId> { - self.ctx.whitelisted_items().iter().cloned().collect() + self.ctx.allowlisted_items().iter().cloned().collect() } fn constrain(&mut self, id: ItemId) -> ConstrainResult { diff --git a/src/ir/analysis/mod.rs b/src/ir/analysis/mod.rs index 2cb021f..ec4d20f 100644 --- a/src/ir/analysis/mod.rs +++ b/src/ir/analysis/mod.rs @@ -183,7 +183,7 @@ where { let mut dependencies = HashMap::default(); - for &item in ctx.whitelisted_items() { + for &item in ctx.allowlisted_items() { dependencies.entry(item).or_insert(vec![]); { @@ -192,7 +192,7 @@ where item.trace( ctx, &mut |sub_item: ItemId, edge_kind| { - if ctx.whitelisted_items().contains(&sub_item) && + if ctx.allowlisted_items().contains(&sub_item) && consider_edge(edge_kind) { dependencies diff --git a/src/ir/analysis/sizedness.rs b/src/ir/analysis/sizedness.rs index d8bced7..a3ef753 100644 --- a/src/ir/analysis/sizedness.rs +++ b/src/ir/analysis/sizedness.rs @@ -194,7 +194,7 @@ impl<'ctx> MonotoneFramework for SizednessAnalysis<'ctx> { fn initial_worklist(&self) -> Vec<TypeId> { self.ctx - .whitelisted_items() + .allowlisted_items() .iter() .cloned() .filter_map(|id| id.as_type_id(self.ctx)) diff --git a/src/ir/analysis/template_params.rs b/src/ir/analysis/template_params.rs index f0d9b5e..c2f18b1 100644 --- a/src/ir/analysis/template_params.rs +++ b/src/ir/analysis/template_params.rs @@ -137,13 +137,13 @@ use crate::{HashMap, HashSet}; /// analysis. If we didn't, then we would mistakenly determine that ever /// template parameter is always used. /// -/// The final wrinkle is handling of blacklisted types. Normally, we say that -/// the set of whitelisted items is the transitive closure of items explicitly -/// called out for whitelisting, *without* any items explicitly called out as -/// blacklisted. However, for the purposes of this analysis's correctness, we +/// The final wrinkle is handling of blocklisted types. Normally, we say that +/// the set of allowlisted items is the transitive closure of items explicitly +/// called out for allowlisting, *without* any items explicitly called out as +/// blocklisted. However, for the purposes of this analysis's correctness, we /// simplify and consider run the analysis on the full transitive closure of -/// whitelisted items. We do, however, treat instantiations of blacklisted items -/// specially; see `constrain_instantiation_of_blacklisted_template` and its +/// allowlisted items. We do, however, treat instantiations of blocklisted items +/// specially; see `constrain_instantiation_of_blocklisted_template` and its /// documentation for details. #[derive(Debug, Clone)] pub struct UsedTemplateParameters<'ctx> { @@ -155,10 +155,10 @@ pub struct UsedTemplateParameters<'ctx> { dependencies: HashMap<ItemId, Vec<ItemId>>, - // The set of whitelisted items, without any blacklisted items reachable - // from the whitelisted items which would otherwise be considered - // whitelisted as well. - whitelisted_items: HashSet<ItemId>, + // The set of allowlisted items, without any blocklisted items reachable + // from the allowlisted items which would otherwise be considered + // allowlisted as well. + allowlisted_items: HashSet<ItemId>, } impl<'ctx> UsedTemplateParameters<'ctx> { @@ -221,19 +221,19 @@ impl<'ctx> UsedTemplateParameters<'ctx> { ) } - /// We say that blacklisted items use all of their template parameters. The - /// blacklisted type is most likely implemented explicitly by the user, + /// We say that blocklisted items use all of their template parameters. The + /// blocklisted type is most likely implemented explicitly by the user, /// since it won't be in the generated bindings, and we don't know exactly /// what they'll to with template parameters, but we can push the issue down /// the line to them. - fn constrain_instantiation_of_blacklisted_template( + fn constrain_instantiation_of_blocklisted_template( &self, this_id: ItemId, used_by_this_id: &mut ItemSet, instantiation: &TemplateInstantiation, ) { trace!( - " instantiation of blacklisted template, uses all template \ + " instantiation of blocklisted template, uses all template \ arguments" ); @@ -379,10 +379,10 @@ impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> { fn new(ctx: &'ctx BindgenContext) -> UsedTemplateParameters<'ctx> { let mut used = HashMap::default(); let mut dependencies = HashMap::default(); - let whitelisted_items: HashSet<_> = - ctx.whitelisted_items().iter().cloned().collect(); + let allowlisted_items: HashSet<_> = + ctx.allowlisted_items().iter().cloned().collect(); - let whitelisted_and_blacklisted_items: ItemSet = whitelisted_items + let allowlisted_and_blocklisted_items: ItemSet = allowlisted_items .iter() .cloned() .flat_map(|i| { @@ -398,7 +398,7 @@ impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> { }) .collect(); - for item in whitelisted_and_blacklisted_items { + for item in allowlisted_and_blocklisted_items { dependencies.entry(item).or_insert(vec![]); used.entry(item).or_insert(Some(ItemSet::new())); @@ -457,17 +457,17 @@ impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> { } if cfg!(feature = "testing_only_extra_assertions") { - // Invariant: The `used` map has an entry for every whitelisted - // item, as well as all explicitly blacklisted items that are - // reachable from whitelisted items. + // Invariant: The `used` map has an entry for every allowlisted + // item, as well as all explicitly blocklisted items that are + // reachable from allowlisted items. // // Invariant: the `dependencies` map has an entry for every - // whitelisted item. + // allowlisted item. // // (This is so that every item we call `constrain` on is guaranteed // to have a set of template parameters, and we can allow - // blacklisted templates to use all of their parameters). - for item in whitelisted_items.iter() { + // blocklisted templates to use all of their parameters). + for item in allowlisted_items.iter() { extra_assert!(used.contains_key(item)); extra_assert!(dependencies.contains_key(item)); item.trace( @@ -485,15 +485,15 @@ impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> { ctx: ctx, used: used, dependencies: dependencies, - whitelisted_items: whitelisted_items, + allowlisted_items: allowlisted_items, } } fn initial_worklist(&self) -> Vec<ItemId> { - // The transitive closure of all whitelisted items, including explicitly - // blacklisted items. + // The transitive closure of all allowlisted items, including explicitly + // blocklisted items. self.ctx - .whitelisted_items() + .allowlisted_items() .iter() .cloned() .flat_map(|i| { @@ -538,7 +538,7 @@ impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> { // template definition uses the corresponding template parameter. Some(&TypeKind::TemplateInstantiation(ref inst)) => { if self - .whitelisted_items + .allowlisted_items .contains(&inst.template_definition().into()) { self.constrain_instantiation( @@ -547,7 +547,7 @@ impl<'ctx> MonotoneFramework for UsedTemplateParameters<'ctx> { inst, ); } else { - self.constrain_instantiation_of_blacklisted_template( + self.constrain_instantiation_of_blocklisted_template( id, &mut used_by_this_id, inst, diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 60b1e2f..52dcddd 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -1642,7 +1642,12 @@ impl CompInfo { /// Requirements: /// 1. Current RustTarget allows for `untagged_union` /// 2. Each field can derive `Copy` - pub fn can_be_rust_union(&self, ctx: &BindgenContext) -> bool { + /// 3. It's not zero-sized. + pub fn can_be_rust_union( + &self, + ctx: &BindgenContext, + layout: Option<&Layout>, + ) -> bool { if !ctx.options().rust_features().untagged_union { return false; } @@ -1651,12 +1656,22 @@ impl CompInfo { return false; } - self.fields().iter().all(|f| match *f { + let all_can_copy = self.fields().iter().all(|f| match *f { Field::DataMember(ref field_data) => { field_data.ty().can_derive_copy(ctx) } Field::Bitfields(_) => true, - }) + }); + + if !all_can_copy { + return false; + } + + if layout.map_or(false, |l| l.size == 0) { + return false; + } + + true } } diff --git a/src/ir/context.rs b/src/ir/context.rs index 0207547..ccb05e7 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -28,7 +28,7 @@ use cexpr; use clang_sys; use proc_macro2::{Ident, Span}; use std::borrow::Cow; -use std::cell::Cell; +use std::cell::{Cell, RefCell}; use std::collections::HashMap as StdHashMap; use std::iter::IntoIterator; use std::mem; @@ -376,14 +376,18 @@ pub struct BindgenContext { /// Whether a bindgen complex was generated generated_bindgen_complex: Cell<bool>, - /// The set of `ItemId`s that are whitelisted. This the very first thing + /// The set of `ItemId`s that are allowlisted. This the very first thing /// computed after parsing our IR, and before running any of our analyses. - whitelisted: Option<ItemSet>, + allowlisted: Option<ItemSet>, - /// The set of `ItemId`s that are whitelisted for code generation _and_ that + /// Cache for calls to `ParseCallbacks::blocklisted_type_implements_trait` + blocklisted_types_implement_traits: + RefCell<HashMap<DeriveTrait, HashMap<ItemId, CanDerive>>>, + + /// The set of `ItemId`s that are allowlisted for code generation _and_ that /// we should generate accounting for the codegen options. /// - /// It's computed right after computing the whitelisted items. + /// It's computed right after computing the allowlisted items. codegen_items: Option<ItemSet>, /// Map from an item's id to the set of template parameter items that it @@ -463,8 +467,8 @@ pub struct BindgenContext { has_float: Option<HashSet<ItemId>>, } -/// A traversal of whitelisted items. -struct WhitelistedItemsTraversal<'ctx> { +/// A traversal of allowlisted items. +struct AllowlistedItemsTraversal<'ctx> { ctx: &'ctx BindgenContext, traversal: ItemTraversal< 'ctx, @@ -474,14 +478,14 @@ struct WhitelistedItemsTraversal<'ctx> { >, } -impl<'ctx> Iterator for WhitelistedItemsTraversal<'ctx> { +impl<'ctx> Iterator for AllowlistedItemsTraversal<'ctx> { type Item = ItemId; fn next(&mut self) -> Option<ItemId> { loop { let id = self.traversal.next()?; - if self.ctx.resolve_item(id).is_blacklisted(self.ctx) { + if self.ctx.resolve_item(id).is_blocklisted(self.ctx) { continue; } @@ -490,8 +494,8 @@ impl<'ctx> Iterator for WhitelistedItemsTraversal<'ctx> { } } -impl<'ctx> WhitelistedItemsTraversal<'ctx> { - /// Construct a new whitelisted items traversal. +impl<'ctx> AllowlistedItemsTraversal<'ctx> { + /// Construct a new allowlisted items traversal. pub fn new<R>( ctx: &'ctx BindgenContext, roots: R, @@ -500,7 +504,7 @@ impl<'ctx> WhitelistedItemsTraversal<'ctx> { where R: IntoIterator<Item = ItemId>, { - WhitelistedItemsTraversal { + AllowlistedItemsTraversal { ctx, traversal: ItemTraversal::new(ctx, roots, predicate), } @@ -559,7 +563,8 @@ If you encounter an error missing from this list, please file an issue or a PR!" target_info, options, generated_bindgen_complex: Cell::new(false), - whitelisted: None, + allowlisted: None, + blocklisted_types_implement_traits: Default::default(), codegen_items: None, used_template_parameters: None, need_bitfield_allocation: Default::default(), @@ -718,8 +723,8 @@ If you encounter an error missing from this list, please file an issue or a PR!" } /// Ensure that every item (other than the root module) is in a module's - /// children list. This is to make sure that every whitelisted item get's - /// codegen'd, even if its parent is not whitelisted. See issue #769 for + /// children list. This is to make sure that every allowlisted item get's + /// codegen'd, even if its parent is not allowlisted. See issue #769 for /// details. fn add_item_to_module(&mut self, item: &Item) { assert!(item.id() != self.root_module); @@ -1024,7 +1029,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" _ => continue, } - let path = item.path_for_whitelisting(self); + let path = item.path_for_allowlisting(self); let replacement = self.replacements.get(&path[1..]); if let Some(replacement) = replacement { @@ -1134,10 +1139,10 @@ If you encounter an error missing from this list, please file an issue or a PR!" self.assert_no_dangling_references(); - // Compute the whitelisted set after processing replacements and + // Compute the allowlisted set after processing replacements and // resolving type refs, as those are the final mutations of the IR // graph, and their completion means that the IR graph is now frozen. - self.compute_whitelisted_and_codegen_items(); + self.compute_allowlisted_and_codegen_items(); // Make sure to do this after processing replacements, since that messes // with the parentage and module children, and we want to assert that it @@ -1293,14 +1298,14 @@ If you encounter an error missing from this list, please file an issue or a PR!" fn find_used_template_parameters(&mut self) { let _t = self.timer("find_used_template_parameters"); - if self.options.whitelist_recursively { + if self.options.allowlist_recursively { let used_params = analyze::<UsedTemplateParameters>(self); self.used_template_parameters = Some(used_params); } else { - // If you aren't recursively whitelisting, then we can't really make + // If you aren't recursively allowlisting, then we can't really make // any sense of template parameter usage, and you're on your own. let mut used_params = HashMap::default(); - for &id in self.whitelisted_items() { + for &id in self.allowlisted_items() { used_params.entry(id).or_insert( id.self_template_params(self) .into_iter() @@ -1319,9 +1324,9 @@ If you encounter an error missing from this list, please file an issue or a PR!" /// template usage information is only computed as we enter the codegen /// phase. /// - /// If the item is blacklisted, then we say that it always uses the template + /// If the item is blocklisted, then we say that it always uses the template /// parameter. This is a little subtle. The template parameter usage - /// analysis only considers whitelisted items, and if any blacklisted item + /// analysis only considers allowlisted items, and if any blocklisted item /// shows up in the generated bindings, it is the user's responsibility to /// manually provide a definition for them. To give them the most /// flexibility when doing that, we assume that they use every template @@ -1336,7 +1341,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" "We only compute template parameter usage as we enter codegen" ); - if self.resolve_item(item).is_blacklisted(self) { + if self.resolve_item(item).is_blocklisted(self) { return true; } @@ -2194,15 +2199,46 @@ If you encounter an error missing from this list, please file an issue or a PR!" self.current_module = previous_id; } - /// Iterate over all (explicitly or transitively) whitelisted items. + /// Iterate over all (explicitly or transitively) allowlisted items. /// - /// If no items are explicitly whitelisted, then all items are considered - /// whitelisted. - pub fn whitelisted_items(&self) -> &ItemSet { + /// If no items are explicitly allowlisted, then all items are considered + /// allowlisted. + pub fn allowlisted_items(&self) -> &ItemSet { assert!(self.in_codegen_phase()); assert!(self.current_module == self.root_module); - self.whitelisted.as_ref().unwrap() + self.allowlisted.as_ref().unwrap() + } + + /// Check whether a particular blocklisted type implements a trait or not. + /// Results may be cached. + pub fn blocklisted_type_implements_trait( + &self, + item: &Item, + derive_trait: DeriveTrait, + ) -> CanDerive { + assert!(self.in_codegen_phase()); + assert!(self.current_module == self.root_module); + + let cb = match self.options.parse_callbacks { + Some(ref cb) => cb, + None => return CanDerive::No, + }; + + *self + .blocklisted_types_implement_traits + .borrow_mut() + .entry(derive_trait) + .or_default() + .entry(item.id()) + .or_insert_with(|| { + item.expect_type() + .name() + .and_then(|name| { + cb.blocklisted_type_implements_trait(name, derive_trait) + }) + .unwrap_or(CanDerive::No) + }) } /// Get a reference to the set of items we should generate. @@ -2212,12 +2248,12 @@ If you encounter an error missing from this list, please file an issue or a PR!" self.codegen_items.as_ref().unwrap() } - /// Compute the whitelisted items set and populate `self.whitelisted`. - fn compute_whitelisted_and_codegen_items(&mut self) { + /// Compute the allowlisted items set and populate `self.allowlisted`. + fn compute_allowlisted_and_codegen_items(&mut self) { assert!(self.in_codegen_phase()); assert!(self.current_module == self.root_module); - assert!(self.whitelisted.is_none()); - let _t = self.timer("compute_whitelisted_and_codegen_items"); + assert!(self.allowlisted.is_none()); + let _t = self.timer("compute_allowlisted_and_codegen_items"); let roots = { let mut roots = self @@ -2225,11 +2261,11 @@ If you encounter an error missing from this list, please file an issue or a PR!" // Only consider roots that are enabled for codegen. .filter(|&(_, item)| item.is_enabled_for_codegen(self)) .filter(|&(_, item)| { - // If nothing is explicitly whitelisted, then everything is fair + // If nothing is explicitly allowlisted, then everything is fair // game. - if self.options().whitelisted_types.is_empty() && - self.options().whitelisted_functions.is_empty() && - self.options().whitelisted_vars.is_empty() + if self.options().allowlisted_types.is_empty() && + self.options().allowlisted_functions.is_empty() && + self.options().allowlisted_vars.is_empty() { return true; } @@ -2240,25 +2276,25 @@ If you encounter an error missing from this list, please file an issue or a PR!" return true; } - let name = item.path_for_whitelisting(self)[1..].join("::"); - debug!("whitelisted_items: testing {:?}", name); + let name = item.path_for_allowlisting(self)[1..].join("::"); + debug!("allowlisted_items: testing {:?}", name); match *item.kind() { ItemKind::Module(..) => true, ItemKind::Function(_) => { - self.options().whitelisted_functions.matches(&name) + self.options().allowlisted_functions.matches(&name) } ItemKind::Var(_) => { - self.options().whitelisted_vars.matches(&name) + self.options().allowlisted_vars.matches(&name) } ItemKind::Type(ref ty) => { - if self.options().whitelisted_types.matches(&name) { + if self.options().allowlisted_types.matches(&name) { return true; } - // Auto-whitelist types that don't need code - // generation if not whitelisting recursively, to + // Auto-allowlist types that don't need code + // generation if not allowlisting recursively, to // make the #[derive] analysis not be lame. - if !self.options().whitelist_recursively { + if !self.options().allowlist_recursively { match *ty.kind() { TypeKind::Void | TypeKind::NullPtr | @@ -2278,7 +2314,7 @@ If you encounter an error missing from this list, please file an issue or a PR!" } // Unnamed top-level enums are special and we - // whitelist them via the `whitelisted_vars` filter, + // allowlist them via the `allowlisted_vars` filter, // since they're effectively top-level constants, // and there's no way for them to be referenced // consistently. @@ -2297,12 +2333,14 @@ If you encounter an error missing from this list, please file an issue or a PR!" } let mut prefix_path = - parent.path_for_whitelisting(self).clone(); + parent.path_for_allowlisting(self).clone(); enum_.variants().iter().any(|variant| { - prefix_path.push(variant.name().into()); + prefix_path.push( + variant.name_for_allowlisting().into(), + ); let name = prefix_path[1..].join("::"); prefix_path.pop().unwrap(); - self.options().whitelisted_vars.matches(&name) + self.options().allowlisted_vars.matches(&name) }) } } @@ -2317,48 +2355,48 @@ If you encounter an error missing from this list, please file an issue or a PR!" roots }; - let whitelisted_items_predicate = - if self.options().whitelist_recursively { + let allowlisted_items_predicate = + if self.options().allowlist_recursively { traversal::all_edges } else { - // Only follow InnerType edges from the whitelisted roots. + // Only follow InnerType edges from the allowlisted roots. // Such inner types (e.g. anonymous structs/unions) are - // always emitted by codegen, and they need to be whitelisted + // always emitted by codegen, and they need to be allowlisted // to make sure they are processed by e.g. the derive analysis. traversal::only_inner_type_edges }; - let whitelisted = WhitelistedItemsTraversal::new( + let allowlisted = AllowlistedItemsTraversal::new( self, roots.clone(), - whitelisted_items_predicate, + allowlisted_items_predicate, ) .collect::<ItemSet>(); - let codegen_items = if self.options().whitelist_recursively { - WhitelistedItemsTraversal::new( + let codegen_items = if self.options().allowlist_recursively { + AllowlistedItemsTraversal::new( self, roots.clone(), traversal::codegen_edges, ) .collect::<ItemSet>() } else { - whitelisted.clone() + allowlisted.clone() }; - self.whitelisted = Some(whitelisted); + self.allowlisted = Some(allowlisted); self.codegen_items = Some(codegen_items); - for item in self.options().whitelisted_functions.unmatched_items() { - warn!("unused option: --whitelist-function {}", item); + for item in self.options().allowlisted_functions.unmatched_items() { + warn!("unused option: --allowlist-function {}", item); } - for item in self.options().whitelisted_vars.unmatched_items() { - warn!("unused option: --whitelist-var {}", item); + for item in self.options().allowlisted_vars.unmatched_items() { + warn!("unused option: --allowlist-var {}", item); } - for item in self.options().whitelisted_types.unmatched_items() { - warn!("unused option: --whitelist-type {}", item); + for item in self.options().allowlisted_types.unmatched_items() { + warn!("unused option: --allowlist-type {}", item); } } @@ -2575,31 +2613,31 @@ If you encounter an error missing from this list, please file an issue or a PR!" /// Check if `--no-partialeq` flag is enabled for this item. pub fn no_partialeq_by_name(&self, item: &Item) -> bool { - let name = item.path_for_whitelisting(self)[1..].join("::"); + let name = item.path_for_allowlisting(self)[1..].join("::"); self.options().no_partialeq_types.matches(&name) } /// Check if `--no-copy` flag is enabled for this item. pub fn no_copy_by_name(&self, item: &Item) -> bool { - let name = item.path_for_whitelisting(self)[1..].join("::"); + let name = item.path_for_allowlisting(self)[1..].join("::"); 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("::"); + let name = item.path_for_allowlisting(self)[1..].join("::"); self.options().no_debug_types.matches(&name) } /// Check if `--no-default` flag is enabled for this item. pub fn no_default_by_name(&self, item: &Item) -> bool { - let name = item.path_for_whitelisting(self)[1..].join("::"); + let name = item.path_for_allowlisting(self)[1..].join("::"); self.options().no_default_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("::"); + let name = item.path_for_allowlisting(self)[1..].join("::"); self.options().no_hash_types.matches(&name) } } diff --git a/src/ir/dot.rs b/src/ir/dot.rs index 6bf75bf..f7d07f1 100644 --- a/src/ir/dot.rs +++ b/src/ir/dot.rs @@ -32,13 +32,13 @@ where let mut err: Option<io::Result<_>> = None; for (id, item) in ctx.items() { - let is_whitelisted = ctx.whitelisted_items().contains(&id); + let is_allowlisted = ctx.allowlisted_items().contains(&id); writeln!( &mut dot_file, r#"{} [fontname="courier", color={}, label=< <table border="0" align="left">"#, id.as_usize(), - if is_whitelisted { "black" } else { "gray" } + if is_allowlisted { "black" } else { "gray" } )?; item.dot_attributes(ctx, &mut dot_file)?; writeln!(&mut dot_file, r#"</table> >];"#)?; @@ -56,7 +56,7 @@ where id.as_usize(), sub_id.as_usize(), edge_kind, - if is_whitelisted { "black" } else { "gray" } + if is_allowlisted { "black" } else { "gray" } ) { Ok(_) => {} Err(e) => err = Some(Err(e)), diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs index dde4bb1..15d4136 100644 --- a/src/ir/enum_ty.rs +++ b/src/ir/enum_ty.rs @@ -118,7 +118,7 @@ impl Enum { } }); - let name = ctx + let new_name = ctx .parse_callbacks() .and_then(|callbacks| { callbacks.enum_variant_name(type_name, &name, val) @@ -130,10 +130,11 @@ impl Enum { .last() .cloned() }) - .unwrap_or(name); + .unwrap_or_else(|| name.clone()); let comment = cursor.raw_comment(); variants.push(EnumVariant::new( + new_name, name, comment, val, @@ -152,7 +153,7 @@ impl Enum { enums: &RegexSet, item: &Item, ) -> bool { - let path = item.path_for_whitelisting(ctx); + let path = item.path_for_allowlisting(ctx); let enum_ty = item.expect_type(); if enums.matches(&path[1..].join("::")) { @@ -224,6 +225,9 @@ pub struct EnumVariant { /// The name of the variant. name: String, + /// The original name of the variant (without user mangling) + name_for_allowlisting: String, + /// An optional doc comment. comment: Option<String>, @@ -251,12 +255,14 @@ impl EnumVariant { /// Construct a new enumeration variant from the given parts. pub fn new( name: String, + name_for_allowlisting: String, comment: Option<String>, val: EnumVariantValue, custom_behavior: Option<EnumVariantCustomBehavior>, ) -> Self { EnumVariant { name, + name_for_allowlisting, comment, val, custom_behavior, @@ -268,6 +274,11 @@ impl EnumVariant { &self.name } + /// Get this variant's name. + pub fn name_for_allowlisting(&self) -> &str { + &self.name_for_allowlisting + } + /// Get this variant's value. pub fn val(&self) -> EnumVariantValue { self.val diff --git a/src/ir/item.rs b/src/ir/item.rs index e9abed7..4541504 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -273,10 +273,10 @@ impl Trace for Item { where T: Tracer, { - // Even if this item is blacklisted/hidden, we want to trace it. It is + // Even if this item is blocklisted/hidden, we want to trace it. It is // traversal iterators' consumers' responsibility to filter items as // needed. Generally, this filtering happens in the implementation of - // `Iterator` for `WhitelistedItems`. Fully tracing blacklisted items is + // `Iterator` for `allowlistedItems`. Fully tracing blocklisted items is // necessary for things like the template parameter usage analysis to // function correctly. @@ -301,12 +301,12 @@ impl Trace for Item { } ItemKind::Module(_) => { // Module -> children edges are "weak", and we do not want to - // trace them. If we did, then whitelisting wouldn't work as + // trace them. If we did, then allowlisting wouldn't work as // expected: everything in every module would end up - // whitelisted. + // allowlisted. // // TODO: make a new edge kind for module -> children edges and - // filter them during whitelisting traversals. + // filter them during allowlisting traversals. } } } @@ -400,9 +400,9 @@ pub struct Item { /// considerably faster in those cases. canonical_name: LazyCell<String>, - /// The path to use for whitelisting and other name-based checks, as - /// returned by `path_for_whitelisting`, lazily constructed. - path_for_whitelisting: LazyCell<Vec<String>>, + /// The path to use for allowlisting and other name-based checks, as + /// returned by `path_for_allowlisting`, lazily constructed. + path_for_allowlisting: LazyCell<Vec<String>>, /// A doc comment over the item, if any. comment: Option<String>, @@ -440,7 +440,7 @@ impl Item { local_id: LazyCell::new(), next_child_local_id: Cell::new(1), canonical_name: LazyCell::new(), - path_for_whitelisting: LazyCell::new(), + path_for_allowlisting: LazyCell::new(), parent_id: parent_id, comment: comment, annotations: annotations.unwrap_or_default(), @@ -623,10 +623,10 @@ impl Item { &self.annotations } - /// Whether this item should be blacklisted. + /// Whether this item should be blocklisted. /// /// This may be due to either annotations or to other kind of configuration. - pub fn is_blacklisted(&self, ctx: &BindgenContext) -> bool { + pub fn is_blocklisted(&self, ctx: &BindgenContext) -> bool { debug_assert!( ctx.in_codegen_phase(), "You're not supposed to call this yet" @@ -635,18 +635,18 @@ impl Item { return true; } - let path = self.path_for_whitelisting(ctx); + let path = self.path_for_allowlisting(ctx); let name = path[1..].join("::"); - ctx.options().blacklisted_items.matches(&name) || + ctx.options().blocklisted_items.matches(&name) || match self.kind { ItemKind::Type(..) => { - ctx.options().blacklisted_types.matches(&name) || + ctx.options().blocklisted_types.matches(&name) || ctx.is_replaced_type(&path, self.id) } ItemKind::Function(..) => { - ctx.options().blacklisted_functions.matches(&name) + ctx.options().blocklisted_functions.matches(&name) } - // TODO: Add constant / namespace blacklisting? + // TODO: Add constant / namespace blocklisting? ItemKind::Var(..) | ItemKind::Module(..) => false, } } @@ -1012,10 +1012,10 @@ impl Item { } } - /// Returns the path we should use for whitelisting / blacklisting, which + /// Returns the path we should use for allowlisting / blocklisting, which /// doesn't include user-mangling. - pub fn path_for_whitelisting(&self, ctx: &BindgenContext) -> &Vec<String> { - self.path_for_whitelisting + pub fn path_for_allowlisting(&self, ctx: &BindgenContext) -> &Vec<String> { + self.path_for_allowlisting .borrow_with(|| self.compute_path(ctx, UserMangled::No)) } @@ -1081,7 +1081,7 @@ impl IsOpaque for Item { ); self.annotations.opaque() || self.as_type().map_or(false, |ty| ty.is_opaque(ctx, self)) || - ctx.opaque_by_name(&self.path_for_whitelisting(ctx)) + ctx.opaque_by_name(&self.path_for_allowlisting(ctx)) } } @@ -1390,7 +1390,7 @@ impl ClangItemParser for Item { if cursor.kind() == CXCursor_UnexposedDecl { Err(ParseError::Recurse) } else { - // We whitelist cursors here known to be unhandled, to prevent being + // We allowlist cursors here known to be unhandled, to prevent being // too noisy about this. match cursor.kind() { CXCursor_MacroDefinition | @@ -1918,7 +1918,7 @@ impl ItemCanonicalPath for Item { /// not. /// /// Most of the callers probably want just yes, but the ones dealing with -/// whitelisting and blacklisting don't. +/// allowlisting and blocklisting don't. #[derive(Copy, Clone, Debug, PartialEq)] enum UserMangled { No, diff --git a/src/ir/template.rs b/src/ir/template.rs index 8c625d1..b519fff 100644 --- a/src/ir/template.rs +++ b/src/ir/template.rs @@ -306,13 +306,13 @@ impl IsOpaque for TemplateInstantiation { // correct fix is to make `canonical_{name,path}` include template // arguments properly. - let mut path = item.path_for_whitelisting(ctx).clone(); + let mut path = item.path_for_allowlisting(ctx).clone(); let args: Vec<_> = self .template_arguments() .iter() .map(|arg| { let arg_path = - ctx.resolve_item(*arg).path_for_whitelisting(ctx); + ctx.resolve_item(*arg).path_for_allowlisting(ctx); arg_path[1..].join("::") }) .collect(); diff --git a/src/ir/traversal.rs b/src/ir/traversal.rs index e4a4470..430dd02 100644 --- a/src/ir/traversal.rs +++ b/src/ir/traversal.rs @@ -201,7 +201,7 @@ pub fn all_edges(_: &BindgenContext, _: Edge) -> bool { /// A `TraversalPredicate` implementation that only follows /// `EdgeKind::InnerType` edges, and therefore traversals using this predicate /// will only visit the traversal's roots and their inner types. This is used -/// in no-recursive-whitelist mode, where inner types such as anonymous +/// in no-recursive-allowlist mode, where inner types such as anonymous /// structs/unions still need to be processed. pub fn only_inner_type_edges(_: &BindgenContext, edge: Edge) -> bool { edge.kind == EdgeKind::InnerType @@ -377,7 +377,7 @@ pub trait Trace { /// An graph traversal of the transitive closure of references between items. /// -/// See `BindgenContext::whitelisted_items` for more information. +/// See `BindgenContext::allowlisted_items` for more information. pub struct ItemTraversal<'ctx, Storage, Queue, Predicate> where Storage: TraversalStorage<'ctx>, @@ -177,8 +177,8 @@ impl Default for CodegenConfig { /// /// // Configure and generate bindings. /// let bindings = builder().header("path/to/input/header") -/// .whitelist_type("SomeCoolClass") -/// .whitelist_function("do_some_cool_thing") +/// .allowlist_type("SomeCoolClass") +/// .allowlist_function("do_some_cool_thing") /// .generate()?; /// /// // Write the generated bindings to an output file. @@ -304,13 +304,13 @@ impl Builder { (&self.options.type_alias, "--type-alias"), (&self.options.new_type_alias, "--new-type-alias"), (&self.options.new_type_alias_deref, "--new-type-alias-deref"), - (&self.options.blacklisted_types, "--blacklist-type"), - (&self.options.blacklisted_functions, "--blacklist-function"), - (&self.options.blacklisted_items, "--blacklist-item"), + (&self.options.blocklisted_types, "--blocklist-type"), + (&self.options.blocklisted_functions, "--blocklist-function"), + (&self.options.blocklisted_items, "--blocklist-item"), (&self.options.opaque_types, "--opaque-type"), - (&self.options.whitelisted_functions, "--whitelist-function"), - (&self.options.whitelisted_types, "--whitelist-type"), - (&self.options.whitelisted_vars, "--whitelist-var"), + (&self.options.allowlisted_functions, "--allowlist-function"), + (&self.options.allowlisted_types, "--allowlist-type"), + (&self.options.allowlisted_vars, "--allowlist-var"), (&self.options.no_partialeq_types, "--no-partialeq"), (&self.options.no_copy_types, "--no-copy"), (&self.options.no_debug_types, "--no-debug"), @@ -379,8 +379,8 @@ impl Builder { output_vector.push("--no-doc-comments".into()); } - if !self.options.whitelist_recursively { - output_vector.push("--no-recursive-whitelist".into()); + if !self.options.allowlist_recursively { + output_vector.push("--no-recursive-allowlist".into()); } if self.options.objc_extern_crate { @@ -545,10 +545,18 @@ impl Builder { output_vector.push(name.clone()); } + if self.options.dynamic_link_require_all { + output_vector.push("--dynamic-link-require-all".into()); + } + if self.options.respect_cxx_access_specs { output_vector.push("--respect-cxx-access-specs".into()); } + if self.options.translate_enum_integer_types { + output_vector.push("--translate-enum-integer-types".into()); + } + // Add clang arguments output_vector.push("--".into()); @@ -642,12 +650,7 @@ impl Builder { } /// Whether the generated bindings should contain documentation comments - /// (docstrings) or not. - /// - /// This ideally will always be true, but it may need to be false until we - /// implement some processing on comments to work around issues as described - /// in [rust-bindgen issue - /// #426](https://github.com/rust-lang/rust-bindgen/issues/426). + /// (docstrings) or not. This is set to true by default. /// /// Note that clang by default excludes comments from system headers, pass /// `-fretain-comments-from-system-headers` as @@ -661,9 +664,9 @@ impl Builder { self } - /// Whether to whitelist recursively or not. Defaults to true. + /// Whether to allowlist recursively or not. Defaults to true. /// - /// Given that we have explicitly whitelisted the "initiate_dance_party" + /// Given that we have explicitly allowlisted the "initiate_dance_party" /// function in this C header: /// /// ```c @@ -676,23 +679,29 @@ impl Builder { /// /// We would normally generate bindings to both the `initiate_dance_party` /// function and the `MoonBoots` struct that it transitively references. By - /// configuring with `whitelist_recursively(false)`, `bindgen` will not emit - /// bindings for anything except the explicitly whitelisted items, and there + /// configuring with `allowlist_recursively(false)`, `bindgen` will not emit + /// bindings for anything except the explicitly allowlisted items, and there /// would be no emitted struct definition for `MoonBoots`. However, the /// `initiate_dance_party` function would still reference `MoonBoots`! /// /// **Disabling this feature will almost certainly cause `bindgen` to emit /// bindings that will not compile!** If you disable this feature, then it /// is *your* responsibility to provide definitions for every type that is - /// referenced from an explicitly whitelisted item. One way to provide the + /// referenced from an explicitly allowlisted item. One way to provide the /// definitions is by using the [`Builder::raw_line`](#method.raw_line) /// method, another would be to define them in Rust and then `include!(...)` /// the bindings immediately afterwards. - pub fn whitelist_recursively(mut self, doit: bool) -> Self { - self.options.whitelist_recursively = doit; + pub fn allowlist_recursively(mut self, doit: bool) -> Self { + self.options.allowlist_recursively = doit; self } + /// Deprecated alias for allowlist_recursively. + #[deprecated(note = "Use allowlist_recursively instead")] + pub fn whitelist_recursively(self, doit: bool) -> Self { + self.allowlist_recursively(doit) + } + /// Generate `#[macro_use] extern crate objc;` instead of `use objc;` /// in the prologue of the files generated from objective-c files pub fn objc_extern_crate(mut self, doit: bool) -> Self { @@ -727,30 +736,53 @@ impl Builder { /// Hide the given type from the generated bindings. Regular expressions are /// supported. - #[deprecated(note = "Use blacklist_type instead")] + #[deprecated(note = "Use blocklist_type instead")] pub fn hide_type<T: AsRef<str>>(self, arg: T) -> Builder { - self.blacklist_type(arg) + self.blocklist_type(arg) + } + + /// Hide the given type from the generated bindings. Regular expressions are + /// supported. + #[deprecated(note = "Use blocklist_type instead")] + pub fn blacklist_type<T: AsRef<str>>(self, arg: T) -> Builder { + self.blocklist_type(arg) } /// Hide the given type from the generated bindings. Regular expressions are /// supported. /// - /// To blacklist types prefixed with "mylib" use `"mylib_.*"`. + /// To blocklist types prefixed with "mylib" use `"mylib_.*"`. /// For more complicated expressions check /// [regex](https://docs.rs/regex/*/regex/) docs - pub fn blacklist_type<T: AsRef<str>>(mut self, arg: T) -> Builder { - self.options.blacklisted_types.insert(arg); + pub fn blocklist_type<T: AsRef<str>>(mut self, arg: T) -> Builder { + self.options.blocklisted_types.insert(arg); self } /// Hide the given function from the generated bindings. Regular expressions /// are supported. + #[deprecated(note = "Use blocklist_function instead")] + pub fn blacklist_function<T: AsRef<str>>(self, arg: T) -> Builder { + self.blocklist_function(arg) + } + + /// Hide the given function from the generated bindings. Regular expressions + /// are supported. /// - /// To blacklist functions prefixed with "mylib" use `"mylib_.*"`. + /// To blocklist functions prefixed with "mylib" use `"mylib_.*"`. /// For more complicated expressions check /// [regex](https://docs.rs/regex/*/regex/) docs - pub fn blacklist_function<T: AsRef<str>>(mut self, arg: T) -> Builder { - self.options.blacklisted_functions.insert(arg); + pub fn blocklist_function<T: AsRef<str>>(mut self, arg: T) -> Builder { + self.options.blocklisted_functions.insert(arg); + self + } + + /// Hide the given item from the generated bindings, regardless of + /// whether it's a type, function, module, etc. Regular + /// expressions are supported. + #[deprecated(note = "Use blocklist_item instead")] + pub fn blacklist_item<T: AsRef<str>>(mut self, arg: T) -> Builder { + self.options.blocklisted_items.insert(arg); self } @@ -758,11 +790,11 @@ impl Builder { /// whether it's a type, function, module, etc. Regular /// expressions are supported. /// - /// To blacklist items prefixed with "mylib" use `"mylib_.*"`. + /// To blocklist items prefixed with "mylib" use `"mylib_.*"`. /// For more complicated expressions check /// [regex](https://docs.rs/regex/*/regex/) docs - pub fn blacklist_item<T: AsRef<str>>(mut self, arg: T) -> Builder { - self.options.blacklisted_items.insert(arg); + pub fn blocklist_item<T: AsRef<str>>(mut self, arg: T) -> Builder { + self.options.blocklisted_items.insert(arg); self } @@ -777,64 +809,86 @@ impl Builder { self } - /// Whitelist the given type so that it (and all types that it transitively + /// Allowlist the given type so that it (and all types that it transitively /// refers to) appears in the generated bindings. Regular expressions are /// supported. - #[deprecated(note = "use whitelist_type instead")] + #[deprecated(note = "use allowlist_type instead")] pub fn whitelisted_type<T: AsRef<str>>(self, arg: T) -> Builder { - self.whitelist_type(arg) + self.allowlist_type(arg) + } + + /// Allowlist the given type so that it (and all types that it transitively + /// refers to) appears in the generated bindings. Regular expressions are + /// supported. + #[deprecated(note = "use allowlist_type instead")] + pub fn whitelist_type<T: AsRef<str>>(self, arg: T) -> Builder { + self.allowlist_type(arg) } - /// Whitelist the given type so that it (and all types that it transitively + /// Allowlist the given type so that it (and all types that it transitively /// refers to) appears in the generated bindings. Regular expressions are /// supported. /// - /// To whitelist types prefixed with "mylib" use `"mylib_.*"`. + /// To allowlist types prefixed with "mylib" use `"mylib_.*"`. /// For more complicated expressions check /// [regex](https://docs.rs/regex/*/regex/) docs - pub fn whitelist_type<T: AsRef<str>>(mut self, arg: T) -> Builder { - self.options.whitelisted_types.insert(arg); + pub fn allowlist_type<T: AsRef<str>>(mut self, arg: T) -> Builder { + self.options.allowlisted_types.insert(arg); self } - /// Whitelist the given function so that it (and all types that it + /// Allowlist the given function so that it (and all types that it /// transitively refers to) appears in the generated bindings. Regular /// expressions are supported. /// - /// To whitelist functions prefixed with "mylib" use `"mylib_.*"`. + /// To allowlist functions prefixed with "mylib" use `"mylib_.*"`. /// For more complicated expressions check /// [regex](https://docs.rs/regex/*/regex/) docs - pub fn whitelist_function<T: AsRef<str>>(mut self, arg: T) -> Builder { - self.options.whitelisted_functions.insert(arg); + pub fn allowlist_function<T: AsRef<str>>(mut self, arg: T) -> Builder { + self.options.allowlisted_functions.insert(arg); self } - /// Whitelist the given function. + /// Allowlist the given function. /// - /// Deprecated: use whitelist_function instead. - #[deprecated(note = "use whitelist_function instead")] + /// Deprecated: use allowlist_function instead. + #[deprecated(note = "use allowlist_function instead")] + pub fn whitelist_function<T: AsRef<str>>(self, arg: T) -> Builder { + self.allowlist_function(arg) + } + + /// Allowlist the given function. + /// + /// Deprecated: use allowlist_function instead. + #[deprecated(note = "use allowlist_function instead")] pub fn whitelisted_function<T: AsRef<str>>(self, arg: T) -> Builder { - self.whitelist_function(arg) + self.allowlist_function(arg) } - /// Whitelist the given variable so that it (and all types that it + /// Allowlist the given variable so that it (and all types that it /// transitively refers to) appears in the generated bindings. Regular /// expressions are supported. /// - /// To whitelist variables prefixed with "mylib" use `"mylib_.*"`. + /// To allowlist variables prefixed with "mylib" use `"mylib_.*"`. /// For more complicated expressions check /// [regex](https://docs.rs/regex/*/regex/) docs - pub fn whitelist_var<T: AsRef<str>>(mut self, arg: T) -> Builder { - self.options.whitelisted_vars.insert(arg); + pub fn allowlist_var<T: AsRef<str>>(mut self, arg: T) -> Builder { + self.options.allowlisted_vars.insert(arg); self } - /// Whitelist the given variable. + /// Deprecated: use allowlist_var instead. + #[deprecated(note = "use allowlist_var instead")] + pub fn whitelist_var<T: AsRef<str>>(self, arg: T) -> Builder { + self.allowlist_var(arg) + } + + /// Allowlist the given variable. /// - /// Deprecated: use whitelist_var instead. - #[deprecated(note = "use whitelist_var instead")] + /// Deprecated: use allowlist_var instead. + #[deprecated(note = "use allowlist_var instead")] pub fn whitelisted_var<T: AsRef<str>>(self, arg: T) -> Builder { - self.whitelist_var(arg) + self.allowlist_var(arg) } /// Set the default style of code to generate for enums @@ -1163,7 +1217,7 @@ impl Builder { /// This method disables that behavior. /// /// Note that this intentionally does not change the names used for - /// whitelisting and blacklisting, which should still be mangled with the + /// allowlisting and blocklisting, which should still be mangled with the /// namespaces. /// /// Note, also, that this option may cause bindgen to generate duplicate @@ -1523,27 +1577,45 @@ impl Builder { self } + /// Require successful linkage for all routines in a shared library. + /// This allows us to optimize function calls by being able to safely assume function pointers + /// are valid. + pub fn dynamic_link_require_all(mut self, req: bool) -> Self { + self.options.dynamic_link_require_all = req; + self + } + /// Generate bindings as `pub` only if the bound item is publically accessible by C++. pub fn respect_cxx_access_specs(mut self, doit: bool) -> Self { self.options.respect_cxx_access_specs = doit; self } + + /// Always translate enum integer types to native Rust integer types. + /// + /// This will result in enums having types such as `u32` and `i16` instead + /// of `c_uint` and `c_short`. Types for Rustified enums are always + /// translated. + pub fn translate_enum_integer_types(mut self, doit: bool) -> Self { + self.options.translate_enum_integer_types = doit; + self + } } /// Configuration options for generated bindings. #[derive(Debug)] struct BindgenOptions { - /// The set of types that have been blacklisted and should not appear + /// The set of types that have been blocklisted and should not appear /// anywhere in the generated code. - blacklisted_types: RegexSet, + blocklisted_types: RegexSet, - /// The set of functions that have been blacklisted and should not appear + /// The set of functions that have been blocklisted and should not appear /// in the generated code. - blacklisted_functions: RegexSet, + blocklisted_functions: RegexSet, /// The set of items, regardless of item-type, that have been - /// blacklisted and should not appear in the generated code. - blacklisted_items: RegexSet, + /// blocklisted and should not appear in the generated code. + blocklisted_items: RegexSet, /// The set of types that should be treated as opaque structures in the /// generated code. @@ -1556,15 +1628,15 @@ struct BindgenOptions { /// code. /// /// This includes all types transitively reachable from any type in this - /// set. One might think of whitelisted types/vars/functions as GC roots, + /// set. One might think of allowlisted types/vars/functions as GC roots, /// and the generated Rust code as including everything that gets marked. - whitelisted_types: RegexSet, + allowlisted_types: RegexSet, - /// Whitelisted functions. See docs for `whitelisted_types` for more. - whitelisted_functions: RegexSet, + /// Allowlisted functions. See docs for `allowlisted_types` for more. + allowlisted_functions: RegexSet, - /// Whitelisted variables. See docs for `whitelisted_types` for more. - whitelisted_vars: RegexSet, + /// Allowlisted variables. See docs for `allowlisted_types` for more. + allowlisted_vars: RegexSet, /// The default style of code to generate for enums default_enum_style: codegen::EnumVariation, @@ -1730,14 +1802,14 @@ struct BindgenOptions { conservative_inline_namespaces: bool, /// Whether to keep documentation comments in the generated output. See the - /// documentation for more details. + /// documentation for more details. Defaults to true. generate_comments: bool, /// Whether to generate inline functions. Defaults to false. generate_inline_functions: bool, - /// Whether to whitelist types recursively. Defaults to true. - whitelist_recursively: bool, + /// Whether to allowlist types recursively. Defaults to true. + allowlist_recursively: bool, /// Instead of emitting 'use objc;' to files generated from objective c files, /// generate '#[macro_use] extern crate objc;' @@ -1777,7 +1849,7 @@ struct BindgenOptions { /// Whether we should record which items in the regex sets ever matched. /// - /// This may be a bit slower, but will enable reporting of unused whitelist + /// This may be a bit slower, but will enable reporting of unused allowlist /// items via the `error!` log. record_matches: bool, @@ -1816,9 +1888,17 @@ struct BindgenOptions { /// this is None, no dynamic bindings are created. dynamic_library_name: Option<String>, + /// Require successful linkage for all routines in a shared library. + /// This allows us to optimize function calls by being able to safely assume function pointers + /// are valid. No effect if `dynamic_library_name` is None. + dynamic_link_require_all: bool, + /// Only make generated bindings `pub` if the items would be publically accessible /// by C++. respect_cxx_access_specs: bool, + + /// Always translate enum integer types to native Rust integer types. + translate_enum_integer_types: bool, } /// TODO(emilio): This is sort of a lie (see the error message that results from @@ -1829,12 +1909,12 @@ impl ::std::panic::UnwindSafe for BindgenOptions {} impl BindgenOptions { fn build(&mut self) { let mut regex_sets = [ - &mut self.whitelisted_vars, - &mut self.whitelisted_types, - &mut self.whitelisted_functions, - &mut self.blacklisted_types, - &mut self.blacklisted_functions, - &mut self.blacklisted_items, + &mut self.allowlisted_vars, + &mut self.allowlisted_types, + &mut self.allowlisted_functions, + &mut self.blocklisted_types, + &mut self.blocklisted_functions, + &mut self.blocklisted_items, &mut self.opaque_types, &mut self.bitfield_enums, &mut self.constified_enums, @@ -1878,14 +1958,14 @@ impl Default for BindgenOptions { BindgenOptions { rust_target, rust_features: rust_target.into(), - blacklisted_types: Default::default(), - blacklisted_functions: Default::default(), - blacklisted_items: Default::default(), + blocklisted_types: Default::default(), + blocklisted_functions: Default::default(), + blocklisted_items: Default::default(), opaque_types: Default::default(), rustfmt_path: Default::default(), - whitelisted_types: Default::default(), - whitelisted_functions: Default::default(), - whitelisted_vars: Default::default(), + allowlisted_types: Default::default(), + allowlisted_functions: Default::default(), + allowlisted_vars: Default::default(), default_enum_style: Default::default(), bitfield_enums: Default::default(), newtype_enums: Default::default(), @@ -1934,7 +2014,7 @@ impl Default for BindgenOptions { conservative_inline_namespaces: false, generate_comments: true, generate_inline_functions: false, - whitelist_recursively: true, + allowlist_recursively: true, generate_block: false, objc_extern_crate: false, block_extern_crate: false, @@ -1955,7 +2035,9 @@ impl Default for BindgenOptions { array_pointers_in_arguments: false, wasm_import_module_name: None, dynamic_library_name: None, + dynamic_link_require_all: false, respect_cxx_access_specs: false, + translate_enum_integer_types: false, } } } @@ -2237,7 +2319,7 @@ impl Bindings { /// Write these bindings as source text to the given `Write`able. pub fn write<'a>(&self, mut writer: Box<dyn Write + 'a>) -> io::Result<()> { if !self.options.disable_header_comment { - let version = Some("0.57.0"); + let version = Some("0.58.1"); let header = format!( "/* automatically generated by rust-bindgen {} */\n\n", version.unwrap_or("(unknown version)") @@ -2444,10 +2526,12 @@ pub struct ClangVersion { pub fn clang_version() -> ClangVersion { ensure_libclang_is_loaded(); + //Debian clang version 11.0.1-2 let raw_v: String = clang::extract_clang_version(); let split_v: Option<Vec<&str>> = raw_v .split_whitespace() - .nth(2) + .filter(|t| t.chars().next().map_or(false, |v| v.is_ascii_digit())) + .next() .map(|v| v.split('.').collect()); match split_v { Some(v) => { @@ -2518,8 +2602,8 @@ fn commandline_flag_unit_test_function() { //Test 2 let bindings = crate::builder() .header("input_header") - .whitelist_type("Distinct_Type") - .whitelist_function("safe_function"); + .allowlist_type("Distinct_Type") + .allowlist_function("safe_function"); let command_line_flags = bindings.command_line_flags(); let test_cases = vec![ @@ -2528,9 +2612,9 @@ fn commandline_flag_unit_test_function() { "--no-derive-default", "--generate", "functions,types,vars,methods,constructors,destructors", - "--whitelist-type", + "--allowlist-type", "Distinct_Type", - "--whitelist-function", + "--allowlist-function", "safe_function", ] .iter() diff --git a/src/options.rs b/src/options.rs index f5c61e2..70b7990 100644 --- a/src/options.rs +++ b/src/options.rs @@ -23,7 +23,7 @@ where ); let matches = App::new("bindgen") - .version(Some("0.57.0").unwrap_or("unknown")) + .version(Some("0.58.1").unwrap_or("unknown")) .about("Generates Rust bindings from C/C++ headers.") .usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...") .args(&[ @@ -136,22 +136,25 @@ where .takes_value(true) .multiple(true) .number_of_values(1), - Arg::with_name("blacklist-type") - .long("blacklist-type") + Arg::with_name("blocklist-type") + .alias("blacklist-type") + .long("blocklist-type") .help("Mark <type> as hidden.") .value_name("type") .takes_value(true) .multiple(true) .number_of_values(1), - Arg::with_name("blacklist-function") - .long("blacklist-function") + Arg::with_name("blocklist-function") + .alias("blacklist-function") + .long("blocklist-function") .help("Mark <function> as hidden.") .value_name("function") .takes_value(true) .multiple(true) .number_of_values(1), - Arg::with_name("blacklist-item") - .long("blacklist-item") + Arg::with_name("blocklist-item") + .alias("blacklist-item") + .long("blocklist-item") .help("Mark <item> as hidden.") .value_name("item") .takes_value(true) @@ -210,12 +213,13 @@ where "Avoid including doc comments in the output, see: \ https://github.com/rust-lang/rust-bindgen/issues/426", ), - Arg::with_name("no-recursive-whitelist") - .long("no-recursive-whitelist") + Arg::with_name("no-recursive-allowlist") + .long("no-recursive-allowlist") + .alias("no-recursive-whitelist") .help( - "Disable whitelisting types recursively. This will cause \ + "Disable allowlisting types recursively. This will cause \ bindgen to emit Rust code that won't compile! See the \ - `bindgen::Builder::whitelist_recursively` method's \ + `bindgen::Builder::allowlist_recursively` method's \ documentation for details.", ), Arg::with_name("objc-extern-crate") @@ -364,11 +368,12 @@ where Arg::with_name("use-msvc-mangling") .long("use-msvc-mangling") .help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."), - Arg::with_name("whitelist-function") - .long("whitelist-function") + Arg::with_name("allowlist-function") + .long("allowlist-function") + .alias("whitelist-function") .help( - "Whitelist all the free-standing functions matching \ - <regex>. Other non-whitelisted functions will not be \ + "Allowlist all the free-standing functions matching \ + <regex>. Other non-allowlisted functions will not be \ generated.", ) .value_name("regex") @@ -378,21 +383,23 @@ where Arg::with_name("generate-inline-functions") .long("generate-inline-functions") .help("Generate inline functions."), - Arg::with_name("whitelist-type") - .long("whitelist-type") + Arg::with_name("allowlist-type") + .long("allowlist-type") + .alias("whitelist-type") .help( - "Only generate types matching <regex>. Other non-whitelisted types will \ + "Only generate types matching <regex>. Other non-allowlisted types will \ not be generated.", ) .value_name("regex") .takes_value(true) .multiple(true) .number_of_values(1), - Arg::with_name("whitelist-var") - .long("whitelist-var") + Arg::with_name("allowlist-var") + .long("allowlist-var") + .alias("whitelist-var") .help( - "Whitelist all the free-standing variables matching \ - <regex>. Other non-whitelisted variables will not be \ + "Allowlist all the free-standing variables matching \ + <regex>. Other non-allowlisted variables will not be \ generated.", ) .value_name("regex") @@ -493,9 +500,15 @@ where .long("dynamic-loading") .takes_value(true) .help("Use dynamic loading mode with the given library name."), + Arg::with_name("dynamic-link-require-all") + .long("dynamic-link-require-all") + .help("Require successful linkage to all functions in the library."), Arg::with_name("respect-cxx-access-specs") .long("respect-cxx-access-specs") .help("Makes generated bindings `pub` only for items if the items are publically accessible in C++."), + Arg::with_name("translate-enum-integer-types") + .long("translate-enum-integer-types") + .help("Always translate enum integer types to native Rust integer types."), ]) // .args() .get_matches_from(args); @@ -582,21 +595,21 @@ where } } - if let Some(hidden_types) = matches.values_of("blacklist-type") { + if let Some(hidden_types) = matches.values_of("blocklist-type") { for ty in hidden_types { - builder = builder.blacklist_type(ty); + builder = builder.blocklist_type(ty); } } - if let Some(hidden_functions) = matches.values_of("blacklist-function") { + if let Some(hidden_functions) = matches.values_of("blocklist-function") { for fun in hidden_functions { - builder = builder.blacklist_function(fun); + builder = builder.blocklist_function(fun); } } - if let Some(hidden_identifiers) = matches.values_of("blacklist-item") { + if let Some(hidden_identifiers) = matches.values_of("blocklist-item") { for id in hidden_identifiers { - builder = builder.blacklist_item(id); + builder = builder.blocklist_item(id); } } @@ -758,8 +771,8 @@ where builder = builder.generate_comments(false); } - if matches.is_present("no-recursive-whitelist") { - builder = builder.whitelist_recursively(false); + if matches.is_present("no-recursive-allowlist") { + builder = builder.allowlist_recursively(false); } if matches.is_present("objc-extern-crate") { @@ -809,21 +822,21 @@ where builder = builder.generate_inline_functions(true); } - if let Some(whitelist) = matches.values_of("whitelist-function") { - for regex in whitelist { - builder = builder.whitelist_function(regex); + if let Some(allowlist) = matches.values_of("allowlist-function") { + for regex in allowlist { + builder = builder.allowlist_function(regex); } } - if let Some(whitelist) = matches.values_of("whitelist-type") { - for regex in whitelist { - builder = builder.whitelist_type(regex); + if let Some(allowlist) = matches.values_of("allowlist-type") { + for regex in allowlist { + builder = builder.allowlist_type(regex); } } - if let Some(whitelist) = matches.values_of("whitelist-var") { - for regex in whitelist { - builder = builder.whitelist_var(regex); + if let Some(allowlist) = matches.values_of("allowlist-var") { + for regex in allowlist { + builder = builder.allowlist_var(regex); } } @@ -918,10 +931,18 @@ where builder = builder.dynamic_library_name(dynamic_library_name); } + if matches.is_present("dynamic-link-require-all") { + builder = builder.dynamic_link_require_all(true); + } + if matches.is_present("respect-cxx-access-specs") { builder = builder.respect_cxx_access_specs(true); } + if matches.is_present("translate-enum-integer-types") { + builder = builder.translate_enum_integer_types(true); + } + let verbose = matches.is_present("verbose"); Ok((builder, output, verbose)) |