Snap for 9626534 from 9ef47dd699866133fa402d726e57ae06cc0d4c89 to udc-d1-release

Change-Id: Ib8c64eba5736a72714501a849f2f1e49ed59df96
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index f1c8552..32c33e6 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
 {
   "git": {
-    "sha1": "89032649044d875983a851fff6fbde2d4e2ceaeb"
-  }
-}
+    "sha1": "ae6817256ac557981906e93a1f866349db85053e"
+  },
+  "path_in_vcs": "bindgen"
+}
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index ed1a6de..2ec6156 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,7 +1,6 @@
 // This file is generated by cargo2android.py --config cargo2android.json.
 // Do not modify this file as changes will be overridden on upgrade.
 
-
 package {
     default_applicable_licenses: ["external_rust_crates_bindgen_license"],
 }
@@ -43,13 +42,15 @@
     name: "libbindgen",
     crate_name: "bindgen",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.63.0",
+    cargo_pkg_version: "0.64.0",
     srcs: [
         "lib.rs",
         ":copy_bindgen_build_out",
     ],
     edition: "2018",
     features: [
+        "cli",
+        "experimental",
         "runtime",
         "which",
         "which-rustfmt",
@@ -70,8 +71,4 @@
         "libwhich",
     ],
     compile_multilib: "first",
-    apex_available: [
-        "//apex_available:platform",
-        "//apex_available:anyapex",
-    ],
 }
diff --git a/Cargo.toml b/Cargo.toml
index 2fa903a..15868cd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,9 +11,9 @@
 
 [package]
 edition = "2018"
-rust-version = "1.57.0"
+rust-version = "1.60.0"
 name = "bindgen"
-version = "0.63.0"
+version = "0.64.0"
 authors = [
     "Jyun-Yan You <[email protected]>",
     "Emilio Cobos Álvarez <[email protected]>",
@@ -24,7 +24,7 @@
 description = "Automatically generates Rust FFI bindings to C and C++ libraries."
 homepage = "https://rust-lang.github.io/rust-bindgen/"
 documentation = "https://docs.rs/bindgen"
-readme = "README.md"
+readme = "../README.md"
 keywords = [
     "bindings",
     "ffi",
@@ -100,11 +100,13 @@
 default-features = false
 
 [features]
+cli = []
 default = [
     "logging",
     "runtime",
     "which-rustfmt",
 ]
+experimental = []
 logging = ["log"]
 runtime = ["clang-sys/runtime"]
 static = ["clang-sys/static"]
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 6522209..bc53be5 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -14,11 +14,11 @@
 repository = "https://github.com/rust-lang/rust-bindgen"
 documentation = "https://docs.rs/bindgen"
 homepage = "https://rust-lang.github.io/rust-bindgen/"
-version = "0.63.0"
+version = "0.64.0"
 edition = "2018"
 build = "build.rs"
 # If you change this, also update README.md and msrv in .github/workflows/bindgen.yml
-rust-version = "1.57.0"
+rust-version = "1.60.0"
 
 [lib]
 name = "bindgen"
@@ -47,6 +47,8 @@
 runtime = ["clang-sys/runtime"]
 # Dynamically discover a `rustfmt` binary using the `which` crate
 which-rustfmt = ["which"]
+cli = []
+experimental = []
 
 # These features only exist for CI testing -- don't use them if you're not hacking
 # on bindgen!
diff --git a/METADATA b/METADATA
index 7dccd8e..c038164 100644
--- a/METADATA
+++ b/METADATA
@@ -1,3 +1,7 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update rust/crates/bindgen
+# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+
 name: "bindgen"
 description: "Automatically generates Rust FFI bindings to C and C++ libraries."
 third_party {
@@ -7,13 +11,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/bindgen/bindgen-0.63.0.crate"
+    value: "https://static.crates.io/crates/bindgen/bindgen-0.64.0.crate"
   }
-  version: "0.63.0"
+  version: "0.64.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2022
-    month: 12
-    day: 6
+    year: 2023
+    month: 2
+    day: 16
   }
 }
diff --git a/README.md b/README.md
deleted file mode 100644
index c78f00d..0000000
--- a/README.md
+++ /dev/null
@@ -1,85 +0,0 @@
-[![crates.io](https://img.shields.io/crates/v/bindgen.svg)](https://crates.io/crates/bindgen)
-[![docs.rs](https://docs.rs/bindgen/badge.svg)](https://docs.rs/bindgen/)
-
-# `bindgen`
-
-**`bindgen` automatically generates Rust FFI bindings to C (and some C++) libraries.**
-
-For example, given the C header `doggo.h`:
-
-```c
-typedef struct Doggo {
-    int many;
-    char wow;
-} Doggo;
-
-void eleven_out_of_ten_majestic_af(Doggo* pupper);
-```
-
-`bindgen` produces Rust FFI code allowing you to call into the `doggo` library's
-functions and use its types:
-
-```rust
-/* automatically generated by rust-bindgen 0.99.9 */
-
-#[repr(C)]
-pub struct Doggo {
-    pub many: ::std::os::raw::c_int,
-    pub wow: ::std::os::raw::c_char,
-}
-
-extern "C" {
-    pub fn eleven_out_of_ten_majestic_af(pupper: *mut Doggo);
-}
-```
-
-## Users Guide
-
-[📚 Read the `bindgen` users guide here! 📚](https://rust-lang.github.io/rust-bindgen)
-
-## MSRV
-
-The minimum supported Rust version is **1.57.0**.
-
-No MSRV bump policy has been established yet, so MSRV may increase in any release.
-
-The MSRV is the minimum Rust version that can be used to *compile* `bindgen`. However, `bindgen` can generate bindings that are compatible with Rust versions below the current MSRV.
-
-## API Reference
-
-[API reference documentation is on docs.rs](https://docs.rs/bindgen)
-
-## Environment Variables
-
-In addition to the [library API](https://docs.rs/bindgen) and [executable command-line API][bindgen-cmdline],
-`bindgen` can be controlled through environment variables.
-
-End-users should set these environment variables to modify `bindgen`'s behavior without modifying the source code of direct consumers of `bindgen`.
-
-- `BINDGEN_EXTRA_CLANG_ARGS`: extra arguments to pass to `clang`
-    - Arguments are whitespace-separated
-    - Use shell-style quoting to pass through whitespace
-    - Examples:
-        - Specify alternate sysroot: `--sysroot=/path/to/sysroot`
-        - Add include search path with spaces: `-I"/path/with spaces"`
-- `BINDGEN_EXTRA_CLANG_ARGS_<TARGET>`: similar to `BINDGEN_EXTRA_CLANG_ARGS`,
-   but used to set per-target arguments to pass to clang. Useful to set system include
-   directories in a target-specific way in cross-compilation environments with multiple targets.
-   Has precedence over `BINDGEN_EXTRA_CLANG_ARGS`.
-
-Additionally, `bindgen` uses `libclang` to parse C and C++ header files.
-To modify how `bindgen` searches for `libclang`, see the [`clang-sys` documentation][clang-sys-env].
-For more details on how `bindgen` uses `libclang`, see the [`bindgen` users guide][bindgen-book-clang].
-
-## Releases
-
-We don't follow a specific release calendar, but if you need a release please
-file an issue requesting that (ping `@emilio` for increased effectiveness).
-
-## Contributing
-
-[See `CONTRIBUTING.md` for hacking on `bindgen`!](./CONTRIBUTING.md)
-
-[bindgen-cmdline]: https://rust-lang.github.io/rust-bindgen/command-line-usage.html
-[clang-sys-env]: https://github.com/KyleMayes/clang-sys#environment-variables
-[bindgen-book-clang]: https://rust-lang.github.io/rust-bindgen/requirements.html#clang
diff --git a/callbacks.rs b/callbacks.rs
index 5e8ac78..dc20e25 100644
--- a/callbacks.rs
+++ b/callbacks.rs
@@ -25,14 +25,23 @@
 /// A trait to allow configuring different kinds of types in different
 /// situations.
 pub trait ParseCallbacks: fmt::Debug {
+    #[cfg(feature = "cli")]
+    #[doc(hidden)]
+    fn cli_args(&self) -> Vec<String> {
+        vec![]
+    }
+
     /// This function will be run on every macro that is identified.
     fn will_parse_macro(&self, _name: &str) -> MacroParsingBehavior {
         MacroParsingBehavior::Default
     }
 
-    /// This function will run for every function. The returned value determines the name visible
-    /// in the bindings.
-    fn generated_name_override(&self, _function_name: &str) -> Option<String> {
+    /// This function will run for every extern variable and function. The returned value determines
+    /// the name visible in the bindings.
+    fn generated_name_override(
+        &self,
+        _item_info: ItemInfo<'_>,
+    ) -> Option<String> {
         None
     }
 
@@ -117,8 +126,40 @@
 
 /// Relevant information about a type to which new derive attributes will be added using
 /// [`ParseCallbacks::add_derives`].
+#[derive(Debug)]
 #[non_exhaustive]
 pub struct DeriveInfo<'a> {
     /// The name of the type.
     pub name: &'a str,
+    /// The kind of the type.
+    pub kind: TypeKind,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+/// The kind of the current type.
+pub enum TypeKind {
+    /// The type is a Rust `struct`.
+    Struct,
+    /// The type is a Rust `enum`.
+    Enum,
+    /// The type is a Rust `union`.
+    Union,
+}
+
+/// An struct providing information about the item being passed to `ParseCallbacks::generated_name_override`.
+#[non_exhaustive]
+pub struct ItemInfo<'a> {
+    /// The name of the item
+    pub name: &'a str,
+    /// The kind of item
+    pub kind: ItemKind,
+}
+
+/// An enum indicating the kind of item for an ItemInfo.
+#[non_exhaustive]
+pub enum ItemKind {
+    /// A Function
+    Function,
+    /// A Variable
+    Var,
 }
diff --git a/cargo2android.json b/cargo2android.json
index 655ad69..fd62b50 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,6 +1,6 @@
 {
   "copy-out": true,
-  "features": "runtime,which-rustfmt",
+  "features": "cli,experimental,runtime,which-rustfmt",
   "host-first-multilib": true,
   "run": true
 }
diff --git a/codegen/dyngen.rs b/codegen/dyngen.rs
index 5e734cc..d8ea811 100644
--- a/codegen/dyngen.rs
+++ b/codegen/dyngen.rs
@@ -170,7 +170,7 @@
         if !is_variadic {
             self.struct_implementation.push(quote! {
                 #(#attributes)*
-                pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty {
+                pub unsafe fn #ident ( &self, #( #args ),* ) #ret_ty {
                     #call_body
                 }
             });
diff --git a/codegen/mod.rs b/codegen/mod.rs
index e537242..b6fb70e 100644
--- a/codegen/mod.rs
+++ b/codegen/mod.rs
@@ -4,6 +4,7 @@
 mod impl_debug;
 mod impl_partialeq;
 mod postprocessing;
+mod serialize;
 pub mod struct_layout;
 
 #[cfg(test)]
@@ -18,6 +19,7 @@
 
 use super::BindgenOptions;
 
+use crate::callbacks::{DeriveInfo, TypeKind as DeriveTypeKind};
 use crate::ir::analysis::{HasVtable, Sizedness};
 use crate::ir::annotations::FieldAccessorKind;
 use crate::ir::comp::{
@@ -58,6 +60,29 @@
 use std::ops;
 use std::str::FromStr;
 
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum CodegenError {
+    Serialize { msg: String, loc: String },
+    Io(String),
+}
+
+impl From<std::io::Error> for CodegenError {
+    fn from(err: std::io::Error) -> Self {
+        Self::Io(err.to_string())
+    }
+}
+
+impl std::fmt::Display for CodegenError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            CodegenError::Serialize { msg, loc } => {
+                write!(f, "serialization error at {}: {}", loc, msg)
+            }
+            CodegenError::Io(err) => err.fmt(f),
+        }
+    }
+}
+
 // Name of type defined in constified enum module
 pub static CONSTIFIED_ENUM_MODULE_REPR_NAME: &str = "Type";
 
@@ -240,6 +265,8 @@
     /// function name to the number of overloads we have already codegen'd for
     /// that name. This lets us give each overload a unique suffix.
     overload_counters: HashMap<String, u32>,
+
+    items_to_serialize: Vec<ItemId>,
 }
 
 impl<'a> CodegenResult<'a> {
@@ -257,6 +284,7 @@
             functions_seen: Default::default(),
             vars_seen: Default::default(),
             overload_counters: Default::default(),
+            items_to_serialize: Default::default(),
         }
     }
 
@@ -434,10 +462,10 @@
     /// Extra information returned to the caller.
     type Return;
 
-    fn codegen<'a>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         extra: &Self::Extra,
     ) -> Self::Return;
 }
@@ -477,10 +505,10 @@
     type Extra = ();
     type Return = ();
 
-    fn codegen<'a>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         _extra: &(),
     ) {
         debug!("<Item as CodeGenerator>::codegen: self = {:?}", self);
@@ -509,10 +537,10 @@
     type Extra = Item;
     type Return = ();
 
-    fn codegen<'a>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         item: &Item,
     ) {
         debug!("<Module as CodeGenerator>::codegen: item = {:?}", item);
@@ -601,10 +629,10 @@
     type Extra = Item;
     type Return = ();
 
-    fn codegen<'a>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         item: &Item,
     ) {
         use crate::ir::var::VarType;
@@ -748,10 +776,10 @@
     type Extra = Item;
     type Return = ();
 
-    fn codegen<'a>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         item: &Item,
     ) {
         debug!("<Type as CodeGenerator>::codegen: item = {:?}", item);
@@ -1069,10 +1097,10 @@
     type Extra = Item;
     type Return = ();
 
-    fn codegen<'b>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'b>,
+        result: &mut CodegenResult<'_>,
         item: &Item,
     ) {
         assert_eq!(item.id(), self.item_id);
@@ -1168,10 +1196,10 @@
     type Extra = Item;
     type Return = ();
 
-    fn codegen<'a>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         item: &Item,
     ) {
         debug_assert!(item.is_enabled_for_codegen(ctx));
@@ -1796,10 +1824,10 @@
     type Extra = Item;
     type Return = ();
 
-    fn codegen<'a>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         item: &Item,
     ) {
         debug!("<CompInfo as CodeGenerator>::codegen: item = {:?}", item);
@@ -2100,11 +2128,18 @@
         let mut derives: Vec<_> = derivable_traits.into();
         derives.extend(item.annotations().derives().iter().map(String::as_str));
 
+        let is_rust_union = is_union && struct_layout.is_rust_union();
+
         // The custom derives callback may return a list of derive attributes;
         // add them to the end of the list.
         let custom_derives = ctx.options().all_callbacks(|cb| {
-            cb.add_derives(&crate::callbacks::DeriveInfo {
+            cb.add_derives(&DeriveInfo {
                 name: &canonical_name,
+                kind: if is_rust_union {
+                    DeriveTypeKind::Union
+                } else {
+                    DeriveTypeKind::Struct
+                },
             })
         });
         // In most cases this will be a no-op, since custom_derives will be empty.
@@ -2118,7 +2153,7 @@
             attributes.push(attributes::must_use());
         }
 
-        let mut tokens = if is_union && struct_layout.is_rust_union() {
+        let mut tokens = if is_rust_union {
             quote! {
                 #( #attributes )*
                 pub union #canonical_ident
@@ -2193,16 +2228,7 @@
                         })
                     };
 
-                    // FIXME when [issue #465](https://github.com/rust-lang/rust-bindgen/issues/465) ready
-                    let too_many_base_vtables = self
-                        .base_members()
-                        .iter()
-                        .filter(|base| base.ty.has_vtable(ctx))
-                        .count() >
-                        1;
-
-                    let should_skip_field_offset_checks =
-                        is_opaque || too_many_base_vtables;
+                    let should_skip_field_offset_checks = is_opaque;
 
                     let check_field_offset = if should_skip_field_offset_checks
                     {
@@ -2406,24 +2432,13 @@
     }
 }
 
-trait MethodCodegen {
-    fn codegen_method<'a>(
+impl Method {
+    fn codegen_method(
         &self,
         ctx: &BindgenContext,
         methods: &mut Vec<proc_macro2::TokenStream>,
         method_names: &mut HashSet<String>,
-        result: &mut CodegenResult<'a>,
-        parent: &CompInfo,
-    );
-}
-
-impl MethodCodegen for Method {
-    fn codegen_method<'a>(
-        &self,
-        ctx: &BindgenContext,
-        methods: &mut Vec<proc_macro2::TokenStream>,
-        method_names: &mut HashSet<String>,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         _parent: &CompInfo,
     ) {
         assert!({
@@ -2720,6 +2735,7 @@
         mut attrs: Vec<proc_macro2::TokenStream>,
         repr: proc_macro2::TokenStream,
         enum_variation: EnumVariation,
+        has_typedef: bool,
     ) -> Self {
         let ident = Ident::new(name, Span::call_site());
 
@@ -2752,10 +2768,12 @@
             EnumVariation::Consts => {
                 let mut variants = Vec::new();
 
-                variants.push(quote! {
-                    #( #attrs )*
-                    pub type #ident = #repr;
-                });
+                if !has_typedef {
+                    variants.push(quote! {
+                        #( #attrs )*
+                        pub type #ident = #repr;
+                    });
+                }
 
                 EnumBuilder::Consts { variants }
             }
@@ -2779,13 +2797,13 @@
     }
 
     /// Add a variant to this enum.
-    fn with_variant<'b>(
+    fn with_variant(
         self,
         ctx: &BindgenContext,
         variant: &EnumVariant,
         mangling_prefix: Option<&str>,
         rust_ty: proc_macro2::TokenStream,
-        result: &mut CodegenResult<'b>,
+        result: &mut CodegenResult<'_>,
         is_ty_named: bool,
     ) -> Self {
         let variant_name = ctx.rust_mangle(variant.name());
@@ -2896,11 +2914,11 @@
         }
     }
 
-    fn build<'b>(
+    fn build(
         self,
         ctx: &BindgenContext,
         rust_ty: proc_macro2::TokenStream,
-        result: &mut CodegenResult<'b>,
+        result: &mut CodegenResult<'_>,
     ) -> proc_macro2::TokenStream {
         match self {
             EnumBuilder::Rust {
@@ -2999,10 +3017,10 @@
     type Extra = Item;
     type Return = ();
 
-    fn codegen<'a>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         item: &Item,
     ) {
         debug!("<Enum as CodeGenerator>::codegen: item = {:?}", item);
@@ -3129,7 +3147,10 @@
             // The custom derives callback may return a list of derive attributes;
             // add them to the end of the list.
             let custom_derives = ctx.options().all_callbacks(|cb| {
-                cb.add_derives(&crate::callbacks::DeriveInfo { name: &name })
+                cb.add_derives(&DeriveInfo {
+                    name: &name,
+                    kind: DeriveTypeKind::Enum,
+                })
             });
             // In most cases this will be a no-op, since custom_derives will be empty.
             derives.extend(custom_derives.iter().map(|s| s.as_str()));
@@ -3137,7 +3158,7 @@
             attrs.push(attributes::derives(&derives));
         }
 
-        fn add_constant<'a>(
+        fn add_constant(
             ctx: &BindgenContext,
             enum_: &Type,
             // Only to avoid recomputing every time.
@@ -3148,7 +3169,7 @@
             variant_name: &Ident,
             referenced_name: &Ident,
             enum_rust_ty: proc_macro2::TokenStream,
-            result: &mut CodegenResult<'a>,
+            result: &mut CodegenResult<'_>,
         ) {
             let constant_name = if enum_.name().is_some() {
                 if ctx.options().prepend_enum_name {
@@ -3168,8 +3189,10 @@
         }
 
         let repr = repr.to_rust_ty_or_opaque(ctx, item);
+        let has_typedef = ctx.is_enum_typedef_combo(item.id());
 
-        let mut builder = EnumBuilder::new(&name, attrs, repr, variation);
+        let mut builder =
+            EnumBuilder::new(&name, attrs, repr, variation, has_typedef);
 
         // A map where we keep a value -> variant relation.
         let mut seen_values = HashMap::<_, Ident>::default();
@@ -3995,20 +4018,25 @@
     /// it.
     type Return = Option<u32>;
 
-    fn codegen<'a>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         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 None,
-            Linkage::External => {}
+        let is_internal = matches!(self.linkage(), Linkage::Internal);
+
+        if is_internal {
+            if ctx.options().wrap_static_fns {
+                result.items_to_serialize.push(item.id());
+            } else {
+                // We can't do anything with Internal functions if we are not wrapping them so just
+                // avoid generating anything for them.
+                return None;
+            }
         }
 
         // Pure virtual methods have no actual symbol, so we can't generate
@@ -4118,6 +4146,7 @@
             write!(&mut canonical_name, "{}", times_seen).unwrap();
         }
 
+        let mut has_link_name_attr = false;
         let link_name = mangled_name.unwrap_or(name);
         if !is_dynamic_function &&
             !utils::names_will_be_identical_after_mangling(
@@ -4127,6 +4156,7 @@
             )
         {
             attributes.push(attributes::link_name(link_name));
+            has_link_name_attr = true;
         }
 
         // Unfortunately this can't piggyback on the `attributes` list because
@@ -4137,6 +4167,11 @@
                 quote! { #[link(wasm_import_module = #name)] }
             });
 
+        if is_internal && ctx.options().wrap_static_fns && !has_link_name_attr {
+            let name = canonical_name.clone() + ctx.wrap_static_fns_suffix();
+            attributes.push(attributes::link_name(&name));
+        }
+
         let ident = ctx.rust_ident(canonical_name);
         let tokens = quote! {
             #wasm_link_attribute
@@ -4150,11 +4185,7 @@
         if is_dynamic_function {
             let args_identifiers =
                 utils::fnsig_argument_identifiers(ctx, signature);
-            let return_item = ctx.resolve_item(signature.return_type());
-            let ret_ty = match *return_item.kind().expect_type().kind() {
-                TypeKind::Void => quote! {()},
-                _ => return_item.to_rust_ty_or_opaque(ctx, &()),
-            };
+            let ret_ty = utils::fnsig_return_ty(ctx, signature);
             result.dynamic_items().push(
                 ident,
                 abi,
@@ -4237,10 +4268,10 @@
     type Extra = Item;
     type Return = ();
 
-    fn codegen<'a>(
+    fn codegen(
         &self,
         ctx: &BindgenContext,
-        result: &mut CodegenResult<'a>,
+        result: &mut CodegenResult<'_>,
         item: &Item,
     ) {
         debug_assert!(item.is_enabled_for_codegen(ctx));
@@ -4445,7 +4476,8 @@
 
 pub(crate) fn codegen(
     context: BindgenContext,
-) -> (proc_macro2::TokenStream, BindgenOptions, Vec<String>) {
+) -> Result<(proc_macro2::TokenStream, BindgenOptions, Vec<String>), CodegenError>
+{
     context.gen(|context| {
         let _t = context.timer("codegen");
         let counter = Cell::new(0);
@@ -4495,21 +4527,73 @@
             result.push(dynamic_items_tokens);
         }
 
-        postprocessing::postprocessing(result.items, context.options())
+        utils::serialize_items(&result, context)?;
+
+        Ok(postprocessing::postprocessing(
+            result.items,
+            context.options(),
+        ))
     })
 }
 
 pub mod utils {
-    use super::{error, ToRustTyOrOpaque};
+    use super::serialize::CSerialize;
+    use super::{error, CodegenError, CodegenResult, ToRustTyOrOpaque};
     use crate::ir::context::BindgenContext;
     use crate::ir::function::{Abi, ClangAbi, FunctionSig};
     use crate::ir::item::{Item, ItemCanonicalPath};
     use crate::ir::ty::TypeKind;
+    use crate::{args_are_cpp, file_is_cpp};
     use proc_macro2;
     use std::borrow::Cow;
     use std::mem;
+    use std::path::PathBuf;
     use std::str::FromStr;
 
+    pub(super) fn serialize_items(
+        result: &CodegenResult,
+        context: &BindgenContext,
+    ) -> Result<(), CodegenError> {
+        if result.items_to_serialize.is_empty() {
+            return Ok(());
+        }
+
+        let path = context
+            .options()
+            .wrap_static_fns_path
+            .as_ref()
+            .map(PathBuf::from)
+            .unwrap_or_else(|| {
+                std::env::temp_dir().join("bindgen").join("extern")
+            });
+
+        let dir = path.parent().unwrap();
+
+        if !dir.exists() {
+            std::fs::create_dir_all(&dir)?;
+        }
+
+        let is_cpp = args_are_cpp(&context.options().clang_args) ||
+            context
+                .options()
+                .input_headers
+                .iter()
+                .any(|h| file_is_cpp(h));
+
+        let source_path = path.with_extension(if is_cpp { "cpp" } else { "c" });
+
+        let mut code = Vec::new();
+
+        for &id in &result.items_to_serialize {
+            let item = context.resolve_item(id);
+            item.serialize(context, (), &mut vec![], &mut code)?;
+        }
+
+        std::fs::write(source_path, code)?;
+
+        Ok(())
+    }
+
     pub fn prepend_bitfield_unit_type(
         ctx: &BindgenContext,
         result: &mut Vec<proc_macro2::TokenStream>,
@@ -4826,23 +4910,50 @@
         })
     }
 
+    fn fnsig_return_ty_internal(
+        ctx: &BindgenContext,
+        sig: &FunctionSig,
+        include_arrow: bool,
+    ) -> proc_macro2::TokenStream {
+        if sig.is_divergent() {
+            return if include_arrow {
+                quote! { -> ! }
+            } else {
+                quote! { ! }
+            };
+        }
+
+        let canonical_type_kind = sig
+            .return_type()
+            .into_resolver()
+            .through_type_refs()
+            .through_type_aliases()
+            .resolve(ctx)
+            .kind()
+            .expect_type()
+            .kind();
+
+        if let TypeKind::Void = canonical_type_kind {
+            return if include_arrow {
+                quote! {}
+            } else {
+                quote! { () }
+            };
+        }
+
+        let ret_ty = sig.return_type().to_rust_ty_or_opaque(ctx, &());
+        if include_arrow {
+            quote! { -> #ret_ty }
+        } else {
+            ret_ty
+        }
+    }
+
     pub fn fnsig_return_ty(
         ctx: &BindgenContext,
         sig: &FunctionSig,
     ) -> proc_macro2::TokenStream {
-        if sig.is_divergent() {
-            return quote! { -> ! };
-        }
-
-        let return_item = ctx.resolve_item(sig.return_type());
-        if let TypeKind::Void = *return_item.kind().expect_type().kind() {
-            quote! {}
-        } else {
-            let ret_ty = return_item.to_rust_ty_or_opaque(ctx, &());
-            quote! {
-                -> #ret_ty
-            }
-        }
+        fnsig_return_ty_internal(ctx, sig, /* include_arrow = */ true)
     }
 
     pub fn fnsig_arguments(
@@ -4957,14 +5068,9 @@
             arg_item.to_rust_ty_or_opaque(ctx, &())
         });
 
-        let return_item = ctx.resolve_item(sig.return_type());
-        let ret_ty =
-            if let TypeKind::Void = *return_item.kind().expect_type().kind() {
-                quote! { () }
-            } else {
-                return_item.to_rust_ty_or_opaque(ctx, &())
-            };
-
+        let ret_ty = fnsig_return_ty_internal(
+            ctx, sig, /* include_arrow = */ false,
+        );
         quote! {
             *const ::block::Block<(#(#args,)*), #ret_ty>
         }
diff --git a/codegen/serialize.rs b/codegen/serialize.rs
new file mode 100644
index 0000000..217098e
--- /dev/null
+++ b/codegen/serialize.rs
@@ -0,0 +1,356 @@
+use std::io::Write;
+
+use crate::callbacks::IntKind;
+
+use crate::ir::comp::CompKind;
+use crate::ir::context::{BindgenContext, TypeId};
+use crate::ir::function::{Function, FunctionKind};
+use crate::ir::item::Item;
+use crate::ir::item::ItemCanonicalName;
+use crate::ir::item_kind::ItemKind;
+use crate::ir::ty::{FloatKind, Type, TypeKind};
+
+use super::CodegenError;
+
+fn get_loc(item: &Item) -> String {
+    item.location()
+        .map(|x| x.to_string())
+        .unwrap_or_else(|| "unknown".to_owned())
+}
+
+pub(crate) trait CSerialize<'a> {
+    type Extra;
+
+    fn serialize<W: Write>(
+        &self,
+        ctx: &BindgenContext,
+        extra: Self::Extra,
+        stack: &mut Vec<String>,
+        writer: &mut W,
+    ) -> Result<(), CodegenError>;
+}
+
+impl<'a> CSerialize<'a> for Item {
+    type Extra = ();
+
+    fn serialize<W: Write>(
+        &self,
+        ctx: &BindgenContext,
+        (): Self::Extra,
+        stack: &mut Vec<String>,
+        writer: &mut W,
+    ) -> Result<(), CodegenError> {
+        match self.kind() {
+            ItemKind::Function(func) => {
+                func.serialize(ctx, self, stack, writer)
+            }
+            kind => {
+                return Err(CodegenError::Serialize {
+                    msg: format!("Cannot serialize item kind {:?}", kind),
+                    loc: get_loc(self),
+                });
+            }
+        }
+    }
+}
+
+impl<'a> CSerialize<'a> for Function {
+    type Extra = &'a Item;
+
+    fn serialize<W: Write>(
+        &self,
+        ctx: &BindgenContext,
+        item: Self::Extra,
+        stack: &mut Vec<String>,
+        writer: &mut W,
+    ) -> Result<(), CodegenError> {
+        if self.kind() != FunctionKind::Function {
+            return Err(CodegenError::Serialize {
+                msg: format!(
+                    "Cannot serialize function kind {:?}",
+                    self.kind(),
+                ),
+                loc: get_loc(item),
+            });
+        }
+
+        let signature = match ctx.resolve_type(self.signature()).kind() {
+            TypeKind::Function(signature) => signature,
+            _ => unreachable!(),
+        };
+
+        let name = self.name();
+
+        // Function argoments stored as `(name, type_id)` tuples.
+        let args = {
+            let mut count = 0;
+
+            signature
+                .argument_types()
+                .iter()
+                .cloned()
+                .map(|(opt_name, type_id)| {
+                    (
+                        opt_name.unwrap_or_else(|| {
+                            let name = format!("arg_{}", count);
+                            count += 1;
+                            name
+                        }),
+                        type_id,
+                    )
+                })
+                .collect::<Vec<_>>()
+        };
+
+        // The name used for the wrapper self.
+        let wrap_name = format!("{}{}", name, ctx.wrap_static_fns_suffix());
+        // The function's return type
+        let ret_ty = signature.return_type();
+
+        // Write `ret_ty wrap_name(args) asm("wrap_name");`
+        ret_ty.serialize(ctx, (), stack, writer)?;
+        write!(writer, " {}(", wrap_name)?;
+        if args.is_empty() {
+            write!(writer, "void")?;
+        } else {
+            serialize_sep(
+                ", ",
+                args.iter(),
+                ctx,
+                writer,
+                |(name, type_id), ctx, buf| {
+                    type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
+                },
+            )?;
+        }
+        writeln!(writer, ") asm(\"{}\");", wrap_name)?;
+
+        // Write `ret_ty wrap_name(args) { return name(arg_names)' }`
+        ret_ty.serialize(ctx, (), stack, writer)?;
+        write!(writer, " {}(", wrap_name)?;
+        serialize_sep(
+            ", ",
+            args.iter(),
+            ctx,
+            writer,
+            |(name, type_id), _, buf| {
+                type_id.serialize(ctx, (), &mut vec![name.clone()], buf)
+            },
+        )?;
+        write!(writer, ") {{ return {}(", name)?;
+        serialize_sep(", ", args.iter(), ctx, writer, |(name, _), _, buf| {
+            write!(buf, "{}", name).map_err(From::from)
+        })?;
+        writeln!(writer, "); }}")?;
+
+        Ok(())
+    }
+}
+
+impl<'a> CSerialize<'a> for TypeId {
+    type Extra = ();
+
+    fn serialize<W: Write>(
+        &self,
+        ctx: &BindgenContext,
+        (): Self::Extra,
+        stack: &mut Vec<String>,
+        writer: &mut W,
+    ) -> Result<(), CodegenError> {
+        let item = ctx.resolve_item(*self);
+        item.expect_type().serialize(ctx, item, stack, writer)
+    }
+}
+
+impl<'a> CSerialize<'a> for Type {
+    type Extra = &'a Item;
+
+    fn serialize<W: Write>(
+        &self,
+        ctx: &BindgenContext,
+        item: Self::Extra,
+        stack: &mut Vec<String>,
+        writer: &mut W,
+    ) -> Result<(), CodegenError> {
+        match self.kind() {
+            TypeKind::Void => {
+                if self.is_const() {
+                    write!(writer, "const ")?;
+                }
+                write!(writer, "void")?
+            }
+            TypeKind::NullPtr => {
+                if self.is_const() {
+                    write!(writer, "const ")?;
+                }
+                write!(writer, "nullptr_t")?
+            }
+            TypeKind::Int(int_kind) => {
+                if self.is_const() {
+                    write!(writer, "const ")?;
+                }
+                match int_kind {
+                    IntKind::Bool => write!(writer, "bool")?,
+                    IntKind::SChar => write!(writer, "signed char")?,
+                    IntKind::UChar => write!(writer, "unsigned char")?,
+                    IntKind::WChar => write!(writer, "wchar_t")?,
+                    IntKind::Short => write!(writer, "short")?,
+                    IntKind::UShort => write!(writer, "unsigned short")?,
+                    IntKind::Int => write!(writer, "int")?,
+                    IntKind::UInt => write!(writer, "unsigned int")?,
+                    IntKind::Long => write!(writer, "long")?,
+                    IntKind::ULong => write!(writer, "unsigned long")?,
+                    IntKind::LongLong => write!(writer, "long long")?,
+                    IntKind::ULongLong => write!(writer, "unsigned long long")?,
+                    IntKind::Char { .. } => write!(writer, "char")?,
+                    int_kind => {
+                        return Err(CodegenError::Serialize {
+                            msg: format!(
+                                "Cannot serialize integer kind {:?}",
+                                int_kind
+                            ),
+                            loc: get_loc(item),
+                        })
+                    }
+                }
+            }
+            TypeKind::Float(float_kind) => {
+                if self.is_const() {
+                    write!(writer, "const ")?;
+                }
+                match float_kind {
+                    FloatKind::Float => write!(writer, "float")?,
+                    FloatKind::Double => write!(writer, "double")?,
+                    FloatKind::LongDouble => write!(writer, "long double")?,
+                    FloatKind::Float128 => write!(writer, "__float128")?,
+                }
+            }
+            TypeKind::Complex(float_kind) => {
+                if self.is_const() {
+                    write!(writer, "const ")?;
+                }
+                match float_kind {
+                    FloatKind::Float => write!(writer, "float complex")?,
+                    FloatKind::Double => write!(writer, "double complex")?,
+                    FloatKind::LongDouble => {
+                        write!(writer, "long double complex")?
+                    }
+                    FloatKind::Float128 => write!(writer, "__complex128")?,
+                }
+            }
+            TypeKind::Alias(type_id) => {
+                if let Some(name) = self.name() {
+                    if self.is_const() {
+                        write!(writer, "const {}", name)?;
+                    } else {
+                        write!(writer, "{}", name)?;
+                    }
+                } else {
+                    type_id.serialize(ctx, (), stack, writer)?;
+                }
+            }
+            TypeKind::Array(type_id, length) => {
+                type_id.serialize(ctx, (), stack, writer)?;
+                write!(writer, " [{}]", length)?
+            }
+            TypeKind::Function(signature) => {
+                if self.is_const() {
+                    stack.push("const ".to_string());
+                }
+
+                signature.return_type().serialize(
+                    ctx,
+                    (),
+                    &mut vec![],
+                    writer,
+                )?;
+
+                write!(writer, " (")?;
+                while let Some(item) = stack.pop() {
+                    write!(writer, "{}", item)?;
+                }
+                write!(writer, ")")?;
+
+                write!(writer, " (")?;
+                serialize_sep(
+                    ", ",
+                    signature.argument_types().iter(),
+                    ctx,
+                    writer,
+                    |(name, type_id), ctx, buf| {
+                        let mut stack = vec![];
+                        if let Some(name) = name {
+                            stack.push(name.clone());
+                        }
+                        type_id.serialize(ctx, (), &mut stack, buf)
+                    },
+                )?;
+                write!(writer, ")")?
+            }
+            TypeKind::ResolvedTypeRef(type_id) => {
+                if self.is_const() {
+                    write!(writer, "const ")?;
+                }
+                type_id.serialize(ctx, (), stack, writer)?
+            }
+            TypeKind::Pointer(type_id) => {
+                if self.is_const() {
+                    stack.push("*const ".to_owned());
+                } else {
+                    stack.push("*".to_owned());
+                }
+                type_id.serialize(ctx, (), stack, writer)?
+            }
+            TypeKind::Comp(comp_info) => {
+                if self.is_const() {
+                    write!(writer, "const ")?;
+                }
+
+                let name = item.canonical_name(ctx);
+
+                match comp_info.kind() {
+                    CompKind::Struct => write!(writer, "struct {}", name)?,
+                    CompKind::Union => write!(writer, "union {}", name)?,
+                };
+            }
+            ty => {
+                return Err(CodegenError::Serialize {
+                    msg: format!("Cannot serialize type kind {:?}", ty),
+                    loc: get_loc(item),
+                })
+            }
+        };
+
+        if !stack.is_empty() {
+            write!(writer, " ")?;
+            while let Some(item) = stack.pop() {
+                write!(writer, "{}", item)?;
+            }
+        }
+
+        Ok(())
+    }
+}
+
+fn serialize_sep<
+    W: Write,
+    F: FnMut(I::Item, &BindgenContext, &mut W) -> Result<(), CodegenError>,
+    I: Iterator,
+>(
+    sep: &str,
+    mut iter: I,
+    ctx: &BindgenContext,
+    buf: &mut W,
+    mut f: F,
+) -> Result<(), CodegenError> {
+    if let Some(item) = iter.next() {
+        f(item, ctx, buf)?;
+        let sep = sep.as_bytes();
+        for item in iter {
+            buf.write_all(sep)?;
+            f(item, ctx, buf)?;
+        }
+    }
+
+    Ok(())
+}
diff --git a/ir/analysis/template_params.rs b/ir/analysis/template_params.rs
index e88b774..f4f0c59 100644
--- a/ir/analysis/template_params.rs
+++ b/ir/analysis/template_params.rs
@@ -424,8 +424,7 @@
             // generic template parameters are used.
             let item_kind =
                 ctx.resolve_item(item).as_type().map(|ty| ty.kind());
-            if let Some(&TypeKind::TemplateInstantiation(ref inst)) = item_kind
-            {
+            if let Some(TypeKind::TemplateInstantiation(inst)) = item_kind {
                 let decl = ctx.resolve_type(inst.template_definition());
                 let args = inst.template_arguments();
 
@@ -540,7 +539,7 @@
             }
             // Template instantiations only use their template arguments if the
             // template definition uses the corresponding template parameter.
-            Some(&TypeKind::TemplateInstantiation(ref inst)) => {
+            Some(TypeKind::TemplateInstantiation(inst)) => {
                 if self
                     .allowlisted_items
                     .contains(&inst.template_definition().into())
diff --git a/ir/comp.rs b/ir/comp.rs
index 039742a..18a4291 100644
--- a/ir/comp.rs
+++ b/ir/comp.rs
@@ -12,7 +12,7 @@
 use crate::clang;
 use crate::codegen::struct_layout::{align_to, bytes_from_bits_pow2};
 use crate::ir::derive::CanDeriveCopy;
-use crate::parse::{ClangItemParser, ParseError};
+use crate::parse::ParseError;
 use crate::HashMap;
 use crate::NonCopyUnionStyle;
 use peeking_take_while::PeekableExt;
diff --git a/ir/context.rs b/ir/context.rs
index 4623b25..b693a70 100644
--- a/ir/context.rs
+++ b/ir/context.rs
@@ -20,7 +20,7 @@
 use super::traversal::{self, Edge, ItemTraversal};
 use super::ty::{FloatKind, Type, TypeKind};
 use crate::clang::{self, Cursor};
-use crate::parse::ClangItemParser;
+use crate::codegen::CodegenError;
 use crate::BindgenOptions;
 use crate::{Entry, HashMap, HashSet};
 use cexpr;
@@ -399,6 +399,22 @@
     /// bitfield allocation units computed. Drained in `compute_bitfield_units`.
     need_bitfield_allocation: Vec<ItemId>,
 
+    /// The set of enums that are defined by a pair of `enum` and `typedef`,
+    /// which is legal in C (but not C++).
+    ///
+    /// ```c++
+    /// // in either order
+    /// enum Enum { Variants... };
+    /// typedef int16_t Enum;
+    /// ```
+    ///
+    /// The stored `ItemId` is that of the `TypeKind::Enum`, not of the
+    /// `TypeKind::Alias`.
+    ///
+    /// This is populated when we enter codegen by `compute_enum_typedef_combos`
+    /// and is always `None` before that and `Some` after.
+    enum_typedef_combos: Option<HashSet<ItemId>>,
+
     /// The set of (`ItemId`s of) types that can't derive debug.
     ///
     /// This is populated when we enter codegen by `compute_cannot_derive_debug`
@@ -566,6 +582,7 @@
             codegen_items: None,
             used_template_parameters: None,
             need_bitfield_allocation: Default::default(),
+            enum_typedef_combos: None,
             cannot_derive_debug: None,
             cannot_derive_default: None,
             cannot_derive_copy: None,
@@ -1130,9 +1147,9 @@
     pub(crate) fn gen<F, Out>(
         mut self,
         cb: F,
-    ) -> (Out, BindgenOptions, Vec<String>)
+    ) -> Result<(Out, BindgenOptions, Vec<String>), CodegenError>
     where
-        F: FnOnce(&Self) -> Out,
+        F: FnOnce(&Self) -> Result<Out, CodegenError>,
     {
         self.in_codegen = true;
 
@@ -1158,6 +1175,7 @@
         self.compute_sizedness();
         self.compute_has_destructor();
         self.find_used_template_parameters();
+        self.compute_enum_typedef_combos();
         self.compute_cannot_derive_debug();
         self.compute_cannot_derive_default();
         self.compute_cannot_derive_copy();
@@ -1166,8 +1184,8 @@
         self.compute_cannot_derive_hash();
         self.compute_cannot_derive_partialord_partialeq_or_eq();
 
-        let ret = cb(&self);
-        (ret, self.options, self.warnings)
+        let ret = cb(&self)?;
+        Ok((ret, self.options, self.warnings))
     }
 
     /// When the `testing_only_extra_assertions` feature is enabled, this
@@ -2477,6 +2495,70 @@
         self.generated_bindgen_complex.get()
     }
 
+    /// Compute which `enum`s have an associated `typedef` definition.
+    fn compute_enum_typedef_combos(&mut self) {
+        let _t = self.timer("compute_enum_typedef_combos");
+        assert!(self.enum_typedef_combos.is_none());
+
+        let mut enum_typedef_combos = HashSet::default();
+        for item in &self.items {
+            if let Some(ItemKind::Module(module)) =
+                item.as_ref().map(Item::kind)
+            {
+                // Find typedefs in this module, and build set of their names.
+                let mut names_of_typedefs = HashSet::default();
+                for child_id in module.children() {
+                    if let Some(ItemKind::Type(ty)) =
+                        self.items[child_id.0].as_ref().map(Item::kind)
+                    {
+                        if let (Some(name), TypeKind::Alias(type_id)) =
+                            (ty.name(), ty.kind())
+                        {
+                            // We disregard aliases that refer to the enum
+                            // itself, such as in `typedef enum { ... } Enum;`.
+                            if type_id
+                                .into_resolver()
+                                .through_type_refs()
+                                .through_type_aliases()
+                                .resolve(self)
+                                .expect_type()
+                                .is_int()
+                            {
+                                names_of_typedefs.insert(name);
+                            }
+                        }
+                    }
+                }
+
+                // Find enums in this module, and record the id of each one that
+                // has a typedef.
+                for child_id in module.children() {
+                    if let Some(ItemKind::Type(ty)) =
+                        self.items[child_id.0].as_ref().map(Item::kind)
+                    {
+                        if let (Some(name), true) = (ty.name(), ty.is_enum()) {
+                            if names_of_typedefs.contains(name) {
+                                enum_typedef_combos.insert(*child_id);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        self.enum_typedef_combos = Some(enum_typedef_combos);
+    }
+
+    /// Look up whether `id` refers to an `enum` whose underlying type is
+    /// defined by a `typedef`.
+    pub fn is_enum_typedef_combo(&self, id: ItemId) -> bool {
+        assert!(
+            self.in_codegen_phase(),
+            "We only compute enum_typedef_combos when we enter codegen",
+        );
+        self.enum_typedef_combos.as_ref().unwrap().contains(&id)
+    }
+
     /// Compute whether we can derive debug.
     fn compute_cannot_derive_debug(&mut self) {
         let _t = self.timer("compute_cannot_derive_debug");
@@ -2711,6 +2793,13 @@
             tokens.into_token_stream()
         }
     }
+
+    pub(crate) fn wrap_static_fns_suffix(&self) -> &str {
+        self.options()
+            .wrap_static_fns_suffix
+            .as_deref()
+            .unwrap_or(crate::DEFAULT_NON_EXTERN_FNS_SUFFIX)
+    }
 }
 
 /// A builder struct for configuring item resolution options.
diff --git a/ir/enum_ty.rs b/ir/enum_ty.rs
index 39677e9..63871fd 100644
--- a/ir/enum_ty.rs
+++ b/ir/enum_ty.rs
@@ -6,7 +6,7 @@
 use super::ty::{Type, TypeKind};
 use crate::clang;
 use crate::ir::annotations::Annotations;
-use crate::parse::{ClangItemParser, ParseError};
+use crate::parse::ParseError;
 use crate::regex_set::RegexSet;
 
 /// An enum representing custom handling that can be given to a variant.
diff --git a/ir/function.rs b/ir/function.rs
index 7dbbb8f..baa2c36 100644
--- a/ir/function.rs
+++ b/ir/function.rs
@@ -6,10 +6,9 @@
 use super::item::Item;
 use super::traversal::{EdgeKind, Trace, Tracer};
 use super::ty::TypeKind;
+use crate::callbacks::{ItemInfo, ItemKind};
 use crate::clang::{self, Attribute};
-use crate::parse::{
-    ClangItemParser, ClangSubItemParser, ParseError, ParseResult,
-};
+use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
 use clang_sys::{self, CXCallingConv};
 use proc_macro2;
 use quote;
@@ -665,7 +664,6 @@
         };
 
         debug!("Function::parse({:?}, {:?})", cursor, cursor.cur_type());
-
         let visibility = cursor.visibility();
         if visibility != CXVisibility_Default {
             return Err(ParseError::Continue);
@@ -675,19 +673,6 @@
             return Err(ParseError::Continue);
         }
 
-        if cursor.is_inlined_function() ||
-            cursor
-                .definition()
-                .map_or(false, |x| x.is_inlined_function())
-        {
-            if !context.options().generate_inline_functions {
-                return Err(ParseError::Continue);
-            }
-            if cursor.is_deleted_function() {
-                return Err(ParseError::Continue);
-            }
-        }
-
         let linkage = cursor.linkage();
         let linkage = match linkage {
             CXLinkage_External | CXLinkage_UniqueExternal => Linkage::External,
@@ -695,6 +680,30 @@
             _ => return Err(ParseError::Continue),
         };
 
+        if cursor.is_inlined_function() ||
+            cursor
+                .definition()
+                .map_or(false, |x| x.is_inlined_function())
+        {
+            if !context.options().generate_inline_functions &&
+                !context.options().wrap_static_fns
+            {
+                return Err(ParseError::Continue);
+            }
+
+            if cursor.is_deleted_function() {
+                return Err(ParseError::Continue);
+            }
+
+            // We cannot handle `inline` functions that are not `static`.
+            if context.options().wrap_static_fns &&
+                cursor.is_inlined_function() &&
+                matches!(linkage, Linkage::External)
+            {
+                return Err(ParseError::Continue);
+            }
+        }
+
         // Grab the signature using Item::from_ty.
         let sig = Item::from_ty(&cursor.cur_type(), cursor, None, context)?;
 
@@ -714,10 +723,12 @@
             // but seems easy enough to handle it here.
             name.push_str("_destructor");
         }
-        if let Some(nm) = context
-            .options()
-            .last_callback(|callbacks| callbacks.generated_name_override(&name))
-        {
+        if let Some(nm) = context.options().last_callback(|callbacks| {
+            callbacks.generated_name_override(ItemInfo {
+                name: name.as_str(),
+                kind: ItemKind::Function,
+            })
+        }) {
             name = nm;
         }
         assert!(!name.is_empty(), "Empty function name.");
@@ -726,7 +737,8 @@
         let comment = cursor.raw_comment();
 
         let function =
-            Self::new(name, mangled_name, sig, comment, kind, linkage);
+            Self::new(name.clone(), mangled_name, sig, comment, kind, linkage);
+
         Ok(ParseResult::New(function, Some(cursor)))
     }
 }
diff --git a/ir/item.rs b/ir/item.rs
index 5e9aff9..40f6f7d 100644
--- a/ir/item.rs
+++ b/ir/item.rs
@@ -18,9 +18,7 @@
 use super::traversal::{EdgeKind, Trace, Tracer};
 use super::ty::{Type, TypeKind};
 use crate::clang;
-use crate::parse::{
-    ClangItemParser, ClangSubItemParser, ParseError, ParseResult,
-};
+use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
 use clang_sys;
 use lazycell::LazyCell;
 use regex;
@@ -1307,8 +1305,8 @@
     }
 }
 
-impl ClangItemParser for Item {
-    fn builtin_type(
+impl Item {
+    pub(crate) fn builtin_type(
         kind: TypeKind,
         is_const: bool,
         ctx: &mut BindgenContext,
@@ -1333,7 +1331,7 @@
         id.as_type_id_unchecked()
     }
 
-    fn parse(
+    pub(crate) fn parse(
         cursor: clang::Cursor,
         parent_id: Option<ItemId>,
         ctx: &mut BindgenContext,
@@ -1479,7 +1477,7 @@
         }
     }
 
-    fn from_ty_or_ref(
+    pub(crate) fn from_ty_or_ref(
         ty: clang::Type,
         location: clang::Cursor,
         parent_id: Option<ItemId>,
@@ -1499,7 +1497,7 @@
     ///
     /// Typerefs are resolved once parsing is completely done, see
     /// `BindgenContext::resolve_typerefs`.
-    fn from_ty_or_ref_with_id(
+    pub(crate) fn from_ty_or_ref_with_id(
         potential_id: ItemId,
         ty: clang::Type,
         location: clang::Cursor,
@@ -1554,7 +1552,7 @@
         potential_id.as_type_id_unchecked()
     }
 
-    fn from_ty(
+    pub(crate) fn from_ty(
         ty: &clang::Type,
         location: clang::Cursor,
         parent_id: Option<ItemId>,
@@ -1572,7 +1570,7 @@
     /// critical some times to obtain information, an optional parent item id,
     /// that will, if it's `None`, become the current module id, and the
     /// context.
-    fn from_ty_with_id(
+    pub(crate) fn from_ty_with_id(
         id: ItemId,
         ty: &clang::Type,
         location: clang::Cursor,
@@ -1742,7 +1740,7 @@
     /// A named type is a template parameter, e.g., the "T" in Foo<T>. They're
     /// always local so it's the only exception when there's no declaration for
     /// a type.
-    fn type_param(
+    pub(crate) fn type_param(
         with_id: Option<ItemId>,
         location: clang::Cursor,
         ctx: &mut BindgenContext,
diff --git a/ir/objc.rs b/ir/objc.rs
index 0845ad0..4f340f6 100644
--- a/ir/objc.rs
+++ b/ir/objc.rs
@@ -6,7 +6,6 @@
 use super::traversal::{Trace, Tracer};
 use super::ty::TypeKind;
 use crate::clang;
-use crate::parse::ClangItemParser;
 use clang_sys::CXChildVisit_Continue;
 use clang_sys::CXCursor_ObjCCategoryDecl;
 use clang_sys::CXCursor_ObjCClassMethodDecl;
@@ -261,7 +260,17 @@
                 if name.is_empty() {
                     None
                 } else {
-                    Some(Ident::new(name, Span::call_site()))
+                    // Try to parse the current name as an identifier. This might fail if the
+                    // name is a keyword so we try to prepend "r#" to it and parse again. If
+                    // this also fails, we panic with the first error.
+                    Some(
+                        syn::parse_str::<Ident>(name)
+                            .or_else(|err| {
+                                syn::parse_str::<Ident>(&format!("r#{}", name))
+                                    .map_err(|_| err)
+                            })
+                            .expect("Invalid identifier"),
+                    )
                 }
             })
             .collect();
diff --git a/ir/template.rs b/ir/template.rs
index 8b06748..e3ef6a9 100644
--- a/ir/template.rs
+++ b/ir/template.rs
@@ -31,7 +31,6 @@
 use super::item::{IsOpaque, Item, ItemAncestors};
 use super::traversal::{EdgeKind, Trace, Tracer};
 use crate::clang;
-use crate::parse::ClangItemParser;
 
 /// Template declaration (and such declaration's template parameters) related
 /// methods.
diff --git a/ir/ty.rs b/ir/ty.rs
index fd6108f..fef340d 100644
--- a/ir/ty.rs
+++ b/ir/ty.rs
@@ -14,7 +14,7 @@
 };
 use super::traversal::{EdgeKind, Trace, Tracer};
 use crate::clang::{self, Cursor};
-use crate::parse::{ClangItemParser, ParseError, ParseResult};
+use crate::parse::{ParseError, ParseResult};
 use std::borrow::Cow;
 use std::io;
 
@@ -95,6 +95,11 @@
         matches!(self.kind, TypeKind::BlockPointer(..))
     }
 
+    /// Is this an integer type, including `bool` or `char`?
+    pub fn is_int(&self) -> bool {
+        matches!(self.kind, TypeKind::Int(_))
+    }
+
     /// Is this a compound type?
     pub fn is_comp(&self) -> bool {
         matches!(self.kind, TypeKind::Comp(..))
diff --git a/ir/var.rs b/ir/var.rs
index c86742f..903e1ff 100644
--- a/ir/var.rs
+++ b/ir/var.rs
@@ -7,12 +7,10 @@
 use super::int::IntKind;
 use super::item::Item;
 use super::ty::{FloatKind, TypeKind};
-use crate::callbacks::MacroParsingBehavior;
+use crate::callbacks::{ItemInfo, ItemKind, MacroParsingBehavior};
 use crate::clang;
 use crate::clang::ClangToken;
-use crate::parse::{
-    ClangItemParser, ClangSubItemParser, ParseError, ParseResult,
-};
+use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
 use cexpr;
 use std::io;
 use std::num::Wrapping;
@@ -274,7 +272,20 @@
                 ))
             }
             CXCursor_VarDecl => {
-                let name = cursor.spelling();
+                let mut name = cursor.spelling();
+                if cursor.linkage() == CXLinkage_External {
+                    if let Some(nm) = ctx.options().last_callback(|callbacks| {
+                        callbacks.generated_name_override(ItemInfo {
+                            name: name.as_str(),
+                            kind: ItemKind::Var,
+                        })
+                    }) {
+                        name = nm;
+                    }
+                }
+                // No more changes to name
+                let name = name;
+
                 if name.is_empty() {
                     warn!("Empty constant name?");
                     return Err(ParseError::Continue);
diff --git a/lib.rs b/lib.rs
index 4b71fb9..1af6f26 100644
--- a/lib.rs
+++ b/lib.rs
@@ -65,7 +65,7 @@
 mod codegen;
 mod deps;
 mod features;
-mod ir;
+pub mod ir;
 mod parse;
 mod regex_set;
 mod time;
@@ -78,6 +78,7 @@
 doc_mod!(parse, parse_docs);
 doc_mod!(regex_set, regex_set_docs);
 
+use codegen::CodegenError;
 use ir::comment;
 
 pub use crate::codegen::{
@@ -90,8 +91,8 @@
 use crate::ir::context::{BindgenContext, ItemId};
 pub use crate::ir::function::Abi;
 use crate::ir::item::Item;
-use crate::parse::{ClangItemParser, ParseError};
-use crate::regex_set::RegexSet;
+use crate::parse::ParseError;
+pub use crate::regex_set::RegexSet;
 
 use std::borrow::Cow;
 use std::env;
@@ -108,6 +109,7 @@
 
 /// Default prefix for the anon fields.
 pub const DEFAULT_ANON_FIELDS_PREFIX: &str = "__bindgen_anon_";
+const DEFAULT_NON_EXTERN_FNS_SUFFIX: &str = "__extern";
 
 fn file_is_cpp(name_file: &str) -> bool {
     name_file.ends_with(".hpp") ||
@@ -244,6 +246,10 @@
 /// regular expressions as arguments. These regular expressions will be parenthesized and wrapped
 /// in `^` and `$`. So if `<regex>` is passed as argument, the regular expression to be stored will
 /// be `^(<regex>)$`.
+///
+/// Releases of `bindgen` with a version lesser or equal to `0.62.0` used to accept the wildcard
+/// pattern `*` as a valid regular expression. This behavior has been deprecated and the `.*`
+/// pattern must be used instead.
 #[derive(Debug, Default, Clone)]
 pub struct Builder {
     options: BindgenOptions,
@@ -649,6 +655,28 @@
             output_vector.push("--wrap-unsafe-ops".into());
         }
 
+        #[cfg(feature = "cli")]
+        for callbacks in &self.options.parse_callbacks {
+            output_vector.extend(callbacks.cli_args());
+        }
+        if self.options.wrap_static_fns {
+            output_vector.push("--wrap-static-fns".into())
+        }
+
+        if let Some(ref path) = self.options.wrap_static_fns_path {
+            output_vector.push("--wrap-static-fns-path".into());
+            output_vector.push(path.display().to_string());
+        }
+
+        if let Some(ref suffix) = self.options.wrap_static_fns_suffix {
+            output_vector.push("--wrap-static-fns-suffix".into());
+            output_vector.push(suffix.clone());
+        }
+
+        if cfg!(feature = "experimental") {
+            output_vector.push("--experimental".into());
+        }
+
         // Add clang arguments
 
         output_vector.push("--".into());
@@ -1544,33 +1572,25 @@
     }
 
     /// Generate the Rust bindings using the options built up thus far.
-    pub fn generate(self) -> Result<Bindings, BindgenError> {
-        let mut options = self.options.clone();
+    pub fn generate(mut self) -> Result<Bindings, BindgenError> {
         // Add any extra arguments from the environment to the clang command line.
-        options.clang_args.extend(get_extra_clang_args());
+        self.options.clang_args.extend(get_extra_clang_args());
 
         // Transform input headers to arguments on the clang command line.
-        options.clang_args.extend(
-            options.input_headers
-                [..options.input_headers.len().saturating_sub(1)]
+        self.options.clang_args.extend(
+            self.options.input_headers
+                [..self.options.input_headers.len().saturating_sub(1)]
                 .iter()
                 .flat_map(|header| ["-include".into(), header.to_string()]),
         );
 
         let input_unsaved_files =
-            std::mem::take(&mut options.input_header_contents)
+            std::mem::take(&mut self.options.input_header_contents)
                 .into_iter()
                 .map(|(name, contents)| clang::UnsavedFile::new(name, contents))
                 .collect::<Vec<_>>();
 
-        match Bindings::generate(options, input_unsaved_files) {
-            GenerateResult::Ok(bindings) => Ok(bindings),
-            GenerateResult::ShouldRestart { header } => self
-                .header(header)
-                .generate_inline_functions(false)
-                .generate(),
-            GenerateResult::Err(err) => Err(err),
-        }
+        Bindings::generate(self.options, input_unsaved_files)
     }
 
     /// Preprocess and dump the input header files to disk.
@@ -1605,7 +1625,7 @@
 
         // For each input header content, add a prefix line of `#line 0 "$name"`
         // followed by the contents.
-        for &(ref name, ref contents) in &self.options.input_header_contents {
+        for (name, contents) in &self.options.input_header_contents {
             is_cpp |= file_is_cpp(name);
 
             wrapper_contents.push_str("#line 0 \"");
@@ -1787,6 +1807,32 @@
         self.options.wrap_unsafe_ops = doit;
         self
     }
+
+    #[cfg(feature = "experimental")]
+    /// Whether to generate extern wrappers for `static` and `static inline` functions. Defaults to
+    /// false.
+    pub fn wrap_static_fns(mut self, doit: bool) -> Self {
+        self.options.wrap_static_fns = doit;
+        self
+    }
+
+    #[cfg(feature = "experimental")]
+    /// Set the path for the source code file that would be created if any wrapper functions must
+    /// be generated due to the presence of static functions.
+    ///
+    /// Bindgen will automatically add the right extension to the header and source code files.
+    pub fn wrap_static_fns_path<T: AsRef<Path>>(mut self, path: T) -> Self {
+        self.options.wrap_static_fns_path = Some(path.as_ref().to_owned());
+        self
+    }
+
+    #[cfg(feature = "experimental")]
+    /// Set the suffix added to the extern wrapper functions generated for `static` and `static
+    /// inline` functions.
+    pub fn wrap_static_fns_suffix<T: AsRef<str>>(mut self, suffix: T) -> Self {
+        self.options.wrap_static_fns_suffix = Some(suffix.as_ref().to_owned());
+        self
+    }
 }
 
 /// Configuration options for generated bindings.
@@ -2127,6 +2173,12 @@
 
     /// Whether to wrap unsafe operations in unsafe blocks or not.
     wrap_unsafe_ops: bool,
+
+    wrap_static_fns: bool,
+
+    wrap_static_fns_suffix: Option<String>,
+
+    wrap_static_fns_path: Option<PathBuf>,
 }
 
 impl BindgenOptions {
@@ -2319,6 +2371,9 @@
             merge_extern_blocks,
             abi_overrides,
             wrap_unsafe_ops,
+            wrap_static_fns,
+            wrap_static_fns_suffix,
+            wrap_static_fns_path,
         }
     }
 }
@@ -2349,18 +2404,6 @@
 #[cfg(not(feature = "runtime"))]
 fn ensure_libclang_is_loaded() {}
 
-#[derive(Debug)]
-enum GenerateResult {
-    Ok(Bindings),
-    /// Error variant raised when bindgen requires to run again with a newly generated header
-    /// input.
-    #[allow(dead_code)]
-    ShouldRestart {
-        header: String,
-    },
-    Err(BindgenError),
-}
-
 /// Error type for rust-bindgen.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 #[non_exhaustive]
@@ -2373,6 +2416,8 @@
     NotExist(PathBuf),
     /// Clang diagnosed an error.
     ClangDiagnostic(String),
+    /// Code generation reported an error.
+    Codegen(CodegenError),
 }
 
 impl std::fmt::Display for BindgenError {
@@ -2390,6 +2435,9 @@
             BindgenError::ClangDiagnostic(message) => {
                 write!(f, "clang diagnosed error: {}", message)
             }
+            BindgenError::Codegen(err) => {
+                write!(f, "codegen error: {}", err)
+            }
         }
     }
 }
@@ -2419,6 +2467,15 @@
         let mut clang_target = "riscv64-".to_owned();
         clang_target.push_str(rust_target.strip_prefix("riscv64gc-").unwrap());
         return clang_target;
+    } else if rust_target.ends_with("-espidf") {
+        let mut clang_target =
+            rust_target.strip_suffix("-espidf").unwrap().to_owned();
+        clang_target.push_str("-elf");
+        if clang_target.starts_with("riscv32imc-") {
+            clang_target = "riscv32-".to_owned() +
+                clang_target.strip_prefix("riscv32imc-").unwrap();
+        }
+        return clang_target;
     }
     rust_target.to_owned()
 }
@@ -2454,7 +2511,7 @@
     pub(crate) fn generate(
         mut options: BindgenOptions,
         input_unsaved_files: Vec<clang::UnsavedFile>,
-    ) -> GenerateResult {
+    ) -> Result<Bindings, BindgenError> {
         ensure_libclang_is_loaded();
 
         #[cfg(feature = "runtime")]
@@ -2575,21 +2632,17 @@
             let path = Path::new(h);
             if let Ok(md) = std::fs::metadata(path) {
                 if md.is_dir() {
-                    return GenerateResult::Err(BindgenError::FolderAsHeader(
-                        path.into(),
-                    ));
+                    return Err(BindgenError::FolderAsHeader(path.into()));
                 }
                 if !can_read(&md.permissions()) {
-                    return GenerateResult::Err(
-                        BindgenError::InsufficientPermissions(path.into()),
-                    );
+                    return Err(BindgenError::InsufficientPermissions(
+                        path.into(),
+                    ));
                 }
                 let h = h.clone();
                 options.clang_args.push(h);
             } else {
-                return GenerateResult::Err(BindgenError::NotExist(
-                    path.into(),
-                ));
+                return Err(BindgenError::NotExist(path.into()));
             }
         }
 
@@ -2617,14 +2670,13 @@
 
         {
             let _t = time::Timer::new("parse").with_output(time_phases);
-            if let Err(err) = parse(&mut context) {
-                return GenerateResult::Err(err);
-            }
+            parse(&mut context)?;
         }
 
-        let (module, options, warnings) = codegen::codegen(context);
+        let (module, options, warnings) =
+            codegen::codegen(context).map_err(BindgenError::Codegen)?;
 
-        GenerateResult::Ok(Bindings {
+        Ok(Bindings {
             options,
             warnings,
             module,
@@ -2645,7 +2697,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 = option_env!("CARGO_PKG_VERSION");
+            let version = Some("0.64.0");
             let header = format!(
                 "/* automatically generated by rust-bindgen {} */\n\n",
                 version.unwrap_or("(unknown version)")
@@ -3002,3 +3054,15 @@
         "riscv64-unknown-linux-gnu"
     )
 }
+
+#[test]
+fn test_rust_to_clang_target_espidf() {
+    assert_eq!(
+        rust_to_clang_target("riscv32imc-esp-espidf"),
+        "riscv32-esp-elf"
+    );
+    assert_eq!(
+        rust_to_clang_target("xtensa-esp32-espidf"),
+        "xtensa-esp32-elf"
+    );
+}
diff --git a/parse.rs b/parse.rs
index f60de43..1fd83cd 100644
--- a/parse.rs
+++ b/parse.rs
@@ -1,8 +1,7 @@
 //! Common traits and types related to parsing our IR from Clang cursors.
 
 use crate::clang;
-use crate::ir::context::{BindgenContext, ItemId, TypeId};
-use crate::ir::ty::TypeKind;
+use crate::ir::context::{BindgenContext, ItemId};
 
 /// Not so much an error in the traditional sense, but a control flow message
 /// when walking over Clang's AST with a cursor.
@@ -39,64 +38,3 @@
         context: &mut BindgenContext,
     ) -> Result<ParseResult<Self>, ParseError>;
 }
-
-/// An intermediate representation item that can be parsed from a Clang cursor.
-pub trait ClangItemParser: Sized {
-    /// Parse this item from the given Clang cursor.
-    fn parse(
-        cursor: clang::Cursor,
-        parent: Option<ItemId>,
-        context: &mut BindgenContext,
-    ) -> Result<ItemId, ParseError>;
-
-    /// Parse this item from the given Clang type.
-    fn from_ty(
-        ty: &clang::Type,
-        location: clang::Cursor,
-        parent: Option<ItemId>,
-        ctx: &mut BindgenContext,
-    ) -> Result<TypeId, ParseError>;
-
-    /// Identical to `from_ty`, but use the given `id` as the `ItemId` for the
-    /// newly parsed item.
-    fn from_ty_with_id(
-        id: ItemId,
-        ty: &clang::Type,
-        location: clang::Cursor,
-        parent: Option<ItemId>,
-        ctx: &mut BindgenContext,
-    ) -> Result<TypeId, ParseError>;
-
-    /// Parse this item from the given Clang type, or if we haven't resolved all
-    /// the other items this one depends on, an unresolved reference.
-    fn from_ty_or_ref(
-        ty: clang::Type,
-        location: clang::Cursor,
-        parent_id: Option<ItemId>,
-        context: &mut BindgenContext,
-    ) -> TypeId;
-
-    /// Identical to `from_ty_or_ref`, but use the given `potential_id` as the
-    /// `ItemId` for the newly parsed item.
-    fn from_ty_or_ref_with_id(
-        potential_id: ItemId,
-        ty: clang::Type,
-        location: clang::Cursor,
-        parent_id: Option<ItemId>,
-        context: &mut BindgenContext,
-    ) -> TypeId;
-
-    /// Create a named template type.
-    fn type_param(
-        with_id: Option<ItemId>,
-        location: clang::Cursor,
-        ctx: &mut BindgenContext,
-    ) -> Option<TypeId>;
-
-    /// Create a builtin type.
-    fn builtin_type(
-        kind: TypeKind,
-        is_const: bool,
-        context: &mut BindgenContext,
-    ) -> TypeId;
-}
diff --git a/patches/bindgen_cmd.diff b/patches/bindgen_cmd.diff
new file mode 100644
index 0000000..9b28ff7
--- /dev/null
+++ b/patches/bindgen_cmd.diff
@@ -0,0 +1,90 @@
+diff --git a/android/bindgen_cmd/Android.bp b/android/bindgen_cmd/Android.bp
+new file mode 100644
+index 0000000..689e7ae
+--- /dev/null
++++ b/android/bindgen_cmd/Android.bp
+@@ -0,0 +1,28 @@
++package {
++    // See: http://go/android-license-faq
++    // A large-scale-change added 'default_applicable_licenses' to import
++    // all of the 'license_kinds' from "external_rust_crates_bindgen_license"
++    // to get the below license kinds:
++    //   SPDX-license-identifier-Apache-2.0
++    default_applicable_licenses: ["external_rust_crates_bindgen_license"],
++}
++
++rust_library_host {
++    name: "libbindgen_cmd",
++    crate_name: "bindgen_cmd",
++    srcs: ["src/lib.rs"],
++    edition: "2018",
++    features: [
++        "clap",
++        "runtime",
++        "which",
++        "which-rustfmt",
++    ],
++    rustlibs: [
++        "libbindgen",
++        "libbindgen_cli",
++        "libclap",
++        "libenv_logger",
++    ],
++    compile_multilib: "first",
++}
+diff --git a/android/bindgen_cmd/src/lib.rs b/android/bindgen_cmd/src/lib.rs
+new file mode 100644
+index 0000000..d33da7f
+--- /dev/null
++++ b/android/bindgen_cmd/src/lib.rs
+@@ -0,0 +1,50 @@
++// Copyright 2020, The Android Open Source Project
++//
++// Licensed under the Apache License, Version 2.0 (the "License");
++// you may not use this file except in compliance with the License.
++// You may obtain a copy of the License at
++//
++//     http://www.apache.org/licenses/LICENSE-2.0
++//
++// Unless required by applicable law or agreed to in writing, software
++// distributed under the License is distributed on an "AS IS" BASIS,
++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++// See the License for the specific language governing permissions and
++// limitations under the License.
++
++//! This is a helper crate for using bindgen as a library from within
++//! Android's build system. Some functionality (such as the type selection
++//! heuristic) is not available on the command line, and so the library
++//! interface may be necessary. Bindgen also needs to receive configuration
++//! from Soong however to find appropriate headers, set global cflags, etc.
++//!
++//! This crate provides the ability to run a hooked version of the command
++//! line bindgen tool, with the ability to call a user-provided transformation
++//! on the the builder before it is used.
++
++use bindgen;
++use bindgen_cli;
++use std::env;
++
++/// Takes in a function describing adjustments to make to a builder
++/// initialized by the command line. `build(|x| x)` is equivalent to
++/// running bindgen. When converting a build.rs, you will want to convert the
++/// additional configuration they do into a function, then pass it to `build`
++/// inside your main function.
++pub fn build<C: FnOnce(bindgen::Builder) -> bindgen::Builder>(configure: C) {
++    env_logger::init();
++
++    match bindgen_cli::builder_from_flags(env::args()) {
++        Ok((builder, output, _)) => {
++            configure(builder)
++                .generate()
++                .expect("Unable to generate bindings")
++                .write(output)
++                .expect("Unable to write output");
++        }
++        Err(error) => {
++            eprintln!("{}", error);
++            std::process::exit(1);
++        }
++    };
++}
diff --git a/regex_set.rs b/regex_set.rs
index 9f1e225..6246dd2 100644
--- a/regex_set.rs
+++ b/regex_set.rs
@@ -16,6 +16,13 @@
 }
 
 impl RegexSet {
+    /// Create a new RegexSet
+    pub fn new() -> RegexSet {
+        RegexSet {
+            ..Default::default()
+        }
+    }
+
     /// Is this set empty?
     pub fn is_empty(&self) -> bool {
         self.items.is_empty()