Snap for 9550355 from 439138eaa22cce0f508f1d17fab24ced1c78af72 to sdk-release

Change-Id: Ie8a8cbe34d0b23711808ba7df4c91e71d6829e3c
diff --git a/Android.bp b/Android.bp
index 62aa9aa..ed1a6de 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,6 +1,7 @@
 // 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"],
 }
@@ -35,61 +36,20 @@
     name: "copy_bindgen_build_out",
     srcs: ["out/*"],
     cmd: "cp $(in) $(genDir)",
-    out: [
-        "host-target.txt",
-        "tests.rs",
-    ],
-}
-
-rust_binary_host {
-    name: "bindgen",
-    // has rustc warnings
-    crate_name: "bindgen",
-    cargo_env_compat: true,
-    cargo_pkg_version: "0.59.2",
-    srcs: [
-        "src/main.rs",
-        ":copy_bindgen_build_out",
-    ],
-    edition: "2018",
-    features: [
-        "clap",
-        "runtime",
-        "which",
-        "which-rustfmt",
-    ],
-    rustlibs: [
-        "libbindgen",
-        "libbitflags",
-        "libcexpr",
-        "libclang_sys",
-        "libclap_deprecated",
-        "liblazy_static",
-        "liblazycell",
-        "libpeeking_take_while",
-        "libproc_macro2",
-        "libquote",
-        "libregex",
-        "librustc_hash",
-        "libshlex",
-        "libwhich",
-    ],
-    compile_multilib: "first",
+    out: ["host-target.txt"],
 }
 
 rust_library_host {
     name: "libbindgen",
-    // has rustc warnings
     crate_name: "bindgen",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.59.2",
+    cargo_pkg_version: "0.63.0",
     srcs: [
-        "src/lib.rs",
+        "lib.rs",
         ":copy_bindgen_build_out",
     ],
     edition: "2018",
     features: [
-        "clap",
         "runtime",
         "which",
         "which-rustfmt",
@@ -98,7 +58,6 @@
         "libbitflags",
         "libcexpr",
         "libclang_sys",
-        "libclap_deprecated",
         "liblazy_static",
         "liblazycell",
         "libpeeking_take_while",
@@ -107,7 +66,12 @@
         "libregex",
         "librustc_hash",
         "libshlex",
+        "libsyn",
         "libwhich",
     ],
     compile_multilib: "first",
+    apex_available: [
+        "//apex_available:platform",
+        "//apex_available:anyapex",
+    ],
 }
diff --git a/Cargo.lock b/Cargo.lock
deleted file mode 100644
index d79a408..0000000
--- a/Cargo.lock
+++ /dev/null
@@ -1,446 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 3
-
-[[package]]
-name = "aho-corasick"
-version = "0.7.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "ansi_term"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
-
-[[package]]
-name = "bindgen"
-version = "0.59.2"
-dependencies = [
- "bitflags",
- "cexpr",
- "clang-sys",
- "clap",
- "diff",
- "env_logger",
- "lazy_static",
- "lazycell",
- "log",
- "peeking_take_while",
- "proc-macro2",
- "quote",
- "regex",
- "rustc-hash",
- "shlex",
- "tempfile",
- "which",
-]
-
-[[package]]
-name = "bitflags"
-version = "1.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
-
-[[package]]
-name = "cexpr"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
-dependencies = [
- "nom",
-]
-
-[[package]]
-name = "cfg-if"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-
-[[package]]
-name = "clang-sys"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "853eda514c284c2287f4bf20ae614f8781f40a81d32ecda6e91449304dfe077c"
-dependencies = [
- "glob",
- "libc",
- "libloading",
-]
-
-[[package]]
-name = "clap"
-version = "2.33.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
-dependencies = [
- "ansi_term",
- "atty",
- "bitflags",
- "strsim",
- "textwrap",
- "unicode-width",
- "vec_map",
-]
-
-[[package]]
-name = "diff"
-version = "0.1.12"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
-
-[[package]]
-name = "either"
-version = "1.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
-
-[[package]]
-name = "env_logger"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
-dependencies = [
- "atty",
- "humantime",
- "log",
- "regex",
- "termcolor",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi",
-]
-
-[[package]]
-name = "glob"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
-
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
-[[package]]
-name = "humantime"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
-
-[[package]]
-name = "lazy_static"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
-
-[[package]]
-name = "lazycell"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
-
-[[package]]
-name = "libc"
-version = "0.2.98"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
-
-[[package]]
-name = "libloading"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a"
-dependencies = [
- "cfg-if",
- "winapi",
-]
-
-[[package]]
-name = "log"
-version = "0.4.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "memchr"
-version = "2.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525"
-
-[[package]]
-name = "minimal-lexical"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c64630dcdd71f1a64c435f54885086a0de5d6a12d104d69b165fb7d5286d677"
-
-[[package]]
-name = "nom"
-version = "7.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ffd9d26838a953b4af82cbeb9f1592c6798916983959be223a7124e992742c1"
-dependencies = [
- "memchr",
- "minimal-lexical",
- "version_check",
-]
-
-[[package]]
-name = "peeking_take_while"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
-
-[[package]]
-name = "ppv-lite86"
-version = "0.2.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
-
-[[package]]
-name = "proc-macro2"
-version = "1.0.28"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
-dependencies = [
- "unicode-xid",
-]
-
-[[package]]
-name = "quote"
-version = "1.0.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
-dependencies = [
- "proc-macro2",
-]
-
-[[package]]
-name = "rand"
-version = "0.8.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
-dependencies = [
- "libc",
- "rand_chacha",
- "rand_core",
- "rand_hc",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
-dependencies = [
- "ppv-lite86",
- "rand_core",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
-dependencies = [
- "getrandom",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
-dependencies = [
- "rand_core",
-]
-
-[[package]]
-name = "redox_syscall"
-version = "0.2.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "regex"
-version = "1.4.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-syntax"
-version = "0.6.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
-
-[[package]]
-name = "remove_dir_all"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "rustc-hash"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-
-[[package]]
-name = "shlex"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
-
-[[package]]
-name = "strsim"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
-
-[[package]]
-name = "tempfile"
-version = "3.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
-dependencies = [
- "cfg-if",
- "libc",
- "rand",
- "redox_syscall",
- "remove_dir_all",
- "winapi",
-]
-
-[[package]]
-name = "termcolor"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
-name = "textwrap"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
-dependencies = [
- "unicode-width",
-]
-
-[[package]]
-name = "unicode-width"
-version = "0.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
-
-[[package]]
-name = "unicode-xid"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
-
-[[package]]
-name = "vec_map"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
-
-[[package]]
-name = "version_check"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
-
-[[package]]
-name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
-
-[[package]]
-name = "which"
-version = "4.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7cc009ab82a2afc94b9e467ab4214aee9cad1356cd9191264203d7d72006e00d"
-dependencies = [
- "either",
- "lazy_static",
- "libc",
-]
-
-[[package]]
-name = "winapi"
-version = "0.3.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
-dependencies = [
- "winapi-i686-pc-windows-gnu",
- "winapi-x86_64-pc-windows-gnu",
-]
-
-[[package]]
-name = "winapi-i686-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
-
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
-[[package]]
-name = "winapi-x86_64-pc-windows-gnu"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
index 8b8853a..2fa903a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,28 +11,36 @@
 
 [package]
 edition = "2018"
+rust-version = "1.57.0"
 name = "bindgen"
-version = "0.59.2"
-authors = ["Jyun-Yan You <jyyou.tw@gmail.com>", "Emilio Cobos Álvarez <emilio@crisal.io>", "Nick Fitzgerald <fitzgen@gmail.com>", "The Servo project developers"]
+version = "0.63.0"
+authors = [
+    "Jyun-Yan You <jyyou.tw@gmail.com>",
+    "Emilio Cobos Álvarez <emilio@crisal.io>",
+    "Nick Fitzgerald <fitzgen@gmail.com>",
+    "The Servo project developers",
+]
 build = "build.rs"
-include = ["LICENSE", "README.md", "Cargo.toml", "build.rs", "src/*.rs", "src/**/*.rs"]
 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"
-keywords = ["bindings", "ffi", "code-generation"]
-categories = ["external-ffi-bindings", "development-tools::ffi"]
+keywords = [
+    "bindings",
+    "ffi",
+    "code-generation",
+]
+categories = [
+    "external-ffi-bindings",
+    "development-tools::ffi",
+]
 license = "BSD-3-Clause"
 repository = "https://github.com/rust-lang/rust-bindgen"
 
 [lib]
-path = "src/lib.rs"
-
-[[bin]]
 name = "bindgen"
-path = "src/main.rs"
-doc = false
-required-features = ["clap"]
+path = "./lib.rs"
+
 [dependencies.bitflags]
 version = "1.0.3"
 
@@ -43,14 +51,6 @@
 version = "1"
 features = ["clang_6_0"]
 
-[dependencies.clap]
-version = "2"
-optional = true
-
-[dependencies.env_logger]
-version = "0.9.0"
-optional = true
-
 [dependencies.lazy_static]
 version = "1"
 
@@ -73,8 +73,11 @@
 default-features = false
 
 [dependencies.regex]
-version = "1.0"
-features = ["std", "unicode"]
+version = "1.5"
+features = [
+    "std",
+    "unicode",
+]
 default-features = false
 
 [dependencies.rustc-hash]
@@ -83,33 +86,30 @@
 [dependencies.shlex]
 version = "1"
 
+[dependencies.syn]
+version = "1.0.99"
+features = [
+    "full",
+    "extra-traits",
+    "visit-mut",
+]
+
 [dependencies.which]
 version = "4.2.1"
 optional = true
 default-features = false
-[dev-dependencies.clap]
-version = "2"
-
-[dev-dependencies.diff]
-version = "0.1"
-
-[dev-dependencies.shlex]
-version = "1"
-
-[dev-dependencies.tempfile]
-version = "3"
 
 [features]
-default = ["logging", "clap", "runtime", "which-rustfmt"]
-logging = ["env_logger", "log"]
+default = [
+    "logging",
+    "runtime",
+    "which-rustfmt",
+]
+logging = ["log"]
 runtime = ["clang-sys/runtime"]
 static = ["clang-sys/static"]
 testing_only_docs = []
 testing_only_extra_assertions = []
-testing_only_libclang_3_9 = []
-testing_only_libclang_4 = []
 testing_only_libclang_5 = []
 testing_only_libclang_9 = []
 which-rustfmt = ["which"]
-[badges.travis-ci]
-repository = "rust-lang/rust-bindgen"
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index ba41a22..6522209 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -10,68 +10,39 @@
 categories = ["external-ffi-bindings", "development-tools::ffi"]
 license = "BSD-3-Clause"
 name = "bindgen"
-readme = "README.md"
+readme = "../README.md"
 repository = "https://github.com/rust-lang/rust-bindgen"
 documentation = "https://docs.rs/bindgen"
 homepage = "https://rust-lang.github.io/rust-bindgen/"
-version = "0.59.2"
+version = "0.63.0"
 edition = "2018"
 build = "build.rs"
-
-include = [
-  "LICENSE",
-  "README.md",
-  "Cargo.toml",
-  "build.rs",
-  "src/*.rs",
-  "src/**/*.rs",
-]
-
-[badges]
-travis-ci = { repository = "rust-lang/rust-bindgen" }
+# If you change this, also update README.md and msrv in .github/workflows/bindgen.yml
+rust-version = "1.57.0"
 
 [lib]
-path = "src/lib.rs"
-
-[[bin]]
 name = "bindgen"
-path = "src/main.rs"
-doc = false
-required-features = ["clap"]
-
-[dev-dependencies]
-diff = "0.1"
-clap = "2"
-shlex = "1"
-tempfile = "3"
+path = "./lib.rs"
 
 [dependencies]
 bitflags = "1.0.3"
 cexpr = "0.6"
-# This kinda sucks: https://github.com/rust-lang/cargo/issues/1982
-clap = { version = "2", optional = true }
 clang-sys = { version = "1", features = ["clang_6_0"] }
 lazycell = "1"
 lazy_static = "1"
 peeking_take_while = "0.1.2"
 quote = { version = "1", default-features = false }
-regex = { version = "1.0", default-features = false , features = [ "std", "unicode"]}
+syn = { version = "1.0.99", features = ["full", "extra-traits", "visit-mut"]}
+regex = { version = "1.5", default-features = false , features = ["std", "unicode"] }
 which = { version = "4.2.1", optional = true, default-features = false }
 shlex = "1"
 rustc-hash = "1.0.1"
 proc-macro2 = { version = "1", default-features = false }
-
-[dependencies.env_logger]
-optional = true
-version = "0.9.0"
-
-[dependencies.log]
-optional = true
-version = "0.4"
+log = { version = "0.4", optional = true }
 
 [features]
-default = ["logging", "clap", "runtime", "which-rustfmt"]
-logging = ["env_logger", "log"]
+default = ["logging", "runtime", "which-rustfmt"]
+logging = ["log"]
 static = ["clang-sys/static"]
 runtime = ["clang-sys/runtime"]
 # Dynamically discover a `rustfmt` binary using the `which` crate
@@ -83,5 +54,3 @@
 testing_only_extra_assertions = []
 testing_only_libclang_9 = []
 testing_only_libclang_5 = []
-testing_only_libclang_4 = []
-testing_only_libclang_3_9 = []
diff --git a/METADATA b/METADATA
index 85b1cce..7dccd8e 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@
   }
   url {
     type: ARCHIVE
-    value: "https://static.crates.io/crates/bindgen/bindgen-0.59.2.crate"
+    value: "https://static.crates.io/crates/bindgen/bindgen-0.63.0.crate"
   }
-  version: "0.59.2"
+  version: "0.63.0"
   license_type: NOTICE
   last_upgrade_date {
     year: 2022
-    month: 3
-    day: 1
+    month: 12
+    day: 6
   }
 }
diff --git a/OWNERS b/OWNERS
index 46fc303..45dc4dd 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1 +1 @@
-include platform/prebuilts/rust:/OWNERS
+include platform/prebuilts/rust:master:/OWNERS
diff --git a/README.md b/README.md
index 7b2dbbc..c78f00d 100644
--- a/README.md
+++ b/README.md
@@ -39,10 +39,12 @@
 
 ## MSRV
 
-The minimum supported Rust version is **1.46**.
+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)
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 96a0732..23bbdf9 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -3,28 +3,12 @@
   "imports": [
     {
       "path": "external/rust/crates/libsqlite3-sys"
-    }
-  ],
-  "presubmit": [
-    {
-      "name": "keystore2_legacy_blobs_test"
     },
     {
-      "name": "keystore2_test"
+      "path": "system/security/keystore2"
     },
     {
-      "name": "legacykeystore_test"
-    }
-  ],
-  "presubmit-rust": [
-    {
-      "name": "keystore2_legacy_blobs_test"
-    },
-    {
-      "name": "keystore2_test"
-    },
-    {
-      "name": "legacykeystore_test"
+      "path": "system/security/keystore2/legacykeystore"
     }
   ]
 }
diff --git a/android/bindgen_cmd/Android.bp b/android/bindgen_cmd/Android.bp
index 85094f7..689e7ae 100644
--- a/android/bindgen_cmd/Android.bp
+++ b/android/bindgen_cmd/Android.bp
@@ -20,7 +20,8 @@
     ],
     rustlibs: [
         "libbindgen",
-        "libclap_deprecated",
+        "libbindgen_cli",
+        "libclap",
         "libenv_logger",
     ],
     compile_multilib: "first",
diff --git a/android/bindgen_cmd/src/lib.rs b/android/bindgen_cmd/src/lib.rs
index a92ac80..d33da7f 100644
--- a/android/bindgen_cmd/src/lib.rs
+++ b/android/bindgen_cmd/src/lib.rs
@@ -23,11 +23,9 @@
 //! on the the builder before it is used.
 
 use bindgen;
+use bindgen_cli;
 use std::env;
 
-#[path = "../../../src/options.rs"]
-mod options;
-
 /// 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
@@ -36,7 +34,7 @@
 pub fn build<C: FnOnce(bindgen::Builder) -> bindgen::Builder>(configure: C) {
     env_logger::init();
 
-    match options::builder_from_flags(env::args()) {
+    match bindgen_cli::builder_from_flags(env::args()) {
         Ok((builder, output, _)) => {
             configure(builder)
                 .generate()
diff --git a/build.rs b/build.rs
index fcc0bb2..8407cea 100644
--- a/build.rs
+++ b/build.rs
@@ -1,76 +1,15 @@
-mod target {
-    use std::env;
-    use std::fs::File;
-    use std::io::Write;
-    use std::path::{Path, PathBuf};
-
-    pub fn main() {
-        let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
-
-        let mut dst =
-            File::create(Path::new(&out_dir).join("host-target.txt")).unwrap();
-        dst.write_all(env::var("TARGET").unwrap().as_bytes())
-            .unwrap();
-    }
-}
-
-mod testgen {
-    use std::char;
-    use std::env;
-    use std::ffi::OsStr;
-    use std::fs::{self, File};
-    use std::io::Write;
-    use std::path::{Path, PathBuf};
-
-    pub fn main() {
-        let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
-        let mut dst =
-            File::create(Path::new(&out_dir).join("tests.rs")).unwrap();
-
-        let manifest_dir =
-            PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
-        let headers_dir = manifest_dir.join("tests").join("headers");
-
-        let headers = match fs::read_dir(headers_dir) {
-            Ok(dir) => dir,
-            // We may not have headers directory after packaging.
-            Err(..) => return,
-        };
-
-        let entries =
-            headers.map(|result| result.expect("Couldn't read header file"));
-
-        println!("cargo:rerun-if-changed=tests/headers");
-
-        for entry in entries {
-            match entry.path().extension().and_then(OsStr::to_str) {
-                Some("h") | Some("hpp") => {
-                    let func = entry
-                        .file_name()
-                        .to_str()
-                        .unwrap()
-                        .replace(|c| !char::is_alphanumeric(c), "_")
-                        .replace("__", "_")
-                        .to_lowercase();
-                    writeln!(
-                        dst,
-                        "test_header!(header_{}, {:?});",
-                        func,
-                        entry.path(),
-                    )
-                    .unwrap();
-                }
-                _ => {}
-            }
-        }
-
-        dst.flush().unwrap();
-    }
-}
+use std::env;
+use std::fs::File;
+use std::io::Write;
+use std::path::{Path, PathBuf};
 
 fn main() {
-    target::main();
-    testgen::main();
+    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
+
+    let mut dst =
+        File::create(Path::new(&out_dir).join("host-target.txt")).unwrap();
+    dst.write_all(env::var("TARGET").unwrap().as_bytes())
+        .unwrap();
 
     // On behalf of clang_sys, rebuild ourselves if important configuration
     // variables change, to ensure that bindings get rebuilt if the
@@ -85,6 +24,6 @@
     );
     println!(
         "cargo:rerun-if-env-changed=BINDGEN_EXTRA_CLANG_ARGS_{}",
-        std::env::var("TARGET").unwrap().replace("-", "_")
+        std::env::var("TARGET").unwrap().replace('-', "_")
     );
 }
diff --git a/src/callbacks.rs b/callbacks.rs
similarity index 84%
rename from src/callbacks.rs
rename to callbacks.rs
index 9b34544..5e8ac78 100644
--- a/src/callbacks.rs
+++ b/callbacks.rs
@@ -5,7 +5,6 @@
 pub use crate::ir::enum_ty::{EnumVariantCustomBehavior, EnumVariantValue};
 pub use crate::ir::int::IntKind;
 use std::fmt;
-use std::panic::UnwindSafe;
 
 /// An enum to allow ignoring parsing of macros.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -25,12 +24,18 @@
 
 /// A trait to allow configuring different kinds of types in different
 /// situations.
-pub trait ParseCallbacks: fmt::Debug + UnwindSafe {
+pub trait ParseCallbacks: fmt::Debug {
     /// 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> {
+        None
+    }
+
     /// The integer kind an integer macro should have, given a name and the
     /// value of that macro, or `None` if you want the default to be chosen.
     fn int_macro(&self, _name: &str, _value: i64) -> Option<IntKind> {
@@ -100,7 +105,20 @@
     ///
     /// If no additional attributes are wanted, this function should return an
     /// empty `Vec`.
-    fn add_derives(&self, _name: &str) -> Vec<String> {
+    fn add_derives(&self, _info: &DeriveInfo<'_>) -> Vec<String> {
         vec![]
     }
+
+    /// Process a source code comment.
+    fn process_comment(&self, _comment: &str) -> Option<String> {
+        None
+    }
+}
+
+/// Relevant information about a type to which new derive attributes will be added using
+/// [`ParseCallbacks::add_derives`].
+#[non_exhaustive]
+pub struct DeriveInfo<'a> {
+    /// The name of the type.
+    pub name: &'a str,
 }
diff --git a/cargo2android.json b/cargo2android.json
index 9e5e68b..655ad69 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,6 +1,6 @@
 {
   "copy-out": true,
-  "features": "clap,runtime,which-rustfmt",
+  "features": "runtime,which-rustfmt",
   "host-first-multilib": true,
   "run": true
-}
\ No newline at end of file
+}
diff --git a/src/clang.rs b/clang.rs
similarity index 91%
rename from src/clang.rs
rename to clang.rs
index 074d459..32a2544 100644
--- a/src/clang.rs
+++ b/clang.rs
@@ -12,6 +12,40 @@
 use std::os::raw::{c_char, c_int, c_longlong, c_uint, c_ulong, c_ulonglong};
 use std::{mem, ptr, slice};
 
+/// Type representing a clang attribute.
+///
+/// Values of this type can be used to check for different attributes using the `has_attrs`
+/// function.
+pub struct Attribute {
+    name: &'static [u8],
+    kind: Option<CXCursorKind>,
+    token_kind: CXTokenKind,
+}
+
+impl Attribute {
+    /// A `warn_unused_result` attribute.
+    pub const MUST_USE: Self = Self {
+        name: b"warn_unused_result",
+        // FIXME(emilio): clang-sys doesn't expose `CXCursor_WarnUnusedResultAttr` (from clang 9).
+        kind: Some(440),
+        token_kind: CXToken_Identifier,
+    };
+
+    /// A `_Noreturn` attribute.
+    pub const NO_RETURN: Self = Self {
+        name: b"_Noreturn",
+        kind: None,
+        token_kind: CXToken_Keyword,
+    };
+
+    /// A `[[noreturn]]` attribute.
+    pub const NO_RETURN_CPP: Self = Self {
+        name: b"noreturn",
+        kind: None,
+        token_kind: CXToken_Identifier,
+    };
+}
+
 /// A cursor into the Clang AST, pointing to an AST node.
 ///
 /// We call the AST node pointed to by the cursor the cursor's "referent".
@@ -52,6 +86,11 @@
         unsafe { clang_isDeclaration(self.kind()) != 0 }
     }
 
+    /// Is this cursor's referent an anonymous record or so?
+    pub fn is_anonymous(&self) -> bool {
+        unsafe { clang_Cursor_isAnonymous(self.x) != 0 }
+    }
+
     /// Get this cursor's referent's spelling.
     pub fn spelling(&self) -> String {
         unsafe { cxstring_into_string(clang_getCursorSpelling(self.x)) }
@@ -276,6 +315,56 @@
         true
     }
 
+    /// Is the referent any kind of template parameter?
+    pub fn is_template_parameter(&self) -> bool {
+        matches!(
+            self.kind(),
+            CXCursor_TemplateTemplateParameter |
+                CXCursor_TemplateTypeParameter |
+                CXCursor_NonTypeTemplateParameter
+        )
+    }
+
+    /// Does the referent's type or value depend on a template parameter?
+    pub fn is_dependent_on_template_parameter(&self) -> bool {
+        fn visitor(
+            found_template_parameter: &mut bool,
+            cur: Cursor,
+        ) -> CXChildVisitResult {
+            // If we found a template parameter, it is dependent.
+            if cur.is_template_parameter() {
+                *found_template_parameter = true;
+                return CXChildVisit_Break;
+            }
+
+            // Get the referent and traverse it as well.
+            if let Some(referenced) = cur.referenced() {
+                if referenced.is_template_parameter() {
+                    *found_template_parameter = true;
+                    return CXChildVisit_Break;
+                }
+
+                referenced
+                    .visit(|next| visitor(found_template_parameter, next));
+                if *found_template_parameter {
+                    return CXChildVisit_Break;
+                }
+            }
+
+            // Continue traversing the AST at the original cursor.
+            CXChildVisit_Recurse
+        }
+
+        if self.is_template_parameter() {
+            return true;
+        }
+
+        let mut found_template_parameter = false;
+        self.visit(|next| visitor(&mut found_template_parameter, next));
+
+        found_template_parameter
+    }
+
     /// Is this cursor pointing a valid referent?
     pub fn is_valid(&self) -> bool {
         unsafe { clang_isInvalid(self.kind()) == 0 }
@@ -485,9 +574,45 @@
             !self.is_defaulted_function()
     }
 
+    /// Is the referent a bit field declaration?
+    pub fn is_bit_field(&self) -> bool {
+        unsafe { clang_Cursor_isBitField(self.x) != 0 }
+    }
+
+    /// Get a cursor to the bit field's width expression, or `None` if it's not
+    /// a bit field.
+    pub fn bit_width_expr(&self) -> Option<Cursor> {
+        if !self.is_bit_field() {
+            return None;
+        }
+
+        let mut result = None;
+        self.visit(|cur| {
+            // The first child may or may not be a TypeRef, depending on whether
+            // the field's type is builtin. Skip it.
+            if cur.kind() == CXCursor_TypeRef {
+                return CXChildVisit_Continue;
+            }
+
+            // The next expression or literal is the bit width.
+            result = Some(cur);
+
+            CXChildVisit_Break
+        });
+
+        result
+    }
+
     /// Get the width of this cursor's referent bit field, or `None` if the
-    /// referent is not a bit field.
+    /// referent is not a bit field or if the width could not be evaluated.
     pub fn bit_width(&self) -> Option<u32> {
+        // It is not safe to check the bit width without ensuring it doesn't
+        // depend on a template parameter. See
+        // https://github.com/rust-lang/rust-bindgen/issues/2239
+        if self.bit_width_expr()?.is_dependent_on_template_parameter() {
+            return None;
+        }
+
         unsafe {
             let w = clang_getFieldDeclBitWidth(self.x);
             if w == -1 {
@@ -532,6 +657,7 @@
     pub fn enum_val_signed(&self) -> Option<i64> {
         unsafe {
             if self.kind() == CXCursor_EnumConstantDecl {
+                #[allow(clippy::unnecessary_cast)]
                 Some(clang_getEnumConstantDeclValue(self.x) as i64)
             } else {
                 None
@@ -545,6 +671,7 @@
     pub fn enum_val_unsigned(&self) -> Option<u64> {
         unsafe {
             if self.kind() == CXCursor_EnumConstantDecl {
+                #[allow(clippy::unnecessary_cast)]
                 Some(clang_getEnumConstantDeclUnsignedValue(self.x) as u64)
             } else {
                 None
@@ -552,35 +679,41 @@
         }
     }
 
-    /// Whether this cursor has the `warn_unused_result` attribute.
-    pub fn has_warn_unused_result_attr(&self) -> bool {
-        // FIXME(emilio): clang-sys doesn't expose this (from clang 9).
-        const CXCursor_WarnUnusedResultAttr: CXCursorKind = 440;
-        self.has_attr("warn_unused_result", Some(CXCursor_WarnUnusedResultAttr))
-    }
+    /// Does this cursor have the given attributes?
+    pub fn has_attrs<const N: usize>(
+        &self,
+        attrs: &[Attribute; N],
+    ) -> [bool; N] {
+        let mut found_attrs = [false; N];
+        let mut found_count = 0;
 
-    /// Does this cursor have the given attribute?
-    ///
-    /// `name` is checked against unexposed attributes.
-    fn has_attr(&self, name: &str, clang_kind: Option<CXCursorKind>) -> bool {
-        let mut found_attr = false;
         self.visit(|cur| {
             let kind = cur.kind();
-            found_attr = clang_kind.map_or(false, |k| k == kind) ||
-                (kind == CXCursor_UnexposedAttr &&
-                    cur.tokens().iter().any(|t| {
-                        t.kind == CXToken_Identifier &&
-                            t.spelling() == name.as_bytes()
-                    }));
+            for (idx, attr) in attrs.iter().enumerate() {
+                let found_attr = &mut found_attrs[idx];
+                if !*found_attr {
+                    // `attr.name` and` attr.token_kind` are checked against unexposed attributes only.
+                    if attr.kind.map_or(false, |k| k == kind) ||
+                        (kind == CXCursor_UnexposedAttr &&
+                            cur.tokens().iter().any(|t| {
+                                t.kind == attr.token_kind &&
+                                    t.spelling() == attr.name
+                            }))
+                    {
+                        *found_attr = true;
+                        found_count += 1;
 
-            if found_attr {
-                CXChildVisit_Break
-            } else {
-                CXChildVisit_Continue
+                        if found_count == N {
+                            return CXChildVisit_Break;
+                        }
+                    }
+                }
             }
+
+            CXChildVisit_Continue
         });
 
-        found_attr
+        found_attrs
     }
 
     /// Given that this cursor's referent is a `typedef`, get the `Type` that is
@@ -1697,7 +1830,7 @@
 
 impl UnsavedFile {
     /// Construct a new unsaved file with the given `name` and `contents`.
-    pub fn new(name: &str, contents: &str) -> UnsavedFile {
+    pub fn new(name: String, contents: String) -> UnsavedFile {
         let name = CString::new(name).unwrap();
         let contents = CString::new(contents).unwrap();
         let x = CXUnsavedFile {
@@ -1789,9 +1922,15 @@
                 format!(" {}number-of-template-args = {}", prefix, num),
             );
         }
-        if let Some(width) = c.bit_width() {
+
+        if c.is_bit_field() {
+            let width = match c.bit_width() {
+                Some(w) => w.to_string(),
+                None => "<unevaluable>".to_string(),
+            };
             print_indent(depth, format!(" {}bit-width = {}", prefix, width));
         }
+
         if let Some(ty) = c.enum_type() {
             print_indent(
                 depth,
@@ -2002,7 +2141,7 @@
     pub fn as_double(&self) -> Option<f64> {
         match self.kind() {
             CXEval_Float => {
-                Some(unsafe { clang_EvalResult_getAsDouble(self.x) } as f64)
+                Some(unsafe { clang_EvalResult_getAsDouble(self.x) })
             }
             _ => None,
         }
@@ -2014,12 +2153,6 @@
             return None;
         }
 
-        if !clang_EvalResult_isUnsignedInt::is_loaded() {
-            // FIXME(emilio): There's no way to detect underflow here, and clang
-            // will just happily give us a value.
-            return Some(unsafe { clang_EvalResult_getAsInt(self.x) } as i64);
-        }
-
         if unsafe { clang_EvalResult_isUnsignedInt(self.x) } != 0 {
             let value = unsafe { clang_EvalResult_getAsUnsigned(self.x) };
             if value > i64::max_value() as c_ulonglong {
@@ -2036,6 +2169,7 @@
         if value < i64::min_value() as c_longlong {
             return None;
         }
+        #[allow(clippy::unnecessary_cast)]
         Some(value as i64)
     }
 
@@ -2071,10 +2205,7 @@
 
 impl TargetInfo {
     /// Tries to obtain target information from libclang.
-    pub fn new(tu: &TranslationUnit) -> Option<Self> {
-        if !clang_getTranslationUnitTargetInfo::is_loaded() {
-            return None;
-        }
+    pub fn new(tu: &TranslationUnit) -> Self {
         let triple;
         let pointer_width;
         unsafe {
@@ -2085,9 +2216,9 @@
         }
         assert!(pointer_width > 0);
         assert_eq!(pointer_width % 8, 0);
-        Some(TargetInfo {
+        TargetInfo {
             triple,
             pointer_width: pointer_width as usize,
-        })
+        }
     }
 }
diff --git a/src/codegen/bitfield_unit.rs b/codegen/bitfield_unit.rs
old mode 100755
new mode 100644
similarity index 100%
rename from src/codegen/bitfield_unit.rs
rename to codegen/bitfield_unit.rs
diff --git a/src/codegen/bitfield_unit_tests.rs b/codegen/bitfield_unit_tests.rs
similarity index 100%
rename from src/codegen/bitfield_unit_tests.rs
rename to codegen/bitfield_unit_tests.rs
diff --git a/src/codegen/dyngen.rs b/codegen/dyngen.rs
similarity index 81%
rename from src/codegen/dyngen.rs
rename to codegen/dyngen.rs
index 71c4dab..5e734cc 100644
--- a/src/codegen/dyngen.rs
+++ b/codegen/dyngen.rs
@@ -1,5 +1,6 @@
 use crate::codegen;
-use crate::ir::function::Abi;
+use crate::ir::context::BindgenContext;
+use crate::ir::function::ClangAbi;
 use proc_macro2::Ident;
 
 /// Used to build the output tokens for dynamic bindings.
@@ -72,12 +73,22 @@
         Self::default()
     }
 
-    pub fn get_tokens(&self, lib_ident: Ident) -> proc_macro2::TokenStream {
+    pub fn get_tokens(
+        &self,
+        lib_ident: Ident,
+        ctx: &BindgenContext,
+    ) -> proc_macro2::TokenStream {
         let struct_members = &self.struct_members;
         let constructor_inits = &self.constructor_inits;
         let init_fields = &self.init_fields;
         let struct_implementation = &self.struct_implementation;
 
+        let from_library = if ctx.options().wrap_unsafe_ops {
+            quote!(unsafe { Self::from_library(library) })
+        } else {
+            quote!(Self::from_library(library))
+        };
+
         quote! {
             extern crate libloading;
 
@@ -92,7 +103,7 @@
                 ) -> Result<Self, ::libloading::Error>
                 where P: AsRef<::std::ffi::OsStr> {
                     let library = ::libloading::Library::new(path)?;
-                    Self::from_library(library)
+                    #from_library
                 }
 
                 pub unsafe fn from_library<L>(
@@ -112,16 +123,19 @@
         }
     }
 
-    pub fn push(
+    #[allow(clippy::too_many_arguments)]
+    pub(crate) fn push(
         &mut self,
         ident: Ident,
-        abi: Abi,
+        abi: ClangAbi,
         is_variadic: bool,
         is_required: bool,
         args: Vec<proc_macro2::TokenStream>,
         args_identifiers: Vec<proc_macro2::TokenStream>,
         ret: proc_macro2::TokenStream,
         ret_ty: proc_macro2::TokenStream,
+        attributes: Vec<proc_macro2::TokenStream>,
+        ctx: &BindgenContext,
     ) {
         if !is_variadic {
             assert_eq!(args.len(), args_identifiers.len());
@@ -145,14 +159,17 @@
         } else {
             quote! { self.#ident.as_ref().expect("Expected function, got error.") }
         };
-        let call_body = quote! {
-            (#fn_)(#( #args_identifiers ),*)
+        let call_body = if ctx.options().wrap_unsafe_ops {
+            quote!(unsafe { (#fn_)(#( #args_identifiers ),*) })
+        } else {
+            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! {
+                #(#attributes)*
                 pub unsafe fn #ident ( &self, #( #args ),* ) -> #ret_ty {
                     #call_body
                 }
@@ -161,13 +178,19 @@
 
         // 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());
+        let library_get = if ctx.options().wrap_unsafe_ops {
+            quote!(unsafe { __library.get(#ident_str) })
+        } else {
+            quote!(__library.get(#ident_str))
+        };
+
         self.constructor_inits.push(if is_required {
             quote! {
-                let #ident = __library.get(#ident_str).map(|sym| *sym)?;
+                let #ident = #library_get.map(|sym| *sym)?;
             }
         } else {
             quote! {
-                let #ident = __library.get(#ident_str).map(|sym| *sym);
+                let #ident = #library_get.map(|sym| *sym);
             }
         });
 
diff --git a/src/codegen/error.rs b/codegen/error.rs
similarity index 100%
rename from src/codegen/error.rs
rename to codegen/error.rs
diff --git a/src/codegen/helpers.rs b/codegen/helpers.rs
similarity index 93%
rename from src/codegen/helpers.rs
rename to codegen/helpers.rs
index 2ce6894..088c7f9 100644
--- a/src/codegen/helpers.rs
+++ b/codegen/helpers.rs
@@ -30,7 +30,7 @@
         let which_ones = which_ones
             .iter()
             .cloned()
-            .map(|one| Ident::new(one, Span::call_site()));
+            .map(|one| TokenStream::from_str(one).expect("derive to be valid"));
         quote! {
             #[derive( #( #which_ones ),* )]
         }
@@ -55,9 +55,11 @@
     }
 
     pub fn doc(comment: String) -> TokenStream {
-        // NOTE(emilio): By this point comments are already preprocessed and in
-        // `///` form. Quote turns them into `#[doc]` comments, but oh well.
-        TokenStream::from_str(&comment).unwrap()
+        if comment.is_empty() {
+            quote!()
+        } else {
+            quote!(#[doc = #comment])
+        }
     }
 
     pub fn link_name(name: &str) -> TokenStream {
@@ -166,9 +168,19 @@
                     #prefix::#ident
                 }
             }
-            None => quote! {
-                ::std::os::raw::#ident
-            },
+            None => {
+                if ctx.options().use_core &&
+                    ctx.options().rust_features().core_ffi_c
+                {
+                    quote! {
+                        ::core::ffi::#ident
+                    }
+                } else {
+                    quote! {
+                        ::std::os::raw::#ident
+                    }
+                }
+            }
         }
     }
 
diff --git a/src/codegen/impl_debug.rs b/codegen/impl_debug.rs
similarity index 100%
rename from src/codegen/impl_debug.rs
rename to codegen/impl_debug.rs
diff --git a/src/codegen/impl_partialeq.rs b/codegen/impl_partialeq.rs
similarity index 100%
rename from src/codegen/impl_partialeq.rs
rename to codegen/impl_partialeq.rs
diff --git a/src/codegen/mod.rs b/codegen/mod.rs
similarity index 89%
rename from src/codegen/mod.rs
rename to codegen/mod.rs
index 19886e3..e537242 100644
--- a/src/codegen/mod.rs
+++ b/codegen/mod.rs
@@ -3,6 +3,7 @@
 mod helpers;
 mod impl_debug;
 mod impl_partialeq;
+mod postprocessing;
 pub mod struct_layout;
 
 #[cfg(test)]
@@ -19,10 +20,9 @@
 
 use crate::ir::analysis::{HasVtable, Sizedness};
 use crate::ir::annotations::FieldAccessorKind;
-use crate::ir::comment;
 use crate::ir::comp::{
-    Base, Bitfield, BitfieldUnit, CompInfo, CompKind, Field, FieldData,
-    FieldMethods, Method, MethodKind,
+    Bitfield, BitfieldUnit, CompInfo, CompKind, Field, FieldData, FieldMethods,
+    Method, MethodKind,
 };
 use crate::ir::context::{BindgenContext, ItemId};
 use crate::ir::derive::{
@@ -31,7 +31,9 @@
 };
 use crate::ir::dot;
 use crate::ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
-use crate::ir::function::{Abi, Function, FunctionKind, FunctionSig, Linkage};
+use crate::ir::function::{
+    Abi, ClangAbi, Function, FunctionKind, FunctionSig, Linkage,
+};
 use crate::ir::int::IntKind;
 use crate::ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath};
 use crate::ir::item_kind::ItemKind;
@@ -84,7 +86,7 @@
     let mut path = top_level_path(ctx, module);
 
     let root = ctx.root_module().canonical_name(ctx);
-    let root_ident = ctx.rust_ident(&root);
+    let root_ident = ctx.rust_ident(root);
     path.push(quote! { #root_ident });
 
     let mut tokens = quote! {};
@@ -110,17 +112,13 @@
     }
 }
 
-fn derives_of_item(item: &Item, ctx: &BindgenContext) -> DerivableTraits {
+fn derives_of_item(
+    item: &Item,
+    ctx: &BindgenContext,
+    packed: bool,
+) -> DerivableTraits {
     let mut derivable_traits = DerivableTraits::empty();
 
-    if item.can_derive_debug(ctx) && !item.annotations().disallow_debug() {
-        derivable_traits |= DerivableTraits::DEBUG;
-    }
-
-    if item.can_derive_default(ctx) && !item.annotations().disallow_default() {
-        derivable_traits |= DerivableTraits::DEFAULT;
-    }
-
     let all_template_params = item.all_template_params(ctx);
 
     if item.can_derive_copy(ctx) && !item.annotations().disallow_copy() {
@@ -137,6 +135,18 @@
             // It's not hard to fix though.
             derivable_traits |= DerivableTraits::CLONE;
         }
+    } else if packed {
+        // If the struct or union is packed, deriving from Copy is required for
+        // deriving from any other trait.
+        return derivable_traits;
+    }
+
+    if item.can_derive_debug(ctx) && !item.annotations().disallow_debug() {
+        derivable_traits |= DerivableTraits::DEBUG;
+    }
+
+    if item.can_derive_default(ctx) && !item.annotations().disallow_default() {
+        derivable_traits |= DerivableTraits::DEFAULT;
     }
 
     if item.can_derive_hash(ctx) {
@@ -788,7 +798,7 @@
                     }
                 };
 
-                let rust_name = ctx.rust_ident(&name);
+                let rust_name = ctx.rust_ident(name);
 
                 let mut tokens = if let Some(comment) = item.comment(ctx) {
                     attributes::doc(comment)
@@ -828,9 +838,34 @@
                 }
 
                 // If this is a known named type, disallow generating anything
-                // for it too.
+                // for it too. If size_t -> usize conversions are enabled, we
+                // need to check that these conversions are permissible, but
+                // nothing needs to be generated, still.
                 let spelling = self.name().expect("Unnamed alias?");
                 if utils::type_from_named(ctx, spelling).is_some() {
+                    if let "size_t" | "ssize_t" = spelling {
+                        let layout = inner_item
+                            .kind()
+                            .expect_type()
+                            .layout(ctx)
+                            .expect("No layout?");
+                        assert_eq!(
+                            layout.size,
+                            ctx.target_pointer_size(),
+                            "Target platform requires `--no-size_t-is-usize`. The size of `{}` ({}) does not match the target pointer size ({})",
+                            spelling,
+                            layout.size,
+                            ctx.target_pointer_size(),
+                            );
+                        assert_eq!(
+                            layout.align,
+                            ctx.target_pointer_size(),
+                            "Target platform requires `--no-size_t-is-usize`. The alignment of `{}` ({}) does not match the target pointer size ({})",
+                            spelling,
+                            layout.align,
+                            ctx.target_pointer_size(),
+                        );
+                    }
                     return;
                 }
 
@@ -926,7 +961,9 @@
 
                         let mut attributes =
                             vec![attributes::repr("transparent")];
-                        let derivable_traits = derives_of_item(item, ctx);
+                        let packed = false; // Types can't be packed in Rust.
+                        let derivable_traits =
+                            derives_of_item(item, ctx, packed);
                         if !derivable_traits.is_empty() {
                             let derives: Vec<_> = derivable_traits.into();
                             attributes.push(attributes::derives(&derives))
@@ -1017,23 +1054,14 @@
 
 struct Vtable<'a> {
     item_id: ItemId,
+    /// A reference to the originating compound object.
     #[allow(dead_code)]
-    methods: &'a [Method],
-    #[allow(dead_code)]
-    base_classes: &'a [Base],
+    comp_info: &'a CompInfo,
 }
 
 impl<'a> Vtable<'a> {
-    fn new(
-        item_id: ItemId,
-        methods: &'a [Method],
-        base_classes: &'a [Base],
-    ) -> Self {
-        Vtable {
-            item_id,
-            methods,
-            base_classes,
-        }
+    fn new(item_id: ItemId, comp_info: &'a CompInfo) -> Self {
+        Vtable { item_id, comp_info }
     }
 }
 
@@ -1049,15 +1077,69 @@
     ) {
         assert_eq!(item.id(), self.item_id);
         debug_assert!(item.is_enabled_for_codegen(ctx));
+        let name = ctx.rust_ident(self.canonical_name(ctx));
 
-        // For now, generate an empty struct, later we should generate function
-        // pointers and whatnot.
-        let name = ctx.rust_ident(&self.canonical_name(ctx));
-        let void = helpers::ast_ty::c_void(ctx);
-        result.push(quote! {
-            #[repr(C)]
-            pub struct #name ( #void );
-        });
+        // For now, we will only generate vtables for classes that:
+        // - do not inherit from others (compilers merge VTable from primary parent class).
+        // - do not contain a virtual destructor (requires ordering; platforms generate different vtables).
+        if ctx.options().vtable_generation &&
+            self.comp_info.base_members().is_empty() &&
+            self.comp_info.destructor().is_none()
+        {
+            let class_ident = ctx.rust_ident(self.item_id.canonical_name(ctx));
+
+            let methods = self
+                .comp_info
+                .methods()
+                .iter()
+                .filter_map(|m| {
+                    if !m.is_virtual() {
+                        return None;
+                    }
+
+                    let function_item = ctx.resolve_item(m.signature());
+                    let function = function_item.expect_function();
+                    let signature_item = ctx.resolve_item(function.signature());
+                    let signature = match signature_item.expect_type().kind() {
+                        TypeKind::Function(ref sig) => sig,
+                        _ => panic!("Function signature type mismatch"),
+                    };
+
+                    // FIXME: Is there a canonical name without the class prepended?
+                    let function_name = function_item.canonical_name(ctx);
+
+                    // FIXME: Need to account for overloading with times_seen (separately from regular function path).
+                    let function_name = ctx.rust_ident(function_name);
+                    let mut args = utils::fnsig_arguments(ctx, signature);
+                    let ret = utils::fnsig_return_ty(ctx, signature);
+
+                    args[0] = if m.is_const() {
+                        quote! { this: *const #class_ident }
+                    } else {
+                        quote! { this: *mut #class_ident }
+                    };
+
+                    Some(quote! {
+                        pub #function_name : unsafe extern "C" fn( #( #args ),* ) #ret
+                    })
+                })
+                .collect::<Vec<_>>();
+
+            result.push(quote! {
+                #[repr(C)]
+                pub struct #name {
+                    #( #methods ),*
+                }
+            })
+        } else {
+            // For the cases we don't support, simply generate an empty struct.
+            let void = helpers::ast_ty::c_void(ctx);
+
+            result.push(quote! {
+                #[repr(C)]
+                pub struct #name ( #void );
+            });
+        }
     }
 }
 
@@ -1157,11 +1239,11 @@
 trait FieldCodegen<'a> {
     type Extra;
 
+    #[allow(clippy::too_many_arguments)]
     fn codegen<F, M>(
         &self,
         ctx: &BindgenContext,
         fields_should_be_private: bool,
-        codegen_depth: usize,
         accessor_kind: FieldAccessorKind,
         parent: &CompInfo,
         result: &mut CodegenResult,
@@ -1181,7 +1263,6 @@
         &self,
         ctx: &BindgenContext,
         fields_should_be_private: bool,
-        codegen_depth: usize,
         accessor_kind: FieldAccessorKind,
         parent: &CompInfo,
         result: &mut CodegenResult,
@@ -1198,7 +1279,6 @@
                 data.codegen(
                     ctx,
                     fields_should_be_private,
-                    codegen_depth,
                     accessor_kind,
                     parent,
                     result,
@@ -1212,7 +1292,6 @@
                 unit.codegen(
                     ctx,
                     fields_should_be_private,
-                    codegen_depth,
                     accessor_kind,
                     parent,
                     result,
@@ -1226,6 +1305,35 @@
     }
 }
 
+fn wrap_union_field_if_needed(
+    ctx: &BindgenContext,
+    struct_layout: &StructLayoutTracker,
+    ty: proc_macro2::TokenStream,
+    result: &mut CodegenResult,
+) -> proc_macro2::TokenStream {
+    if struct_layout.is_rust_union() {
+        if struct_layout.can_copy_union_fields() {
+            ty
+        } else {
+            let prefix = ctx.trait_prefix();
+            quote! {
+                ::#prefix::mem::ManuallyDrop<#ty>
+            }
+        }
+    } else {
+        result.saw_bindgen_union();
+        if ctx.options().enable_cxx_namespaces {
+            quote! {
+                root::__BindgenUnionField<#ty>
+            }
+        } else {
+            quote! {
+                __BindgenUnionField<#ty>
+            }
+        }
+    }
+}
+
 impl<'a> FieldCodegen<'a> for FieldData {
     type Extra = ();
 
@@ -1233,7 +1341,6 @@
         &self,
         ctx: &BindgenContext,
         fields_should_be_private: bool,
-        codegen_depth: usize,
         accessor_kind: FieldAccessorKind,
         parent: &CompInfo,
         result: &mut CodegenResult,
@@ -1256,17 +1363,8 @@
         ty.append_implicit_template_params(ctx, field_item);
 
         // NB: If supported, we use proper `union` types.
-        let ty = if parent.is_union() && !struct_layout.is_rust_union() {
-            result.saw_bindgen_union();
-            if ctx.options().enable_cxx_namespaces {
-                quote! {
-                    root::__BindgenUnionField<#ty>
-                }
-            } else {
-                quote! {
-                    __BindgenUnionField<#ty>
-                }
-            }
+        let ty = if parent.is_union() {
+            wrap_union_field_if_needed(ctx, struct_layout, ty, result)
         } else if let Some(item) = field_ty.is_incomplete_array(ctx) {
             result.saw_incomplete_array();
 
@@ -1288,8 +1386,7 @@
         let mut field = quote! {};
         if ctx.options().generate_comments {
             if let Some(raw_comment) = self.comment() {
-                let comment =
-                    comment::preprocess(raw_comment, codegen_depth + 1);
+                let comment = ctx.options().process_comment(raw_comment);
                 field = attributes::doc(comment);
             }
         }
@@ -1449,7 +1546,6 @@
         &self,
         ctx: &BindgenContext,
         fields_should_be_private: bool,
-        codegen_depth: usize,
         accessor_kind: FieldAccessorKind,
         parent: &CompInfo,
         result: &mut CodegenResult,
@@ -1467,26 +1563,20 @@
 
         let layout = self.layout();
         let unit_field_ty = helpers::bitfield_unit(ctx, layout);
-        let field_ty = {
-            if parent.is_union() && !struct_layout.is_rust_union() {
-                result.saw_bindgen_union();
-                if ctx.options().enable_cxx_namespaces {
-                    quote! {
-                        root::__BindgenUnionField<#unit_field_ty>
-                    }
-                } else {
-                    quote! {
-                        __BindgenUnionField<#unit_field_ty>
-                    }
-                }
-            } else {
-                unit_field_ty.clone()
-            }
+        let field_ty = if parent.is_union() {
+            wrap_union_field_if_needed(
+                ctx,
+                struct_layout,
+                unit_field_ty.clone(),
+                result,
+            )
+        } else {
+            unit_field_ty.clone()
         };
 
         {
             let align_field_name = format!("_bitfield_align_{}", self.nth());
-            let align_field_ident = ctx.rust_ident(&align_field_name);
+            let align_field_ident = ctx.rust_ident(align_field_name);
             let align_ty = match self.layout().align {
                 n if n >= 8 => quote! { u64 },
                 4 => quote! { u32 },
@@ -1532,7 +1622,6 @@
             bf.codegen(
                 ctx,
                 fields_should_be_private,
-                codegen_depth,
                 accessor_kind,
                 parent,
                 result,
@@ -1607,7 +1696,6 @@
         &self,
         ctx: &BindgenContext,
         fields_should_be_private: bool,
-        _codegen_depth: usize,
         _accessor_kind: FieldAccessorKind,
         parent: &CompInfo,
         _result: &mut CodegenResult,
@@ -1749,8 +1837,7 @@
 
         if !is_opaque {
             if item.has_vtable_ptr(ctx) {
-                let vtable =
-                    Vtable::new(item.id(), self.methods(), self.base_members());
+                let vtable = Vtable::new(item.id(), self);
                 vtable.codegen(ctx, result, item);
 
                 let vtable_type = vtable
@@ -1786,7 +1873,6 @@
 
         let mut methods = vec![];
         if !is_opaque {
-            let codegen_depth = item.codegen_depth(ctx);
             let fields_should_be_private =
                 item.annotations().private_fields().unwrap_or(false);
             let struct_accessor_kind = item
@@ -1797,7 +1883,6 @@
                 field.codegen(
                     ctx,
                     fields_should_be_private,
-                    codegen_depth,
                     struct_accessor_kind,
                     self,
                     result,
@@ -1982,7 +2067,7 @@
             }
         }
 
-        let derivable_traits = derives_of_item(item, ctx);
+        let derivable_traits = derives_of_item(item, ctx, packed);
         if !derivable_traits.contains(DerivableTraits::DEBUG) {
             needs_debug_impl = ctx.options().derive_debug &&
                 ctx.options().impl_debug &&
@@ -2017,19 +2102,19 @@
 
         // The custom derives callback may return a list of derive attributes;
         // add them to the end of the list.
-        let custom_derives;
-        if let Some(cb) = &ctx.options().parse_callbacks {
-            custom_derives = cb.add_derives(&canonical_name);
-            // 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()));
-        };
+        let custom_derives = ctx.options().all_callbacks(|cb| {
+            cb.add_derives(&crate::callbacks::DeriveInfo {
+                name: &canonical_name,
+            })
+        });
+        // 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()));
 
         if !derives.is_empty() {
             attributes.push(attributes::derives(&derives))
         }
 
-        if item.annotations().must_use_type() || ctx.must_use_type_by_name(item)
-        {
+        if item.must_use(ctx) {
             attributes.push(attributes::must_use());
         }
 
@@ -2123,41 +2208,52 @@
                     {
                         vec![]
                     } else {
-                        let asserts = self.fields()
-                                .iter()
-                                .filter_map(|field| match *field {
-                                    Field::DataMember(ref f) if f.name().is_some() => Some(f),
-                                    _ => None,
+                        self.fields()
+                            .iter()
+                            .filter_map(|field| match *field {
+                                Field::DataMember(ref f) if f.name().is_some() => Some(f),
+                                _ => None,
+                            })
+                            .flat_map(|field| {
+                                let name = field.name().unwrap();
+                                field.offset().map(|offset| {
+                                    let field_offset = offset / 8;
+                                    let field_name = ctx.rust_ident(name);
+                                    quote! {
+                                        assert_eq!(
+                                            unsafe {
+                                                ::#prefix::ptr::addr_of!((*ptr).#field_name) as usize - ptr as usize
+                                            },
+                                            #field_offset,
+                                            concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name))
+                                        );
+                                    }
                                 })
-                                .flat_map(|field| {
-                                    let name = field.name().unwrap();
-                                    field.offset().map(|offset| {
-                                        let field_offset = offset / 8;
-                                        let field_name = ctx.rust_ident(name);
+                            })
+                            .collect()
+                    };
 
-                                        quote! {
-                                            assert_eq!(
-                                                unsafe {
-                                                    &(*(::#prefix::ptr::null::<#canonical_ident>())).#field_name as *const _ as usize
-                                                },
-                                                #field_offset,
-                                                concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name))
-                                            );
-                                        }
-                                    })
-                                })
-                                .collect::<Vec<proc_macro2::TokenStream>>();
-
-                        asserts
+                    let uninit_decl = if !check_field_offset.is_empty() {
+                        // FIXME: When MSRV >= 1.59.0, we can use
+                        // > const PTR: *const #canonical_ident = ::#prefix::mem::MaybeUninit::uninit().as_ptr();
+                        Some(quote! {
+                            // Use a shared MaybeUninit so that rustc with
+                            // opt-level=0 doesn't take too much stack space,
+                            // see #2218.
+                            const UNINIT: ::#prefix::mem::MaybeUninit<#canonical_ident> = ::#prefix::mem::MaybeUninit::uninit();
+                            let ptr = UNINIT.as_ptr();
+                        })
+                    } else {
+                        None
                     };
 
                     let item = quote! {
                         #[test]
                         fn #fn_name() {
+                            #uninit_decl
                             assert_eq!(#size_of_expr,
                                        #size,
                                        concat!("Size of: ", stringify!(#canonical_ident)));
-
                             #check_struct_align
                             #( #check_field_offset )*
                         }
@@ -2315,7 +2411,7 @@
         &self,
         ctx: &BindgenContext,
         methods: &mut Vec<proc_macro2::TokenStream>,
-        method_names: &mut HashMap<String, usize>,
+        method_names: &mut HashSet<String>,
         result: &mut CodegenResult<'a>,
         parent: &CompInfo,
     );
@@ -2326,7 +2422,7 @@
         &self,
         ctx: &BindgenContext,
         methods: &mut Vec<proc_macro2::TokenStream>,
-        method_names: &mut HashMap<String, usize>,
+        method_names: &mut HashSet<String>,
         result: &mut CodegenResult<'a>,
         _parent: &CompInfo,
     ) {
@@ -2370,9 +2466,20 @@
             _ => panic!("How in the world?"),
         };
 
-        if let (Abi::ThisCall, false) =
-            (signature.abi(), ctx.options().rust_features().thiscall_abi)
-        {
+        let supported_abi = match signature.abi(ctx, Some(&*name)) {
+            ClangAbi::Known(Abi::ThisCall) => {
+                ctx.options().rust_features().thiscall_abi
+            }
+            ClangAbi::Known(Abi::Vectorcall) => {
+                ctx.options().rust_features().vectorcall_abi
+            }
+            ClangAbi::Known(Abi::CUnwind) => {
+                ctx.options().rust_features().c_unwind_abi
+            }
+            _ => true,
+        };
+
+        if !supported_abi {
             return;
         }
 
@@ -2382,16 +2489,22 @@
             return;
         }
 
-        let count = {
-            let count = method_names.entry(name.clone()).or_insert(0);
-            *count += 1;
-            *count - 1
-        };
+        if method_names.contains(&name) {
+            let mut count = 1;
+            let mut new_name;
 
-        if count != 0 {
-            name.push_str(&count.to_string());
+            while {
+                new_name = format!("{}{}", name, count);
+                method_names.contains(&new_name)
+            } {
+                count += 1;
+            }
+
+            name = new_name;
         }
 
+        method_names.insert(name.clone());
+
         let mut function_name = function_item.canonical_name(ctx);
         if times_seen > 0 {
             write!(&mut function_name, "{}", times_seen).unwrap();
@@ -2472,9 +2585,7 @@
             })
         }
 
-        let block = quote! {
-            #( #stmts );*
-        };
+        let block = ctx.wrap_unsafe_ops(quote! ( #( #stmts );*));
 
         let mut attrs = vec![attributes::inline()];
 
@@ -2495,7 +2606,7 @@
 }
 
 /// A helper type that represents different enum variations.
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum EnumVariation {
     /// The code for this enum will use a Rust enum. Note that creating this in unsafe code
     /// (including FFI) with an invalid value will invoke undefined behaviour, whether or not
@@ -2508,6 +2619,8 @@
     NewType {
         /// Indicates whether the newtype will have bitwise operators
         is_bitfield: bool,
+        /// Indicates whether the variants will be represented as global constants
+        is_global: bool,
     },
     /// The code for this enum will use consts
     Consts,
@@ -2545,16 +2658,26 @@
             "rust_non_exhaustive" => Ok(EnumVariation::Rust {
                 non_exhaustive: true,
             }),
-            "bitfield" => Ok(EnumVariation::NewType { is_bitfield: true }),
+            "bitfield" => Ok(EnumVariation::NewType {
+                is_bitfield: true,
+                is_global: false,
+            }),
             "consts" => Ok(EnumVariation::Consts),
             "moduleconsts" => Ok(EnumVariation::ModuleConsts),
-            "newtype" => Ok(EnumVariation::NewType { is_bitfield: false }),
+            "newtype" => Ok(EnumVariation::NewType {
+                is_bitfield: false,
+                is_global: false,
+            }),
+            "newtype_global" => Ok(EnumVariation::NewType {
+                is_bitfield: false,
+                is_global: true,
+            }),
             _ => Err(std::io::Error::new(
                 std::io::ErrorKind::InvalidInput,
                 concat!(
                     "Got an invalid EnumVariation. Accepted values ",
                     "are 'rust', 'rust_non_exhaustive', 'bitfield', 'consts',",
-                    "'moduleconsts', and 'newtype'."
+                    "'moduleconsts', 'newtype' and 'newtype_global'."
                 ),
             )),
         }
@@ -2564,41 +2687,27 @@
 /// A helper type to construct different enum variations.
 enum EnumBuilder<'a> {
     Rust {
-        codegen_depth: usize,
         attrs: Vec<proc_macro2::TokenStream>,
         ident: Ident,
         tokens: proc_macro2::TokenStream,
         emitted_any_variants: bool,
     },
     NewType {
-        codegen_depth: usize,
         canonical_name: &'a str,
         tokens: proc_macro2::TokenStream,
         is_bitfield: bool,
+        is_global: bool,
     },
     Consts {
-        repr: proc_macro2::TokenStream,
         variants: Vec<proc_macro2::TokenStream>,
-        codegen_depth: usize,
     },
     ModuleConsts {
-        codegen_depth: usize,
         module_name: &'a str,
         module_items: Vec<proc_macro2::TokenStream>,
     },
 }
 
 impl<'a> EnumBuilder<'a> {
-    /// Returns the depth of the code generation for a variant of this enum.
-    fn codegen_depth(&self) -> usize {
-        match *self {
-            EnumBuilder::Rust { codegen_depth, .. } |
-            EnumBuilder::NewType { codegen_depth, .. } |
-            EnumBuilder::ModuleConsts { codegen_depth, .. } |
-            EnumBuilder::Consts { codegen_depth, .. } => codegen_depth,
-        }
-    }
-
     /// Returns true if the builder is for a rustified enum.
     fn is_rust_enum(&self) -> bool {
         matches!(*self, EnumBuilder::Rust { .. })
@@ -2611,19 +2720,21 @@
         mut attrs: Vec<proc_macro2::TokenStream>,
         repr: proc_macro2::TokenStream,
         enum_variation: EnumVariation,
-        enum_codegen_depth: usize,
     ) -> Self {
         let ident = Ident::new(name, Span::call_site());
 
         match enum_variation {
-            EnumVariation::NewType { is_bitfield } => EnumBuilder::NewType {
-                codegen_depth: enum_codegen_depth,
+            EnumVariation::NewType {
+                is_bitfield,
+                is_global,
+            } => EnumBuilder::NewType {
                 canonical_name: name,
                 tokens: quote! {
                     #( #attrs )*
                     pub struct #ident (pub #repr);
                 },
                 is_bitfield,
+                is_global,
             },
 
             EnumVariation::Rust { .. } => {
@@ -2631,7 +2742,6 @@
                 attrs.insert(0, quote! { #[repr( #repr )] });
                 let tokens = quote!();
                 EnumBuilder::Rust {
-                    codegen_depth: enum_codegen_depth + 1,
                     attrs,
                     ident,
                     tokens,
@@ -2647,11 +2757,7 @@
                     pub type #ident = #repr;
                 });
 
-                EnumBuilder::Consts {
-                    repr,
-                    variants,
-                    codegen_depth: enum_codegen_depth,
-                }
+                EnumBuilder::Consts { variants }
             }
 
             EnumVariation::ModuleConsts => {
@@ -2665,7 +2771,6 @@
                 };
 
                 EnumBuilder::ModuleConsts {
-                    codegen_depth: enum_codegen_depth + 1,
                     module_name: name,
                     module_items: vec![type_definition],
                 }
@@ -2697,8 +2802,7 @@
         let mut doc = quote! {};
         if ctx.options().generate_comments {
             if let Some(raw_comment) = variant.comment() {
-                let comment =
-                    comment::preprocess(raw_comment, self.codegen_depth());
+                let comment = ctx.options().process_comment(raw_comment);
                 doc = attributes::doc(comment);
             }
         }
@@ -2709,13 +2813,11 @@
                 ident,
                 tokens,
                 emitted_any_variants: _,
-                codegen_depth,
             } => {
                 let name = ctx.rust_ident(variant_name);
                 EnumBuilder::Rust {
                     attrs,
                     ident,
-                    codegen_depth,
                     tokens: quote! {
                         #tokens
                         #doc
@@ -2725,11 +2827,18 @@
                 }
             }
 
-            EnumBuilder::NewType { canonical_name, .. } => {
-                if ctx.options().rust_features().associated_const && is_ty_named
+            EnumBuilder::NewType {
+                canonical_name,
+                is_global,
+                ..
+            } => {
+                if ctx.options().rust_features().associated_const &&
+                    is_ty_named &&
+                    !is_global
                 {
                     let enum_ident = ctx.rust_ident(canonical_name);
                     let variant_ident = ctx.rust_ident(variant_name);
+
                     result.push(quote! {
                         impl #enum_ident {
                             #doc
@@ -2752,7 +2861,7 @@
                 self
             }
 
-            EnumBuilder::Consts { ref repr, .. } => {
+            EnumBuilder::Consts { .. } => {
                 let constant_name = match mangling_prefix {
                     Some(prefix) => {
                         Cow::Owned(format!("{}_{}", prefix, variant_name))
@@ -2760,18 +2869,15 @@
                     None => variant_name,
                 };
 
-                let ty = if is_ty_named { &rust_ty } else { repr };
-
                 let ident = ctx.rust_ident(constant_name);
                 result.push(quote! {
                     #doc
-                    pub const #ident : #ty = #expr ;
+                    pub const #ident : #rust_ty = #expr ;
                 });
 
                 self
             }
             EnumBuilder::ModuleConsts {
-                codegen_depth,
                 module_name,
                 mut module_items,
             } => {
@@ -2785,7 +2891,6 @@
                 EnumBuilder::ModuleConsts {
                     module_name,
                     module_items,
-                    codegen_depth,
                 }
             }
         }
@@ -2998,21 +3103,16 @@
             attrs.push(attributes::doc(comment));
         }
 
-        if item.annotations().must_use_type() || ctx.must_use_type_by_name(item)
-        {
+        if item.must_use(ctx) {
             attrs.push(attributes::must_use());
         }
 
         if !variation.is_const() {
-            let mut derives = derives_of_item(item, ctx);
-            // For backwards compat, enums always derive Debug/Clone/Eq/PartialEq/Hash, even
-            // if we don't generate those by default.
-            if !item.annotations().disallow_debug() {
-                derives.insert(DerivableTraits::DEBUG);
-            }
-            if !item.annotations().disallow_copy() {
-                derives.insert(DerivableTraits::COPY);
-            }
+            let packed = false; // Enums can't be packed in Rust.
+            let mut derives = derives_of_item(item, ctx, packed);
+            // For backwards compat, enums always derive
+            // Clone/Eq/PartialEq/Hash, even if we don't generate those by
+            // default.
             derives.insert(
                 DerivableTraits::CLONE |
                     DerivableTraits::HASH |
@@ -3028,12 +3128,11 @@
 
             // The custom derives callback may return a list of derive attributes;
             // add them to the end of the list.
-            let custom_derives;
-            if let Some(cb) = &ctx.options().parse_callbacks {
-                custom_derives = cb.add_derives(&name);
-                // 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()));
-            };
+            let custom_derives = ctx.options().all_callbacks(|cb| {
+                cb.add_derives(&crate::callbacks::DeriveInfo { name: &name })
+            });
+            // 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()));
 
             attrs.push(attributes::derives(&derives));
         }
@@ -3070,13 +3169,7 @@
 
         let repr = repr.to_rust_ty_or_opaque(ctx, item);
 
-        let mut builder = EnumBuilder::new(
-            &name,
-            attrs,
-            repr,
-            variation,
-            item.codegen_depth(ctx),
-        );
+        let mut builder = EnumBuilder::new(&name, attrs, repr, variation);
 
         // A map where we keep a value -> variant relation.
         let mut seen_values = HashMap::<_, Ident>::default();
@@ -3154,7 +3247,7 @@
                                 ctx,
                                 enum_ty,
                                 &ident,
-                                &Ident::new(&*mangled_name, Span::call_site()),
+                                &Ident::new(&mangled_name, Span::call_site()),
                                 existing_variant_name,
                                 enum_rust_ty.clone(),
                                 result,
@@ -3223,7 +3316,7 @@
 }
 
 /// Enum for the default type of macro constants.
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum MacroTypeVariation {
     /// Use i32 or i64
     Signed,
@@ -3267,7 +3360,7 @@
 }
 
 /// Enum for how aliases should be translated.
-#[derive(Copy, Clone, PartialEq, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum AliasVariation {
     /// Convert to regular Rust alias
     TypeAlias,
@@ -3314,6 +3407,52 @@
     }
 }
 
+/// Enum for how non-Copy unions should be translated.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum NonCopyUnionStyle {
+    /// Wrap members in a type generated by bindgen.
+    BindgenWrapper,
+    /// Wrap members in [`::core::mem::ManuallyDrop`].
+    ///
+    /// Note: `ManuallyDrop` was stabilized in Rust 1.20.0, do not use it if your
+    /// MSRV is lower.
+    ManuallyDrop,
+}
+
+impl NonCopyUnionStyle {
+    /// Convert an `NonCopyUnionStyle` to its str representation.
+    pub fn as_str(&self) -> &'static str {
+        match self {
+            Self::BindgenWrapper => "bindgen_wrapper",
+            Self::ManuallyDrop => "manually_drop",
+        }
+    }
+}
+
+impl Default for NonCopyUnionStyle {
+    fn default() -> Self {
+        Self::BindgenWrapper
+    }
+}
+
+impl std::str::FromStr for NonCopyUnionStyle {
+    type Err = std::io::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "bindgen_wrapper" => Ok(Self::BindgenWrapper),
+            "manually_drop" => Ok(Self::ManuallyDrop),
+            _ => Err(std::io::Error::new(
+                std::io::ErrorKind::InvalidInput,
+                concat!(
+                    "Got an invalid NonCopyUnionStyle. Accepted values ",
+                    "are 'bindgen_wrapper' and 'manually_drop'"
+                ),
+            )),
+        }
+    }
+}
+
 /// Fallible conversion to an opaque blob.
 ///
 /// Implementors of this trait should provide the `try_get_layout` method to
@@ -3705,7 +3844,7 @@
             }
             TypeKind::TypeParam => {
                 let name = item.canonical_name(ctx);
-                let ident = ctx.rust_ident(&name);
+                let ident = ctx.rust_ident(name);
                 Ok(quote! {
                     #ident
                 })
@@ -3821,13 +3960,27 @@
         // TODO: we might want to consider ignoring the reference return value.
         let ret = utils::fnsig_return_ty(ctx, self);
         let arguments = utils::fnsig_arguments(ctx, self);
-        let abi = self.abi();
+        let abi = self.abi(ctx, None);
 
         match abi {
-            Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
+            ClangAbi::Known(Abi::ThisCall)
+                if !ctx.options().rust_features().thiscall_abi =>
+            {
                 warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
                 Ok(proc_macro2::TokenStream::new())
             }
+            ClangAbi::Known(Abi::Vectorcall)
+                if !ctx.options().rust_features().vectorcall_abi =>
+            {
+                warn!("Skipping function with vectorcall ABI that isn't supported by the configured Rust target");
+                Ok(proc_macro2::TokenStream::new())
+            }
+            ClangAbi::Known(Abi::CUnwind)
+                if !ctx.options().rust_features().c_unwind_abi =>
+            {
+                warn!("Skipping function with C-unwind ABI that isn't supported by the configured Rust target");
+                Ok(proc_macro2::TokenStream::new())
+            }
             _ => Ok(quote! {
                 unsafe extern #abi fn ( #( #arguments ),* ) #ret
             }),
@@ -3860,14 +4013,17 @@
 
         // Pure virtual methods have no actual symbol, so we can't generate
         // something meaningful for them.
-        match self.kind() {
+        let is_dynamic_function = match self.kind() {
             FunctionKind::Method(ref method_kind)
                 if method_kind.is_pure_virtual() =>
             {
                 return None;
             }
-            _ => {}
-        }
+            FunctionKind::Function => {
+                ctx.options().dynamic_library_name.is_some()
+            }
+            _ => false,
+        };
 
         // Similar to static member variables in a class template, we can't
         // generate bindings to template functions, because the set of
@@ -3904,26 +4060,49 @@
 
         let mut attributes = vec![];
 
-        if signature.must_use() &&
-            ctx.options().rust_features().must_use_function
-        {
-            attributes.push(attributes::must_use());
+        if ctx.options().rust_features().must_use_function {
+            let must_use = signature.must_use() || {
+                let ret_ty = signature
+                    .return_type()
+                    .into_resolver()
+                    .through_type_refs()
+                    .resolve(ctx);
+                ret_ty.must_use(ctx)
+            };
+
+            if must_use {
+                attributes.push(attributes::must_use());
+            }
         }
 
         if let Some(comment) = item.comment(ctx) {
             attributes.push(attributes::doc(comment));
         }
 
-        let abi = match signature.abi() {
-            Abi::ThisCall if !ctx.options().rust_features().thiscall_abi => {
+        let abi = match signature.abi(ctx, Some(name)) {
+            ClangAbi::Known(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 None;
             }
-            Abi::Win64 if signature.is_variadic() => {
+            ClangAbi::Known(Abi::Vectorcall)
+                if !ctx.options().rust_features().vectorcall_abi =>
+            {
+                warn!("Skipping function with vectorcall ABI that isn't supported by the configured Rust target");
+                return None;
+            }
+            ClangAbi::Known(Abi::CUnwind)
+                if !ctx.options().rust_features().c_unwind_abi =>
+            {
+                warn!("Skipping function with C-unwind ABI that isn't supported by the configured Rust target");
+                return None;
+            }
+            ClangAbi::Known(Abi::Win64) if signature.is_variadic() => {
                 warn!("Skipping variadic function with Win64 ABI that isn't supported");
                 return None;
             }
-            Abi::Unknown(unknown_abi) => {
+            ClangAbi::Unknown(unknown_abi) => {
                 panic!(
                     "Invalid or unknown abi {:?} for function {:?} ({:?})",
                     unknown_abi, canonical_name, self
@@ -3940,11 +4119,13 @@
         }
 
         let link_name = mangled_name.unwrap_or(name);
-        if !utils::names_will_be_identical_after_mangling(
-            &canonical_name,
-            link_name,
-            Some(abi),
-        ) {
+        if !is_dynamic_function &&
+            !utils::names_will_be_identical_after_mangling(
+                &canonical_name,
+                link_name,
+                Some(abi),
+            )
+        {
             attributes.push(attributes::link_name(link_name));
         }
 
@@ -3966,9 +4147,7 @@
         };
 
         // If we're doing dynamic binding generation, add to the dynamic items.
-        if ctx.options().dynamic_library_name.is_some() &&
-            self.kind() == FunctionKind::Function
-        {
+        if is_dynamic_function {
             let args_identifiers =
                 utils::fnsig_argument_identifiers(ctx, signature);
             let return_item = ctx.resolve_item(signature.return_type());
@@ -3985,6 +4164,8 @@
                 args_identifiers,
                 ret,
                 ret_ty,
+                attributes,
+                ctx,
             );
         } else {
             result.push(tokens);
@@ -3996,9 +4177,19 @@
 fn objc_method_codegen(
     ctx: &BindgenContext,
     method: &ObjCMethod,
+    methods: &mut Vec<proc_macro2::TokenStream>,
     class_name: Option<&str>,
+    rust_class_name: &str,
     prefix: &str,
-) -> proc_macro2::TokenStream {
+) {
+    // This would ideally resolve the method into an Item, and use
+    // Item::process_before_codegen; however, ObjC methods are not currently
+    // made into function items.
+    let name = format!("{}::{}{}", rust_class_name, prefix, method.rust_name());
+    if ctx.options().blocklisted_items.matches(name) {
+        return;
+    }
+
     let signature = method.signature();
     let fn_args = utils::fnsig_arguments(ctx, signature);
     let fn_ret = utils::fnsig_return_ty(ctx, signature);
@@ -4018,29 +4209,28 @@
 
     let methods_and_args = method.format_method_call(&fn_args);
 
-    let body = if method.is_class_method() {
-        let class_name = ctx.rust_ident(
-            class_name
-                .expect("Generating a class method without class name?")
-                .to_owned(),
-        );
-        quote! {
-            msg_send!(class!(#class_name), #methods_and_args)
-        }
-    } else {
-        quote! {
-            msg_send!(*self, #methods_and_args)
-        }
+    let body = {
+        let body = if method.is_class_method() {
+            let class_name = ctx.rust_ident(
+                class_name
+                    .expect("Generating a class method without class name?"),
+            );
+            quote!(msg_send!(class!(#class_name), #methods_and_args))
+        } else {
+            quote!(msg_send!(*self, #methods_and_args))
+        };
+
+        ctx.wrap_unsafe_ops(body)
     };
 
     let method_name =
         ctx.rust_ident(format!("{}{}", prefix, method.rust_name()));
 
-    quote! {
+    methods.push(quote! {
         unsafe fn #method_name #sig where <Self as std::ops::Deref>::Target: objc::Message + Sized {
             #body
         }
-    }
+    });
 }
 
 impl CodeGenerator for ObjCInterface {
@@ -4056,10 +4246,17 @@
         debug_assert!(item.is_enabled_for_codegen(ctx));
 
         let mut impl_items = vec![];
+        let rust_class_name = item.path_for_allowlisting(ctx)[1..].join("::");
 
         for method in self.methods() {
-            let impl_item = objc_method_codegen(ctx, method, None, "");
-            impl_items.push(impl_item);
+            objc_method_codegen(
+                ctx,
+                method,
+                &mut impl_items,
+                None,
+                &rust_class_name,
+                "",
+            );
         }
 
         for class_method in self.class_methods() {
@@ -4069,13 +4266,14 @@
                 .map(|m| m.rust_name())
                 .any(|x| x == class_method.rust_name());
             let prefix = if ambiquity { "class_" } else { "" };
-            let impl_item = objc_method_codegen(
+            objc_method_codegen(
                 ctx,
                 class_method,
+                &mut impl_items,
                 Some(self.name()),
+                &rust_class_name,
                 prefix,
             );
-            impl_items.push(impl_item);
         }
 
         let trait_name = ctx.rust_ident(self.rust_name());
@@ -4090,7 +4288,7 @@
                 .collect();
 
             quote! {
-                pub trait #trait_name <#(#template_names),*> : #trait_constraints {
+                pub trait #trait_name <#(#template_names:'static),*> : #trait_constraints {
                     #( #impl_items )*
                 }
             }
@@ -4106,7 +4304,7 @@
         if !self.is_category() && !self.is_protocol() {
             let struct_block = quote! {
                 #[repr(transparent)]
-                #[derive(Clone)]
+                #[derive(Debug, Copy, Clone)]
                 pub struct #class_name(pub id);
                 impl std::ops::Deref for #class_name {
                     type Target = objc::runtime::Object;
@@ -4120,7 +4318,7 @@
                 impl #class_name {
                     pub fn alloc() -> Self {
                         Self(unsafe {
-                            msg_send!(objc::class!(#class_name), alloc)
+                            msg_send!(class!(#class_name), alloc)
                         })
                     }
                 }
@@ -4247,7 +4445,7 @@
 
 pub(crate) fn codegen(
     context: BindgenContext,
-) -> (Vec<proc_macro2::TokenStream>, BindgenOptions) {
+) -> (proc_macro2::TokenStream, BindgenOptions, Vec<String>) {
     context.gen(|context| {
         let _t = context.timer("codegen");
         let counter = Cell::new(0);
@@ -4293,18 +4491,18 @@
         if let Some(ref lib_name) = context.options().dynamic_library_name {
             let lib_ident = context.rust_ident(lib_name);
             let dynamic_items_tokens =
-                result.dynamic_items().get_tokens(lib_ident);
+                result.dynamic_items().get_tokens(lib_ident, context);
             result.push(dynamic_items_tokens);
         }
 
-        result.items
+        postprocessing::postprocessing(result.items, context.options())
     })
 }
 
 pub mod utils {
     use super::{error, ToRustTyOrOpaque};
     use crate::ir::context::BindgenContext;
-    use crate::ir::function::{Abi, FunctionSig};
+    use crate::ir::function::{Abi, ClangAbi, FunctionSig};
     use crate::ir::item::{Item, ItemCanonicalPath};
     use crate::ir::ty::TypeKind;
     use proc_macro2;
@@ -4342,7 +4540,7 @@
             }
         } else {
             quote! {
-                use objc;
+                use objc::{self, msg_send, sel, sel_impl, class};
             }
         };
 
@@ -4396,6 +4594,9 @@
             pub struct __BindgenUnionField<T>(::#prefix::marker::PhantomData<T>);
         };
 
+        let transmute =
+            ctx.wrap_unsafe_ops(quote!(::#prefix::mem::transmute(self)));
+
         let union_field_impl = quote! {
             impl<T> __BindgenUnionField<T> {
                 #[inline]
@@ -4405,12 +4606,12 @@
 
                 #[inline]
                 pub unsafe fn as_ref(&self) -> &T {
-                    ::#prefix::mem::transmute(self)
+                    #transmute
                 }
 
                 #[inline]
                 pub unsafe fn as_mut(&mut self) -> &mut T {
-                    ::#prefix::mem::transmute(self)
+                    #transmute
                 }
             }
         };
@@ -4505,6 +4706,13 @@
                 ::#prefix::marker::PhantomData<T>, [T; 0]);
         };
 
+        let from_raw_parts = ctx.wrap_unsafe_ops(quote! (
+            ::#prefix::slice::from_raw_parts(self.as_ptr(), len)
+        ));
+        let from_raw_parts_mut = ctx.wrap_unsafe_ops(quote! (
+            ::#prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
+        ));
+
         let incomplete_array_impl = quote! {
             impl<T> __IncompleteArrayField<T> {
                 #[inline]
@@ -4524,12 +4732,12 @@
 
                 #[inline]
                 pub unsafe fn as_slice(&self, len: usize) -> &[T] {
-                    ::#prefix::slice::from_raw_parts(self.as_ptr(), len)
+                    #from_raw_parts
                 }
 
                 #[inline]
                 pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] {
-                    ::#prefix::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
+                    #from_raw_parts_mut
                 }
             }
         };
@@ -4622,6 +4830,10 @@
         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! {}
@@ -4761,10 +4973,10 @@
     // Returns true if `canonical_name` will end up as `mangled_name` at the
     // machine code level, i.e. after LLVM has applied any target specific
     // mangling.
-    pub fn names_will_be_identical_after_mangling(
+    pub(crate) fn names_will_be_identical_after_mangling(
         canonical_name: &str,
         mangled_name: &str,
-        call_conv: Option<Abi>,
+        call_conv: Option<ClangAbi>,
     ) -> bool {
         // If the mangled name and the canonical name are the same then no
         // mangling can have happened between the two versions.
@@ -4777,13 +4989,13 @@
         let mangled_name = mangled_name.as_bytes();
 
         let (mangling_prefix, expect_suffix) = match call_conv {
-            Some(Abi::C) |
+            Some(ClangAbi::Known(Abi::C)) |
             // None is the case for global variables
             None => {
                 (b'_', false)
             }
-            Some(Abi::Stdcall) => (b'_', true),
-            Some(Abi::Fastcall) => (b'@', true),
+            Some(ClangAbi::Known(Abi::Stdcall)) => (b'_', true),
+            Some(ClangAbi::Known(Abi::Fastcall)) => (b'@', true),
 
             // This is something we don't recognize, stay on the safe side
             // by emitting the `#[link_name]` attribute
diff --git a/codegen/postprocessing/merge_extern_blocks.rs b/codegen/postprocessing/merge_extern_blocks.rs
new file mode 100644
index 0000000..05e7e9e
--- /dev/null
+++ b/codegen/postprocessing/merge_extern_blocks.rs
@@ -0,0 +1,66 @@
+use syn::{
+    visit_mut::{visit_item_mod_mut, VisitMut},
+    Item, ItemForeignMod, ItemMod,
+};
+
+pub(super) fn merge_extern_blocks(item_mod: &mut ItemMod) {
+    Visitor.visit_item_mod_mut(item_mod)
+}
+
+struct Visitor;
+
+impl VisitMut for Visitor {
+    fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) {
+        if let Some((_, ref mut items)) = item_mod.content {
+            // Keep all the extern blocks in a different `Vec` for faster search.
+            let mut extern_blocks = Vec::<ItemForeignMod>::new();
+
+            for item in std::mem::take(items) {
+                if let Item::ForeignMod(ItemForeignMod {
+                    attrs,
+                    abi,
+                    brace_token,
+                    items: extern_block_items,
+                }) = item
+                {
+                    let mut exists = false;
+                    for extern_block in &mut extern_blocks {
+                        // Check if there is a extern block with the same ABI and
+                        // attributes.
+                        if extern_block.attrs == attrs &&
+                            extern_block.abi == abi
+                        {
+                            // Merge the items of the two blocks.
+                            extern_block
+                                .items
+                                .extend_from_slice(&extern_block_items);
+                            exists = true;
+                            break;
+                        }
+                    }
+                    // If no existing extern block had the same ABI and attributes, store
+                    // it.
+                    if !exists {
+                        extern_blocks.push(ItemForeignMod {
+                            attrs,
+                            abi,
+                            brace_token,
+                            items: extern_block_items,
+                        });
+                    }
+                } else {
+                    // If the item is not an extern block, we don't have to do anything and just
+                    // push it back.
+                    items.push(item);
+                }
+            }
+
+            // Move all the extern blocks alongside the rest of the items.
+            for extern_block in extern_blocks {
+                items.push(Item::ForeignMod(extern_block));
+            }
+        }
+
+        visit_item_mod_mut(self, item_mod)
+    }
+}
diff --git a/codegen/postprocessing/mod.rs b/codegen/postprocessing/mod.rs
new file mode 100644
index 0000000..1d5a498
--- /dev/null
+++ b/codegen/postprocessing/mod.rs
@@ -0,0 +1,66 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{parse2, ItemMod};
+
+use crate::BindgenOptions;
+
+mod merge_extern_blocks;
+mod sort_semantically;
+
+use merge_extern_blocks::merge_extern_blocks;
+use sort_semantically::sort_semantically;
+
+struct PostProcessingPass {
+    should_run: fn(&BindgenOptions) -> bool,
+    run: fn(&mut ItemMod),
+}
+
+// TODO: This can be a const fn when mutable references are allowed in const
+// context.
+macro_rules! pass {
+    ($pass:ident) => {
+        PostProcessingPass {
+            should_run: |options| options.$pass,
+            run: |item_mod| $pass(item_mod),
+        }
+    };
+}
+
+const PASSES: &[PostProcessingPass] =
+    &[pass!(merge_extern_blocks), pass!(sort_semantically)];
+
+pub(crate) fn postprocessing(
+    items: Vec<TokenStream>,
+    options: &BindgenOptions,
+) -> TokenStream {
+    let require_syn = PASSES.iter().any(|pass| (pass.should_run)(options));
+    if !require_syn {
+        return items.into_iter().collect();
+    }
+    let module_wrapped_tokens =
+        quote!(mod wrapper_for_postprocessing_hack { #( #items )* });
+
+    // This syn business is a hack, for now. This means that we are re-parsing already
+    // generated code using `syn` (as opposed to `quote`) because `syn` provides us more
+    // control over the elements.
+    // One caveat is that some of the items coming from `quote`d output might have
+    // multiple items within them. Hence, we have to wrap the incoming in a `mod`.
+    // The `unwrap` here is deliberate because bindgen should generate valid rust items at all
+    // times.
+    let mut item_mod = parse2::<ItemMod>(module_wrapped_tokens).unwrap();
+
+    for pass in PASSES {
+        if (pass.should_run)(options) {
+            (pass.run)(&mut item_mod);
+        }
+    }
+
+    let synful_items = item_mod
+        .content
+        .map(|(_, items)| items)
+        .unwrap_or_default()
+        .into_iter()
+        .map(|item| item.into_token_stream());
+
+    quote! { #( #synful_items )* }
+}
diff --git a/codegen/postprocessing/sort_semantically.rs b/codegen/postprocessing/sort_semantically.rs
new file mode 100644
index 0000000..4f23ab7
--- /dev/null
+++ b/codegen/postprocessing/sort_semantically.rs
@@ -0,0 +1,38 @@
+use syn::{
+    visit_mut::{visit_item_mod_mut, VisitMut},
+    Item, ItemMod,
+};
+
+pub(super) fn sort_semantically(item_mod: &mut ItemMod) {
+    Visitor.visit_item_mod_mut(item_mod)
+}
+
+struct Visitor;
+
+impl VisitMut for Visitor {
+    fn visit_item_mod_mut(&mut self, item_mod: &mut ItemMod) {
+        if let Some((_, ref mut items)) = item_mod.content {
+            items.sort_by_key(|item| match item {
+                Item::Type(_) => 0,
+                Item::Struct(_) => 1,
+                Item::Const(_) => 2,
+                Item::Fn(_) => 3,
+                Item::Enum(_) => 4,
+                Item::Union(_) => 5,
+                Item::Static(_) => 6,
+                Item::Trait(_) => 7,
+                Item::TraitAlias(_) => 8,
+                Item::Impl(_) => 9,
+                Item::Mod(_) => 10,
+                Item::Use(_) => 11,
+                Item::Verbatim(_) => 12,
+                Item::ExternCrate(_) => 13,
+                Item::ForeignMod(_) => 14,
+                Item::Macro(_) => 15,
+                Item::Macro2(_) => 16,
+                _ => 18,
+            });
+        }
+        visit_item_mod_mut(self, item_mod)
+    }
+}
diff --git a/src/codegen/struct_layout.rs b/codegen/struct_layout.rs
similarity index 97%
rename from src/codegen/struct_layout.rs
rename to codegen/struct_layout.rs
index 657be0b..ddac1b0 100644
--- a/src/codegen/struct_layout.rs
+++ b/codegen/struct_layout.rs
@@ -20,6 +20,7 @@
     is_packed: bool,
     known_type_layout: Option<Layout>,
     is_rust_union: bool,
+    can_copy_union_fields: bool,
     latest_offset: usize,
     padding_count: usize,
     latest_field_layout: Option<Layout>,
@@ -90,8 +91,8 @@
     ) -> 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());
+        let (is_rust_union, can_copy_union_fields) =
+            comp.is_rust_union(ctx, known_type_layout.as_ref(), name);
         StructLayoutTracker {
             name,
             ctx,
@@ -99,6 +100,7 @@
             is_packed,
             known_type_layout,
             is_rust_union,
+            can_copy_union_fields,
             latest_offset: 0,
             padding_count: 0,
             latest_field_layout: None,
@@ -107,6 +109,10 @@
         }
     }
 
+    pub fn can_copy_union_fields(&self) -> bool {
+        self.can_copy_union_fields
+    }
+
     pub fn is_rust_union(&self) -> bool {
         self.is_rust_union
     }
diff --git a/csmith-fuzzing/README.md b/csmith-fuzzing/README.md
deleted file mode 100644
index cdd6d08..0000000
--- a/csmith-fuzzing/README.md
+++ /dev/null
@@ -1,65 +0,0 @@
-# Fuzzing `bindgen` with `csmith`
-
-[`csmith`][csmith] generates random C and C++ programs that can be used as test
-cases for compilers. When testing `bindgen` with `csmith`, we interpret the
-generated programs as header files, and emit Rust bindings to them. If `bindgen`
-panics, the emitted bindings won't compile with `rustc`, or the generated layout
-tests in the bindings fail, then we report an issue containing the test case!
-
-<!-- START doctoc generated TOC please keep comment here to allow auto update -->
-<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
-
-
-- [Prerequisites](#prerequisites)
-- [Running the Fuzzer](#running-the-fuzzer)
-- [Reporting Issues](#reporting-issues)
-
-<!-- END doctoc generated TOC please keep comment here to allow auto update -->
-
-## Prerequisites
-
-Requires `python3`, `csmith`, and `creduce` to be in `$PATH`.
-
-Many OS package managers have `csmith` and `creduce` packages:
-
-```
-$ sudo apt install csmith creduce
-$ brew install csmith creduce
-$ # Etc...
-```
-
-## Running the Fuzzer
-
-Run `csmith` and test `bindgen` on the generated test cases with this command:
-
-```
-$ ./driver.py
-```
-
-The driver will keep running until it encounters an error in `bindgen`.
-
-Each invocation of `./driver.py` will use its own temporary directories, so
-running it in multiple terminals in parallel is supported.
-
-`csmith` is run with `--no-checksum --nomain --max-block-size 1
---max-block-depth 1` which disables the `main` function, and makes function
-bodies as simple as possible as `bindgen` does not care about them, but they
-cannot be completely disabled in `csmith`. Run `csmith --help` to see what
-exactly those options do.
-
-## Reporting Issues
-
-Once the fuzz driver finds a test case that causes some kind of error in
-`bindgen` or its emitted bindings, it is helpful to
-[run C-Reduce on the test case][creducing] to remove the parts that are
-irrelevant to reproducing the error. This is ***very*** helpful for the folks
-who further investigate the issue and come up with a fix!
-
-Additionally, mention that you discovered the issue via `csmith` and we will add
-the `A-csmith` label. You can find all the issues discovered with `csmith`, and
-related to fuzzing with `csmith`, by looking up
-[all issues tagged with the `A-csmith` label][csmith-issues].
-
-[csmith]: https://github.com/csmith-project/csmith
-[creducing]: ../CONTRIBUTING.md#using-creduce-to-minimize-test-cases
-[csmith-issues]: https://github.com/rust-lang/rust-bindgen/issues?q=label%3AA-csmith
diff --git a/src/deps.rs b/deps.rs
similarity index 94%
rename from src/deps.rs
rename to deps.rs
index 479c396..987225b 100644
--- a/src/deps.rs
+++ b/deps.rs
@@ -1,7 +1,7 @@
 /// Generating build depfiles from parsed bindings.
 use std::{collections::BTreeSet, path::PathBuf};
 
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 pub(crate) struct DepfileSpec {
     pub output_module: String,
     pub depfile_path: PathBuf,
diff --git a/src/extra_assertions.rs b/extra_assertions.rs
similarity index 100%
rename from src/extra_assertions.rs
rename to extra_assertions.rs
diff --git a/src/features.rs b/features.rs
similarity index 77%
rename from src/features.rs
rename to features.rs
index a786f07..4fee5d6 100644
--- a/src/features.rs
+++ b/features.rs
@@ -2,6 +2,7 @@
 
 #![deny(missing_docs)]
 #![deny(unused_extern_crates)]
+#![allow(deprecated)]
 
 use std::io;
 use std::str::FromStr;
@@ -86,35 +87,35 @@
     ( $x_macro:ident ) => {
         $x_macro!(
             /// Rust stable 1.0
-            => Stable_1_0 => 1.0;
+            #[deprecated = "This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues"] => Stable_1_0 => 1.0;
             /// Rust stable 1.17
             ///  * Static lifetime elision ([RFC 1623](https://github.com/rust-lang/rfcs/blob/master/text/1623-static.md))
-            => Stable_1_17 => 1.17;
+            #[deprecated = "This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues"] => Stable_1_17 => 1.17;
             /// Rust stable 1.19
             ///  * Untagged unions ([RFC 1444](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md))
-            => Stable_1_19 => 1.19;
+            #[deprecated = "This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues"] => Stable_1_19 => 1.19;
             /// Rust stable 1.20
             ///  * Associated constants ([PR](https://github.com/rust-lang/rust/pull/42809))
-            => Stable_1_20 => 1.20;
+            #[deprecated = "This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues"] => Stable_1_20 => 1.20;
             /// Rust stable 1.21
             ///  * Builtin impls for `Clone` ([PR](https://github.com/rust-lang/rust/pull/43690))
-            => Stable_1_21 => 1.21;
+            #[deprecated = "This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues"] => Stable_1_21 => 1.21;
             /// Rust stable 1.25
             ///  * `repr(align)` ([PR](https://github.com/rust-lang/rust/pull/47006))
-            => Stable_1_25 => 1.25;
+            #[deprecated = "This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues"] => Stable_1_25 => 1.25;
             /// Rust stable 1.26
             ///  * [i128 / u128 support](https://doc.rust-lang.org/std/primitive.i128.html)
-            => Stable_1_26 => 1.26;
+            #[deprecated = "This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues"] => Stable_1_26 => 1.26;
             /// Rust stable 1.27
             ///  * `must_use` attribute on functions ([PR](https://github.com/rust-lang/rust/pull/48925))
-            => Stable_1_27 => 1.27;
+            #[deprecated = "This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues"] => Stable_1_27 => 1.27;
             /// Rust stable 1.28
             ///  * `repr(transparent)` ([PR](https://github.com/rust-lang/rust/pull/51562))
-            => Stable_1_28 => 1.28;
+            #[deprecated = "This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues"] => Stable_1_28 => 1.28;
             /// Rust stable 1.30
             ///  * `const fn` support for limited cases ([PR](https://github.com/rust-lang/rust/pull/54835/)
             /// *  [c_void available in core](https://doc.rust-lang.org/core/ffi/enum.c_void.html)
-            => Stable_1_30 => 1.30;
+            #[deprecated = "This rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues"] => Stable_1_30 => 1.30;
             /// Rust stable 1.33
             ///  * repr(packed(N)) ([PR](https://github.com/rust-lang/rust/pull/57049))
             => Stable_1_33 => 1.33;
@@ -127,8 +128,13 @@
             /// Rust stable 1.47
             /// * `larger_arrays` ([Tracking issue](https://github.com/rust-lang/rust/pull/74060))
             => Stable_1_47 => 1.47;
+            /// Rust stable 1.64
+            ///  * `core_ffi_c` ([Tracking issue](https://github.com/rust-lang/rust/issues/94501))
+            => Stable_1_64 => 1.64;
             /// Nightly rust
             ///  * `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
+            ///  * `vectorcall` calling convention (no tracking issue)
+            ///  * `c_unwind` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/74990))
             => Nightly => nightly;
         );
     }
@@ -138,7 +144,7 @@
 rust_target_base!(rust_target_values_def);
 
 /// Latest stable release of Rust
-pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_47;
+pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_64;
 
 /// Create RustFeatures struct definition, new(), and a getter for each field
 macro_rules! rust_feature_def {
@@ -232,8 +238,13 @@
     Stable_1_47 {
         => larger_arrays;
     }
+    Stable_1_64 {
+        => core_ffi_c;
+    }
     Nightly {
         => thiscall_abi;
+        => vectorcall_abi;
+        => c_unwind_abi;
     }
 );
 
@@ -259,7 +270,8 @@
                 !f_1_0.associated_const &&
                 !f_1_0.builtin_clone_impls &&
                 !f_1_0.repr_align &&
-                !f_1_0.thiscall_abi
+                !f_1_0.thiscall_abi &&
+                !f_1_0.vectorcall_abi
         );
         let f_1_21 = RustFeatures::from(RustTarget::Stable_1_21);
         assert!(
@@ -269,7 +281,8 @@
                 f_1_21.associated_const &&
                 f_1_21.builtin_clone_impls &&
                 !f_1_21.repr_align &&
-                !f_1_21.thiscall_abi
+                !f_1_21.thiscall_abi &&
+                !f_1_21.vectorcall_abi
         );
         let f_nightly = RustFeatures::from(RustTarget::Nightly);
         assert!(
@@ -280,7 +293,9 @@
                 f_nightly.builtin_clone_impls &&
                 f_nightly.maybe_uninit &&
                 f_nightly.repr_align &&
-                f_nightly.thiscall_abi
+                f_nightly.thiscall_abi &&
+                f_nightly.vectorcall_abi &&
+                f_nightly.c_unwind_abi
         );
     }
 
diff --git a/src/ir/analysis/derive.rs b/ir/analysis/derive.rs
similarity index 98%
rename from src/ir/analysis/derive.rs
rename to ir/analysis/derive.rs
index f63458e..d888cd5 100644
--- a/src/ir/analysis/derive.rs
+++ b/ir/analysis/derive.rs
@@ -485,11 +485,11 @@
     fn consider_edge_tmpl_inst(&self) -> EdgePredicate {
         match self {
             DeriveTrait::PartialEqOrPartialOrd => consider_edge_default,
-            _ => |kind| match kind {
-                EdgeKind::TemplateArgument | EdgeKind::TemplateDeclaration => {
-                    true
-                }
-                _ => false,
+            _ => |kind| {
+                matches!(
+                    kind,
+                    EdgeKind::TemplateArgument | EdgeKind::TemplateDeclaration
+                )
             },
         }
     }
diff --git a/src/ir/analysis/has_destructor.rs b/ir/analysis/has_destructor.rs
similarity index 100%
rename from src/ir/analysis/has_destructor.rs
rename to ir/analysis/has_destructor.rs
diff --git a/src/ir/analysis/has_float.rs b/ir/analysis/has_float.rs
similarity index 100%
rename from src/ir/analysis/has_float.rs
rename to ir/analysis/has_float.rs
diff --git a/src/ir/analysis/has_type_param_in_array.rs b/ir/analysis/has_type_param_in_array.rs
similarity index 100%
rename from src/ir/analysis/has_type_param_in_array.rs
rename to ir/analysis/has_type_param_in_array.rs
diff --git a/src/ir/analysis/has_vtable.rs b/ir/analysis/has_vtable.rs
similarity index 100%
rename from src/ir/analysis/has_vtable.rs
rename to ir/analysis/has_vtable.rs
diff --git a/src/ir/analysis/mod.rs b/ir/analysis/mod.rs
similarity index 96%
rename from src/ir/analysis/mod.rs
rename to ir/analysis/mod.rs
index eb9a1c0..40dfc6d 100644
--- a/src/ir/analysis/mod.rs
+++ b/ir/analysis/mod.rs
@@ -281,9 +281,13 @@
         fn reverse(&self) -> Graph {
             let mut reversed = Graph::default();
             for (node, edges) in self.0.iter() {
-                reversed.0.entry(*node).or_insert(vec![]);
+                reversed.0.entry(*node).or_insert_with(Vec::new);
                 for referent in edges.iter() {
-                    reversed.0.entry(*referent).or_insert(vec![]).push(*node);
+                    reversed
+                        .0
+                        .entry(*referent)
+                        .or_insert_with(Vec::new)
+                        .push(*node);
                 }
             }
             reversed
@@ -306,8 +310,8 @@
             let reversed = graph.reverse();
             ReachableFrom {
                 reachable: Default::default(),
-                graph: graph,
-                reversed: reversed,
+                graph,
+                reversed,
             }
         }
 
@@ -328,7 +332,7 @@
             let original_size = self
                 .reachable
                 .entry(node)
-                .or_insert(HashSet::default())
+                .or_insert_with(HashSet::default)
                 .len();
 
             for sub_node in self.graph.0[&node].iter() {
@@ -337,7 +341,7 @@
                 let sub_reachable = self
                     .reachable
                     .entry(*sub_node)
-                    .or_insert(HashSet::default())
+                    .or_insert_with(HashSet::default)
                     .clone();
 
                 for transitive in sub_reachable {
diff --git a/src/ir/analysis/sizedness.rs b/ir/analysis/sizedness.rs
similarity index 100%
rename from src/ir/analysis/sizedness.rs
rename to ir/analysis/sizedness.rs
diff --git a/src/ir/analysis/template_params.rs b/ir/analysis/template_params.rs
similarity index 100%
rename from src/ir/analysis/template_params.rs
rename to ir/analysis/template_params.rs
diff --git a/src/ir/annotations.rs b/ir/annotations.rs
similarity index 98%
rename from src/ir/annotations.rs
rename to ir/annotations.rs
index 9bcda50..288c11e 100644
--- a/src/ir/annotations.rs
+++ b/ir/annotations.rs
@@ -7,7 +7,7 @@
 use crate::clang;
 
 /// What kind of accessor should we provide for a field?
-#[derive(Copy, PartialEq, Clone, Debug)]
+#[derive(Copy, PartialEq, Eq, Clone, Debug)]
 pub enum FieldAccessorKind {
     /// No accessor.
     None,
@@ -25,7 +25,7 @@
 /// documentation:
 ///
 /// http://www.stack.nl/~dimitri/doxygen/manual/docblocks.html
-#[derive(Default, Clone, PartialEq, Debug)]
+#[derive(Default, Clone, PartialEq, Eq, Debug)]
 pub struct Annotations {
     /// Whether this item is marked as opaque. Only applies to types.
     opaque: bool,
diff --git a/src/ir/comment.rs b/ir/comment.rs
similarity index 60%
rename from src/ir/comment.rs
rename to ir/comment.rs
index c96e3eb..3eb17aa 100644
--- a/src/ir/comment.rs
+++ b/ir/comment.rs
@@ -12,10 +12,10 @@
 }
 
 /// Preprocesses a C/C++ comment so that it is a valid Rust comment.
-pub fn preprocess(comment: &str, indent: usize) -> String {
+pub fn preprocess(comment: &str) -> String {
     match self::kind(comment) {
-        Some(Kind::SingleLines) => preprocess_single_lines(comment, indent),
-        Some(Kind::MultiLine) => preprocess_multi_line(comment, indent),
+        Some(Kind::SingleLines) => preprocess_single_lines(comment),
+        Some(Kind::MultiLine) => preprocess_multi_line(comment),
         None => comment.to_owned(),
     }
 }
@@ -31,56 +31,34 @@
     }
 }
 
-fn make_indent(indent: usize) -> String {
-    const RUST_INDENTATION: usize = 4;
-    " ".repeat(indent * RUST_INDENTATION)
-}
-
 /// Preprocesses multiple single line comments.
 ///
 /// Handles lines starting with both `//` and `///`.
-fn preprocess_single_lines(comment: &str, indent: usize) -> String {
+fn preprocess_single_lines(comment: &str) -> String {
     debug_assert!(comment.starts_with("//"), "comment is not single line");
 
-    let indent = make_indent(indent);
-    let mut is_first = true;
     let lines: Vec<_> = comment
         .lines()
         .map(|l| l.trim().trim_start_matches('/'))
-        .map(|l| {
-            let indent = if is_first { "" } else { &*indent };
-            is_first = false;
-            format!("{}///{}", indent, l)
-        })
         .collect();
     lines.join("\n")
 }
 
-fn preprocess_multi_line(comment: &str, indent: usize) -> String {
+fn preprocess_multi_line(comment: &str) -> String {
     let comment = comment
         .trim_start_matches('/')
         .trim_end_matches('/')
         .trim_end_matches('*');
 
-    let indent = make_indent(indent);
     // Strip any potential `*` characters preceding each line.
-    let mut is_first = true;
     let mut lines: Vec<_> = comment
         .lines()
         .map(|line| line.trim().trim_start_matches('*').trim_start_matches('!'))
         .skip_while(|line| line.trim().is_empty()) // Skip the first empty lines.
-        .map(|line| {
-            let indent = if is_first { "" } else { &*indent };
-            is_first = false;
-            format!("{}///{}", indent, line)
-        })
         .collect();
 
     // Remove the trailing line corresponding to the `*/`.
-    if lines
-        .last()
-        .map_or(false, |l| l.trim().is_empty() || l.trim() == "///")
-    {
+    if lines.last().map_or(false, |l| l.trim().is_empty()) {
         lines.pop();
     }
 
@@ -99,21 +77,24 @@
 
     #[test]
     fn processes_single_lines_correctly() {
-        assert_eq!(preprocess("/// hello", 0), "/// hello");
-        assert_eq!(preprocess("// hello", 0), "/// hello");
-        assert_eq!(preprocess("//    hello", 0), "///    hello");
+        assert_eq!(preprocess("///"), "");
+        assert_eq!(preprocess("/// hello"), " hello");
+        assert_eq!(preprocess("// hello"), " hello");
+        assert_eq!(preprocess("//    hello"), "    hello");
     }
 
     #[test]
     fn processes_multi_lines_correctly() {
+        assert_eq!(preprocess("/**/"), "");
+
         assert_eq!(
-            preprocess("/** hello \n * world \n * foo \n */", 0),
-            "/// hello\n/// world\n/// foo"
+            preprocess("/** hello \n * world \n * foo \n */"),
+            " hello\n world\n foo"
         );
 
         assert_eq!(
-            preprocess("/**\nhello\n*world\n*foo\n*/", 0),
-            "///hello\n///world\n///foo"
+            preprocess("/**\nhello\n*world\n*foo\n*/"),
+            "hello\nworld\nfoo"
         );
     }
 }
diff --git a/src/ir/comp.rs b/ir/comp.rs
similarity index 96%
rename from src/ir/comp.rs
rename to ir/comp.rs
index a221e52..039742a 100644
--- a/src/ir/comp.rs
+++ b/ir/comp.rs
@@ -14,13 +14,14 @@
 use crate::ir::derive::CanDeriveCopy;
 use crate::parse::{ClangItemParser, ParseError};
 use crate::HashMap;
+use crate::NonCopyUnionStyle;
 use peeking_take_while::PeekableExt;
 use std::cmp;
 use std::io;
 use std::mem;
 
 /// The kind of compound type.
-#[derive(Debug, Copy, Clone, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub enum CompKind {
     /// A struct.
     Struct,
@@ -29,7 +30,7 @@
 }
 
 /// The kind of C++ method.
-#[derive(Debug, Copy, Clone, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub enum MethodKind {
     /// A constructor. We represent it as method for convenience, to avoid code
     /// duplication.
@@ -55,12 +56,10 @@
 impl MethodKind {
     /// Is this a destructor method?
     pub fn is_destructor(&self) -> bool {
-        match *self {
-            MethodKind::Destructor | MethodKind::VirtualDestructor { .. } => {
-                true
-            }
-            _ => false,
-        }
+        matches!(
+            *self,
+            MethodKind::Destructor | MethodKind::VirtualDestructor { .. }
+        )
     }
 
     /// Is this a pure virtual method?
@@ -1045,6 +1044,11 @@
     /// size_t)
     has_non_type_template_params: bool,
 
+    /// Whether this type has a bit field member whose width couldn't be
+    /// evaluated (e.g. if it depends on a template parameter). We generate an
+    /// opaque type in this case.
+    has_unevaluable_bit_field_width: bool,
+
     /// Whether we saw `__attribute__((packed))` on or within this type.
     packed_attr: bool,
 
@@ -1078,6 +1082,7 @@
             has_destructor: false,
             has_nonempty_base: false,
             has_non_type_template_params: false,
+            has_unevaluable_bit_field_width: false,
             packed_attr: false,
             found_unknown_attr: false,
             is_forward_declaration: false,
@@ -1317,7 +1322,21 @@
                         }
                     }
 
-                    let bit_width = cur.bit_width();
+                    let bit_width = if cur.is_bit_field() {
+                        let width = cur.bit_width();
+
+                        // Make opaque type if the bit width couldn't be
+                        // evaluated.
+                        if width.is_none() {
+                            ci.has_unevaluable_bit_field_width = true;
+                            return CXChildVisit_Break;
+                        }
+
+                        width
+                    } else {
+                        None
+                    };
+
                     let field_type = Item::from_ty_or_ref(
                         cur.cur_type(),
                         cur,
@@ -1403,8 +1422,7 @@
 
                         // A declaration of an union or a struct without name
                         // could also be an unnamed field, unfortunately.
-                        if cur.spelling().is_empty() &&
-                            cur.kind() != CXCursor_EnumDecl
+                        if cur.is_anonymous() && cur.kind() != CXCursor_EnumDecl
                         {
                             let ty = cur.cur_type();
                             let public = cur.public_accessible();
@@ -1662,21 +1680,37 @@
     ///
     /// Requirements:
     ///     1. Current RustTarget allows for `untagged_union`
-    ///     2. Each field can derive `Copy`
+    ///     2. Each field can derive `Copy` or we use ManuallyDrop.
     ///     3. It's not zero-sized.
-    pub fn can_be_rust_union(
+    ///
+    /// Second boolean returns whether all fields can be copied (and thus
+    /// ManuallyDrop is not needed).
+    pub fn is_rust_union(
         &self,
         ctx: &BindgenContext,
         layout: Option<&Layout>,
-    ) -> bool {
+        name: &str,
+    ) -> (bool, bool) {
+        if !self.is_union() {
+            return (false, false);
+        }
+
         if !ctx.options().rust_features().untagged_union {
-            return false;
+            return (false, false);
         }
 
         if self.is_forward_declaration() {
-            return false;
+            return (false, false);
         }
 
+        let union_style = if ctx.options().bindgen_wrapper_union.matches(name) {
+            NonCopyUnionStyle::BindgenWrapper
+        } else if ctx.options().manually_drop_union.matches(name) {
+            NonCopyUnionStyle::ManuallyDrop
+        } else {
+            ctx.options().default_non_copy_union_style
+        };
+
         let all_can_copy = self.fields().iter().all(|f| match *f {
             Field::DataMember(ref field_data) => {
                 field_data.ty().can_derive_copy(ctx)
@@ -1684,15 +1718,15 @@
             Field::Bitfields(_) => true,
         });
 
-        if !all_can_copy {
-            return false;
+        if !all_can_copy && union_style == NonCopyUnionStyle::BindgenWrapper {
+            return (false, false);
         }
 
         if layout.map_or(false, |l| l.size == 0) {
-            return false;
+            return (false, false);
         }
 
-        true
+        (true, all_can_copy)
     }
 }
 
@@ -1753,7 +1787,9 @@
     type Extra = Option<Layout>;
 
     fn is_opaque(&self, ctx: &BindgenContext, layout: &Option<Layout>) -> bool {
-        if self.has_non_type_template_params {
+        if self.has_non_type_template_params ||
+            self.has_unevaluable_bit_field_width
+        {
             return true;
         }
 
diff --git a/src/ir/context.rs b/ir/context.rs
similarity index 93%
rename from src/ir/context.rs
rename to ir/context.rs
index a9e19fb..4623b25 100644
--- a/src/ir/context.rs
+++ b/ir/context.rs
@@ -19,14 +19,14 @@
 use super::template::{TemplateInstantiation, TemplateParameters};
 use super::traversal::{self, Edge, ItemTraversal};
 use super::ty::{FloatKind, Type, TypeKind};
-use crate::callbacks::ParseCallbacks;
 use crate::clang::{self, Cursor};
 use crate::parse::ClangItemParser;
 use crate::BindgenOptions;
 use crate::{Entry, HashMap, HashSet};
 use cexpr;
 use clang_sys;
-use proc_macro2::{Ident, Span};
+use proc_macro2::{Ident, Span, TokenStream};
+use quote::ToTokens;
 use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
 use std::collections::{BTreeSet, HashMap as StdHashMap};
@@ -364,14 +364,11 @@
 
     in_codegen: bool,
 
-    /// The clang index for parsing.
-    index: clang::Index,
-
     /// The translation unit for parsing.
     translation_unit: clang::TranslationUnit,
 
     /// Target information that can be useful for some stuff.
-    target_info: Option<clang::TargetInfo>,
+    target_info: clang::TargetInfo,
 
     /// The options given by the user via cli or other medium.
     options: BindgenOptions,
@@ -420,12 +417,6 @@
     /// and is always `None` before that and `Some` after.
     cannot_derive_copy: Option<HashSet<ItemId>>,
 
-    /// The set of (`ItemId`s of) types that can't derive copy in array.
-    ///
-    /// This is populated when we enter codegen by `compute_cannot_derive_copy`
-    /// and is always `None` before that and `Some` after.
-    cannot_derive_copy_in_array: Option<HashSet<ItemId>>,
-
     /// The set of (`ItemId`s of) types that can't derive hash.
     ///
     /// This is populated when we enter codegen by `compute_can_derive_hash`
@@ -468,17 +459,15 @@
     /// Populated when we enter codegen by `compute_has_float`; always `None`
     /// before that and `Some` after.
     has_float: Option<HashSet<ItemId>>,
+
+    /// The set of warnings raised during binding generation.
+    warnings: Vec<String>,
 }
 
 /// A traversal of allowlisted items.
 struct AllowlistedItemsTraversal<'ctx> {
     ctx: &'ctx BindgenContext,
-    traversal: ItemTraversal<
-        'ctx,
-        ItemSet,
-        Vec<ItemId>,
-        for<'a> fn(&'a BindgenContext, Edge) -> bool,
-    >,
+    traversal: ItemTraversal<'ctx, ItemSet, Vec<ItemId>>,
 }
 
 impl<'ctx> Iterator for AllowlistedItemsTraversal<'ctx> {
@@ -516,7 +505,10 @@
 
 impl BindgenContext {
     /// Construct the context for the given `options`.
-    pub(crate) fn new(options: BindgenOptions) -> Self {
+    pub(crate) fn new(
+        options: BindgenOptions,
+        input_unsaved_files: &[clang::UnsavedFile],
+    ) -> Self {
         // TODO(emilio): Use the CXTargetInfo here when available.
         //
         // see: https://reviews.llvm.org/D32389
@@ -533,7 +525,7 @@
                 &index,
                 "",
                 &options.clang_args,
-                &options.input_unsaved_files,
+                input_unsaved_files,
                 parse_options,
             ).expect("libclang error; possible causes include:
 - Invalid flag syntax
@@ -549,11 +541,7 @@
         let root_module_id = root_module.id().as_module_id_unchecked();
 
         // depfiles need to include the explicitly listed headers too
-        let mut deps = BTreeSet::default();
-        if let Some(filename) = &options.input_header {
-            deps.insert(filename.clone());
-        }
-        deps.extend(options.extra_input_headers.iter().cloned());
+        let deps = options.input_headers.iter().cloned().collect();
 
         BindgenContext {
             items: vec![Some(root_module)],
@@ -569,7 +557,6 @@
             replacements: Default::default(),
             collected_typerefs: false,
             in_codegen: false,
-            index,
             translation_unit,
             target_info,
             options,
@@ -582,7 +569,6 @@
             cannot_derive_debug: None,
             cannot_derive_default: None,
             cannot_derive_copy: None,
-            cannot_derive_copy_in_array: None,
             cannot_derive_hash: None,
             cannot_derive_partialeq_or_partialord: None,
             sizedness: None,
@@ -590,15 +576,13 @@
             have_destructor: None,
             has_type_param_in_array: None,
             has_float: None,
+            warnings: Vec::new(),
         }
     }
 
     /// Returns `true` if the target architecture is wasm32
     pub fn is_target_wasm32(&self) -> bool {
-        match self.target_info {
-            Some(ref ti) => ti.triple.starts_with("wasm32-"),
-            None => false,
-        }
+        self.target_info.triple.starts_with("wasm32-")
     }
 
     /// Creates a timer for the current bindgen phase. If time_phases is `true`,
@@ -611,10 +595,7 @@
     /// Returns the pointer width to use for the target for the current
     /// translation.
     pub fn target_pointer_size(&self) -> usize {
-        if let Some(ref ti) = self.target_info {
-            return ti.pointer_width / 8;
-        }
-        mem::size_of::<*mut ()>()
+        self.target_info.pointer_width / 8
     }
 
     /// Get the stack of partially parsed types that we are in the middle of
@@ -638,15 +619,10 @@
         )
     }
 
-    /// Get the user-provided callbacks by reference, if any.
-    pub fn parse_callbacks(&self) -> Option<&dyn ParseCallbacks> {
-        self.options().parse_callbacks.as_deref()
-    }
-
     /// Add another path to the set of included files.
     pub fn include_file(&mut self, filename: String) {
-        if let Some(cbs) = self.parse_callbacks() {
-            cbs.include_file(&filename);
+        for cb in &self.options().parse_callbacks {
+            cb.include_file(&filename);
         }
         self.deps.insert(filename);
     }
@@ -838,7 +814,7 @@
             name.contains('$') ||
             matches!(
                 name,
-                "abstract" | "alignof" | "as" | "async" | "become" |
+                "abstract" | "alignof" | "as" | "async" | "await" | "become" |
                     "box" | "break" | "const" | "continue" | "crate" | "do" |
                     "dyn" | "else" | "enum" | "extern" | "false" | "final" |
                     "fn" | "for" | "if" | "impl" | "in" | "let" | "loop" |
@@ -853,9 +829,9 @@
             )
         {
             let mut s = name.to_owned();
-            s = s.replace("@", "_");
-            s = s.replace("?", "_");
-            s = s.replace("$", "_");
+            s = s.replace('@', "_");
+            s = s.replace('?', "_");
+            s = s.replace('$', "_");
             s.push('_');
             return Cow::Owned(s);
         }
@@ -1151,7 +1127,10 @@
 
     /// Enter the code generation phase, invoke the given callback `cb`, and
     /// leave the code generation phase.
-    pub(crate) fn gen<F, Out>(mut self, cb: F) -> (Out, BindgenOptions)
+    pub(crate) fn gen<F, Out>(
+        mut self,
+        cb: F,
+    ) -> (Out, BindgenOptions, Vec<String>)
     where
         F: FnOnce(&Self) -> Out,
     {
@@ -1188,7 +1167,7 @@
         self.compute_cannot_derive_partialord_partialeq_or_eq();
 
         let ret = cb(&self);
-        (ret, self.options)
+        (ret, self.options, self.warnings)
     }
 
     /// When the `testing_only_extra_assertions` feature is enabled, this
@@ -2092,7 +2071,7 @@
             self.in_codegen_phase(),
             "You're not supposed to call this yet"
         );
-        self.options.opaque_types.matches(&path[1..].join("::"))
+        self.options.opaque_types.matches(path[1..].join("::"))
     }
 
     /// Get the options used to configure this bindgen context.
@@ -2119,13 +2098,18 @@
         }
 
         let mut kind = ModuleKind::Normal;
-        let mut found_namespace_keyword = false;
+        let mut looking_for_name = false;
         for token in cursor.tokens().iter() {
             match token.spelling() {
                 b"inline" => {
-                    assert!(!found_namespace_keyword);
-                    assert!(kind != ModuleKind::Inline);
+                    debug_assert!(
+                        kind != ModuleKind::Inline,
+                        "Multiple inline keywords?"
+                    );
                     kind = ModuleKind::Inline;
+                    // When hitting a nested inline namespace we get a spelling
+                    // that looks like ["inline", "foo"]. Deal with it properly.
+                    looking_for_name = true;
                 }
                 // The double colon allows us to handle nested namespaces like
                 // namespace foo::bar { }
@@ -2134,45 +2118,39 @@
                 // but the tokenization of the second begins with the double
                 // colon. That's ok, so we only need to handle the weird
                 // tokenization here.
-                //
-                // Fortunately enough, inline nested namespace specifiers aren't
-                // a thing, and are invalid C++ :)
                 b"namespace" | b"::" => {
-                    found_namespace_keyword = true;
+                    looking_for_name = true;
                 }
                 b"{" => {
-                    assert!(found_namespace_keyword);
+                    // This should be an anonymous namespace.
+                    assert!(looking_for_name);
                     break;
                 }
-                name if found_namespace_keyword => {
-                    if module_name.is_none() {
-                        module_name =
-                            Some(String::from_utf8_lossy(name).into_owned());
+                name => {
+                    if looking_for_name {
+                        if module_name.is_none() {
+                            module_name = Some(
+                                String::from_utf8_lossy(name).into_owned(),
+                            );
+                        }
+                        break;
+                    } else {
+                        // This is _likely_, but not certainly, a macro that's
+                        // been placed just before the namespace keyword.
+                        // Unfortunately, clang tokens don't let us easily see
+                        // through the ifdef tokens, so we don't know what this
+                        // token should really be. Instead of panicking though,
+                        // we warn the user that we assumed the token was blank,
+                        // and then move on.
+                        //
+                        // See also https://github.com/rust-lang/rust-bindgen/issues/1676.
+                        warn!(
+                            "Ignored unknown namespace prefix '{}' at {:?} in {:?}",
+                            String::from_utf8_lossy(name),
+                            token,
+                            cursor
+                        );
                     }
-                    break;
-                }
-                spelling if !found_namespace_keyword => {
-                    // This is _likely_, but not certainly, a macro that's been placed just before
-                    // the namespace keyword. Unfortunately, clang tokens don't let us easily see
-                    // through the ifdef tokens, so we don't know what this token should really be.
-                    // Instead of panicking though, we warn the user that we assumed the token was
-                    // blank, and then move on.
-                    //
-                    // See also https://github.com/rust-lang/rust-bindgen/issues/1676.
-                    warn!(
-                        "Ignored unknown namespace prefix '{}' at {:?} in {:?}",
-                        String::from_utf8_lossy(spelling),
-                        token,
-                        cursor
-                    );
-                }
-                spelling => {
-                    panic!(
-                        "Unknown token '{}' while processing namespace at {:?} in {:?}",
-                        String::from_utf8_lossy(spelling),
-                        token,
-                        cursor
-                    );
                 }
             }
         }
@@ -2257,32 +2235,40 @@
             .or_insert_with(|| {
                 item.expect_type()
                     .name()
-                    .and_then(|name| match self.options.parse_callbacks {
-                        Some(ref cb) => cb.blocklisted_type_implements_trait(
-                            name,
-                            derive_trait,
-                        ),
-                        // Sized integer types from <stdint.h> get mapped to Rust primitive
-                        // types regardless of whether they are blocklisted, so ensure that
-                        // standard traits are considered derivable for them too.
-                        None => match name {
-                            "int8_t" | "uint8_t" | "int16_t" | "uint16_t" |
-                            "int32_t" | "uint32_t" | "int64_t" |
-                            "uint64_t" | "uintptr_t" | "intptr_t" |
-                            "ptrdiff_t" => Some(CanDerive::Yes),
-                            "size_t" if self.options.size_t_is_usize => {
+                    .and_then(|name| {
+                        if self.options.parse_callbacks.is_empty() {
+                            // Sized integer types from <stdint.h> get mapped to Rust primitive
+                            // types regardless of whether they are blocklisted, so ensure that
+                            // standard traits are considered derivable for them too.
+                            if self.is_stdint_type(name) {
                                 Some(CanDerive::Yes)
+                            } else {
+                                Some(CanDerive::No)
                             }
-                            "ssize_t" if self.options.size_t_is_usize => {
-                                Some(CanDerive::Yes)
-                            }
-                            _ => Some(CanDerive::No),
-                        },
+                        } else {
+                            self.options.last_callback(|cb| {
+                                cb.blocklisted_type_implements_trait(
+                                    name,
+                                    derive_trait,
+                                )
+                            })
+                        }
                     })
                     .unwrap_or(CanDerive::No)
             })
     }
 
+    /// Is the given type a type from <stdint.h> that corresponds to a Rust primitive type?
+    pub fn is_stdint_type(&self, name: &str) -> bool {
+        match name {
+            "int8_t" | "uint8_t" | "int16_t" | "uint16_t" | "int32_t" |
+            "uint32_t" | "int64_t" | "uint64_t" | "uintptr_t" |
+            "intptr_t" | "ptrdiff_t" => true,
+            "size_t" | "ssize_t" => self.options.size_t_is_usize,
+            _ => false,
+        }
+    }
+
     /// Get a reference to the set of items we should generate.
     pub fn codegen_items(&self) -> &ItemSet {
         assert!(self.in_codegen_phase());
@@ -2307,7 +2293,8 @@
                     // game.
                     if self.options().allowlisted_types.is_empty() &&
                         self.options().allowlisted_functions.is_empty() &&
-                        self.options().allowlisted_vars.is_empty()
+                        self.options().allowlisted_vars.is_empty() &&
+                        self.options().allowlisted_files.is_empty()
                     {
                         return true;
                     }
@@ -2318,6 +2305,23 @@
                         return true;
                     }
 
+                    // Items with a source location in an explicitly allowlisted file
+                    // are always included.
+                    if !self.options().allowlisted_files.is_empty() {
+                        if let Some(location) = item.location() {
+                            let (file, _, _, _) = location.location();
+                            if let Some(filename) = file.name() {
+                                if self
+                                    .options()
+                                    .allowlisted_files
+                                    .matches(filename)
+                                {
+                                    return true;
+                                }
+                            }
+                        }
+                    }
+
                     let name = item.path_for_allowlisting(self)[1..].join("::");
                     debug!("allowlisted_items: testing {:?}", name);
                     match *item.kind() {
@@ -2352,7 +2356,10 @@
                                     TypeKind::Opaque |
                                     TypeKind::TypeParam => return true,
                                     _ => {}
-                                };
+                                }
+                                if self.is_stdint_type(&name) {
+                                    return true;
+                                }
                             }
 
                             // Unnamed top-level enums are special and we
@@ -2382,7 +2389,7 @@
                                 );
                                 let name = prefix_path[1..].join("::");
                                 prefix_path.pop().unwrap();
-                                self.options().allowlisted_vars.matches(&name)
+                                self.options().allowlisted_vars.matches(name)
                             })
                         }
                     }
@@ -2429,16 +2436,24 @@
         self.allowlisted = Some(allowlisted);
         self.codegen_items = Some(codegen_items);
 
+        let mut warnings = Vec::new();
+
         for item in self.options().allowlisted_functions.unmatched_items() {
-            warn!("unused option: --allowlist-function {}", item);
+            warnings
+                .push(format!("unused option: --allowlist-function {}", item));
         }
 
         for item in self.options().allowlisted_vars.unmatched_items() {
-            warn!("unused option: --allowlist-var {}", item);
+            warnings.push(format!("unused option: --allowlist-var {}", item));
         }
 
         for item in self.options().allowlisted_types.unmatched_items() {
-            warn!("unused option: --allowlist-type {}", item);
+            warnings.push(format!("unused option: --allowlist-type {}", item));
+        }
+
+        for msg in warnings {
+            warn!("{}", msg);
+            self.warnings.push(msg);
         }
     }
 
@@ -2656,37 +2671,45 @@
     /// 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_allowlisting(self)[1..].join("::");
-        self.options().no_partialeq_types.matches(&name)
+        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_allowlisting(self)[1..].join("::");
-        self.options().no_copy_types.matches(&name)
+        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_allowlisting(self)[1..].join("::");
-        self.options().no_debug_types.matches(&name)
+        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_allowlisting(self)[1..].join("::");
-        self.options().no_default_types.matches(&name)
+        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_allowlisting(self)[1..].join("::");
-        self.options().no_hash_types.matches(&name)
+        self.options().no_hash_types.matches(name)
     }
 
     /// Check if `--must-use-type` flag is enabled for this item.
     pub fn must_use_type_by_name(&self, item: &Item) -> bool {
         let name = item.path_for_allowlisting(self)[1..].join("::");
-        self.options().must_use_types.matches(&name)
+        self.options().must_use_types.matches(name)
+    }
+
+    pub(crate) fn wrap_unsafe_ops(&self, tokens: impl ToTokens) -> TokenStream {
+        if self.options.wrap_unsafe_ops {
+            quote!(unsafe { #tokens })
+        } else {
+            tokens.into_token_stream()
+        }
     }
 }
 
diff --git a/src/ir/derive.rs b/ir/derive.rs
similarity index 100%
rename from src/ir/derive.rs
rename to ir/derive.rs
diff --git a/src/ir/dot.rs b/ir/dot.rs
similarity index 100%
rename from src/ir/dot.rs
rename to ir/dot.rs
diff --git a/src/ir/enum_ty.rs b/ir/enum_ty.rs
similarity index 91%
rename from src/ir/enum_ty.rs
rename to ir/enum_ty.rs
index 97455c9..39677e9 100644
--- a/src/ir/enum_ty.rs
+++ b/ir/enum_ty.rs
@@ -102,8 +102,8 @@
                     let name = cursor.spelling();
                     let annotations = Annotations::new(&cursor);
                     let custom_behavior = ctx
-                        .parse_callbacks()
-                        .and_then(|callbacks| {
+                        .options()
+                        .last_callback(|callbacks| {
                             callbacks
                                 .enum_variant_behavior(type_name, &name, val)
                         })
@@ -119,8 +119,8 @@
                         });
 
                     let new_name = ctx
-                        .parse_callbacks()
-                        .and_then(|callbacks| {
+                        .options()
+                        .last_callback(|callbacks| {
                             callbacks.enum_variant_name(type_name, &name, val)
                         })
                         .or_else(|| {
@@ -156,7 +156,7 @@
         let path = item.path_for_allowlisting(ctx);
         let enum_ty = item.expect_type();
 
-        if enums.matches(&path[1..].join("::")) {
+        if enums.matches(path[1..].join("::")) {
             return true;
         }
 
@@ -165,7 +165,7 @@
             return false;
         }
 
-        self.variants().iter().any(|v| enums.matches(&v.name()))
+        self.variants().iter().any(|v| enums.matches(v.name()))
     }
 
     /// Returns the final representation of the enum.
@@ -187,10 +187,25 @@
             &ctx.options().bitfield_enums,
             item,
         ) {
-            EnumVariation::NewType { is_bitfield: true }
+            EnumVariation::NewType {
+                is_bitfield: true,
+                is_global: false,
+            }
         } else if self.is_matching_enum(ctx, &ctx.options().newtype_enums, item)
         {
-            EnumVariation::NewType { is_bitfield: false }
+            EnumVariation::NewType {
+                is_bitfield: false,
+                is_global: false,
+            }
+        } else if self.is_matching_enum(
+            ctx,
+            &ctx.options().newtype_global_enums,
+            item,
+        ) {
+            EnumVariation::NewType {
+                is_bitfield: false,
+                is_global: true,
+            }
         } else if self.is_matching_enum(
             ctx,
             &ctx.options().rustified_enums,
diff --git a/src/ir/function.rs b/ir/function.rs
similarity index 81%
rename from src/ir/function.rs
rename to ir/function.rs
index a3a2bbf..7dbbb8f 100644
--- a/src/ir/function.rs
+++ b/ir/function.rs
@@ -6,7 +6,7 @@
 use super::item::Item;
 use super::traversal::{EdgeKind, Trace, Tracer};
 use super::ty::TypeKind;
-use crate::clang;
+use crate::clang::{self, Attribute};
 use crate::parse::{
     ClangItemParser, ClangSubItemParser, ParseError, ParseResult,
 };
@@ -15,11 +15,12 @@
 use quote;
 use quote::TokenStreamExt;
 use std::io;
+use std::str::FromStr;
 
 const RUST_DERIVE_FUNPTR_LIMIT: usize = 12;
 
 /// What kind of a function are we looking at?
-#[derive(Debug, Copy, Clone, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub enum FunctionKind {
     /// A plain, free function.
     Function,
@@ -131,6 +132,11 @@
         self.signature
     }
 
+    /// Get this function's comment.
+    pub fn comment(&self) -> Option<&str> {
+        self.comment.as_deref()
+    }
+
     /// Get this function's kind.
     pub fn kind(&self) -> FunctionKind {
         self.kind
@@ -165,8 +171,8 @@
     }
 }
 
-/// An ABI extracted from a clang cursor.
-#[derive(Debug, Copy, Clone)]
+/// A valid rust ABI.
+#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
 pub enum Abi {
     /// The default C ABI.
     C,
@@ -176,35 +182,82 @@
     Fastcall,
     /// The "thiscall" ABI.
     ThisCall,
+    /// The "vectorcall" ABI.
+    Vectorcall,
     /// The "aapcs" ABI.
     Aapcs,
     /// The "win64" ABI.
     Win64,
-    /// An unknown or invalid ABI.
-    Unknown(CXCallingConv),
+    /// The "C-unwind" ABI.
+    CUnwind,
 }
 
-impl Abi {
-    /// Returns whether this Abi is known or not.
-    fn is_unknown(&self) -> bool {
-        matches!(*self, Abi::Unknown(..))
+impl FromStr for Abi {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "C" => Ok(Self::C),
+            "stdcall" => Ok(Self::Stdcall),
+            "fastcall" => Ok(Self::Fastcall),
+            "thiscall" => Ok(Self::ThisCall),
+            "vectorcall" => Ok(Self::Vectorcall),
+            "aapcs" => Ok(Self::Aapcs),
+            "win64" => Ok(Self::Win64),
+            "C-unwind" => Ok(Self::CUnwind),
+            _ => Err(format!("Invalid or unknown ABI {:?}", s)),
+        }
+    }
+}
+
+impl std::fmt::Display for Abi {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let s = match *self {
+            Self::C => "C",
+            Self::Stdcall => "stdcall",
+            Self::Fastcall => "fastcall",
+            Self::ThisCall => "thiscall",
+            Self::Vectorcall => "vectorcall",
+            Self::Aapcs => "aapcs",
+            Self::Win64 => "win64",
+            Self::CUnwind => "C-unwind",
+        };
+
+        s.fmt(f)
     }
 }
 
 impl quote::ToTokens for Abi {
     fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
-        tokens.append_all(match *self {
-            Abi::C => quote! { "C" },
-            Abi::Stdcall => quote! { "stdcall" },
-            Abi::Fastcall => quote! { "fastcall" },
-            Abi::ThisCall => quote! { "thiscall" },
-            Abi::Aapcs => quote! { "aapcs" },
-            Abi::Win64 => quote! { "win64" },
-            Abi::Unknown(cc) => panic!(
+        let abi = self.to_string();
+        tokens.append_all(quote! { #abi });
+    }
+}
+
+/// An ABI extracted from a clang cursor.
+#[derive(Debug, Copy, Clone)]
+pub(crate) enum ClangAbi {
+    Known(Abi),
+    /// An unknown or invalid ABI.
+    Unknown(CXCallingConv),
+}
+
+impl ClangAbi {
+    /// Returns whether this Abi is known or not.
+    fn is_unknown(&self) -> bool {
+        matches!(*self, ClangAbi::Unknown(..))
+    }
+}
+
+impl quote::ToTokens for ClangAbi {
+    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
+        match *self {
+            Self::Known(abi) => abi.to_tokens(tokens),
+            Self::Unknown(cc) => panic!(
                 "Cannot turn unknown calling convention to tokens: {:?}",
                 cc
             ),
-        });
+        }
     }
 }
 
@@ -220,25 +273,27 @@
 
     /// Whether this function is variadic.
     is_variadic: bool,
+    is_divergent: bool,
 
     /// Whether this function's return value must be used.
     must_use: bool,
 
     /// The ABI of this function.
-    abi: Abi,
+    abi: ClangAbi,
 }
 
-fn get_abi(cc: CXCallingConv) -> Abi {
+fn get_abi(cc: CXCallingConv) -> ClangAbi {
     use clang_sys::*;
     match cc {
-        CXCallingConv_Default => Abi::C,
-        CXCallingConv_C => Abi::C,
-        CXCallingConv_X86StdCall => Abi::Stdcall,
-        CXCallingConv_X86FastCall => Abi::Fastcall,
-        CXCallingConv_X86ThisCall => Abi::ThisCall,
-        CXCallingConv_AAPCS => Abi::Aapcs,
-        CXCallingConv_X86_64Win64 => Abi::Win64,
-        other => Abi::Unknown(other),
+        CXCallingConv_Default => ClangAbi::Known(Abi::C),
+        CXCallingConv_C => ClangAbi::Known(Abi::C),
+        CXCallingConv_X86StdCall => ClangAbi::Known(Abi::Stdcall),
+        CXCallingConv_X86FastCall => ClangAbi::Known(Abi::Fastcall),
+        CXCallingConv_X86ThisCall => ClangAbi::Known(Abi::ThisCall),
+        CXCallingConv_X86VectorCall => ClangAbi::Known(Abi::Vectorcall),
+        CXCallingConv_AAPCS => ClangAbi::Known(Abi::Aapcs),
+        CXCallingConv_X86_64Win64 => ClangAbi::Known(Abi::Win64),
+        other => ClangAbi::Unknown(other),
     }
 }
 
@@ -344,23 +399,6 @@
 }
 
 impl FunctionSig {
-    /// Construct a new function signature.
-    pub fn new(
-        return_type: TypeId,
-        argument_types: Vec<(Option<String>, TypeId)>,
-        is_variadic: bool,
-        must_use: bool,
-        abi: Abi,
-    ) -> Self {
-        FunctionSig {
-            return_type,
-            argument_types,
-            is_variadic,
-            must_use,
-            abi,
-        }
-    }
-
     /// Construct a new function signature from the given Clang type.
     pub fn from_ty(
         ty: &clang::Type,
@@ -438,8 +476,23 @@
             }
         };
 
-        let must_use = ctx.options().enable_function_attribute_detection &&
-            cursor.has_warn_unused_result_attr();
+        let (must_use, mut is_divergent) =
+            if ctx.options().enable_function_attribute_detection {
+                let [must_use, no_return, no_return_cpp] = cursor.has_attrs(&[
+                    Attribute::MUST_USE,
+                    Attribute::NO_RETURN,
+                    Attribute::NO_RETURN_CPP,
+                ]);
+                (must_use, no_return || no_return_cpp)
+            } else {
+                Default::default()
+            };
+
+        // This looks easy to break but the clang parser keeps the type spelling clean even if
+        // other attributes are added.
+        is_divergent =
+            is_divergent || ty.spelling().contains("__attribute__((noreturn))");
+
         let is_method = kind == CXCursor_CXXMethod;
         let is_constructor = kind == CXCursor_Constructor;
         let is_destructor = kind == CXCursor_Destructor;
@@ -513,13 +566,21 @@
                 call_conv = cursor_call_conv;
             }
         }
+
         let abi = get_abi(call_conv);
 
         if abi.is_unknown() {
             warn!("Unknown calling convention: {:?}", call_conv);
         }
 
-        Ok(Self::new(ret, args, ty.is_variadic(), must_use, abi))
+        Ok(FunctionSig {
+            return_type: ret,
+            argument_types: args,
+            is_variadic: ty.is_variadic(),
+            is_divergent,
+            must_use,
+            abi,
+        })
     }
 
     /// Get this function signature's return type.
@@ -533,8 +594,27 @@
     }
 
     /// Get this function signature's ABI.
-    pub fn abi(&self) -> Abi {
-        self.abi
+    pub(crate) fn abi(
+        &self,
+        ctx: &BindgenContext,
+        name: Option<&str>,
+    ) -> ClangAbi {
+        // FIXME (pvdrz): Try to do this check lazily instead. Maybe store the ABI inside `ctx`
+        // instead?.
+        if let Some(name) = name {
+            if let Some((abi, _)) = ctx
+                .options()
+                .abi_overrides
+                .iter()
+                .find(|(_, regex_set)| regex_set.matches(name))
+            {
+                ClangAbi::Known(*abi)
+            } else {
+                self.abi
+            }
+        } else {
+            self.abi
+        }
     }
 
     /// Is this function signature variadic?
@@ -564,7 +644,11 @@
             return false;
         }
 
-        matches!(self.abi, Abi::C | Abi::Unknown(..))
+        matches!(self.abi, ClangAbi::Known(Abi::C) | ClangAbi::Unknown(..))
+    }
+
+    pub(crate) fn is_divergent(&self) -> bool {
+        self.is_divergent
     }
 }
 
@@ -591,7 +675,11 @@
             return Err(ParseError::Continue);
         }
 
-        if cursor.is_inlined_function() {
+        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);
             }
@@ -626,6 +714,13 @@
             // 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))
+        {
+            name = nm;
+        }
+        assert!(!name.is_empty(), "Empty function name.");
 
         let mangled_name = cursor_mangling(context, &cursor);
         let comment = cursor.raw_comment();
diff --git a/src/ir/int.rs b/ir/int.rs
similarity index 100%
rename from src/ir/int.rs
rename to ir/int.rs
diff --git a/src/ir/item.rs b/ir/item.rs
similarity index 98%
rename from src/ir/item.rs
rename to ir/item.rs
index 8692575..5e9aff9 100644
--- a/src/ir/item.rs
+++ b/ir/item.rs
@@ -3,7 +3,6 @@
 use super::super::codegen::{EnumVariation, CONSTIFIED_ENUM_MODULE_REPR_NAME};
 use super::analysis::{HasVtable, HasVtableResult, Sizedness, SizednessResult};
 use super::annotations::Annotations;
-use super::comment;
 use super::comp::{CompKind, MethodKind};
 use super::context::{BindgenContext, ItemId, PartialType, TypeId};
 use super::derive::{
@@ -515,9 +514,9 @@
             return None;
         }
 
-        self.comment.as_ref().map(|comment| {
-            comment::preprocess(comment, self.codegen_depth(ctx))
-        })
+        self.comment
+            .as_ref()
+            .map(|comment| ctx.options().process_comment(comment))
     }
 
     /// What kind of item is this?
@@ -530,6 +529,11 @@
         &mut self.kind
     }
 
+    /// Where in the source is this item located?
+    pub fn location(&self) -> Option<&clang::SourceLocation> {
+        self.location.as_ref()
+    }
+
     /// Get an identifier that differentiates this item from its siblings.
     ///
     /// This should stay relatively stable in the face of code motion outside or
@@ -645,7 +649,7 @@
             if let Some(location) = &self.location {
                 let (file, _, _, _) = location.location();
                 if let Some(filename) = file.name() {
-                    if ctx.options().blocklisted_files.matches(&filename) {
+                    if ctx.options().blocklisted_files.matches(filename) {
                         return true;
                     }
                 }
@@ -927,8 +931,8 @@
         let name = names.join("_");
 
         let name = if opt.user_mangled == UserMangled::Yes {
-            ctx.parse_callbacks()
-                .and_then(|callbacks| callbacks.item_name(&name))
+            ctx.options()
+                .last_callback(|callbacks| callbacks.item_name(&name))
                 .unwrap_or(name)
         } else {
             name
@@ -1091,6 +1095,11 @@
             _ => return None,
         })
     }
+
+    /// Whether this is a #[must_use] type.
+    pub fn must_use(&self, ctx: &BindgenContext) -> bool {
+        self.annotations().must_use_type() || ctx.must_use_type_by_name(self)
+    }
 }
 
 impl<T> IsOpaque for T
@@ -1889,7 +1898,7 @@
 
         // See tests/headers/const_tparam.hpp and
         // tests/headers/variadic_tname.hpp.
-        let name = ty_spelling.replace("const ", "").replace(".", "");
+        let name = ty_spelling.replace("const ", "").replace('.', "");
 
         let id = with_id.unwrap_or_else(|| ctx.next_item_id());
         let item = Item::new(
diff --git a/src/ir/item_kind.rs b/ir/item_kind.rs
similarity index 100%
rename from src/ir/item_kind.rs
rename to ir/item_kind.rs
diff --git a/src/ir/layout.rs b/ir/layout.rs
similarity index 97%
rename from src/ir/layout.rs
rename to ir/layout.rs
index 6cf9113..6f45030 100644
--- a/src/ir/layout.rs
+++ b/ir/layout.rs
@@ -7,7 +7,7 @@
 use std::cmp;
 
 /// A type that represents the struct layout of a type.
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 pub struct Layout {
     /// The size (in bytes) of this layout.
     pub size: usize,
@@ -93,7 +93,7 @@
 }
 
 /// When we are treating a type as opaque, it is just a blob with a `Layout`.
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct Opaque(pub Layout);
 
 impl Opaque {
diff --git a/src/ir/mod.rs b/ir/mod.rs
similarity index 100%
rename from src/ir/mod.rs
rename to ir/mod.rs
diff --git a/src/ir/module.rs b/ir/module.rs
similarity index 100%
rename from src/ir/module.rs
rename to ir/module.rs
diff --git a/src/ir/objc.rs b/ir/objc.rs
similarity index 100%
rename from src/ir/objc.rs
rename to ir/objc.rs
diff --git a/src/ir/template.rs b/ir/template.rs
similarity index 100%
rename from src/ir/template.rs
rename to ir/template.rs
diff --git a/src/ir/traversal.rs b/ir/traversal.rs
similarity index 89%
rename from src/ir/traversal.rs
rename to ir/traversal.rs
index 088e744..f14483f 100644
--- a/src/ir/traversal.rs
+++ b/ir/traversal.rs
@@ -179,17 +179,10 @@
 
 /// A predicate to allow visiting only sub-sets of the whole IR graph by
 /// excluding certain edges from being followed by the traversal.
-pub trait TraversalPredicate {
-    /// Should the traversal follow this edge, and visit everything that is
-    /// reachable through it?
-    fn should_follow(&self, ctx: &BindgenContext, edge: Edge) -> bool;
-}
-
-impl TraversalPredicate for for<'a> fn(&'a BindgenContext, Edge) -> bool {
-    fn should_follow(&self, ctx: &BindgenContext, edge: Edge) -> bool {
-        (*self)(ctx, edge)
-    }
-}
+///
+/// The predicate must return true if the traversal should follow this edge
+/// and visit everything that is reachable through it.
+pub type TraversalPredicate = for<'a> fn(&'a BindgenContext, Edge) -> bool;
 
 /// A `TraversalPredicate` implementation that follows all edges, and therefore
 /// traversals using this predicate will see the whole IR graph reachable from
@@ -378,11 +371,10 @@
 /// An graph traversal of the transitive closure of references between items.
 ///
 /// See `BindgenContext::allowlisted_items` for more information.
-pub struct ItemTraversal<'ctx, Storage, Queue, Predicate>
+pub struct ItemTraversal<'ctx, Storage, Queue>
 where
     Storage: TraversalStorage<'ctx>,
     Queue: TraversalQueue,
-    Predicate: TraversalPredicate,
 {
     ctx: &'ctx BindgenContext,
 
@@ -393,25 +385,23 @@
     queue: Queue,
 
     /// The predicate that determines which edges this traversal will follow.
-    predicate: Predicate,
+    predicate: TraversalPredicate,
 
     /// The item we are currently traversing.
     currently_traversing: Option<ItemId>,
 }
 
-impl<'ctx, Storage, Queue, Predicate>
-    ItemTraversal<'ctx, Storage, Queue, Predicate>
+impl<'ctx, Storage, Queue> ItemTraversal<'ctx, Storage, Queue>
 where
     Storage: TraversalStorage<'ctx>,
     Queue: TraversalQueue,
-    Predicate: TraversalPredicate,
 {
     /// Begin a new traversal, starting from the given roots.
     pub fn new<R>(
         ctx: &'ctx BindgenContext,
         roots: R,
-        predicate: Predicate,
-    ) -> ItemTraversal<'ctx, Storage, Queue, Predicate>
+        predicate: TraversalPredicate,
+    ) -> ItemTraversal<'ctx, Storage, Queue>
     where
         R: IntoIterator<Item = ItemId>,
     {
@@ -433,16 +423,14 @@
     }
 }
 
-impl<'ctx, Storage, Queue, Predicate> Tracer
-    for ItemTraversal<'ctx, Storage, Queue, Predicate>
+impl<'ctx, Storage, Queue> Tracer for ItemTraversal<'ctx, Storage, Queue>
 where
     Storage: TraversalStorage<'ctx>,
     Queue: TraversalQueue,
-    Predicate: TraversalPredicate,
 {
     fn visit_kind(&mut self, item: ItemId, kind: EdgeKind) {
         let edge = Edge::new(item, kind);
-        if !self.predicate.should_follow(self.ctx, edge) {
+        if !(self.predicate)(self.ctx, edge) {
             return;
         }
 
@@ -454,12 +442,10 @@
     }
 }
 
-impl<'ctx, Storage, Queue, Predicate> Iterator
-    for ItemTraversal<'ctx, Storage, Queue, Predicate>
+impl<'ctx, Storage, Queue> Iterator for ItemTraversal<'ctx, Storage, Queue>
 where
     Storage: TraversalStorage<'ctx>,
     Queue: TraversalQueue,
-    Predicate: TraversalPredicate,
 {
     type Item = ItemId;
 
@@ -488,21 +474,5 @@
 ///
 /// See `BindgenContext::assert_no_dangling_item_traversal` for more
 /// information.
-pub type AssertNoDanglingItemsTraversal<'ctx> = ItemTraversal<
-    'ctx,
-    Paths<'ctx>,
-    VecDeque<ItemId>,
-    for<'a> fn(&'a BindgenContext, Edge) -> bool,
->;
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    #[allow(dead_code)]
-    fn traversal_predicate_is_object_safe() {
-        // This should compile only if TraversalPredicate is object safe.
-        fn takes_by_trait_object(_: &dyn TraversalPredicate) {}
-    }
-}
+pub type AssertNoDanglingItemsTraversal<'ctx> =
+    ItemTraversal<'ctx, Paths<'ctx>, VecDeque<ItemId>>;
diff --git a/src/ir/ty.rs b/ir/ty.rs
similarity index 94%
rename from src/ir/ty.rs
rename to ir/ty.rs
index d573408..fd6108f 100644
--- a/src/ir/ty.rs
+++ b/ir/ty.rs
@@ -564,7 +564,7 @@
 }
 
 /// The kind of float this type represents.
-#[derive(Debug, Copy, Clone, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub enum FloatKind {
     /// A `float`.
     Float,
@@ -698,7 +698,12 @@
 
         let layout = ty.fallible_layout(ctx).ok();
         let cursor = ty.declaration();
-        let mut name = cursor.spelling();
+        let is_anonymous = cursor.is_anonymous();
+        let mut name = if is_anonymous {
+            None
+        } else {
+            Some(cursor.spelling()).filter(|n| !n.is_empty())
+        };
 
         debug!(
             "from_clang_ty: {:?}, ty: {:?}, loc: {:?}",
@@ -732,7 +737,7 @@
             if is_canonical_objcpointer && is_template_type_param {
                 // Objective-C generics are just ids with fancy name.
                 // To keep it simple, just name them ids
-                name = "id".to_owned();
+                name = Some("id".to_owned());
             }
         }
 
@@ -861,7 +866,7 @@
                                         return Err(ParseError::Recurse);
                                     }
                                 } else {
-                                    name = location.spelling();
+                                    name = Some(location.spelling());
                                 }
 
                                 let complex = CompInfo::from_ty(
@@ -903,7 +908,7 @@
                                                 CXType_Typedef
                                             );
 
-                                            name = current.spelling();
+                                            name = Some(location.spelling());
 
                                             let inner_ty = cur
                                                 .typedef_type()
@@ -1031,7 +1036,16 @@
                 CXType_ObjCObjectPointer |
                 CXType_MemberPointer |
                 CXType_Pointer => {
-                    let pointee = ty.pointee_type().unwrap();
+                    let mut pointee = ty.pointee_type().unwrap();
+                    if *ty != canonical_ty {
+                        let canonical_pointee =
+                            canonical_ty.pointee_type().unwrap();
+                        // clang sometimes loses pointee constness here, see
+                        // #2244.
+                        if canonical_pointee.is_const() != pointee.is_const() {
+                            pointee = canonical_pointee;
+                        }
+                    }
                     let inner =
                         Item::from_ty_or_ref(pointee, location, None, ctx);
                     TypeKind::Pointer(inner)
@@ -1080,9 +1094,9 @@
                 }
                 CXType_Typedef => {
                     let inner = cursor.typedef_type().expect("Not valid Type?");
-                    let inner =
+                    let inner_id =
                         Item::from_ty_or_ref(inner, location, None, ctx);
-                    if inner == potential_id {
+                    if inner_id == potential_id {
                         warn!(
                             "Generating oqaque type instead of self-referential \
                             typedef");
@@ -1090,16 +1104,31 @@
                         // within the clang parsing.
                         TypeKind::Opaque
                     } else {
-                        TypeKind::Alias(inner)
+                        // Check if this type definition is an alias to a pointer of a `struct` /
+                        // `union` / `enum` with the same name and add the `_ptr` suffix to it to
+                        // avoid name collisions.
+                        if let Some(ref mut name) = name {
+                            if inner.kind() == CXType_Pointer &&
+                                !ctx.options().c_naming
+                            {
+                                let pointee = inner.pointee_type().unwrap();
+                                if pointee.kind() == CXType_Elaborated &&
+                                    pointee.declaration().spelling() == *name
+                                {
+                                    *name += "_ptr";
+                                }
+                            }
+                        }
+                        TypeKind::Alias(inner_id)
                     }
                 }
                 CXType_Enum => {
                     let enum_ = Enum::from_ty(ty, ctx).expect("Not an enum?");
 
-                    if name.is_empty() {
+                    if !is_anonymous {
                         let pretty_name = ty.spelling();
                         if clang::is_valid_identifier(&pretty_name) {
-                            name = pretty_name;
+                            name = Some(pretty_name);
                         }
                     }
 
@@ -1114,12 +1143,12 @@
                     )
                     .expect("Not a complex type?");
 
-                    if name.is_empty() {
+                    if !is_anonymous {
                         // The pretty-printed name may contain typedefed name,
                         // but may also be "struct (anonymous at .h:1)"
                         let pretty_name = ty.spelling();
                         if clang::is_valid_identifier(&pretty_name) {
-                            name = pretty_name;
+                            name = Some(pretty_name);
                         }
                     }
 
@@ -1131,8 +1160,7 @@
                         location,
                         None,
                         ctx,
-                    )
-                    .expect("Not able to resolve vector element?");
+                    )?;
                     TypeKind::Vector(inner, ty.num_elements().unwrap())
                 }
                 CXType_ConstantArray => {
@@ -1159,7 +1187,9 @@
                 CXType_ObjCClass | CXType_ObjCInterface => {
                     let interface = ObjCInterface::from_ty(&location, ctx)
                         .expect("Not a valid objc interface?");
-                    name = interface.rust_name();
+                    if !is_anonymous {
+                        name = Some(interface.rust_name());
+                    }
                     TypeKind::ObjCInterface(interface)
                 }
                 CXType_Dependent => {
@@ -1177,7 +1207,7 @@
             }
         };
 
-        let name = if name.is_empty() { None } else { Some(name) };
+        name = name.filter(|n| !n.is_empty());
 
         let is_const = ty.is_const() ||
             (ty.kind() == CXType_ConstantArray &&
@@ -1197,6 +1227,13 @@
     where
         T: Tracer,
     {
+        if self
+            .name()
+            .map_or(false, |name| context.is_stdint_type(name))
+        {
+            // These types are special-cased in codegen and don't need to be traversed.
+            return;
+        }
         match *self.kind() {
             TypeKind::Pointer(inner) |
             TypeKind::Reference(inner) |
diff --git a/src/ir/var.rs b/ir/var.rs
similarity index 79%
rename from src/ir/var.rs
rename to ir/var.rs
index cd17937..c86742f 100644
--- a/src/ir/var.rs
+++ b/ir/var.rs
@@ -149,52 +149,27 @@
     }
 }
 
-/// Determines whether a set of tokens from a CXCursor_MacroDefinition
-/// represent a function-like macro. If so, calls the func_macro callback
-/// and returns `Err(ParseError::Continue)` to signal to skip further
-/// processing. If conversion to UTF-8 fails (it is performed only where it
-/// should be infallible), then `Err(ParseError::Continue)` is returned as well.
+/// Parses tokens from a CXCursor_MacroDefinition pointing into a function-like
+/// macro, and calls the func_macro callback.
 fn handle_function_macro(
     cursor: &clang::Cursor,
-    tokens: &[ClangToken],
     callbacks: &dyn crate::callbacks::ParseCallbacks,
-) -> Result<(), ParseError> {
-    // TODO: Hoist the `is_macro_function_like` check into this function's
-    // caller, and thus avoid allocating the `tokens` vector for non-functional
-    // macros.
-    let is_functional_macro = cursor.is_macro_function_like();
-
-    if !is_functional_macro {
-        return Ok(());
-    }
-
+) {
     let is_closing_paren = |t: &ClangToken| {
         // Test cheap token kind before comparing exact spellings.
         t.kind == clang_sys::CXToken_Punctuation && t.spelling() == b")"
     };
-    let boundary = tokens.iter().position(is_closing_paren);
-
-    let mut spelled = tokens.iter().map(ClangToken::spelling);
-    // Add 1, to convert index to length.
-    let left = spelled
-        .by_ref()
-        .take(boundary.ok_or(ParseError::Continue)? + 1);
-    let left = left.collect::<Vec<_>>().concat();
-    let left = String::from_utf8(left).map_err(|_| ParseError::Continue)?;
-    let right = spelled;
-    // Drop last token with LLVM < 4.0, due to an LLVM bug.
-    //
-    // See:
-    //   https://bugs.llvm.org//show_bug.cgi?id=9069
-    let len = match (right.len(), crate::clang_version().parsed) {
-        (len, Some((v, _))) if len > 0 && v < 4 => len - 1,
-        (len, _) => len,
-    };
-    let right: Vec<_> = right.take(len).collect();
-    callbacks.func_macro(&left, &right);
-
-    // We handled the macro, skip future macro processing.
-    Err(ParseError::Continue)
+    let tokens: Vec<_> = cursor.tokens().iter().collect();
+    if let Some(boundary) = tokens.iter().position(is_closing_paren) {
+        let mut spelled = tokens.iter().map(ClangToken::spelling);
+        // Add 1, to convert index to length.
+        let left = spelled.by_ref().take(boundary + 1);
+        let left = left.collect::<Vec<_>>().concat();
+        if let Ok(left) = String::from_utf8(left) {
+            let right: Vec<_> = spelled.collect();
+            callbacks.func_macro(&left, &right);
+        }
+    }
 }
 
 impl ClangSubItemParser for Var {
@@ -207,9 +182,7 @@
         use clang_sys::*;
         match cursor.kind() {
             CXCursor_MacroDefinition => {
-                let tokens: Vec<_> = cursor.tokens().iter().collect();
-
-                if let Some(callbacks) = ctx.parse_callbacks() {
+                for callbacks in &ctx.options().parse_callbacks {
                     match callbacks.will_parse_macro(&cursor.spelling()) {
                         MacroParsingBehavior::Ignore => {
                             return Err(ParseError::Continue);
@@ -217,10 +190,14 @@
                         MacroParsingBehavior::Default => {}
                     }
 
-                    handle_function_macro(&cursor, &tokens, callbacks)?;
+                    if cursor.is_macro_function_like() {
+                        handle_function_macro(&cursor, callbacks.as_ref());
+                        // We handled the macro, skip macro processing below.
+                        return Err(ParseError::Continue);
+                    }
                 }
 
-                let value = parse_macro(ctx, &tokens);
+                let value = parse_macro(ctx, &cursor);
 
                 let (id, value) = match value {
                     Some(v) => v,
@@ -272,15 +249,15 @@
                             true,
                             ctx,
                         );
-                        if let Some(callbacks) = ctx.parse_callbacks() {
+                        for callbacks in &ctx.options().parse_callbacks {
                             callbacks.str_macro(&name, &val);
                         }
                         (TypeKind::Pointer(char_ty), VarType::String(val))
                     }
                     EvalResult::Int(Wrapping(value)) => {
                         let kind = ctx
-                            .parse_callbacks()
-                            .and_then(|c| c.int_macro(&name, value))
+                            .options()
+                            .last_callback(|c| c.int_macro(&name, value))
                             .unwrap_or_else(|| {
                                 default_macro_constant_type(ctx, value)
                             });
@@ -308,18 +285,19 @@
                 // TODO(emilio): do we have to special-case constant arrays in
                 // some other places?
                 let is_const = ty.is_const() ||
-                    (ty.kind() == CXType_ConstantArray &&
+                    ([CXType_ConstantArray, CXType_IncompleteArray]
+                        .contains(&ty.kind()) &&
                         ty.elem_type()
                             .map_or(false, |element| element.is_const()));
 
                 let ty = match Item::from_ty(&ty, cursor, None, ctx) {
                     Ok(ty) => ty,
                     Err(e) => {
-                        assert_eq!(
-                            ty.kind(),
-                            CXType_Auto,
+                        assert!(
+                            matches!(ty.kind(), CXType_Auto | CXType_Unexposed),
                             "Couldn't resolve constant type, and it \
-                             wasn't an nondeductible auto type!"
+                             wasn't an nondeductible auto type or unexposed \
+                             type!"
                         );
                         return Err(e);
                     }
@@ -348,8 +326,7 @@
 
                     let mut val = cursor.evaluate().and_then(|v| v.as_int());
                     if val.is_none() || !kind.signedness_matches(val.unwrap()) {
-                        let tu = ctx.translation_unit();
-                        val = get_integer_literal_from_cursor(&cursor, tu);
+                        val = get_integer_literal_from_cursor(&cursor);
                     }
 
                     val.map(|val| {
@@ -387,29 +364,14 @@
 /// Try and parse a macro using all the macros parsed until now.
 fn parse_macro(
     ctx: &BindgenContext,
-    tokens: &[ClangToken],
+    cursor: &clang::Cursor,
 ) -> Option<(Vec<u8>, cexpr::expr::EvalResult)> {
     use cexpr::expr;
 
-    let mut cexpr_tokens: Vec<_> = tokens
-        .iter()
-        .filter_map(ClangToken::as_cexpr_token)
-        .collect();
+    let cexpr_tokens = cursor.cexpr_tokens();
 
     let parser = expr::IdentifierParser::new(ctx.parsed_macros());
 
-    if let Ok((_, (id, val))) = parser.macro_definition(&cexpr_tokens) {
-        return Some((id.into(), val));
-    }
-
-    // Try without the last token, to workaround a libclang bug in versions
-    // previous to 4.0.
-    //
-    // See:
-    //   https://bugs.llvm.org//show_bug.cgi?id=9069
-    //   https://reviews.llvm.org/D26446
-    cexpr_tokens.pop()?;
-
     match parser.macro_definition(&cexpr_tokens) {
         Ok((_, (id, val))) => Some((id.into(), val)),
         _ => None,
@@ -429,10 +391,7 @@
     }
 }
 
-fn get_integer_literal_from_cursor(
-    cursor: &clang::Cursor,
-    unit: &clang::TranslationUnit,
-) -> Option<i64> {
+fn get_integer_literal_from_cursor(cursor: &clang::Cursor) -> Option<i64> {
     use clang_sys::*;
     let mut value = None;
     cursor.visit(|c| {
@@ -441,7 +400,7 @@
                 value = parse_int_literal_tokens(&c);
             }
             CXCursor_UnexposedExpr => {
-                value = get_integer_literal_from_cursor(&c, unit);
+                value = get_integer_literal_from_cursor(&c);
             }
             _ => (),
         }
diff --git a/src/lib.rs b/lib.rs
similarity index 71%
rename from src/lib.rs
rename to lib.rs
index 9a90dac..4b71fb9 100644
--- a/src/lib.rs
+++ b/lib.rs
@@ -49,6 +49,18 @@
     };
 }
 
+macro_rules! fn_with_regex_arg {
+    ($(#[$attrs:meta])* pub fn $($tokens:tt)*) => {
+        $(#[$attrs])*
+        /// Check the [regular expression arguments] section and the [regex] crate
+        /// documentation for further information.
+        ///
+        /// [regular expression arguments]: ./struct.Builder.html#regular-expression-arguments
+        /// [regex]: <https://docs.rs/regex>
+        pub fn $($tokens)*
+    };
+}
+
 mod clang;
 mod codegen;
 mod deps;
@@ -66,22 +78,28 @@
 doc_mod!(parse, parse_docs);
 doc_mod!(regex_set, regex_set_docs);
 
-pub use crate::codegen::{AliasVariation, EnumVariation, MacroTypeVariation};
+use ir::comment;
+
+pub use crate::codegen::{
+    AliasVariation, EnumVariation, MacroTypeVariation, NonCopyUnionStyle,
+};
 use crate::features::RustFeatures;
 pub use crate::features::{
     RustTarget, LATEST_STABLE_RUST, RUST_TARGET_STRINGS,
 };
 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 std::borrow::Cow;
+use std::env;
 use std::fs::{File, OpenOptions};
 use std::io::{self, Write};
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
-use std::{env, iter};
+use std::rc::Rc;
 
 // Some convenient typedefs for a fast hash map and hash set.
 type HashMap<K, V> = ::rustc_hash::FxHashMap<K, V>;
@@ -219,12 +237,16 @@
 /// End-users of the crate may need to set the `BINDGEN_EXTRA_CLANG_ARGS` environment variable to
 /// add additional arguments. For example, to build against a different sysroot a user could set
 /// `BINDGEN_EXTRA_CLANG_ARGS` to `--sysroot=/path/to/sysroot`.
-#[derive(Debug, Default)]
+///
+/// # Regular expression arguments
+///
+/// Some [`Builder`] methods like the `allowlist_*` and `blocklist_*` family of methods allow
+/// 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>)$`.
+#[derive(Debug, Default, Clone)]
 pub struct Builder {
     options: BindgenOptions,
-    input_headers: Vec<String>,
-    // Tuples of unsaved file contents of the form (name, contents).
-    input_header_contents: Vec<(String, String)>,
 }
 
 /// Construct a new [`Builder`](./struct.Builder.html).
@@ -232,12 +254,26 @@
     Default::default()
 }
 
+fn get_extra_clang_args() -> Vec<String> {
+    // Add any extra arguments from the environment to the clang command line.
+    let extra_clang_args =
+        match get_target_dependent_env_var("BINDGEN_EXTRA_CLANG_ARGS") {
+            None => return vec![],
+            Some(s) => s,
+        };
+    // Try to parse it with shell quoting. If we fail, make it one single big argument.
+    if let Some(strings) = shlex::split(&extra_clang_args) {
+        return strings;
+    }
+    vec![extra_clang_args]
+}
+
 impl Builder {
     /// Generates the command line flags use for creating `Builder`.
     pub fn command_line_flags(&self) -> Vec<String> {
         let mut output_vector: Vec<String> = Vec::new();
 
-        if let Some(header) = self.input_headers.last().cloned() {
+        if let Some(header) = self.options.input_headers.last().cloned() {
             // Positional argument 'header'
             output_vector.push(header);
         }
@@ -264,11 +300,19 @@
                     codegen::EnumVariation::Rust {
                         non_exhaustive: true,
                     } => "rust_non_exhaustive",
-                    codegen::EnumVariation::NewType { is_bitfield: true } => {
-                        "bitfield"
-                    }
-                    codegen::EnumVariation::NewType { is_bitfield: false } => {
-                        "newtype"
+                    codegen::EnumVariation::NewType {
+                        is_bitfield: true,
+                        ..
+                    } => "bitfield",
+                    codegen::EnumVariation::NewType {
+                        is_bitfield: false,
+                        is_global,
+                    } => {
+                        if is_global {
+                            "newtype_global"
+                        } else {
+                            "newtype"
+                        }
                     }
                     codegen::EnumVariation::Consts => "consts",
                     codegen::EnumVariation::ModuleConsts => "moduleconsts",
@@ -289,9 +333,17 @@
                 .push(self.options.default_alias_style.as_str().into());
         }
 
+        if self.options.default_non_copy_union_style != Default::default() {
+            output_vector.push("--default-non-copy-union-style".into());
+            output_vector.push(
+                self.options.default_non_copy_union_style.as_str().into(),
+            );
+        }
+
         let regex_sets = &[
             (&self.options.bitfield_enums, "--bitfield-enum"),
             (&self.options.newtype_enums, "--newtype-enum"),
+            (&self.options.newtype_global_enums, "--newtype-global-enum"),
             (&self.options.rustified_enums, "--rustified-enum"),
             (
                 &self.options.rustified_non_exhaustive_enums,
@@ -305,6 +357,11 @@
             (&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.bindgen_wrapper_union,
+                "--bindgen-wrapper-union",
+            ),
+            (&self.options.manually_drop_union, "--manually-drop-union"),
             (&self.options.blocklisted_types, "--blocklist-type"),
             (&self.options.blocklisted_functions, "--blocklist-function"),
             (&self.options.blocklisted_items, "--blocklist-item"),
@@ -313,6 +370,7 @@
             (&self.options.allowlisted_functions, "--allowlist-function"),
             (&self.options.allowlisted_types, "--allowlist-type"),
             (&self.options.allowlisted_vars, "--allowlist-var"),
+            (&self.options.allowlisted_files, "--allowlist-file"),
             (&self.options.no_partialeq_types, "--no-partialeq"),
             (&self.options.no_copy_types, "--no-copy"),
             (&self.options.no_debug_types, "--no-debug"),
@@ -328,6 +386,13 @@
             }
         }
 
+        for (abi, set) in &self.options.abi_overrides {
+            for item in set.get_items() {
+                output_vector.push("--override-abi".to_owned());
+                output_vector.push(format!("{}={}", item, abi));
+            }
+        }
+
         if !self.options.layout_tests {
             output_vector.push("--no-layout-tests".into());
         }
@@ -525,8 +590,8 @@
             output_vector.push("--no-record-matches".into());
         }
 
-        if self.options.size_t_is_usize {
-            output_vector.push("--size_t-is-usize".into());
+        if !self.options.size_t_is_usize {
+            output_vector.push("--no-size_t-is-usize".into());
         }
 
         if !self.options.rustfmt_bindings {
@@ -568,6 +633,22 @@
             output_vector.push("--explicit-padding".into());
         }
 
+        if self.options.vtable_generation {
+            output_vector.push("--vtable-generation".into());
+        }
+
+        if self.options.sort_semantically {
+            output_vector.push("--sort-semantically".into());
+        }
+
+        if self.options.merge_extern_blocks {
+            output_vector.push("--merge-extern-blocks".into());
+        }
+
+        if self.options.wrap_unsafe_ops {
+            output_vector.push("--wrap-unsafe-ops".into());
+        }
+
         // Add clang arguments
 
         output_vector.push("--".into());
@@ -576,13 +657,13 @@
             output_vector.extend(self.options.clang_args.iter().cloned());
         }
 
-        if self.input_headers.len() > 1 {
-            // To pass more than one header, we need to pass all but the last
-            // header via the `-include` clang arg
-            for header in &self.input_headers[..self.input_headers.len() - 1] {
-                output_vector.push("-include".to_string());
-                output_vector.push(header.clone());
-            }
+        // To pass more than one header, we need to pass all but the last
+        // header via the `-include` clang arg
+        for header in &self.options.input_headers
+            [..self.options.input_headers.len().saturating_sub(1)]
+        {
+            output_vector.push("-include".to_string());
+            output_vector.push(header.clone());
         }
 
         output_vector
@@ -611,7 +692,7 @@
     ///     .unwrap();
     /// ```
     pub fn header<T: Into<String>>(mut self, header: T) -> Builder {
-        self.input_headers.push(header.into());
+        self.options.input_headers.push(header.into());
         self
     }
 
@@ -640,7 +721,8 @@
             .to_str()
             .expect("Cannot convert current directory name to string")
             .to_owned();
-        self.input_header_contents
+        self.options
+            .input_header_contents
             .push((absolute_path, contents.into()));
         self
     }
@@ -649,6 +731,13 @@
     ///
     /// The default is the latest stable Rust version
     pub fn rust_target(mut self, rust_target: RustTarget) -> Self {
+        #[allow(deprecated)]
+        if rust_target <= RustTarget::Stable_1_30 {
+            warn!(
+                "The {} rust target is deprecated. If you have a good reason to use this target please report it at https://github.com/rust-lang/rust-bindgen/issues",
+                String::from(rust_target)
+            );
+        }
         self.options.set_rust_target(rust_target);
         self
     }
@@ -720,12 +809,6 @@
         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 {
@@ -758,168 +841,110 @@
         self
     }
 
-    /// Hide the given type from the generated bindings. Regular expressions are
-    /// supported.
-    #[deprecated(note = "Use blocklist_type instead")]
-    pub fn hide_type<T: AsRef<str>>(self, arg: T) -> Builder {
-        self.blocklist_type(arg)
+    fn_with_regex_arg! {
+        /// Hide the given type from the generated bindings. Regular expressions are
+        /// supported.
+        ///
+        /// To blocklist types prefixed with "mylib" use `"mylib_.*"`.
+        pub fn blocklist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.blocklisted_types.insert(arg);
+            self
+        }
     }
 
-    /// 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)
+    fn_with_regex_arg! {
+        /// Hide the given function from the generated bindings. Regular expressions
+        /// are supported.
+        ///
+        /// Methods can be blocklisted by prefixing the name of the type implementing
+        /// them followed by an underscore. So if `Foo` has a method `bar`, it can
+        /// be blocklisted as `Foo_bar`.
+        ///
+        /// To blocklist functions prefixed with "mylib" use `"mylib_.*"`.
+        pub fn blocklist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.blocklisted_functions.insert(arg);
+            self
+        }
     }
 
-    /// Hide the given type from the generated bindings. Regular expressions are
-    /// supported.
-    ///
-    /// To blocklist types prefixed with "mylib" use `"mylib_.*"`.
-    /// For more complicated expressions check
-    /// [regex](https://docs.rs/regex/*/regex/) docs
-    pub fn blocklist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.blocklisted_types.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Hide the given item from the generated bindings, regardless of
+        /// whether it's a type, function, module, etc. Regular
+        /// expressions are supported.
+        ///
+        /// To blocklist items prefixed with "mylib" use `"mylib_.*"`.
+        pub fn blocklist_item<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.blocklisted_items.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)
+    fn_with_regex_arg! {
+        /// Hide any contents of the given file from the generated bindings,
+        /// regardless of whether it's a type, function, module etc.
+        pub fn blocklist_file<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.blocklisted_files.insert(arg);
+            self
+        }
     }
 
-    /// Hide the given function from the generated bindings. Regular expressions
-    /// are supported.
-    ///
-    /// To blocklist functions prefixed with "mylib" use `"mylib_.*"`.
-    /// For more complicated expressions check
-    /// [regex](https://docs.rs/regex/*/regex/) docs
-    pub fn blocklist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.blocklisted_functions.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Treat the given type as opaque in the generated bindings. Regular
+        /// expressions are supported.
+        ///
+        /// To change types prefixed with "mylib" into opaque, use `"mylib_.*"`.
+        pub fn opaque_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.opaque_types.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
+    fn_with_regex_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 allowlist types prefixed with "mylib" use `"mylib_.*"`.
+        pub fn allowlist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.allowlisted_types.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.
-    ///
-    /// To blocklist items prefixed with "mylib" use `"mylib_.*"`.
-    /// For more complicated expressions check
-    /// [regex](https://docs.rs/regex/*/regex/) docs
-    pub fn blocklist_item<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.blocklisted_items.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Allowlist the given function so that it (and all types that it
+        /// transitively refers to) appears in the generated bindings. Regular
+        /// expressions are supported.
+        ///
+        /// Methods can be allowlisted by prefixing the name of the type
+        /// implementing them followed by an underscore. So if `Foo` has a method
+        /// `bar`, it can be allowlisted as `Foo_bar`.
+        ///
+        /// To allowlist functions prefixed with "mylib" use `"mylib_.*"`.
+        pub fn allowlist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.allowlisted_functions.insert(arg);
+            self
+        }
     }
 
-    /// Hide any contents of the given file from the generated bindings,
-    /// regardless of whether it's a type, function, module etc.
-    pub fn blocklist_file<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.blocklisted_files.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// 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 allowlist variables prefixed with "mylib" use `"mylib_.*"`.
+        pub fn allowlist_var<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.allowlisted_vars.insert(arg);
+            self
+        }
     }
 
-    /// Treat the given type as opaque in the generated bindings. Regular
-    /// expressions are supported.
-    ///
-    /// To change types prefixed with "mylib" into opaque, use `"mylib_.*"`.
-    /// For more complicated expressions check
-    /// [regex](https://docs.rs/regex/*/regex/) docs
-    pub fn opaque_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.opaque_types.insert(arg);
-        self
-    }
-
-    /// 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 whitelisted_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.
-    #[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 allowlist types prefixed with "mylib" use `"mylib_.*"`.
-    /// For more complicated expressions check
-    /// [regex](https://docs.rs/regex/*/regex/) docs
-    pub fn allowlist_type<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.allowlisted_types.insert(arg);
-        self
-    }
-
-    /// 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 allowlist functions prefixed with "mylib" use `"mylib_.*"`.
-    /// For more complicated expressions check
-    /// [regex](https://docs.rs/regex/*/regex/) docs
-    pub fn allowlist_function<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.allowlisted_functions.insert(arg);
-        self
-    }
-
-    /// Allowlist the given function.
-    ///
-    /// 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.allowlist_function(arg)
-    }
-
-    /// 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 allowlist variables prefixed with "mylib" use `"mylib_.*"`.
-    /// For more complicated expressions check
-    /// [regex](https://docs.rs/regex/*/regex/) docs
-    pub fn allowlist_var<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.allowlisted_vars.insert(arg);
-        self
-    }
-
-    /// 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 allowlist_var instead.
-    #[deprecated(note = "use allowlist_var instead")]
-    pub fn whitelisted_var<T: AsRef<str>>(self, arg: T) -> Builder {
-        self.allowlist_var(arg)
+    fn_with_regex_arg! {
+        /// Allowlist the given file so that its contents appear in the generated bindings.
+        pub fn allowlist_file<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.allowlisted_files.insert(arg);
+            self
+        }
     }
 
     /// Set the default style of code to generate for enums
@@ -931,75 +956,101 @@
         self
     }
 
-    /// Mark the given enum (or set of enums, if using a pattern) as being
-    /// bitfield-like. Regular expressions are supported.
-    ///
-    /// This makes bindgen generate a type that isn't a rust `enum`. Regular
-    /// expressions are supported.
-    ///
-    /// This is similar to the newtype enum style, but with the bitwise
-    /// operators implemented.
-    pub fn bitfield_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.bitfield_enums.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Mark the given enum (or set of enums, if using a pattern) as being
+        /// bitfield-like. Regular expressions are supported.
+        ///
+        /// This makes bindgen generate a type that isn't a rust `enum`. Regular
+        /// expressions are supported.
+        ///
+        /// This is similar to the newtype enum style, but with the bitwise
+        /// operators implemented.
+        pub fn bitfield_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.bitfield_enums.insert(arg);
+            self
+        }
     }
 
-    /// Mark the given enum (or set of enums, if using a pattern) as a newtype.
-    /// Regular expressions are supported.
-    ///
-    /// This makes bindgen generate a type that isn't a Rust `enum`. Regular
-    /// expressions are supported.
-    pub fn newtype_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.newtype_enums.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Mark the given enum (or set of enums, if using a pattern) as a newtype.
+        /// Regular expressions are supported.
+        ///
+        /// This makes bindgen generate a type that isn't a Rust `enum`. Regular
+        /// expressions are supported.
+        pub fn newtype_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.newtype_enums.insert(arg);
+            self
+        }
     }
 
-    /// Mark the given enum (or set of enums, if using a pattern) as a Rust
-    /// enum.
-    ///
-    /// This makes bindgen generate enums instead of constants. Regular
-    /// expressions are supported.
-    ///
-    /// **Use this with caution**, creating this in unsafe code
-    /// (including FFI) with an invalid value will invoke undefined behaviour.
-    /// You may want to use the newtype enum style instead.
-    pub fn rustified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.rustified_enums.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Mark the given enum (or set of enums, if using a pattern) as a newtype
+        /// whose variants are exposed as global constants.
+        ///
+        /// Regular expressions are supported.
+        ///
+        /// This makes bindgen generate a type that isn't a Rust `enum`. Regular
+        /// expressions are supported.
+        pub fn newtype_global_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.newtype_global_enums.insert(arg);
+            self
+        }
     }
 
-    /// Mark the given enum (or set of enums, if using a pattern) as a Rust
-    /// enum with the `#[non_exhaustive]` attribute.
-    ///
-    /// This makes bindgen generate enums instead of constants. Regular
-    /// expressions are supported.
-    ///
-    /// **Use this with caution**, creating this in unsafe code
-    /// (including FFI) with an invalid value will invoke undefined behaviour.
-    /// You may want to use the newtype enum style instead.
-    pub fn rustified_non_exhaustive_enum<T: AsRef<str>>(
-        mut self,
-        arg: T,
-    ) -> Builder {
-        self.options.rustified_non_exhaustive_enums.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Mark the given enum (or set of enums, if using a pattern) as a Rust
+        /// enum.
+        ///
+        /// This makes bindgen generate enums instead of constants. Regular
+        /// expressions are supported.
+        ///
+        /// **Use this with caution**, creating this in unsafe code
+        /// (including FFI) with an invalid value will invoke undefined behaviour.
+        /// You may want to use the newtype enum style instead.
+        pub fn rustified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.rustified_enums.insert(arg);
+            self
+        }
     }
 
-    /// Mark the given enum (or set of enums, if using a pattern) as a set of
-    /// constants that are not to be put into a module.
-    pub fn constified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.constified_enums.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Mark the given enum (or set of enums, if using a pattern) as a Rust
+        /// enum with the `#[non_exhaustive]` attribute.
+        ///
+        /// This makes bindgen generate enums instead of constants. Regular
+        /// expressions are supported.
+        ///
+        /// **Use this with caution**, creating this in unsafe code
+        /// (including FFI) with an invalid value will invoke undefined behaviour.
+        /// You may want to use the newtype enum style instead.
+        pub fn rustified_non_exhaustive_enum<T: AsRef<str>>(
+            mut self,
+            arg: T,
+        ) -> Builder {
+            self.options.rustified_non_exhaustive_enums.insert(arg);
+            self
+        }
     }
 
-    /// Mark the given enum (or set of enums, if using a pattern) as a set of
-    /// constants that should be put into a module.
-    ///
-    /// This makes bindgen generate modules containing constants instead of
-    /// just constants. Regular expressions are supported.
-    pub fn constified_enum_module<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.constified_enum_modules.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Mark the given enum (or set of enums, if using a pattern) as a set of
+        /// constants that are not to be put into a module.
+        pub fn constified_enum<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.constified_enums.insert(arg);
+            self
+        }
+    }
+
+    fn_with_regex_arg! {
+        /// Mark the given enum (or set of enums, if using a pattern) as a set of
+        /// constants that should be put into a module.
+        ///
+        /// This makes bindgen generate modules containing constants instead of
+        /// just constants. Regular expressions are supported.
+        pub fn constified_enum_module<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.constified_enum_modules.insert(arg);
+            self
+        }
     }
 
     /// Set the default type for macro constants
@@ -1020,41 +1071,79 @@
         self
     }
 
-    /// Mark the given typedef alias (or set of aliases, if using a pattern) to
-    /// use regular Rust type aliasing.
-    ///
-    /// This is the default behavior and should be used if `default_alias_style`
-    /// was set to NewType or NewTypeDeref and you want to override it for a
-    /// set of typedefs.
-    pub fn type_alias<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.type_alias.insert(arg);
+    fn_with_regex_arg! {
+        /// Mark the given typedef alias (or set of aliases, if using a pattern) to
+        /// use regular Rust type aliasing.
+        ///
+        /// This is the default behavior and should be used if `default_alias_style`
+        /// was set to NewType or NewTypeDeref and you want to override it for a
+        /// set of typedefs.
+        pub fn type_alias<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.type_alias.insert(arg);
+            self
+        }
+    }
+
+    fn_with_regex_arg! {
+        /// Mark the given typedef alias (or set of aliases, if using a pattern) to
+        /// be generated as a new type by having the aliased type be wrapped in a
+        /// #[repr(transparent)] struct.
+        ///
+        /// Used to enforce stricter type checking.
+        pub fn new_type_alias<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.new_type_alias.insert(arg);
+            self
+        }
+    }
+
+    fn_with_regex_arg! {
+        /// Mark the given typedef alias (or set of aliases, if using a pattern) to
+        /// be generated as a new type by having the aliased type be wrapped in a
+        /// #[repr(transparent)] struct and also have an automatically generated
+        /// impl's of `Deref` and `DerefMut` to their aliased type.
+        pub fn new_type_alias_deref<T: AsRef<str>>(mut self, arg: T) -> Builder {
+            self.options.new_type_alias_deref.insert(arg);
+            self
+        }
+    }
+
+    /// Set the default style of code to generate for unions with a non-Copy member.
+    pub fn default_non_copy_union_style(
+        mut self,
+        arg: codegen::NonCopyUnionStyle,
+    ) -> Self {
+        self.options.default_non_copy_union_style = arg;
         self
     }
 
-    /// Mark the given typedef alias (or set of aliases, if using a pattern) to
-    /// be generated as a new type by having the aliased type be wrapped in a
-    /// #[repr(transparent)] struct.
-    ///
-    /// Used to enforce stricter type checking.
-    pub fn new_type_alias<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.new_type_alias.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Mark the given union (or set of union, if using a pattern) to use
+        /// a bindgen-generated wrapper for its members if at least one is non-Copy.
+        pub fn bindgen_wrapper_union<T: AsRef<str>>(mut self, arg: T) -> Self {
+            self.options.bindgen_wrapper_union.insert(arg);
+            self
+        }
     }
 
-    /// Mark the given typedef alias (or set of aliases, if using a pattern) to
-    /// be generated as a new type by having the aliased type be wrapped in a
-    /// #[repr(transparent)] struct and also have an automatically generated
-    /// impl's of `Deref` and `DerefMut` to their aliased type.
-    pub fn new_type_alias_deref<T: AsRef<str>>(mut self, arg: T) -> Builder {
-        self.options.new_type_alias_deref.insert(arg);
-        self
+    fn_with_regex_arg! {
+        /// Mark the given union (or set of union, if using a pattern) to use
+        /// [`::core::mem::ManuallyDrop`] for its members if at least one is non-Copy.
+        ///
+        /// Note: `ManuallyDrop` was stabilized in Rust 1.20.0, do not use it if your
+        /// MSRV is lower.
+        pub fn manually_drop_union<T: AsRef<str>>(mut self, arg: T) -> Self {
+            self.options.manually_drop_union.insert(arg);
+            self
+        }
     }
 
-    /// Add a string to prepend to the generated bindings. The string is passed
-    /// through without any modification.
-    pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Self {
-        self.options.raw_lines.push(arg.into());
-        self
+    fn_with_regex_arg! {
+        /// Add a string to prepend to the generated bindings. The string is passed
+        /// through without any modification.
+        pub fn raw_line<T: Into<String>>(mut self, arg: T) -> Self {
+            self.options.raw_lines.push(arg.into());
+            self
+        }
     }
 
     /// Add a given line to the beginning of module `mod`.
@@ -1336,17 +1425,6 @@
         self
     }
 
-    /// Avoid generating any unstable Rust, such as Rust unions, in the generated bindings.
-    #[deprecated(note = "please use `rust_target` instead")]
-    pub fn unstable_rust(self, doit: bool) -> Self {
-        let rust_target = if doit {
-            RustTarget::Nightly
-        } else {
-            LATEST_STABLE_RUST
-        };
-        self.rust_target(rust_target)
-    }
-
     /// Use core instead of libstd in the generated bindings.
     pub fn use_core(mut self) -> Builder {
         self.options.use_core = true;
@@ -1371,7 +1449,7 @@
         mut self,
         cb: Box<dyn callbacks::ParseCallbacks>,
     ) -> Self {
-        self.options.parse_callbacks = Some(cb);
+        self.options.parse_callbacks.push(Rc::from(cb));
         self
     }
 
@@ -1443,39 +1521,56 @@
         self
     }
 
+    /// If true, enables experimental support to generate vtable functions.
+    ///
+    /// Should mostly work, though some edge cases are likely to be broken.
+    pub fn vtable_generation(mut self, doit: bool) -> Self {
+        self.options.vtable_generation = doit;
+        self
+    }
+
+    /// If true, enables the sorting of the output in a predefined manner.
+    ///
+    /// TODO: Perhaps move the sorting order out into a config
+    pub fn sort_semantically(mut self, doit: bool) -> Self {
+        self.options.sort_semantically = doit;
+        self
+    }
+
+    /// If true, merges extern blocks.
+    pub fn merge_extern_blocks(mut self, doit: bool) -> Self {
+        self.options.merge_extern_blocks = doit;
+        self
+    }
+
     /// Generate the Rust bindings using the options built up thus far.
-    pub fn generate(mut self) -> Result<Bindings, ()> {
+    pub fn generate(self) -> Result<Bindings, BindgenError> {
+        let mut options = self.options.clone();
         // Add any extra arguments from the environment to the clang command line.
-        if let Some(extra_clang_args) =
-            get_target_dependent_env_var("BINDGEN_EXTRA_CLANG_ARGS")
-        {
-            // Try to parse it with shell quoting. If we fail, make it one single big argument.
-            if let Some(strings) = shlex::split(&extra_clang_args) {
-                self.options.clang_args.extend(strings);
-            } else {
-                self.options.clang_args.push(extra_clang_args);
-            };
-        }
+        options.clang_args.extend(get_extra_clang_args());
 
         // Transform input headers to arguments on the clang command line.
-        self.options.input_header = self.input_headers.pop();
-        self.options.extra_input_headers = self.input_headers;
-        self.options.clang_args.extend(
-            self.options.extra_input_headers.iter().flat_map(|header| {
-                iter::once("-include".into())
-                    .chain(iter::once(header.to_string()))
-            }),
+        options.clang_args.extend(
+            options.input_headers
+                [..options.input_headers.len().saturating_sub(1)]
+                .iter()
+                .flat_map(|header| ["-include".into(), header.to_string()]),
         );
 
-        self.options.input_unsaved_files.extend(
-            self.input_header_contents
-                .drain(..)
-                .map(|(name, contents)| {
-                    clang::UnsavedFile::new(&name, &contents)
-                }),
-        );
+        let input_unsaved_files =
+            std::mem::take(&mut options.input_header_contents)
+                .into_iter()
+                .map(|(name, contents)| clang::UnsavedFile::new(name, contents))
+                .collect::<Vec<_>>();
 
-        Bindings::generate(self.options)
+        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),
+        }
     }
 
     /// Preprocess and dump the input header files to disk.
@@ -1500,7 +1595,7 @@
         let mut is_cpp = args_are_cpp(&self.options.clang_args);
 
         // For each input header, add `#include "$header"`.
-        for header in &self.input_headers {
+        for header in &self.options.input_headers {
             is_cpp |= file_is_cpp(header);
 
             wrapper_contents.push_str("#include \"");
@@ -1510,7 +1605,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.input_header_contents {
+        for &(ref name, ref contents) in &self.options.input_header_contents {
             is_cpp |= file_is_cpp(name);
 
             wrapper_contents.push_str("#line 0 \"");
@@ -1530,7 +1625,7 @@
             wrapper_file.write_all(wrapper_contents.as_bytes())?;
         }
 
-        let mut cmd = Command::new(&clang.path);
+        let mut cmd = Command::new(clang.path);
         cmd.arg("-save-temps")
             .arg("-E")
             .arg("-C")
@@ -1542,6 +1637,10 @@
             cmd.arg(a);
         }
 
+        for a in get_extra_clang_args() {
+            cmd.arg(a);
+        }
+
         let mut child = cmd.spawn()?;
 
         let mut preprocessed = child.stdout.take().unwrap();
@@ -1562,46 +1661,58 @@
         }
     }
 
-    /// Don't derive `PartialEq` for a given type. Regular
-    /// expressions are supported.
-    pub fn no_partialeq<T: Into<String>>(mut self, arg: T) -> Builder {
-        self.options.no_partialeq_types.insert(arg.into());
-        self
+    fn_with_regex_arg! {
+        /// Don't derive `PartialEq` for a given type. Regular
+        /// expressions are supported.
+        pub fn no_partialeq<T: Into<String>>(mut self, arg: T) -> Builder {
+            self.options.no_partialeq_types.insert(arg.into());
+            self
+        }
     }
 
-    /// Don't derive `Copy` for a given type. Regular
-    /// expressions are supported.
-    pub fn no_copy<T: Into<String>>(mut self, arg: T) -> Self {
-        self.options.no_copy_types.insert(arg.into());
-        self
+    fn_with_regex_arg! {
+        /// Don't derive `Copy` for a given type. Regular
+        /// expressions are supported.
+        pub fn no_copy<T: Into<String>>(mut self, arg: T) -> Self {
+            self.options.no_copy_types.insert(arg.into());
+            self
+        }
     }
 
-    /// Don't derive `Debug` for a given type. Regular
-    /// expressions are supported.
-    pub fn no_debug<T: Into<String>>(mut self, arg: T) -> Self {
-        self.options.no_debug_types.insert(arg.into());
-        self
+    fn_with_regex_arg! {
+        /// Don't derive `Debug` for a given type. Regular
+        /// expressions are supported.
+        pub fn no_debug<T: Into<String>>(mut self, arg: T) -> Self {
+            self.options.no_debug_types.insert(arg.into());
+            self
+        }
     }
 
-    /// Don't derive/impl `Default` for a given type. Regular
-    /// expressions are supported.
-    pub fn no_default<T: Into<String>>(mut self, arg: T) -> Self {
-        self.options.no_default_types.insert(arg.into());
-        self
+    fn_with_regex_arg! {
+        /// Don't derive/impl `Default` for a given type. Regular
+        /// expressions are supported.
+        pub fn no_default<T: Into<String>>(mut self, arg: T) -> Self {
+            self.options.no_default_types.insert(arg.into());
+            self
+        }
     }
 
-    /// Don't derive `Hash` for a given type. Regular
-    /// expressions are supported.
-    pub fn no_hash<T: Into<String>>(mut self, arg: T) -> Builder {
-        self.options.no_hash_types.insert(arg.into());
-        self
+    fn_with_regex_arg! {
+        /// Don't derive `Hash` for a given type. Regular
+        /// expressions are supported.
+        pub fn no_hash<T: Into<String>>(mut self, arg: T) -> Builder {
+            self.options.no_hash_types.insert(arg.into());
+            self
+        }
     }
 
-    /// Add `#[must_use]` for the given type. Regular
-    /// expressions are supported.
-    pub fn must_use_type<T: Into<String>>(mut self, arg: T) -> Builder {
-        self.options.must_use_types.insert(arg.into());
-        self
+    fn_with_regex_arg! {
+        /// Add `#[must_use]` for the given type. Regular
+        /// expressions are supported.
+        pub fn must_use_type<T: Into<String>>(mut self, arg: T) -> Builder {
+            self.options.must_use_types.insert(arg.into());
+            self
+        }
     }
 
     /// Set whether `arr[size]` should be treated as `*mut T` or `*mut [T; size]` (same for mut)
@@ -1660,10 +1771,26 @@
         self.options.c_naming = doit;
         self
     }
+
+    /// Override the ABI of a given function. Regular expressions are supported.
+    pub fn override_abi<T: Into<String>>(mut self, abi: Abi, arg: T) -> Self {
+        self.options
+            .abi_overrides
+            .entry(abi)
+            .or_default()
+            .insert(arg.into());
+        self
+    }
+
+    /// If true, wraps unsafe operations in unsafe blocks.
+    pub fn wrap_unsafe_ops(mut self, doit: bool) -> Self {
+        self.options.wrap_unsafe_ops = doit;
+        self
+    }
 }
 
 /// Configuration options for generated bindings.
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 struct BindgenOptions {
     /// The set of types that have been blocklisted and should not appear
     /// anywhere in the generated code.
@@ -1705,6 +1832,9 @@
     /// Allowlisted variables. See docs for `allowlisted_types` for more.
     allowlisted_vars: RegexSet,
 
+    /// The set of files whose contents should be allowlisted.
+    allowlisted_files: RegexSet,
+
     /// The default style of code to generate for enums
     default_enum_style: codegen::EnumVariation,
 
@@ -1715,6 +1845,9 @@
     /// The enum patterns to mark an enum as a newtype.
     newtype_enums: RegexSet,
 
+    /// The enum patterns to mark an enum as a global newtype.
+    newtype_global_enums: RegexSet,
+
     /// The enum patterns to mark an enum as a Rust enum.
     rustified_enums: RegexSet,
 
@@ -1743,6 +1876,18 @@
     /// Deref and Deref to their aliased type.
     new_type_alias_deref: RegexSet,
 
+    /// The default style of code to generate for union containing non-Copy
+    /// members.
+    default_non_copy_union_style: codegen::NonCopyUnionStyle,
+
+    /// The union patterns to mark an non-Copy union as using the bindgen
+    /// generated wrapper.
+    bindgen_wrapper_union: RegexSet,
+
+    /// The union patterns to mark an non-Copy union as using the
+    /// `::core::mem::ManuallyDrop` wrapper.
+    manually_drop_union: RegexSet,
+
     /// Whether we should generate builtins or not.
     builtins: bool,
 
@@ -1827,13 +1972,6 @@
     /// Whether to time the bindgen phases.
     time_phases: bool,
 
-    /// True if we should generate constant names that are **directly** under
-    /// namespaces.
-    namespaced_constants: bool,
-
-    /// True if we should use MSVC name mangling rules.
-    msvc_mangling: bool,
-
     /// Whether we should convert float types to f32/f64 types.
     convert_floats: bool,
 
@@ -1849,18 +1987,15 @@
     /// The set of arguments to pass straight through to Clang.
     clang_args: Vec<String>,
 
-    /// The input header file.
-    input_header: Option<String>,
+    /// The input header files.
+    input_headers: Vec<String>,
 
-    /// Any additional input header files.
-    extra_input_headers: Vec<String>,
-
-    /// Unsaved files for input.
-    input_unsaved_files: Vec<clang::UnsavedFile>,
+    /// Tuples of unsaved file contents of the form (name, contents).
+    input_header_contents: Vec<(String, String)>,
 
     /// A user-provided visitor to allow customizing different kinds of
     /// situations.
-    parse_callbacks: Option<Box<dyn callbacks::ParseCallbacks>>,
+    parse_callbacks: Vec<Rc<dyn callbacks::ParseCallbacks>>,
 
     /// Which kind of items should we generate? By default, we'll generate all
     /// of them.
@@ -1978,19 +2113,29 @@
 
     /// Always output explicit padding fields
     force_explicit_padding: bool,
-}
 
-/// TODO(emilio): This is sort of a lie (see the error message that results from
-/// removing this), but since we don't share references across panic boundaries
-/// it's ok.
-impl ::std::panic::UnwindSafe for BindgenOptions {}
+    /// Emit vtable functions.
+    vtable_generation: bool,
+
+    /// Sort the code generation.
+    sort_semantically: bool,
+
+    /// Deduplicate `extern` blocks.
+    merge_extern_blocks: bool,
+
+    abi_overrides: HashMap<Abi, RegexSet>,
+
+    /// Whether to wrap unsafe operations in unsafe blocks or not.
+    wrap_unsafe_ops: bool,
+}
 
 impl BindgenOptions {
     fn build(&mut self) {
-        let mut regex_sets = [
+        let regex_sets = [
             &mut self.allowlisted_vars,
             &mut self.allowlisted_types,
             &mut self.allowlisted_functions,
+            &mut self.allowlisted_files,
             &mut self.blocklisted_types,
             &mut self.blocklisted_functions,
             &mut self.blocklisted_items,
@@ -2000,11 +2145,14 @@
             &mut self.constified_enums,
             &mut self.constified_enum_modules,
             &mut self.newtype_enums,
+            &mut self.newtype_global_enums,
             &mut self.rustified_enums,
             &mut self.rustified_non_exhaustive_enums,
             &mut self.type_alias,
             &mut self.new_type_alias,
             &mut self.new_type_alias_deref,
+            &mut self.bindgen_wrapper_union,
+            &mut self.manually_drop_union,
             &mut self.no_partialeq_types,
             &mut self.no_copy_types,
             &mut self.no_debug_types,
@@ -2013,7 +2161,7 @@
             &mut self.must_use_types,
         ];
         let record_matches = self.record_matches;
-        for regex_set in &mut regex_sets {
+        for regex_set in self.abi_overrides.values_mut().chain(regex_sets) {
             regex_set.build(record_matches);
         }
     }
@@ -2030,101 +2178,147 @@
     pub fn rust_features(&self) -> RustFeatures {
         self.rust_features
     }
+
+    fn last_callback<T>(
+        &self,
+        f: impl Fn(&dyn callbacks::ParseCallbacks) -> Option<T>,
+    ) -> Option<T> {
+        self.parse_callbacks
+            .iter()
+            .filter_map(|cb| f(cb.as_ref()))
+            .last()
+    }
+
+    fn all_callbacks<T>(
+        &self,
+        f: impl Fn(&dyn callbacks::ParseCallbacks) -> Vec<T>,
+    ) -> Vec<T> {
+        self.parse_callbacks
+            .iter()
+            .flat_map(|cb| f(cb.as_ref()))
+            .collect()
+    }
+
+    fn process_comment(&self, comment: &str) -> String {
+        let comment = comment::preprocess(comment);
+        self.parse_callbacks
+            .last()
+            .and_then(|cb| cb.process_comment(&comment))
+            .unwrap_or(comment)
+    }
 }
 
 impl Default for BindgenOptions {
     fn default() -> BindgenOptions {
+        macro_rules! options {
+            ($($field:ident $(: $value:expr)?,)* --default-fields-- $($default_field:ident,)*) => {
+                BindgenOptions {
+                    $($field $(: $value)*,)*
+                    $($default_field: Default::default(),)*
+                }
+            };
+        }
+
         let rust_target = RustTarget::default();
 
-        BindgenOptions {
+        options! {
             rust_target,
             rust_features: rust_target.into(),
-            blocklisted_types: Default::default(),
-            blocklisted_functions: Default::default(),
-            blocklisted_items: Default::default(),
-            blocklisted_files: Default::default(),
-            opaque_types: Default::default(),
-            rustfmt_path: Default::default(),
-            depfile: 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(),
-            rustified_enums: Default::default(),
-            rustified_non_exhaustive_enums: Default::default(),
-            constified_enums: Default::default(),
-            constified_enum_modules: Default::default(),
-            default_macro_constant_type: Default::default(),
-            default_alias_style: Default::default(),
-            type_alias: Default::default(),
-            new_type_alias: Default::default(),
-            new_type_alias_deref: Default::default(),
-            builtins: false,
-            emit_ast: false,
-            emit_ir: false,
-            emit_ir_graphviz: None,
             layout_tests: true,
-            impl_debug: false,
-            impl_partialeq: false,
             derive_copy: true,
             derive_debug: true,
-            derive_default: false,
-            derive_hash: false,
-            derive_partialord: false,
-            derive_ord: false,
-            derive_partialeq: false,
-            derive_eq: false,
-            enable_cxx_namespaces: false,
-            enable_function_attribute_detection: false,
-            disable_name_namespacing: false,
-            disable_nested_struct_naming: false,
-            disable_header_comment: false,
-            use_core: false,
-            ctypes_prefix: None,
             anon_fields_prefix: DEFAULT_ANON_FIELDS_PREFIX.into(),
-            namespaced_constants: true,
-            msvc_mangling: false,
             convert_floats: true,
-            raw_lines: vec![],
-            module_lines: HashMap::default(),
-            clang_args: vec![],
-            input_header: None,
-            extra_input_headers: vec![],
-            input_unsaved_files: vec![],
-            parse_callbacks: None,
             codegen_config: CodegenConfig::all(),
-            conservative_inline_namespaces: false,
             generate_comments: true,
-            generate_inline_functions: false,
             allowlist_recursively: true,
-            generate_block: false,
-            objc_extern_crate: false,
-            block_extern_crate: false,
             enable_mangling: true,
             detect_include_paths: true,
-            fit_macro_constants: false,
             prepend_enum_name: true,
-            time_phases: false,
             record_matches: true,
             rustfmt_bindings: true,
-            size_t_is_usize: false,
-            rustfmt_configuration_file: None,
-            no_partialeq_types: Default::default(),
-            no_copy_types: Default::default(),
-            no_debug_types: Default::default(),
-            no_default_types: Default::default(),
-            no_hash_types: Default::default(),
-            must_use_types: Default::default(),
-            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,
-            c_naming: false,
-            force_explicit_padding: false,
+            size_t_is_usize: true,
+
+            --default-fields--
+            blocklisted_types,
+            blocklisted_functions,
+            blocklisted_items,
+            blocklisted_files,
+            opaque_types,
+            rustfmt_path,
+            depfile,
+            allowlisted_types,
+            allowlisted_functions,
+            allowlisted_vars,
+            allowlisted_files,
+            default_enum_style,
+            bitfield_enums,
+            newtype_enums,
+            newtype_global_enums,
+            rustified_enums,
+            rustified_non_exhaustive_enums,
+            constified_enums,
+            constified_enum_modules,
+            default_macro_constant_type,
+            default_alias_style,
+            type_alias,
+            new_type_alias,
+            new_type_alias_deref,
+            default_non_copy_union_style,
+            bindgen_wrapper_union,
+            manually_drop_union,
+            builtins,
+            emit_ast,
+            emit_ir,
+            emit_ir_graphviz,
+            impl_debug,
+            impl_partialeq,
+            derive_default,
+            derive_hash,
+            derive_partialord,
+            derive_ord,
+            derive_partialeq,
+            derive_eq,
+            enable_cxx_namespaces,
+            enable_function_attribute_detection,
+            disable_name_namespacing,
+            disable_nested_struct_naming,
+            disable_header_comment,
+            use_core,
+            ctypes_prefix,
+            raw_lines,
+            module_lines,
+            clang_args,
+            input_headers,
+            input_header_contents,
+            parse_callbacks,
+            conservative_inline_namespaces,
+            generate_inline_functions,
+            generate_block,
+            objc_extern_crate,
+            block_extern_crate,
+            fit_macro_constants,
+            time_phases,
+            rustfmt_configuration_file,
+            no_partialeq_types,
+            no_copy_types,
+            no_debug_types,
+            no_default_types,
+            no_hash_types,
+            must_use_types,
+            array_pointers_in_arguments,
+            wasm_import_module_name,
+            dynamic_library_name,
+            dynamic_link_require_all,
+            respect_cxx_access_specs,
+            translate_enum_integer_types,
+            c_naming,
+            force_explicit_padding,
+            vtable_generation,
+            sort_semantically,
+            merge_extern_blocks,
+            abi_overrides,
+            wrap_unsafe_ops,
         }
     }
 }
@@ -2155,10 +2349,58 @@
 #[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]
+pub enum BindgenError {
+    /// The header was a folder.
+    FolderAsHeader(PathBuf),
+    /// Permissions to read the header is insufficient.
+    InsufficientPermissions(PathBuf),
+    /// The header does not exist.
+    NotExist(PathBuf),
+    /// Clang diagnosed an error.
+    ClangDiagnostic(String),
+}
+
+impl std::fmt::Display for BindgenError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            BindgenError::FolderAsHeader(h) => {
+                write!(f, "'{}' is a folder", h.display())
+            }
+            BindgenError::InsufficientPermissions(h) => {
+                write!(f, "insufficient permissions to read '{}'", h.display())
+            }
+            BindgenError::NotExist(h) => {
+                write!(f, "header '{}' does not exist.", h.display())
+            }
+            BindgenError::ClangDiagnostic(message) => {
+                write!(f, "clang diagnosed error: {}", message)
+            }
+        }
+    }
+}
+
+impl std::error::Error for BindgenError {}
+
 /// Generated Rust bindings.
 #[derive(Debug)]
 pub struct Bindings {
     options: BindgenOptions,
+    warnings: Vec<String>,
     module: proc_macro2::TokenStream,
 }
 
@@ -2173,6 +2415,10 @@
         clang_target
             .push_str(rust_target.strip_prefix("aarch64-apple-").unwrap());
         return clang_target;
+    } else if rust_target.starts_with("riscv64gc-") {
+        let mut clang_target = "riscv64-".to_owned();
+        clang_target.push_str(rust_target.strip_prefix("riscv64gc-").unwrap());
+        return clang_target;
     }
     rust_target.to_owned()
 }
@@ -2207,7 +2453,8 @@
     /// Generate bindings for the given options.
     pub(crate) fn generate(
         mut options: BindgenOptions,
-    ) -> Result<Bindings, ()> {
+        input_unsaved_files: Vec<clang::UnsavedFile>,
+    ) -> GenerateResult {
         ensure_libclang_is_loaded();
 
         #[cfg(feature = "runtime")]
@@ -2293,7 +2540,7 @@
 
             // Whether we are working with C or C++ inputs.
             let is_cpp = args_are_cpp(&options.clang_args) ||
-                options.input_header.as_deref().map_or(false, file_is_cpp);
+                options.input_headers.iter().any(|h| file_is_cpp(h));
 
             let search_paths = if is_cpp {
                 clang.cpp_search_paths
@@ -2324,28 +2571,30 @@
             true
         }
 
-        if let Some(h) = options.input_header.as_ref() {
-            if let Ok(md) = std::fs::metadata(h) {
+        if let Some(h) = options.input_headers.last() {
+            let path = Path::new(h);
+            if let Ok(md) = std::fs::metadata(path) {
                 if md.is_dir() {
-                    eprintln!("error: '{}' is a folder", h);
-                    return Err(());
+                    return GenerateResult::Err(BindgenError::FolderAsHeader(
+                        path.into(),
+                    ));
                 }
                 if !can_read(&md.permissions()) {
-                    eprintln!(
-                        "error: insufficient permissions to read '{}'",
-                        h
+                    return GenerateResult::Err(
+                        BindgenError::InsufficientPermissions(path.into()),
                     );
-                    return Err(());
                 }
-                options.clang_args.push(h.clone())
+                let h = h.clone();
+                options.clang_args.push(h);
             } else {
-                eprintln!("error: header '{}' does not exist.", h);
-                return Err(());
+                return GenerateResult::Err(BindgenError::NotExist(
+                    path.into(),
+                ));
             }
         }
 
-        for (idx, f) in options.input_unsaved_files.iter().enumerate() {
-            if idx != 0 || options.input_header.is_some() {
+        for (idx, f) in input_unsaved_files.iter().enumerate() {
+            if idx != 0 || !options.input_headers.is_empty() {
                 options.clang_args.push("-include".to_owned());
             }
             options.clang_args.push(f.name.to_str().unwrap().to_owned())
@@ -2354,7 +2603,7 @@
         debug!("Fixed-up options: {:?}", options);
 
         let time_phases = options.time_phases;
-        let mut context = BindgenContext::new(options);
+        let mut context = BindgenContext::new(options, &input_unsaved_files);
 
         if is_host_build {
             debug_assert_eq!(
@@ -2368,16 +2617,17 @@
 
         {
             let _t = time::Timer::new("parse").with_output(time_phases);
-            parse(&mut context)?;
+            if let Err(err) = parse(&mut context) {
+                return GenerateResult::Err(err);
+            }
         }
 
-        let (items, options) = codegen::codegen(context);
+        let (module, options, warnings) = codegen::codegen(context);
 
-        Ok(Bindings {
+        GenerateResult::Ok(Bindings {
             options,
-            module: quote! {
-                #( #items )*
-            },
+            warnings,
+            module,
         })
     }
 
@@ -2395,7 +2645,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.59.2");
+            let version = option_env!("CARGO_PKG_VERSION");
             let header = format!(
                 "/* automatically generated by rust-bindgen {} */\n\n",
                 version.unwrap_or("(unknown version)")
@@ -2474,7 +2724,7 @@
             .as_ref()
             .and_then(|f| f.to_str())
         {
-            cmd.args(&["--config-path", path]);
+            cmd.args(["--config-path", path]);
         }
 
         let mut child = cmd.spawn()?;
@@ -2519,6 +2769,23 @@
             _ => Ok(Cow::Owned(source)),
         }
     }
+
+    /// Emit all the warning messages raised while generating the bindings in a build script.
+    ///
+    /// If you are using `bindgen` outside of a build script you should use [`Bindings::warnings`]
+    /// and handle the messages accordingly instead.
+    #[inline]
+    pub fn emit_warnings(&self) {
+        for message in &self.warnings {
+            println!("cargo:warning={}", message);
+        }
+    }
+
+    /// Return all the warning messages raised while generating the bindings.
+    #[inline]
+    pub fn warnings(&self) -> &[String] {
+        &self.warnings
+    }
 }
 
 impl std::fmt::Display for Bindings {
@@ -2561,19 +2828,24 @@
 }
 
 /// Parse the Clang AST into our `Item` internal representation.
-fn parse(context: &mut BindgenContext) -> Result<(), ()> {
+fn parse(context: &mut BindgenContext) -> Result<(), BindgenError> {
     use clang_sys::*;
 
-    let mut any_error = false;
+    let mut error = None;
     for d in context.translation_unit().diags().iter() {
         let msg = d.format();
         let is_err = d.severity() >= CXDiagnostic_Error;
-        eprintln!("{}, err: {}", msg, is_err);
-        any_error |= is_err;
+        if is_err {
+            let error = error.get_or_insert_with(String::new);
+            error.push_str(&msg);
+            error.push('\n');
+        } else {
+            eprintln!("clang diag: {}", msg);
+        }
     }
 
-    if any_error {
-        return Err(());
+    if let Some(message) = error {
+        return Err(BindgenError::ClangDiagnostic(message));
     }
 
     let cursor = context.translation_unit().cursor();
@@ -2641,11 +2913,10 @@
 /// Looks for the env var `var_${TARGET}`, and falls back to just `var` when it is not found.
 fn get_target_dependent_env_var(var: &str) -> Option<String> {
     if let Ok(target) = env::var("TARGET") {
-        if let Ok(v) = env::var(&format!("{}_{}", var, target)) {
+        if let Ok(v) = env::var(format!("{}_{}", var, target)) {
             return Some(v);
         }
-        if let Ok(v) =
-            env::var(&format!("{}_{}", var, target.replace("-", "_")))
+        if let Ok(v) = env::var(format!("{}_{}", var, target.replace('-', "_")))
         {
             return Some(v);
         }
@@ -2691,9 +2962,7 @@
     .map(|&x| x.into())
     .collect::<Vec<String>>();
 
-    assert!(test_cases
-        .iter()
-        .all(|ref x| command_line_flags.contains(x),));
+    assert!(test_cases.iter().all(|x| command_line_flags.contains(x)));
 
     //Test 2
     let bindings = crate::builder()
@@ -2718,12 +2987,18 @@
     .collect::<Vec<String>>();
     println!("{:?}", command_line_flags);
 
-    assert!(test_cases
-        .iter()
-        .all(|ref x| command_line_flags.contains(x),));
+    assert!(test_cases.iter().all(|x| command_line_flags.contains(x)));
 }
 
 #[test]
 fn test_rust_to_clang_target() {
     assert_eq!(rust_to_clang_target("aarch64-apple-ios"), "arm64-apple-ios");
 }
+
+#[test]
+fn test_rust_to_clang_target_riscv() {
+    assert_eq!(
+        rust_to_clang_target("riscv64gc-unknown-linux-gnu"),
+        "riscv64-unknown-linux-gnu"
+    )
+}
diff --git a/src/log_stubs.rs b/log_stubs.rs
similarity index 100%
rename from src/log_stubs.rs
rename to log_stubs.rs
diff --git a/out/tests.rs b/out/tests.rs
deleted file mode 100644
index e69de29..0000000
--- a/out/tests.rs
+++ /dev/null
diff --git a/src/parse.rs b/parse.rs
similarity index 100%
rename from src/parse.rs
rename to parse.rs
diff --git a/post_update.sh b/post_update.sh
deleted file mode 100755
index 52614aa..0000000
--- a/post_update.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-# $1 Path to the new version.
-# $2 Path to the old version.
-
-set -x
-set -e
-
-cp -a -n -r $2/android $1/
diff --git a/src/regex_set.rs b/regex_set.rs
similarity index 87%
rename from src/regex_set.rs
rename to regex_set.rs
index 127c001..9f1e225 100644
--- a/src/regex_set.rs
+++ b/regex_set.rs
@@ -4,7 +4,7 @@
 use std::cell::Cell;
 
 /// A dynamic set of regular expressions.
-#[derive(Debug, Default)]
+#[derive(Clone, Debug, Default)]
 pub struct RegexSet {
     items: Vec<String>,
     /// Whether any of the items in the set was ever matched. The length of this
@@ -26,7 +26,11 @@
     where
         S: AsRef<str>,
     {
-        self.items.push(string.as_ref().to_owned());
+        let string = string.as_ref().to_owned();
+        if string == "*" {
+            warn!("using wildcard patterns (`*`) is no longer considered valid. Use `.*` instead");
+        }
+        self.items.push(string);
         self.matched.push(Cell::new(false));
         self.set = None;
     }
@@ -53,7 +57,7 @@
     /// Must be called before calling `matches()`, or it will always return
     /// false.
     pub fn build(&mut self, record_matches: bool) {
-        let items = self.items.iter().map(|item| format!("^{}$", item));
+        let items = self.items.iter().map(|item| format!("^({})$", item));
         self.record_matches = record_matches;
         self.set = match RxSet::new(items) {
             Ok(x) => Some(x),
diff --git a/src/main.rs b/src/main.rs
deleted file mode 100644
index f3398db..0000000
--- a/src/main.rs
+++ /dev/null
@@ -1,113 +0,0 @@
-extern crate bindgen;
-#[cfg(feature = "logging")]
-extern crate env_logger;
-#[macro_use]
-#[cfg(feature = "logging")]
-extern crate log;
-extern crate clap;
-
-use bindgen::clang_version;
-use std::env;
-use std::panic;
-
-#[macro_use]
-#[cfg(not(feature = "logging"))]
-mod log_stubs;
-
-mod options;
-use crate::options::builder_from_flags;
-
-fn clang_version_check() {
-    let version = clang_version();
-    let expected_version = if cfg!(feature = "testing_only_libclang_9") {
-        Some((9, 0))
-    } else if cfg!(feature = "testing_only_libclang_5") {
-        Some((5, 0))
-    } else if cfg!(feature = "testing_only_libclang_4") {
-        Some((4, 0))
-    } else if cfg!(feature = "testing_only_libclang_3_9") {
-        Some((3, 9))
-    } else {
-        None
-    };
-
-    info!(
-        "Clang Version: {}, parsed: {:?}",
-        version.full, version.parsed
-    );
-
-    if expected_version.is_some() {
-        // assert_eq!(version.parsed, version.parsed);
-    }
-}
-
-pub fn main() {
-    #[cfg(feature = "logging")]
-    env_logger::init();
-
-    match builder_from_flags(env::args()) {
-        Ok((builder, output, verbose)) => {
-            clang_version_check();
-            let builder_result = panic::catch_unwind(|| {
-                builder.generate().expect("Unable to generate bindings")
-            });
-
-            if builder_result.is_err() {
-                if verbose {
-                    print_verbose_err();
-                }
-                std::process::exit(1);
-            }
-
-            let bindings = builder_result.unwrap();
-            bindings.write(output).expect("Unable to write output");
-        }
-        Err(error) => {
-            println!("{}", error);
-            std::process::exit(1);
-        }
-    };
-}
-
-fn print_verbose_err() {
-    println!("Bindgen unexpectedly panicked");
-    println!(
-        "This may be caused by one of the known-unsupported \
-         things (https://rust-lang.github.io/rust-bindgen/cpp.html), \
-         please modify the bindgen flags to work around it as \
-         described in https://rust-lang.github.io/rust-bindgen/cpp.html"
-    );
-    println!(
-        "Otherwise, please file an issue at \
-         https://github.com/rust-lang/rust-bindgen/issues/new"
-    );
-}
-
-#[cfg(test)]
-mod test {
-    fn build_flags_output_helper(builder: &bindgen::Builder) {
-        let mut command_line_flags = builder.command_line_flags();
-        command_line_flags.insert(0, "bindgen".to_string());
-
-        let flags_quoted: Vec<String> = command_line_flags
-            .iter()
-            .map(|x| format!("{}", shlex::quote(x)))
-            .collect();
-        let flags_str = flags_quoted.join(" ");
-        println!("{}", flags_str);
-
-        let (builder, _output, _verbose) =
-            crate::options::builder_from_flags(command_line_flags.into_iter())
-                .unwrap();
-        builder.generate().expect("failed to generate bindings");
-    }
-
-    #[test]
-    fn commandline_multiple_headers() {
-        let bindings = bindgen::Builder::default()
-            .header("tests/headers/char.h")
-            .header("tests/headers/func_ptr.h")
-            .header("tests/headers/16-byte-alignment.h");
-        build_flags_output_helper(&bindings);
-    }
-}
diff --git a/src/options.rs b/src/options.rs
deleted file mode 100644
index 94f3047..0000000
--- a/src/options.rs
+++ /dev/null
@@ -1,1000 +0,0 @@
-use bindgen::{
-    builder, AliasVariation, Builder, CodegenConfig, EnumVariation,
-    MacroTypeVariation, RustTarget, DEFAULT_ANON_FIELDS_PREFIX,
-    RUST_TARGET_STRINGS,
-};
-use clap::{App, Arg};
-use std::fs::File;
-use std::io::{self, stderr, Error, ErrorKind, Write};
-use std::path::PathBuf;
-use std::str::FromStr;
-
-/// Construct a new [`Builder`](./struct.Builder.html) from command line flags.
-pub fn builder_from_flags<I>(
-    args: I,
-) -> Result<(Builder, Box<dyn io::Write>, bool), io::Error>
-where
-    I: Iterator<Item = String>,
-{
-    let rust_target_help = format!(
-        "Version of the Rust compiler to target. Valid options are: {:?}. Defaults to {:?}.",
-        RUST_TARGET_STRINGS,
-        String::from(RustTarget::default())
-    );
-
-    let matches = App::new("bindgen")
-        .version(Some("0.59.2").unwrap_or("unknown"))
-        .about("Generates Rust bindings from C/C++ headers.")
-        .usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...")
-        .args(&[
-            Arg::with_name("header")
-                .help("C or C++ header file")
-                .required(true),
-            Arg::with_name("depfile")
-                .long("depfile")
-                .takes_value(true)
-                .help("Path to write depfile to"),
-            Arg::with_name("default-enum-style")
-                .long("default-enum-style")
-                .help("The default style of code used to generate enums.")
-                .value_name("variant")
-                .default_value("consts")
-                .possible_values(&[
-                    "consts",
-                    "moduleconsts",
-                    "bitfield",
-                    "newtype",
-                    "rust",
-                    "rust_non_exhaustive",
-                ])
-                .multiple(false),
-            Arg::with_name("bitfield-enum")
-                .long("bitfield-enum")
-                .help(
-                    "Mark any enum whose name matches <regex> as a set of \
-                     bitfield flags.",
-                )
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("newtype-enum")
-                .long("newtype-enum")
-                .help("Mark any enum whose name matches <regex> as a newtype.")
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("rustified-enum")
-                .long("rustified-enum")
-                .help("Mark any enum whose name matches <regex> as a Rust enum.")
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("constified-enum")
-                .long("constified-enum")
-                .help(
-                    "Mark any enum whose name matches <regex> as a series of \
-                     constants.",
-                )
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("constified-enum-module")
-                .long("constified-enum-module")
-                .help(
-                    "Mark any enum whose name matches <regex> as a module of \
-                     constants.",
-                )
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("default-macro-constant-type")
-                .long("default-macro-constant-type")
-                .help("The default signed/unsigned type for C macro constants.")
-                .value_name("variant")
-                .default_value("unsigned")
-                .possible_values(&["signed", "unsigned"])
-                .multiple(false),
-            Arg::with_name("default-alias-style")
-                .long("default-alias-style")
-                .help("The default style of code used to generate typedefs.")
-                .value_name("variant")
-                .default_value("type_alias")
-                .possible_values(&[
-                    "type_alias",
-                    "new_type",
-                    "new_type_deref",
-                ])
-                .multiple(false),
-            Arg::with_name("normal-alias")
-                .long("normal-alias")
-                .help(
-                    "Mark any typedef alias whose name matches <regex> to use \
-                     normal type aliasing.",
-                )
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-             Arg::with_name("new-type-alias")
-                .long("new-type-alias")
-                .help(
-                    "Mark any typedef alias whose name matches <regex> to have \
-                     a new type generated for it.",
-                )
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-             Arg::with_name("new-type-alias-deref")
-                .long("new-type-alias-deref")
-                .help(
-                    "Mark any typedef alias whose name matches <regex> to have \
-                     a new type with Deref and DerefMut to the inner type.",
-                )
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            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("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("blocklist-item")
-                .alias("blacklist-item")
-                .long("blocklist-item")
-                .help("Mark <item> as hidden.")
-                .value_name("item")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("blocklist-file")
-                .alias("blacklist-file")
-                .long("blocklist-file")
-                .help("Mark all contents of <path> as hidden.")
-                .value_name("path")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("no-layout-tests")
-                .long("no-layout-tests")
-                .help("Avoid generating layout tests for any type."),
-            Arg::with_name("no-derive-copy")
-                .long("no-derive-copy")
-                .help("Avoid deriving Copy on any type."),
-            Arg::with_name("no-derive-debug")
-                .long("no-derive-debug")
-                .help("Avoid deriving Debug on any type."),
-            Arg::with_name("no-derive-default")
-                .long("no-derive-default")
-                .hidden(true)
-                .help("Avoid deriving Default on any type."),
-            Arg::with_name("impl-debug").long("impl-debug").help(
-                "Create Debug implementation, if it can not be derived \
-                 automatically.",
-            ),
-            Arg::with_name("impl-partialeq")
-                .long("impl-partialeq")
-                .help(
-                    "Create PartialEq implementation, if it can not be derived \
-                     automatically.",
-                ),
-            Arg::with_name("with-derive-default")
-                .long("with-derive-default")
-                .help("Derive Default on any type."),
-            Arg::with_name("with-derive-hash")
-                .long("with-derive-hash")
-                .help("Derive hash on any type."),
-            Arg::with_name("with-derive-partialeq")
-                .long("with-derive-partialeq")
-                .help("Derive partialeq on any type."),
-            Arg::with_name("with-derive-partialord")
-                .long("with-derive-partialord")
-                .help("Derive partialord on any type."),
-            Arg::with_name("with-derive-eq")
-                .long("with-derive-eq")
-                .help(
-                    "Derive eq on any type. Enable this option also \
-                     enables --with-derive-partialeq",
-                ),
-            Arg::with_name("with-derive-ord")
-                .long("with-derive-ord")
-                .help(
-                    "Derive ord on any type. Enable this option also \
-                     enables --with-derive-partialord",
-                ),
-            Arg::with_name("no-doc-comments")
-                .long("no-doc-comments")
-                .help(
-                    "Avoid including doc comments in the output, see: \
-                     https://github.com/rust-lang/rust-bindgen/issues/426",
-                ),
-            Arg::with_name("no-recursive-allowlist")
-                .long("no-recursive-allowlist")
-                .alias("no-recursive-whitelist")
-                .help(
-                    "Disable allowlisting types recursively. This will cause \
-                     bindgen to emit Rust code that won't compile! See the \
-                     `bindgen::Builder::allowlist_recursively` method's \
-                     documentation for details.",
-                ),
-            Arg::with_name("objc-extern-crate")
-                .long("objc-extern-crate")
-                .help("Use extern crate instead of use for objc."),
-            Arg::with_name("generate-block")
-                .long("generate-block")
-                .help("Generate block signatures instead of void pointers."),
-            Arg::with_name("block-extern-crate")
-                .long("block-extern-crate")
-                .help("Use extern crate instead of use for block."),
-            Arg::with_name("distrust-clang-mangling")
-                .long("distrust-clang-mangling")
-                .help("Do not trust the libclang-provided mangling"),
-            Arg::with_name("builtins").long("builtins").help(
-                "Output bindings for builtin definitions, e.g. \
-                 __builtin_va_list.",
-            ),
-            Arg::with_name("ctypes-prefix")
-                .long("ctypes-prefix")
-                .help(
-                    "Use the given prefix before raw types instead of \
-                     ::std::os::raw.",
-                )
-                .value_name("prefix")
-                .takes_value(true),
-            Arg::with_name("anon-fields-prefix")
-                .long("anon-fields-prefix")
-                .help("Use the given prefix for the anon fields.")
-                .value_name("prefix")
-                .default_value(DEFAULT_ANON_FIELDS_PREFIX)
-                .takes_value(true),
-            Arg::with_name("time-phases")
-                .long("time-phases")
-                .help("Time the different bindgen phases and print to stderr"),
-            // All positional arguments after the end of options marker, `--`
-            Arg::with_name("clang-args").last(true).multiple(true),
-            Arg::with_name("emit-clang-ast")
-                .long("emit-clang-ast")
-                .help("Output the Clang AST for debugging purposes."),
-            Arg::with_name("emit-ir")
-                .long("emit-ir")
-                .help("Output our internal IR for debugging purposes."),
-            Arg::with_name("emit-ir-graphviz")
-                .long("emit-ir-graphviz")
-                .help("Dump graphviz dot file.")
-                .value_name("path")
-                .takes_value(true),
-            Arg::with_name("enable-cxx-namespaces")
-                .long("enable-cxx-namespaces")
-                .help("Enable support for C++ namespaces."),
-            Arg::with_name("disable-name-namespacing")
-                .long("disable-name-namespacing")
-                .help(
-                    "Disable namespacing via mangling, causing bindgen to \
-                     generate names like \"Baz\" instead of \"foo_bar_Baz\" \
-                     for an input name \"foo::bar::Baz\".",
-                ),
-            Arg::with_name("disable-nested-struct-naming")
-                .long("disable-nested-struct-naming")
-                .help(
-                    "Disable nested struct naming, causing bindgen to generate \
-                     names like \"bar\" instead of \"foo_bar\" for a nested \
-                     definition \"struct foo { struct bar { } b; };\"."
-                ),
-            Arg::with_name("disable-untagged-union")
-                .long("disable-untagged-union")
-                .help(
-                    "Disable support for native Rust unions.",
-                ),
-            Arg::with_name("disable-header-comment")
-                .long("disable-header-comment")
-                .help("Suppress insertion of bindgen's version identifier into generated bindings.")
-                .multiple(true),
-            Arg::with_name("ignore-functions")
-                .long("ignore-functions")
-                .help(
-                    "Do not generate bindings for functions or methods. This \
-                     is useful when you only care about struct layouts.",
-                ),
-            Arg::with_name("generate")
-                .long("generate")
-                .help(
-                    "Generate only given items, split by commas. \
-                     Valid values are \"functions\",\"types\", \"vars\", \
-                     \"methods\", \"constructors\" and \"destructors\".",
-                )
-                .takes_value(true),
-            Arg::with_name("ignore-methods")
-                .long("ignore-methods")
-                .help("Do not generate bindings for methods."),
-            Arg::with_name("no-convert-floats")
-                .long("no-convert-floats")
-                .help("Do not automatically convert floats to f32/f64."),
-            Arg::with_name("no-prepend-enum-name")
-                .long("no-prepend-enum-name")
-                .help("Do not prepend the enum name to constant or newtype variants."),
-            Arg::with_name("no-include-path-detection")
-                .long("no-include-path-detection")
-                .help("Do not try to detect default include paths"),
-            Arg::with_name("fit-macro-constant-types")
-                .long("fit-macro-constant-types")
-                .help("Try to fit macro constants into types smaller than u32/i32"),
-            Arg::with_name("unstable-rust")
-                .long("unstable-rust")
-                .help("Generate unstable Rust code (deprecated; use --rust-target instead).")
-                .multiple(true), // FIXME: Pass legacy test suite
-            Arg::with_name("opaque-type")
-                .long("opaque-type")
-                .help("Mark <type> as opaque.")
-                .value_name("type")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("output")
-                .short("o")
-                .long("output")
-                .help("Write Rust bindings to <output>.")
-                .takes_value(true),
-            Arg::with_name("raw-line")
-                .long("raw-line")
-                .help("Add a raw line of Rust code at the beginning of output.")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("module-raw-line")
-                .long("module-raw-line")
-                .help("Add a raw line of Rust code to a given module.")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(2)
-                .value_names(&["module-name", "raw-line"]),
-            Arg::with_name("rust-target")
-                .long("rust-target")
-                .help(&rust_target_help)
-                .takes_value(true),
-            Arg::with_name("use-core")
-                .long("use-core")
-                .help("Use types from Rust core instead of std."),
-            Arg::with_name("conservative-inline-namespaces")
-                .long("conservative-inline-namespaces")
-                .help(
-                    "Conservatively generate inline namespaces to avoid name \
-                     conflicts.",
-                ),
-            Arg::with_name("use-msvc-mangling")
-                .long("use-msvc-mangling")
-                .help("MSVC C++ ABI mangling. DEPRECATED: Has no effect."),
-            Arg::with_name("allowlist-function")
-                .long("allowlist-function")
-                .alias("whitelist-function")
-                .help(
-                    "Allowlist all the free-standing functions matching \
-                     <regex>. Other non-allowlisted functions will not be \
-                     generated.",
-                )
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("generate-inline-functions")
-                .long("generate-inline-functions")
-                .help("Generate inline functions."),
-            Arg::with_name("allowlist-type")
-                .long("allowlist-type")
-                .alias("whitelist-type")
-                .help(
-                    "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("allowlist-var")
-                .long("allowlist-var")
-                .alias("whitelist-var")
-                .help(
-                    "Allowlist all the free-standing variables matching \
-                     <regex>. Other non-allowlisted variables will not be \
-                     generated.",
-                )
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("verbose")
-                .long("verbose")
-                .help("Print verbose error messages."),
-            Arg::with_name("dump-preprocessed-input")
-                .long("dump-preprocessed-input")
-                .help(
-                    "Preprocess and dump the input header files to disk. \
-                     Useful when debugging bindgen, using C-Reduce, or when \
-                     filing issues. The resulting file will be named \
-                     something like `__bindgen.i` or `__bindgen.ii`.",
-                ),
-            Arg::with_name("no-record-matches")
-                .long("no-record-matches")
-                .help(
-                    "Do not record matching items in the regex sets. \
-                     This disables reporting of unused items.",
-                ),
-            Arg::with_name("size_t-is-usize")
-                .long("size_t-is-usize")
-                .help("Translate size_t to usize."),
-            Arg::with_name("no-rustfmt-bindings")
-                .long("no-rustfmt-bindings")
-                .help("Do not format the generated bindings with rustfmt."),
-            Arg::with_name("rustfmt-bindings")
-                .long("rustfmt-bindings")
-                .help(
-                    "Format the generated bindings with rustfmt. DEPRECATED: \
-                     --rustfmt-bindings is now enabled by default. Disable \
-                     with --no-rustfmt-bindings.",
-                ),
-            Arg::with_name("rustfmt-configuration-file")
-                .long("rustfmt-configuration-file")
-                .help(
-                    "The absolute path to the rustfmt configuration file. \
-                     The configuration file will be used for formatting the bindings. \
-                     This parameter is incompatible with --no-rustfmt-bindings.",
-                )
-                .value_name("path")
-                .takes_value(true)
-                .multiple(false)
-                .number_of_values(1),
-            Arg::with_name("no-partialeq")
-                .long("no-partialeq")
-                .help("Avoid deriving PartialEq for types matching <regex>.")
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("no-copy")
-                .long("no-copy")
-                .help("Avoid deriving Copy for types matching <regex>.")
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("no-debug")
-                .long("no-debug")
-                .help("Avoid deriving Debug for types matching <regex>.")
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("no-default")
-                .long("no-default")
-                .help("Avoid deriving/implement Default for types matching <regex>.")
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("no-hash")
-                .long("no-hash")
-                .help("Avoid deriving Hash for types matching <regex>.")
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("must-use-type")
-                .long("must-use-type")
-                .help("Add #[must_use] annotation to types matching <regex>.")
-                .value_name("regex")
-                .takes_value(true)
-                .multiple(true)
-                .number_of_values(1),
-            Arg::with_name("enable-function-attribute-detection")
-                .long("enable-function-attribute-detection")
-                .help(
-                    "Enables detecting unexposed attributes in functions (slow).
-                       Used to generate #[must_use] annotations.",
-                ),
-            Arg::with_name("use-array-pointers-in-arguments")
-                .long("use-array-pointers-in-arguments")
-                .help("Use `*const [T; size]` instead of `*const T` for C arrays"),
-            Arg::with_name("wasm-import-module-name")
-                .long("wasm-import-module-name")
-                .value_name("name")
-                .takes_value(true)
-                .help("The name to be used in a #[link(wasm_import_module = ...)] statement"),
-            Arg::with_name("dynamic-loading")
-                .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."),
-            Arg::with_name("c-naming")
-                .long("c-naming")
-                .help("Generate types with C style naming."),
-            Arg::with_name("explicit-padding")
-                .long("explicit-padding")
-                .help("Always output explicit padding fields."),
-        ]) // .args()
-        .get_matches_from(args);
-
-    let mut builder = builder();
-
-    if let Some(header) = matches.value_of("header") {
-        builder = builder.header(header);
-    } else {
-        return Err(Error::new(ErrorKind::Other, "Header not found"));
-    }
-
-    if matches.is_present("unstable-rust") {
-        builder = builder.rust_target(RustTarget::Nightly);
-        writeln!(
-            &mut stderr(),
-            "warning: the `--unstable-rust` option is deprecated"
-        )
-        .expect("Unable to write error message");
-    }
-
-    if let Some(rust_target) = matches.value_of("rust-target") {
-        builder = builder.rust_target(RustTarget::from_str(rust_target)?);
-    }
-
-    if let Some(variant) = matches.value_of("default-enum-style") {
-        builder = builder.default_enum_style(EnumVariation::from_str(variant)?)
-    }
-
-    if let Some(bitfields) = matches.values_of("bitfield-enum") {
-        for regex in bitfields {
-            builder = builder.bitfield_enum(regex);
-        }
-    }
-
-    if let Some(newtypes) = matches.values_of("newtype-enum") {
-        for regex in newtypes {
-            builder = builder.newtype_enum(regex);
-        }
-    }
-
-    if let Some(rustifieds) = matches.values_of("rustified-enum") {
-        for regex in rustifieds {
-            builder = builder.rustified_enum(regex);
-        }
-    }
-
-    if let Some(const_enums) = matches.values_of("constified-enum") {
-        for regex in const_enums {
-            builder = builder.constified_enum(regex);
-        }
-    }
-
-    if let Some(constified_mods) = matches.values_of("constified-enum-module") {
-        for regex in constified_mods {
-            builder = builder.constified_enum_module(regex);
-        }
-    }
-
-    if let Some(variant) = matches.value_of("default-macro-constant-type") {
-        builder = builder
-            .default_macro_constant_type(MacroTypeVariation::from_str(variant)?)
-    }
-
-    if let Some(variant) = matches.value_of("default-alias-style") {
-        builder =
-            builder.default_alias_style(AliasVariation::from_str(variant)?);
-    }
-
-    if let Some(type_alias) = matches.values_of("normal-alias") {
-        for regex in type_alias {
-            builder = builder.type_alias(regex);
-        }
-    }
-
-    if let Some(new_type) = matches.values_of("new-type-alias") {
-        for regex in new_type {
-            builder = builder.new_type_alias(regex);
-        }
-    }
-
-    if let Some(new_type_deref) = matches.values_of("new-type-alias-deref") {
-        for regex in new_type_deref {
-            builder = builder.new_type_alias_deref(regex);
-        }
-    }
-
-    if let Some(hidden_types) = matches.values_of("blocklist-type") {
-        for ty in hidden_types {
-            builder = builder.blocklist_type(ty);
-        }
-    }
-
-    if let Some(hidden_functions) = matches.values_of("blocklist-function") {
-        for fun in hidden_functions {
-            builder = builder.blocklist_function(fun);
-        }
-    }
-
-    if let Some(hidden_identifiers) = matches.values_of("blocklist-item") {
-        for id in hidden_identifiers {
-            builder = builder.blocklist_item(id);
-        }
-    }
-
-    if let Some(hidden_files) = matches.values_of("blocklist-file") {
-        for file in hidden_files {
-            builder = builder.blocklist_file(file);
-        }
-    }
-
-    if matches.is_present("builtins") {
-        builder = builder.emit_builtins();
-    }
-
-    if matches.is_present("no-layout-tests") {
-        builder = builder.layout_tests(false);
-    }
-
-    if matches.is_present("no-derive-copy") {
-        builder = builder.derive_copy(false);
-    }
-
-    if matches.is_present("no-derive-debug") {
-        builder = builder.derive_debug(false);
-    }
-
-    if matches.is_present("impl-debug") {
-        builder = builder.impl_debug(true);
-    }
-
-    if matches.is_present("impl-partialeq") {
-        builder = builder.impl_partialeq(true);
-    }
-
-    if matches.is_present("with-derive-default") {
-        builder = builder.derive_default(true);
-    }
-
-    if matches.is_present("with-derive-hash") {
-        builder = builder.derive_hash(true);
-    }
-
-    if matches.is_present("with-derive-partialeq") {
-        builder = builder.derive_partialeq(true);
-    }
-
-    if matches.is_present("with-derive-partialord") {
-        builder = builder.derive_partialord(true);
-    }
-
-    if matches.is_present("with-derive-eq") {
-        builder = builder.derive_eq(true);
-    }
-
-    if matches.is_present("with-derive-ord") {
-        builder = builder.derive_ord(true);
-    }
-
-    if matches.is_present("no-derive-default") {
-        builder = builder.derive_default(false);
-    }
-
-    if matches.is_present("no-prepend-enum-name") {
-        builder = builder.prepend_enum_name(false);
-    }
-
-    if matches.is_present("no-include-path-detection") {
-        builder = builder.detect_include_paths(false);
-    }
-
-    if matches.is_present("fit-macro-constant-types") {
-        builder = builder.fit_macro_constants(true);
-    }
-
-    if matches.is_present("time-phases") {
-        builder = builder.time_phases(true);
-    }
-
-    if matches.is_present("use-array-pointers-in-arguments") {
-        builder = builder.array_pointers_in_arguments(true);
-    }
-
-    if let Some(wasm_import_name) = matches.value_of("wasm-import-module-name")
-    {
-        builder = builder.wasm_import_module_name(wasm_import_name);
-    }
-
-    if let Some(prefix) = matches.value_of("ctypes-prefix") {
-        builder = builder.ctypes_prefix(prefix);
-    }
-
-    if let Some(prefix) = matches.value_of("anon-fields-prefix") {
-        builder = builder.anon_fields_prefix(prefix);
-    }
-
-    if let Some(what_to_generate) = matches.value_of("generate") {
-        let mut config = CodegenConfig::empty();
-        for what in what_to_generate.split(',') {
-            match what {
-                "functions" => config.insert(CodegenConfig::FUNCTIONS),
-                "types" => config.insert(CodegenConfig::TYPES),
-                "vars" => config.insert(CodegenConfig::VARS),
-                "methods" => config.insert(CodegenConfig::METHODS),
-                "constructors" => config.insert(CodegenConfig::CONSTRUCTORS),
-                "destructors" => config.insert(CodegenConfig::DESTRUCTORS),
-                otherwise => {
-                    return Err(Error::new(
-                        ErrorKind::Other,
-                        format!("Unknown generate item: {}", otherwise),
-                    ));
-                }
-            }
-        }
-        builder = builder.with_codegen_config(config);
-    }
-
-    if matches.is_present("emit-clang-ast") {
-        builder = builder.emit_clang_ast();
-    }
-
-    if matches.is_present("emit-ir") {
-        builder = builder.emit_ir();
-    }
-
-    if let Some(path) = matches.value_of("emit-ir-graphviz") {
-        builder = builder.emit_ir_graphviz(path);
-    }
-
-    if matches.is_present("enable-cxx-namespaces") {
-        builder = builder.enable_cxx_namespaces();
-    }
-
-    if matches.is_present("enable-function-attribute-detection") {
-        builder = builder.enable_function_attribute_detection();
-    }
-
-    if matches.is_present("disable-name-namespacing") {
-        builder = builder.disable_name_namespacing();
-    }
-
-    if matches.is_present("disable-nested-struct-naming") {
-        builder = builder.disable_nested_struct_naming();
-    }
-
-    if matches.is_present("disable-untagged-union") {
-        builder = builder.disable_untagged_union();
-    }
-
-    if matches.is_present("disable-header-comment") {
-        builder = builder.disable_header_comment();
-    }
-
-    if matches.is_present("ignore-functions") {
-        builder = builder.ignore_functions();
-    }
-
-    if matches.is_present("ignore-methods") {
-        builder = builder.ignore_methods();
-    }
-
-    if matches.is_present("no-convert-floats") {
-        builder = builder.no_convert_floats();
-    }
-
-    if matches.is_present("no-doc-comments") {
-        builder = builder.generate_comments(false);
-    }
-
-    if matches.is_present("no-recursive-allowlist") {
-        builder = builder.allowlist_recursively(false);
-    }
-
-    if matches.is_present("objc-extern-crate") {
-        builder = builder.objc_extern_crate(true);
-    }
-
-    if matches.is_present("generate-block") {
-        builder = builder.generate_block(true);
-    }
-
-    if matches.is_present("block-extern-crate") {
-        builder = builder.block_extern_crate(true);
-    }
-
-    if let Some(opaque_types) = matches.values_of("opaque-type") {
-        for ty in opaque_types {
-            builder = builder.opaque_type(ty);
-        }
-    }
-
-    if let Some(lines) = matches.values_of("raw-line") {
-        for line in lines {
-            builder = builder.raw_line(line);
-        }
-    }
-
-    if let Some(mut values) = matches.values_of("module-raw-line") {
-        while let Some(module) = values.next() {
-            let line = values.next().unwrap();
-            builder = builder.module_raw_line(module, line);
-        }
-    }
-
-    if matches.is_present("use-core") {
-        builder = builder.use_core();
-    }
-
-    if matches.is_present("distrust-clang-mangling") {
-        builder = builder.trust_clang_mangling(false);
-    }
-
-    if matches.is_present("conservative-inline-namespaces") {
-        builder = builder.conservative_inline_namespaces();
-    }
-
-    if matches.is_present("generate-inline-functions") {
-        builder = builder.generate_inline_functions(true);
-    }
-
-    if let Some(allowlist) = matches.values_of("allowlist-function") {
-        for regex in allowlist {
-            builder = builder.allowlist_function(regex);
-        }
-    }
-
-    if let Some(allowlist) = matches.values_of("allowlist-type") {
-        for regex in allowlist {
-            builder = builder.allowlist_type(regex);
-        }
-    }
-
-    if let Some(allowlist) = matches.values_of("allowlist-var") {
-        for regex in allowlist {
-            builder = builder.allowlist_var(regex);
-        }
-    }
-
-    if let Some(args) = matches.values_of("clang-args") {
-        for arg in args {
-            builder = builder.clang_arg(arg);
-        }
-    }
-
-    let output = if let Some(path) = matches.value_of("output") {
-        let file = File::create(path)?;
-        if let Some(depfile) = matches.value_of("depfile") {
-            builder = builder.depfile(path, depfile);
-        }
-        Box::new(io::BufWriter::new(file)) as Box<dyn io::Write>
-    } else {
-        if let Some(depfile) = matches.value_of("depfile") {
-            builder = builder.depfile("-", depfile);
-        }
-        Box::new(io::BufWriter::new(io::stdout())) as Box<dyn io::Write>
-    };
-
-    if matches.is_present("dump-preprocessed-input") {
-        builder.dump_preprocessed_input()?;
-    }
-
-    if matches.is_present("no-record-matches") {
-        builder = builder.record_matches(false);
-    }
-
-    if matches.is_present("size_t-is-usize") {
-        builder = builder.size_t_is_usize(true);
-    }
-
-    let no_rustfmt_bindings = matches.is_present("no-rustfmt-bindings");
-    if no_rustfmt_bindings {
-        builder = builder.rustfmt_bindings(false);
-    }
-
-    if let Some(path_str) = matches.value_of("rustfmt-configuration-file") {
-        let path = PathBuf::from(path_str);
-
-        if no_rustfmt_bindings {
-            return Err(Error::new(
-                ErrorKind::Other,
-                "Cannot supply both --rustfmt-configuration-file and --no-rustfmt-bindings",
-            ));
-        }
-
-        if !path.is_absolute() {
-            return Err(Error::new(
-                ErrorKind::Other,
-                "--rustfmt-configuration--file needs to be an absolute path!",
-            ));
-        }
-
-        if path.to_str().is_none() {
-            return Err(Error::new(
-                ErrorKind::Other,
-                "--rustfmt-configuration-file contains non-valid UTF8 characters.",
-            ));
-        }
-
-        builder = builder.rustfmt_configuration_file(Some(path));
-    }
-
-    if let Some(no_partialeq) = matches.values_of("no-partialeq") {
-        for regex in no_partialeq {
-            builder = builder.no_partialeq(regex);
-        }
-    }
-
-    if let Some(no_copy) = matches.values_of("no-copy") {
-        for regex in no_copy {
-            builder = builder.no_copy(regex);
-        }
-    }
-
-    if let Some(no_debug) = matches.values_of("no-debug") {
-        for regex in no_debug {
-            builder = builder.no_debug(regex);
-        }
-    }
-
-    if let Some(no_default) = matches.values_of("no-default") {
-        for regex in no_default {
-            builder = builder.no_default(regex);
-        }
-    }
-
-    if let Some(no_hash) = matches.values_of("no-hash") {
-        for regex in no_hash {
-            builder = builder.no_hash(regex);
-        }
-    }
-
-    if let Some(must_use_type) = matches.values_of("must-use-type") {
-        for regex in must_use_type {
-            builder = builder.must_use_type(regex);
-        }
-    }
-
-    if let Some(dynamic_library_name) = matches.value_of("dynamic-loading") {
-        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);
-    }
-
-    if matches.is_present("c-naming") {
-        builder = builder.c_naming(true);
-    }
-
-    if matches.is_present("explicit-padding") {
-        builder = builder.explicit_padding(true);
-    }
-
-    let verbose = matches.is_present("verbose");
-
-    Ok((builder, output, verbose))
-}
diff --git a/src/time.rs b/time.rs
similarity index 100%
rename from src/time.rs
rename to time.rs