Snap for 7295815 from c1527f10f53365eb5c66eee3981825faf9f14429 to sc-release

Change-Id: I2eb79d3e1ac5ed08d96c0344e0acdec3693222d0
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"
   }
 }
diff --git a/Android.bp b/Android.bp
index df447b4..305d025 100644
--- a/Android.bp
+++ b/Android.bp
@@ -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 @@
 //   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
diff --git a/Cargo.lock b/Cargo.lock
index 7e09431..7fc4535 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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 @@
 
 [[package]]
 name = "bindgen"
-version = "0.57.0"
+version = "0.58.1"
 dependencies = [
  "bitflags",
  "cexpr",
@@ -247,9 +249,9 @@
 
 [[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"
diff --git a/Cargo.toml b/Cargo.toml
index fdb4a1a..7cf9236 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
 [package]
 edition = "2018"
 name = "bindgen"
-version = "0.57.0"
+version = "0.58.1"
 authors = ["Jyun-Yan You <[email protected]>", "Emilio Cobos Álvarez <[email protected]>", "Nick Fitzgerald <[email protected]>", "The Servo project developers"]
 build = "build.rs"
 include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
@@ -82,7 +82,7 @@
 version = "1.0.1"
 
 [dependencies.shlex]
-version = "0.1"
+version = "1"
 
 [dependencies.which]
 version = "3.0"
@@ -95,7 +95,7 @@
 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 @@
 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 @@
 [dev-dependencies]
 diff = "0.1"
 clap = "2"
-shlex = "0.1"
+shlex = "1"
 
 [dependencies]
 bitflags = "1.0.3"
@@ -56,7 +56,7 @@
 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.
diff --git a/METADATA b/METADATA
index 743cf5b..bed57d2 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   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 @@
 
     /// 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 @@
         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 @@
                     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 @@
         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 @@
             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 @@
     ) -> 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,16 +422,51 @@
     /// 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 Item {
+    fn process_before_codegen(
+        &self,
+        ctx: &BindgenContext,
+        result: &mut CodegenResult,
+    ) -> bool {
+        if !self.is_enabled_for_codegen(ctx) {
+            return false;
+        }
+
+        if self.is_blocklisted(ctx) || result.seen(self.id()) {
+            debug!(
+                "<Item as CodeGenerator>::process_before_codegen: Ignoring hidden or seen: \
+                 self = {:?}",
+                self
+            );
+            return false;
+        }
+
+        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-allowlisted item in code generation: {:?}", self);
+        }
+
+        result.set_seen(self.id());
+        true
+    }
 }
 
 impl CodeGenerator for Item {
     type Extra = ();
+    type Return = ();
 
     fn codegen<'a>(
         &self,
@@ -439,29 +474,11 @@
         result: &mut CodegenResult<'a>,
         _extra: &(),
     ) {
-        if !self.is_enabled_for_codegen(ctx) {
-            return;
-        }
-
-        if self.is_blacklisted(ctx) || result.seen(self.id()) {
-            debug!(
-                "<Item as CodeGenerator>::codegen: Ignoring hidden or seen: \
-                 self = {:?}",
-                self
-            );
-            return;
-        }
-
         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);
+        if !self.process_before_codegen(ctx, result) {
+            return;
         }
 
-        result.set_seen(self.id());
-
         match *self.kind() {
             ItemKind::Module(ref module) => {
                 module.codegen(ctx, result, self);
@@ -481,6 +498,7 @@
 
 impl CodeGenerator for Module {
     type Extra = Item;
+    type Return = ();
 
     fn codegen<'a>(
         &self,
@@ -572,6 +590,8 @@
 
 impl CodeGenerator for Var {
     type Extra = Item;
+    type Return = ();
+
     fn codegen<'a>(
         &self,
         ctx: &BindgenContext,
@@ -698,6 +718,7 @@
 
 impl CodeGenerator for Type {
     type Extra = Item;
+    type Return = ();
 
     fn codegen<'a>(
         &self,
@@ -725,7 +746,7 @@
                 // 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> CodeGenerator for Vtable<'a> {
     type Extra = Item;
+    type Return = ();
 
     fn codegen<'b>(
         &self,
@@ -1048,6 +1070,7 @@
 
 impl CodeGenerator for TemplateInstantiation {
     type Extra = Item;
+    type Return = ();
 
     fn codegen<'a>(
         &self,
@@ -1219,7 +1242,7 @@
         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 @@
             .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 @@
         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 @@
         _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 @@
             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 CodeGenerator for CompInfo {
     type Extra = Item;
+    type Return = ();
 
     fn codegen<'a>(
         &self,
@@ -1768,15 +1790,53 @@
             }
         }
 
-        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 @@
                     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 @@
                     }
                 }
             }
-        } 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 @@
             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 @@
 
         // 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 @@
             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 @@
     /// 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 @@
             },
 
             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 CodeGenerator for Enum {
     type Extra = Item;
+    type Return = ();
 
     fn codegen<'a>(
         &self,
@@ -2815,51 +2853,73 @@
         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 signed = repr.is_signed();
-        let size = layout
-            .map(|l| l.size)
-            .or_else(|| repr.known_size())
-            .unwrap_or(0);
+                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 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"
+                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
+                    }
+                };
+
+                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 @@
             });
         }
 
-        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 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 @@
             FunctionKind::Method(ref method_kind)
                 if method_kind.is_pure_virtual() =>
             {
-                return;
+                return None;
             }
             _ => {}
         }
@@ -3740,7 +3798,7 @@
         // 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 @@
             // 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 @@
             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 @@
             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 @@
                 ident,
                 abi,
                 signature.is_variadic(),
+                ctx.options().dynamic_link_require_all,
                 args,
                 args_identifiers,
                 ret,
@@ -3854,6 +3913,7 @@
         } else {
             result.push(tokens);
         }
+        Some(times_seen)
     }
 }
 
@@ -3909,6 +3969,7 @@
 
 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 @@
     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 @@
     ) -> 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 @@
         }
     }
 
+    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 @@
         // 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 @@
                 }
             }
         }
+        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 @@
 
         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::{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 @@
     }
 
     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 @@
     }
 
     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 @@
     }
 
     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 @@
     }
 
     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 @@
     }
 
     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 @@
     }
 
     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 @@
 {
     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 @@
             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 @@
 
     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 @@
 /// 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 @@
 
     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 @@
             )
     }
 
-    /// 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 @@
     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 @@
             })
             .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 @@
         }
 
         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 @@
             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 @@
             // 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 @@
                         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 @@
     /// 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 @@
             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 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 @@
     /// 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 @@
     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 @@
     >,
 }
 
-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> 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 @@
     where
         R: IntoIterator<Item = ItemId>,
     {
-        WhitelistedItemsTraversal {
+        AllowlistedItemsTraversal {
             ctx,
             traversal: ItemTraversal::new(ctx, roots, predicate),
         }
@@ -559,7 +563,8 @@
             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 @@
     }
 
     /// 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 @@
                 _ => 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 @@
 
         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 @@
 
     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 @@
     /// 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 @@
             "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 @@
         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 @@
         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 @@
                 // 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 @@
                         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 @@
                             }
 
                             // 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 @@
                             }
 
                             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 @@
             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 @@
 
     /// 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 @@
     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 @@
                     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 @@
                             }
                         });
 
-                    let name = ctx
+                    let new_name = ctx
                         .parse_callbacks()
                         .and_then(|callbacks| {
                             callbacks.enum_variant_name(type_name, &name, val)
@@ -130,10 +130,11 @@
                                 .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 @@
         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 @@
     /// 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 @@
     /// 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 @@
         &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 @@
     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 @@
             }
             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 @@
     /// 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 @@
             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 @@
         &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 @@
             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 @@
         }
     }
 
-    /// 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 @@
         );
         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 @@
         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 @@
 /// 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 @@
         // 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 @@
 /// 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 @@
 
 /// 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>,
diff --git a/src/lib.rs b/src/lib.rs
index 65cf66a..d0253db 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -177,8 +177,8 @@
 ///
 /// // 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 @@
             (&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 @@
             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 @@
             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 @@
     }
 
     /// 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 @@
         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 @@
     ///
     /// 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 @@
 
     /// 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 @@
     /// 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 @@
         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)
     }
 
-    /// 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 allowlist_type instead")]
+    pub fn whitelist_type<T: AsRef<str>>(self, arg: T) -> Builder {
+        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.
     ///
-    /// 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 @@
     /// 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 @@
         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 @@
     /// 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 @@
     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 @@
 
     /// 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 @@
     /// 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 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 @@
         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 @@
             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 @@
             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 @@
     /// 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 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 @@
     //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 @@
         "--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 @@
     );
 
     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 @@
                 .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 @@
                     "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 @@
             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 @@
             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 @@
                 .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 @@
         }
     }
 
-    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 @@
         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 @@
         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 @@
         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))