Repository: rust-lang/rust-bindgen
Pull request #2663 (2023-10-15 18:28:25)

Better working destructors on windows
Tries to solve #1725 and #2092.

I found that clang can only generate one entry when calling `clang_Cursor_getCXXManglings` with the Microsoft ABI. Also the conditions for "group 1" destructors don't apply at all on the MS ABI, having a completely different mangling format.

Also, it seems like the entry from `clang_Cursor_getCXXManglings` will always be the regular "base" destructor that is most interesting usually, while the entry from `clang_Cursor_getMangling` will always be the "vbase destructor" that's supposed to be able to destroy anything. However, only the base destructor is always available, the other ones being generated on the fly when the code actually needs it.

So far, the code always chose the vbase dtor that happened to never exist, and this is why the code always failed with a link error.

What I wish I figured out how to do was to get the information from clang under which ABI we operate at the moment, but I couldn't find a way to do this, so I just checked if we run under Windows instead. I suspect this might not work well with the MinGW target.

With the `main` branch unmodified I get one failed test under WSL and over 500 under Windows. I did not see whether I could have Windows only tests, but it looked like a lot of effort to get all tests working under Windows at this point, so I don't know if I could add any tests at the moment.

[Here](https://gist.github.com/xTachyon/7d2e7ca801521c47cb152d9bea5e7895) is the manual test I performed. Most usual things seems to work fine, except for classes that use virtual inheritance (the vbase destructor) because it's not the correct destructor to call directly. It seems to crash in a deterministic fashion on my machine from a null pointer access, _so it might be fine?_ This is just trying to make the best of out of a bad situation.

Is there anything I could do make it better? Sorry for the rambly description.

xTachyon: r? @emilio
xTachyon: There doesn't seem to be any `clang_TargetInfo_*` to get the ABI, but I figured just checking if the triple constains `msvc` should be good enough.

Is this better?

Patch:
diff --git a/.github/workflows/bindgen.yml b/.github/workflows/bindgen.yml
index c7c37bbc..3f85cd86 100644
--- a/.github/workflows/bindgen.yml
+++ b/.github/workflows/bindgen.yml
@@ -238,7 +238,7 @@ jobs:
           override: true
       
       - name: Check cfg
-        run: cargo check -Z unstable-options -Z check-cfg=features
+        run: cargo check -Z unstable-options -Z check-cfg
 
   test-book:
     runs-on: ubuntu-latest
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 00000000..f79ce103
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,21 @@
+# To trigger this:
+# - go to Actions > Publish
+# - click the Run Workflow dropdown in the top-right
+name: Publish
+on: workflow_dispatch
+env:
+  CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
+jobs:
+  cargo-publish:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout sources
+        uses: actions/checkout@v3
+      - name: Install stable toolchain
+        uses: dtolnay/rust-toolchain@master
+        with:
+          toolchain: stable
+      - name: Publish bindgen (lib)
+        run: cargo publish --package bindgen --token ${CARGO_REGISTRY_TOKEN}
+      - name: Publish bindgen-cli
+        run: cargo publish --package bindgen-cli --token ${CARGO_REGISTRY_TOKEN}
diff --git a/.github/workflows/sync-master-from-main.yml b/.github/workflows/sync-master-from-main.yml
deleted file mode 100644
index 56142450..00000000
--- a/.github/workflows/sync-master-from-main.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-name: sync master from main
-
-on:
-  push:
-    branches:
-      - main
-
-jobs:
-  sync-branches:
-    runs-on: ubuntu-latest
-    name: Keep master and main in sync until master is done
-    steps:
-      - name: Checkout
-        uses: actions/checkout@v3
-      - name: Merge master <- main
-        uses: devmasx/merge-branch@master
-        with:
-          type: now
-          from_branch: main
-          target_branch: master
-          github_token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index a924030c..a610640e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,8 @@ csmith-fuzzing/platform.info
 
 # Backups of test cases from C-Reduce
 **/*.orig
+
+# node.js files
+node_modules
+package-lock.json
+package.json
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9149d45d..e3f2c9e9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,175 +7,195 @@
   - [Removed](#removed)
   - [Fixed](#fixed)
   - [Security](#security)
-- [0.68.1](#0681)
+- [0.69.1 (2023-11-02)](#0691-2023-11-02)
   - [Fixed](#fixed-1)
-- [0.68.0](#0680)
+- [0.69.0 (2023-11-01)](#0690-2023-11-01)
   - [Added](#added-1)
   - [Changed](#changed-1)
   - [Removed](#removed-1)
   - [Fixed](#fixed-2)
-- [0.67.0](#0670)
-- [0.66.1](#0661)
-  - [Removed](#removed-2)
-- [0.66.0](#0660)
+  - [Security](#security-1)
+- [0.68.1](#0681)
+  - [Fixed](#fixed-3)
+- [0.68.0](#0680)
   - [Added](#added-2)
   - [Changed](#changed-2)
+  - [Removed](#removed-2)
+  - [Fixed](#fixed-4)
+- [0.67.0](#0670)
+- [0.66.1](#0661)
   - [Removed](#removed-3)
-- [0.65.1](#0651)
-  - [Fixed](#fixed-3)
-- [0.65.0](#0650)
+- [0.66.0](#0660)
   - [Added](#added-3)
   - [Changed](#changed-3)
   - [Removed](#removed-4)
-- [0.64.0](#0640)
+- [0.65.1](#0651)
+  - [Fixed](#fixed-5)
+- [0.65.0](#0650)
   - [Added](#added-4)
   - [Changed](#changed-4)
-- [0.63.0](#0630)
+  - [Removed](#removed-5)
+- [0.64.0](#0640)
   - [Added](#added-5)
   - [Changed](#changed-5)
-  - [Removed](#removed-5)
-- [0.62.0](#0620)
+- [0.63.0](#0630)
   - [Added](#added-6)
   - [Changed](#changed-6)
-  - [Fixed](#fixed-4)
-- [0.61.0](#0610)
+  - [Removed](#removed-6)
+- [0.62.0](#0620)
   - [Added](#added-7)
   - [Changed](#changed-7)
-  - [Fixed](#fixed-5)
-- [0.60.1](#0601)
   - [Fixed](#fixed-6)
-- [0.60.0](#0600)
+- [0.61.0](#0610)
   - [Added](#added-8)
-  - [Fixed](#fixed-7)
   - [Changed](#changed-8)
-  - [Removed](#removed-6)
-- [0.59.2](#0592)
-- [0.59.1](#0591)
+  - [Fixed](#fixed-7)
+- [0.60.1](#0601)
   - [Fixed](#fixed-8)
-- [0.59.0](#0590)
+- [0.60.0](#0600)
   - [Added](#added-9)
   - [Fixed](#fixed-9)
   - [Changed](#changed-9)
-- [0.58.1](#0581)
-  - [Added](#added-10)
-- [0.58.0](#0580)
-  - [Added](#added-11)
-  - [Fixed](#fixed-10)
-  - [Changed](#changed-10)
-  - [Deprecated](#deprecated)
   - [Removed](#removed-7)
+- [0.59.2](#0592)
+- [0.59.1](#0591)
+  - [Fixed](#fixed-10)
+- [0.59.0](#0590)
+  - [Added](#added-10)
   - [Fixed](#fixed-11)
-  - [Security](#security-1)
-- [0.57.0](#0570)
+  - [Changed](#changed-10)
+- [0.58.1](#0581)
+  - [Added](#added-11)
+- [0.58.0](#0580)
   - [Added](#added-12)
   - [Fixed](#fixed-12)
-- [0.56.0](#0560)
-  - [Added](#added-13)
   - [Changed](#changed-11)
+  - [Deprecated](#deprecated)
+  - [Removed](#removed-8)
   - [Fixed](#fixed-13)
-- [0.55.1](#0551)
+  - [Security](#security-2)
+- [0.57.0](#0570)
+  - [Added](#added-13)
   - [Fixed](#fixed-14)
-- [0.55.0](#0550)
-  - [Removed](#removed-8)
+- [0.56.0](#0560)
   - [Added](#added-14)
   - [Changed](#changed-12)
   - [Fixed](#fixed-15)
-- [0.54.1](#0541)
+- [0.55.1](#0551)
+  - [Fixed](#fixed-16)
+- [0.55.0](#0550)
+  - [Removed](#removed-9)
   - [Added](#added-15)
   - [Changed](#changed-13)
-  - [Fixed](#fixed-16)
-- [0.54.0](#0540)
+  - [Fixed](#fixed-17)
+- [0.54.1](#0541)
   - [Added](#added-16)
   - [Changed](#changed-14)
-  - [Fixed](#fixed-17)
-- [0.53.3](#0533)
-  - [Added](#added-17)
   - [Fixed](#fixed-18)
-- [0.53.2](#0532)
+- [0.54.0](#0540)
+  - [Added](#added-17)
   - [Changed](#changed-15)
-- [0.53.1](#0531)
+  - [Fixed](#fixed-19)
+- [0.53.3](#0533)
   - [Added](#added-18)
-- [0.53.0](#0530)
-  - [Added](#added-19)
+  - [Fixed](#fixed-20)
+- [0.53.2](#0532)
   - [Changed](#changed-16)
-  - [Fixed](#fixed-19)
-- [0.52.0](#0520)
+- [0.53.1](#0531)
+  - [Added](#added-19)
+- [0.53.0](#0530)
   - [Added](#added-20)
   - [Changed](#changed-17)
-  - [Fixed](#fixed-20)
-- [0.51.1](#0511)
   - [Fixed](#fixed-21)
+- [0.52.0](#0520)
+  - [Added](#added-21)
   - [Changed](#changed-18)
-- [0.51.0](#0510)
   - [Fixed](#fixed-22)
+- [0.51.1](#0511)
+  - [Fixed](#fixed-23)
   - [Changed](#changed-19)
-  - [Added](#added-21)
-- [0.50.0](#0500)
+- [0.51.0](#0510)
+  - [Fixed](#fixed-24)
+  - [Changed](#changed-20)
   - [Added](#added-22)
-- [0.49.3](#0493)
+- [0.50.0](#0500)
   - [Added](#added-23)
+- [0.49.3](#0493)
+  - [Added](#added-24)
 - [0.49.2](#0492)
-  - [Changed](#changed-20)
-- [0.49.1](#0491)
-  - [Fixed](#fixed-23)
   - [Changed](#changed-21)
-- [0.49.0](#0490)
-  - [Added](#added-24)
-  - [Fixed](#fixed-24)
+- [0.49.1](#0491)
+  - [Fixed](#fixed-25)
   - [Changed](#changed-22)
+- [0.49.0](#0490)
+  - [Added](#added-25)
+  - [Fixed](#fixed-26)
+  - [Changed](#changed-23)
 - [0.48.1](#0481)
-  - [Fixed](#fixed-25)
+  - [Fixed](#fixed-27)
 - [0.48.0](#0480)
-  - [Changed](#changed-23)
-  - [Fixed](#fixed-26)
+  - [Changed](#changed-24)
+  - [Fixed](#fixed-28)
 - [0.47.4](#0474)
-  - [Added](#added-25)
+  - [Added](#added-26)
 - [0.47.3](#0473)
-  - [Changed](#changed-24)
+  - [Changed](#changed-25)
 - [0.47.2](#0472)
-  - [Fixed](#fixed-27)
+  - [Fixed](#fixed-29)
 - [0.47.1](#0471)
-  - [Changed](#changed-25)
-  - [Fixed](#fixed-28)
-- [0.47.0](#0470)
   - [Changed](#changed-26)
-  - [Fixed](#fixed-29)
-- [0.33.1 .. 0.46.0](#0331--0460)
-  - [Added](#added-26)
-  - [Removed](#removed-9)
-  - [Changed](#changed-27)
   - [Fixed](#fixed-30)
-- [0.33.1](#0331)
+- [0.47.0](#0470)
+  - [Changed](#changed-27)
   - [Fixed](#fixed-31)
+- [0.33.1 .. 0.46.0](#0331--0460)
+  - [Added](#added-27)
+  - [Removed](#removed-10)
+  - [Changed](#changed-28)
+  - [Fixed](#fixed-32)
+- [0.33.1](#0331)
+  - [Fixed](#fixed-33)
 - [0.33.0](#0330)
 - [0.32.2](#0322)
-  - [Fixed](#fixed-32)
+  - [Fixed](#fixed-34)
 - [0.32.1](#0321)
-  - [Fixed](#fixed-33)
+  - [Fixed](#fixed-35)
 - [0.32.0](#0320)
-  - [Added](#added-27)
-  - [Changed](#changed-28)
-  - [Fixed](#fixed-34)
-- [0.31.0](#0310)
   - [Added](#added-28)
   - [Changed](#changed-29)
-  - [Deprecated](#deprecated-1)
-  - [Removed](#removed-10)
-  - [Fixed](#fixed-35)
-- [0.30.0](#0300)
+  - [Fixed](#fixed-36)
+- [0.31.0](#0310)
   - [Added](#added-29)
   - [Changed](#changed-30)
-  - [Deprecated](#deprecated-2)
-  - [Fixed](#fixed-36)
-- [0.29.0](#0290)
+  - [Deprecated](#deprecated-1)
+  - [Removed](#removed-11)
+  - [Fixed](#fixed-37)
+- [0.30.0](#0300)
   - [Added](#added-30)
   - [Changed](#changed-31)
-  - [Fixed](#fixed-37)
+  - [Deprecated](#deprecated-2)
+  - [Fixed](#fixed-38)
+- [0.29.0](#0290)
+  - [Added](#added-31)
+  - [Changed](#changed-32)
+  - [Fixed](#fixed-39)
 
 <!-- END doctoc generated TOC please keep comment here to allow auto update -->
 
 --------------------------------------------------------------------------------
 # Unreleased
+## Added
+## Changed
+## Removed
+## Fixed
+## Security
+
+# 0.69.1 (2023-11-02)
+
+## Fixed
+- Allow to run `bindgen -v` without an input header argument.
+
+# 0.69.0 (2023-11-01)
 
 ## Added
 - Added the `ParseCallbacks::header_file` callback which runs on every filename passed to `Builder::header`.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 25cad1e9..7e5cdc53 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -542,16 +542,11 @@ like the following is a useful way to check what has landed:
  $ git log --oneline v0.62.0..HEAD
  ```
 
-Also worth checking the [next-release tag](https://github.com/rust-lang/rust-bindgen/pulls?q=is%3Apr+label%3Anext-release).
-
-Once that's done and the changelog is up-to-date, run `doctoc` on it.
-
-If needed, install it locally by running:
-
-```
-$ npm install doctoc
-$ ./node_modules/doctoc/doctoc.js CHANGELOG.md
-```
+Also worth checking the [next-release
+tag](https://github.com/rust-lang/rust-bindgen/pulls?q=is%3Apr+label%3Anext-release).
+It is very important that you do not rename the `Unreleased` section of the
+changelog as this will be done automatically using `cargo release` on a further
+step.
 
 ### Merge to `main`
 
@@ -561,13 +556,21 @@ important fix) you can skip this.
 
 ### Tag and publish
 
-Once you're in the right branch, do:
+Once you're in `main`. Remember to install `doctoc` by running:
+```
+npm install doctoc
+```
 
+And then run:
 ```
-cargo release [patch|minor] --execute
+cargo release [patch|minor] --no-publish --execute
 ```
+
 This does the following:
 
+- Bump the version.
+- Turn the `Unreleased` section of the changelog into the section for the version being published.
+- Update the table of contents of the changelog using `doctoc`.
 - Tag (`git tag`) the HEAD commit
 - Publish (`cargo publish`) bindgen and bindgen-cli
 - Push (`git push`) to GitHub
@@ -602,4 +605,20 @@ cargo dist init # from "cargo install cargo-dist"
 cargo dist generate-ci # to update .github/workflows/release.yml
 ```
 
+### What to do if a Github release fails
+
+If the release process failed after you run `cargo release` you can manually
+delete the tag and release from Github. Also remember to delete the tag locally
+by running `git tag -d`. Once all the extra changes are in the `main` branch
+you can trigger a release by creating a new tag using `git tag` and push it
+using `git push --tag`.
+
+### Create a new crates.io release
+
+Go to [the Publish
+workflow](https://github.com/rust-lang/rust-bindgen/actions/workflows/publish.yml)
+and run a new workflow using the "Run Workflow" button.
+
+Remember that crates.io releases cannot be deleted!
+
 [prettyplease]: https://github.com/dtolnay/prettyplease
diff --git a/Cargo.lock b/Cargo.lock
index 40cb0777..a4d120a8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -23,7 +23,7 @@ dependencies = [
 
 [[package]]
 name = "bindgen"
-version = "0.68.1"
+version = "0.69.1"
 dependencies = [
  "annotate-snippets",
  "bitflags 2.2.1",
@@ -45,7 +45,7 @@ dependencies = [
 
 [[package]]
 name = "bindgen-cli"
-version = "0.68.1"
+version = "0.69.1"
 dependencies = [
  "bindgen",
  "clap",
@@ -203,17 +203,6 @@ dependencies = [
  "termcolor",
 ]
 
-[[package]]
-name = "errno"
-version = "0.2.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
-dependencies = [
- "errno-dragonfly",
- "libc",
- "winapi",
-]
-
 [[package]]
 name = "errno"
 version = "0.3.1"
@@ -548,16 +537,16 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
 
 [[package]]
 name = "rustix"
-version = "0.36.7"
+version = "0.36.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
+checksum = "6da3636faa25820d8648e0e31c5d519bbb01f72fdf57131f0f5f7da5fed36eab"
 dependencies = [
  "bitflags 1.3.2",
- "errno 0.2.8",
+ "errno",
  "io-lifetimes",
  "libc",
  "linux-raw-sys 0.1.4",
- "windows-sys 0.42.0",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -567,7 +556,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "62b24138615de35e32031d041a09032ef3487a616d901ca4db224e7d557efae2"
 dependencies = [
  "bitflags 1.3.2",
- "errno 0.3.1",
+ "errno",
  "io-lifetimes",
  "libc",
  "linux-raw-sys 0.3.8",
@@ -623,7 +612,7 @@ dependencies = [
  "cfg-if",
  "fastrand",
  "redox_syscall",
- "rustix 0.36.7",
+ "rustix 0.36.16",
  "windows-sys 0.42.0",
 ]
 
diff --git a/Cargo.toml b/Cargo.toml
index 3f674e69..0730e061 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -36,12 +36,6 @@ tag-name = "v{{version}}"
 # Don't release any crate unless its manifest has `release = true`
 release = false
 
-# Add version and date to changelog file
-[[workspace.metadata.release.pre-release-replacements]]
-file = "CHANGELOG.md"
-search = "# Unreleased"
-replace = "# {{version}} ({{date}})"
-
 # The profile that 'cargo dist' will build with
 [profile.dist]
 inherits = "release"
diff --git a/bindgen-cli/Cargo.toml b/bindgen-cli/Cargo.toml
index 07e77861..27389528 100644
--- a/bindgen-cli/Cargo.toml
+++ b/bindgen-cli/Cargo.toml
@@ -11,7 +11,7 @@ readme = "../README.md"
 repository = "https://github.com/rust-lang/rust-bindgen"
 documentation = "https://docs.rs/bindgen"
 homepage = "https://rust-lang.github.io/rust-bindgen/"
-version = "0.68.1"
+version = "0.69.1"
 edition = "2018"
 rust-version = "1.64.0"
 
@@ -20,7 +20,7 @@ path = "main.rs"
 name = "bindgen"
 
 [dependencies]
-bindgen = { path = "../bindgen", version = "=0.68.1",  default-features = false, features = ["__cli", "experimental"] }
+bindgen = { path = "../bindgen", version = "=0.69.1",  default-features = false, features = ["__cli", "experimental"] }
 clap = { version = "4", features = ["derive"] }
 clap_complete = "4"
 env_logger = { version = "0.10.0", optional = true }
diff --git a/bindgen-cli/options.rs b/bindgen-cli/options.rs
index d52ccb8e..f82d3919 100644
--- a/bindgen-cli/options.rs
+++ b/bindgen-cli/options.rs
@@ -95,7 +95,7 @@ fn parse_custom_derive(
 )]
 struct BindgenCommand {
     /// C or C++ header file.
-    header: String,
+    header: Option<String>,
     /// Path to write depfile to.
     #[arg(long)]
     depfile: Option<String>,
@@ -589,7 +589,11 @@ where
 
     let mut builder = builder();
 
-    builder = builder.header(header);
+    if let Some(header) = header {
+        builder = builder.header(header);
+    } else {
+        return Err(io::Error::new(io::ErrorKind::Other, "Header not found"));
+    }
 
     if let Some(rust_target) = rust_target {
         builder = builder.rust_target(rust_target);
diff --git a/bindgen/Cargo.toml b/bindgen/Cargo.toml
index d7b6df9f..18f43c04 100644
--- a/bindgen/Cargo.toml
+++ b/bindgen/Cargo.toml
@@ -14,7 +14,7 @@ readme = "../README.md"
 repository = "https://github.com/rust-lang/rust-bindgen"
 documentation = "https://docs.rs/bindgen"
 homepage = "https://rust-lang.github.io/rust-bindgen/"
-version = "0.68.1"
+version = "0.69.1"
 edition = "2018"
 build = "build.rs"
 # If you change this, also update README.md and msrv in .github/workflows/bindgen.yml
@@ -65,3 +65,10 @@ features = ["experimental"]
 
 [package.metadata.release]
 release = true
+pre-release-hook = ["../node_modules/doctoc/doctoc.js", "../CHANGELOG.md"]
+
+# Add version and date to changelog file
+[[package.metadata.release.pre-release-replacements]]
+file = "../CHANGELOG.md"
+search = "# Unreleased"
+replace = "# Unreleased\n## Added\n## Changed\n## Removed\n## Fixed\n## Security\n\n# {{version}} ({{date}})"
diff --git a/bindgen/clang.rs b/bindgen/clang.rs
index 3438bfa2..4a4ed89d 100644
--- a/bindgen/clang.rs
+++ b/bindgen/clang.rs
@@ -2297,6 +2297,15 @@ impl Drop for EvalResult {
         unsafe { clang_EvalResult_dispose(self.x) };
     }
 }
+/// ABI kinds as defined in
+/// <https://github.com/llvm/llvm-project/blob/ddf1de20a3f7db3bca1ef6ba7e6cbb90aac5fd2d/clang/include/clang/Basic/TargetCXXABI.def>
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
+pub(crate) enum ABIKind {
+    /// All the regular targets like Linux, Mac, WASM, etc. implement the Itanium ABI
+    GenericItanium,
+    /// The ABI used when compiling for the MSVC target
+    Microsoft,
+}
 
 /// Target information obtained from libclang.
 #[derive(Debug)]
@@ -2305,6 +2314,8 @@ pub(crate) struct TargetInfo {
     pub(crate) triple: String,
     /// The width of the pointer _in bits_.
     pub(crate) pointer_width: usize,
+    /// The ABI of the target
+    pub(crate) abi: ABIKind,
 }
 
 impl TargetInfo {
@@ -2320,9 +2331,17 @@ impl TargetInfo {
         }
         assert!(pointer_width > 0);
         assert_eq!(pointer_width % 8, 0);
+
+        let abi = if triple.contains("msvc") {
+            ABIKind::Microsoft
+        } else {
+            ABIKind::GenericItanium
+        };
+
         TargetInfo {
             triple,
             pointer_width: pointer_width as usize,
+            abi,
         }
     }
 }
diff --git a/bindgen/codegen/helpers.rs b/bindgen/codegen/helpers.rs
index 7ef44fe0..48bfe56d 100644
--- a/bindgen/codegen/helpers.rs
+++ b/bindgen/codegen/helpers.rs
@@ -232,6 +232,15 @@ pub(crate) mod ast_ty {
         //
         // Also, maybe this one shouldn't be the default?
         match (fk, ctx.options().convert_floats) {
+            (FloatKind::Float16, _) => {
+                // TODO: do f16 when rust lands it
+                ctx.generated_bindgen_float16();
+                if ctx.options().enable_cxx_namespaces {
+                    syn::parse_quote! { root::__BindgenFloat16 }
+                } else {
+                    syn::parse_quote! { __BindgenFloat16 }
+                }
+            }
             (FloatKind::Float, true) => syn::parse_quote! { f32 },
             (FloatKind::Double, true) => syn::parse_quote! { f64 },
             (FloatKind::Float, false) => raw_type(ctx, "c_float"),
diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs
index 8e136063..c84320ce 100644
--- a/bindgen/codegen/mod.rs
+++ b/bindgen/codegen/mod.rs
@@ -578,6 +578,9 @@ impl CodeGenerator for Module {
                 if result.saw_incomplete_array {
                     utils::prepend_incomplete_array_types(ctx, &mut *result);
                 }
+                if ctx.need_bindgen_float16_type() {
+                    utils::prepend_float16_type(&mut *result);
+                }
                 if ctx.need_bindgen_complex_type() {
                     utils::prepend_complex_type(&mut *result);
                 }
@@ -5136,6 +5139,20 @@ pub(crate) mod utils {
         result.extend(old_items);
     }
 
+    pub(crate) fn prepend_float16_type(
+        result: &mut Vec<proc_macro2::TokenStream>,
+    ) {
+        let float16_type = quote! {
+            #[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
+            #[repr(transparent)]
+            pub struct __BindgenFloat16(pub u16);
+        };
+
+        let items = vec![float16_type];
+        let old_items = mem::replace(result, items);
+        result.extend(old_items);
+    }
+
     pub(crate) fn prepend_complex_type(
         result: &mut Vec<proc_macro2::TokenStream>,
     ) {
diff --git a/bindgen/codegen/serialize.rs b/bindgen/codegen/serialize.rs
index 02c46802..9765a8bd 100644
--- a/bindgen/codegen/serialize.rs
+++ b/bindgen/codegen/serialize.rs
@@ -270,6 +270,7 @@ impl<'a> CSerialize<'a> for Type {
                     write!(writer, "const ")?;
                 }
                 match float_kind {
+                    FloatKind::Float16 => write!(writer, "_Float16")?,
                     FloatKind::Float => write!(writer, "float")?,
                     FloatKind::Double => write!(writer, "double")?,
                     FloatKind::LongDouble => write!(writer, "long double")?,
@@ -281,6 +282,7 @@ impl<'a> CSerialize<'a> for Type {
                     write!(writer, "const ")?;
                 }
                 match float_kind {
+                    FloatKind::Float16 => write!(writer, "_Float16 complex")?,
                     FloatKind::Float => write!(writer, "float complex")?,
                     FloatKind::Double => write!(writer, "double complex")?,
                     FloatKind::LongDouble => {
diff --git a/bindgen/codegen/struct_layout.rs b/bindgen/codegen/struct_layout.rs
index 56730603..83d78361 100644
--- a/bindgen/codegen/struct_layout.rs
+++ b/bindgen/codegen/struct_layout.rs
@@ -156,9 +156,7 @@ impl<'a> StructLayoutTracker<'a> {
 
         self.latest_field_layout = Some(layout);
         self.last_field_was_bitfield = true;
-        // NB: We intentionally don't update the max_field_align here, since our
-        // bitfields code doesn't necessarily guarantee it, so we need to
-        // actually generate the dummy alignment.
+        self.max_field_align = cmp::max(self.max_field_align, layout.align);
     }
 
     /// Returns a padding field if necessary for a given new field _before_
diff --git a/bindgen/ir/context.rs b/bindgen/ir/context.rs
index c5e2832c..517d3365 100644
--- a/bindgen/ir/context.rs
+++ b/bindgen/ir/context.rs
@@ -19,7 +19,7 @@ use super::module::{Module, ModuleKind};
 use super::template::{TemplateInstantiation, TemplateParameters};
 use super::traversal::{self, Edge, ItemTraversal};
 use super::ty::{FloatKind, Type, TypeKind};
-use crate::clang::{self, Cursor};
+use crate::clang::{self, ABIKind, Cursor};
 use crate::codegen::CodegenError;
 use crate::BindgenOptions;
 use crate::{Entry, HashMap, HashSet};
@@ -386,6 +386,9 @@ pub(crate) struct BindgenContext {
     /// Whether a bindgen complex was generated
     generated_bindgen_complex: Cell<bool>,
 
+    /// Whether a bindgen float16 was generated
+    generated_bindgen_float16: Cell<bool>,
+
     /// The set of `ItemId`s that are allowlisted. This the very first thing
     /// computed after parsing our IR, and before running any of our analyses.
     allowlisted: Option<ItemSet>,
@@ -585,6 +588,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
             target_info,
             options,
             generated_bindgen_complex: Cell::new(false),
+            generated_bindgen_float16: Cell::new(false),
             allowlisted: None,
             blocklisted_types_implement_traits: Default::default(),
             codegen_items: None,
@@ -622,6 +626,11 @@ If you encounter an error missing from this list, please file an issue or a PR!"
         self.target_info.pointer_width / 8
     }
 
+    /// Returns the ABI, which is mostly useful for determining the mangling kind.
+    pub(crate) fn abi_kind(&self) -> ABIKind {
+        self.target_info.abi
+    }
+
     /// Get the stack of partially parsed types that we are in the middle of
     /// parsing.
     pub(crate) fn currently_parsed_types(&self) -> &[PartialType] {
@@ -2005,6 +2014,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
             CXType_ULongLong => TypeKind::Int(IntKind::ULongLong),
             CXType_Int128 => TypeKind::Int(IntKind::I128),
             CXType_UInt128 => TypeKind::Int(IntKind::U128),
+            CXType_Float16 | CXType_Half => TypeKind::Float(FloatKind::Float16),
             CXType_Float => TypeKind::Float(FloatKind::Float),
             CXType_Double => TypeKind::Float(FloatKind::Double),
             CXType_LongDouble => TypeKind::Float(FloatKind::LongDouble),
@@ -2013,6 +2023,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
                 let float_type =
                     ty.elem_type().expect("Not able to resolve complex type?");
                 let float_kind = match float_type.kind() {
+                    CXType_Float16 | CXType_Half => FloatKind::Float16,
                     CXType_Float => FloatKind::Float,
                     CXType_Double => FloatKind::Double,
                     CXType_LongDouble => FloatKind::LongDouble,
@@ -2528,6 +2539,16 @@ If you encounter an error missing from this list, please file an issue or a PR!"
         self.generated_bindgen_complex.get()
     }
 
+    /// Call if a bindgen float16 is generated
+    pub(crate) fn generated_bindgen_float16(&self) {
+        self.generated_bindgen_float16.set(true)
+    }
+
+    /// Whether we need to generate the bindgen float16 type
+    pub(crate) fn need_bindgen_float16_type(&self) -> bool {
+        self.generated_bindgen_float16.get()
+    }
+
     /// Compute which `enum`s have an associated `typedef` definition.
     fn compute_enum_typedef_combos(&mut self) {
         let _t = self.timer("compute_enum_typedef_combos");
diff --git a/bindgen/ir/function.rs b/bindgen/ir/function.rs
index 5bfb70ef..6679a3d5 100644
--- a/bindgen/ir/function.rs
+++ b/bindgen/ir/function.rs
@@ -7,7 +7,7 @@ use super::item::Item;
 use super::traversal::{EdgeKind, Trace, Tracer};
 use super::ty::TypeKind;
 use crate::callbacks::{ItemInfo, ItemKind};
-use crate::clang::{self, Attribute};
+use crate::clang::{self, ABIKind, Attribute};
 use crate::parse::{ClangSubItemParser, ParseError, ParseResult};
 use clang_sys::{self, CXCallingConv};
 
@@ -303,6 +303,7 @@ fn get_abi(cc: CXCallingConv) -> ClangAbi {
         CXCallingConv_X86VectorCall => ClangAbi::Known(Abi::Vectorcall),
         CXCallingConv_AAPCS => ClangAbi::Known(Abi::Aapcs),
         CXCallingConv_X86_64Win64 => ClangAbi::Known(Abi::Win64),
+        CXCallingConv_AArch64VectorCall => ClangAbi::Known(Abi::Vectorcall),
         other => ClangAbi::Unknown(other),
     }
 }
@@ -323,11 +324,12 @@ pub(crate) fn cursor_mangling(
         return None;
     }
 
+    let is_itanium_abi = ctx.abi_kind() == ABIKind::GenericItanium;
     let is_destructor = cursor.kind() == clang_sys::CXCursor_Destructor;
     if let Ok(mut manglings) = cursor.cxx_manglings() {
         while let Some(m) = manglings.pop() {
             // Only generate the destructor group 1, see below.
-            if is_destructor && !m.ends_with("D1Ev") {
+            if is_itanium_abi && is_destructor && !m.ends_with("D1Ev") {
                 continue;
             }
 
@@ -340,7 +342,7 @@ pub(crate) fn cursor_mangling(
         return None;
     }
 
-    if is_destructor {
+    if is_itanium_abi && is_destructor {
         // With old (3.8-) libclang versions, and the Itanium ABI, clang returns
         // the "destructor group 0" symbol, which means that it'll try to free
         // memory, which definitely isn't what we want.
diff --git a/bindgen/ir/item.rs b/bindgen/ir/item.rs
index 4abca5c4..dd587b08 100644
--- a/bindgen/ir/item.rs
+++ b/bindgen/ir/item.rs
@@ -98,13 +98,13 @@ pub(crate) trait ItemAncestors {
     fn ancestors<'a>(&self, ctx: &'a BindgenContext) -> ItemAncestorsIter<'a>;
 }
 
-#[cfg(__testing_only_extra_assertions)]
+#[cfg(feature = "__testing_only_extra_assertions")]
 type DebugOnlyItemSet = ItemSet;
 
-#[cfg(not(__testing_only_extra_assertions))]
+#[cfg(not(feature = "__testing_only_extra_assertions"))]
 struct DebugOnlyItemSet;
 
-#[cfg(not(__testing_only_extra_assertions))]
+#[cfg(not(feature = "__testing_only_extra_assertions"))]
 impl DebugOnlyItemSet {
     fn new() -> Self {
         DebugOnlyItemSet
@@ -1432,57 +1432,58 @@ impl Item {
             }
         }
 
-        // Guess how does clang treat extern "C" blocks?
-        if cursor.kind() == CXCursor_UnexposedDecl {
-            Err(ParseError::Recurse)
-        } else {
+        match cursor.kind() {
+            // On Clang 18+, extern "C" is reported accurately as a LinkageSpec.
+            // Older LLVM treat it as UnexposedDecl.
+            CXCursor_LinkageSpec | CXCursor_UnexposedDecl => {
+                Err(ParseError::Recurse)
+            }
+
             // We allowlist cursors here known to be unhandled, to prevent being
             // too noisy about this.
-            match cursor.kind() {
-                CXCursor_MacroDefinition |
-                CXCursor_MacroExpansion |
-                CXCursor_UsingDeclaration |
-                CXCursor_UsingDirective |
-                CXCursor_StaticAssert |
-                CXCursor_FunctionTemplate => {
-                    debug!(
-                        "Unhandled cursor kind {:?}: {:?}",
-                        cursor.kind(),
-                        cursor
-                    );
-                }
-                CXCursor_InclusionDirective => {
-                    let file = cursor.get_included_file_name();
-                    match file {
-                        None => {
-                            warn!(
-                                "Inclusion of a nameless file in {:?}",
-                                cursor
-                            );
-                        }
-                        Some(included_file) => {
-                            for cb in &ctx.options().parse_callbacks {
-                                cb.include_file(&included_file);
-                            }
+            CXCursor_MacroDefinition |
+            CXCursor_MacroExpansion |
+            CXCursor_UsingDeclaration |
+            CXCursor_UsingDirective |
+            CXCursor_StaticAssert |
+            CXCursor_FunctionTemplate => {
+                debug!(
+                    "Unhandled cursor kind {:?}: {:?}",
+                    cursor.kind(),
+                    cursor
+                );
+                Err(ParseError::Continue)
+            }
 
-                            ctx.add_dep(included_file.into_boxed_str());
-                        }
+            CXCursor_InclusionDirective => {
+                let file = cursor.get_included_file_name();
+                match file {
+                    None => {
+                        warn!("Inclusion of a nameless file in {:?}", cursor);
                     }
-                }
-                _ => {
-                    // ignore toplevel operator overloads
-                    let spelling = cursor.spelling();
-                    if !spelling.starts_with("operator") {
-                        warn!(
-                            "Unhandled cursor kind {:?}: {:?}",
-                            cursor.kind(),
-                            cursor
-                        );
+                    Some(included_file) => {
+                        for cb in &ctx.options().parse_callbacks {
+                            cb.include_file(&included_file);
+                        }
+
+                        ctx.add_dep(included_file.into_boxed_str());
                     }
                 }
+                Err(ParseError::Continue)
             }
 
-            Err(ParseError::Continue)
+            _ => {
+                // ignore toplevel operator overloads
+                let spelling = cursor.spelling();
+                if !spelling.starts_with("operator") {
+                    warn!(
+                        "Unhandled cursor kind {:?}: {:?}",
+                        cursor.kind(),
+                        cursor
+                    );
+                }
+                Err(ParseError::Continue)
+            }
         }
     }
 
diff --git a/bindgen/ir/ty.rs b/bindgen/ir/ty.rs
index 1aee0659..b7a42932 100644
--- a/bindgen/ir/ty.rs
+++ b/bindgen/ir/ty.rs
@@ -558,6 +558,8 @@ impl TemplateParameters for TypeKind {
 /// The kind of float this type represents.
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 pub(crate) enum FloatKind {
+    /// A half (`_Float16` or `__fp16`)
+    Float16,
     /// A `float`.
     Float,
     /// A `double`.
diff --git a/bindgen/lib.rs b/bindgen/lib.rs
index 54348e22..70aa6714 100644
--- a/bindgen/lib.rs
+++ b/bindgen/lib.rs
@@ -927,22 +927,24 @@ impl Bindings {
 
     /// Write these bindings as source text to the given `Write`able.
     pub fn write<'a>(&self, mut writer: Box<dyn Write + 'a>) -> io::Result<()> {
+        const NL: &str = if cfg!(windows) { "\r\n" } else { "\n" };
+
         if !self.options.disable_header_comment {
             let version =
                 option_env!("CARGO_PKG_VERSION").unwrap_or("(unknown version)");
-            let header = format!(
-                "/* automatically generated by rust-bindgen {version} */\n\n",
-            );
-            writer.write_all(header.as_bytes())?;
+            writeln!(
+                writer,
+                "/* automatically generated by rust-bindgen {version} */{NL}",
+            )?;
         }
 
         for line in self.options.raw_lines.iter() {
             writer.write_all(line.as_bytes())?;
-            writer.write_all("\n".as_bytes())?;
+            writer.write_all(NL.as_bytes())?;
         }
 
         if !self.options.raw_lines.is_empty() {
-            writer.write_all("\n".as_bytes())?;
+            writer.write_all(NL.as_bytes())?;
         }
 
         match self.format_tokens(&self.module) {


Test patch:
diff --git a/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs b/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs
index cf045436..ea126bbb 100644
--- a/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs
+++ b/bindgen-tests/tests/expectations/tests/bitfield-32bit-overflow.rs
@@ -83,7 +83,7 @@ where
         }
     }
 }
-#[repr(C, packed)]
+#[repr(C)]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct MuchBitfield {
     pub _bitfield_align_1: [u8; 0],
diff --git a/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs b/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs
index 8cd1997a..ce3ea41e 100644
--- a/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs
+++ b/bindgen-tests/tests/expectations/tests/bitfield-method-same-name.rs
@@ -83,7 +83,7 @@ where
         }
     }
 }
-#[repr(C, packed)]
+#[repr(C)]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct Foo {
     pub _bitfield_align_1: [u8; 0],
diff --git a/bindgen-tests/tests/expectations/tests/bitfield_align.rs b/bindgen-tests/tests/expectations/tests/bitfield_align.rs
index 559038ed..80023279 100644
--- a/bindgen-tests/tests/expectations/tests/bitfield_align.rs
+++ b/bindgen-tests/tests/expectations/tests/bitfield_align.rs
@@ -332,7 +332,6 @@ impl A {
     }
 }
 #[repr(C)]
-#[repr(align(4))]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct B {
     pub _bitfield_align_1: [u32; 0],
diff --git a/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs b/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs
index dc49137e..963d86f9 100644
--- a/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs
+++ b/bindgen-tests/tests/expectations/tests/bitfield_align_2.rs
@@ -93,7 +93,6 @@ pub enum MyEnum {
     FOUR = 3,
 }
 #[repr(C)]
-#[repr(align(8))]
 #[derive(Debug, Copy, Clone)]
 pub struct TaggedPtr {
     pub _bitfield_align_1: [u64; 0],
diff --git a/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs b/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs
index ea1502eb..7104682e 100644
--- a/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs
+++ b/bindgen-tests/tests/expectations/tests/bitfield_method_mangling.rs
@@ -84,7 +84,6 @@ where
     }
 }
 #[repr(C)]
-#[repr(align(4))]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct mach_msg_type_descriptor_t {
     pub _bitfield_align_1: [u32; 0],
diff --git a/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs b/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs
index c37b42f2..e3168f51 100644
--- a/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs
+++ b/bindgen-tests/tests/expectations/tests/bitfield_pragma_packed.rs
@@ -83,7 +83,7 @@ where
         }
     }
 }
-#[repr(C, packed)]
+#[repr(C)]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct Struct {
     pub _bitfield_align_1: [u8; 0],
@@ -215,3 +215,97 @@ impl Struct {
         __bindgen_bitfield_unit
     }
 }
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct Inner {
+    pub _bitfield_align_1: [u16; 0],
+    pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>,
+}
+#[test]
+fn bindgen_test_layout_Inner() {
+    assert_eq!(
+        ::std::mem::size_of::<Inner>(),
+        4usize,
+        concat!("Size of: ", stringify!(Inner)),
+    );
+    assert_eq!(
+        ::std::mem::align_of::<Inner>(),
+        2usize,
+        concat!("Alignment of ", stringify!(Inner)),
+    );
+}
+impl Inner {
+    #[inline]
+    pub fn a(&self) -> ::std::os::raw::c_ushort {
+        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 16u8) as u16) }
+    }
+    #[inline]
+    pub fn set_a(&mut self, val: ::std::os::raw::c_ushort) {
+        unsafe {
+            let val: u16 = ::std::mem::transmute(val);
+            self._bitfield_1.set(0usize, 16u8, val as u64)
+        }
+    }
+    #[inline]
+    pub fn b(&self) -> ::std::os::raw::c_ushort {
+        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 16u8) as u16) }
+    }
+    #[inline]
+    pub fn set_b(&mut self, val: ::std::os::raw::c_ushort) {
+        unsafe {
+            let val: u16 = ::std::mem::transmute(val);
+            self._bitfield_1.set(16usize, 16u8, val as u64)
+        }
+    }
+    #[inline]
+    pub fn new_bitfield_1(
+        a: ::std::os::raw::c_ushort,
+        b: ::std::os::raw::c_ushort,
+    ) -> __BindgenBitfieldUnit<[u8; 4usize]> {
+        let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default();
+        __bindgen_bitfield_unit
+            .set(
+                0usize,
+                16u8,
+                {
+                    let a: u16 = unsafe { ::std::mem::transmute(a) };
+                    a as u64
+                },
+            );
+        __bindgen_bitfield_unit
+            .set(
+                16usize,
+                16u8,
+                {
+                    let b: u16 = unsafe { ::std::mem::transmute(b) };
+                    b as u64
+                },
+            );
+        __bindgen_bitfield_unit
+    }
+}
+#[repr(C, packed)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct Outer {
+    pub inner: Inner,
+}
+#[test]
+fn bindgen_test_layout_Outer() {
+    const UNINIT: ::std::mem::MaybeUninit<Outer> = ::std::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::std::mem::size_of::<Outer>(),
+        4usize,
+        concat!("Size of: ", stringify!(Outer)),
+    );
+    assert_eq!(
+        ::std::mem::align_of::<Outer>(),
+        1usize,
+        concat!("Alignment of ", stringify!(Outer)),
+    );
+    assert_eq!(
+        unsafe { ::std::ptr::addr_of!((*ptr).inner) as usize - ptr as usize },
+        0usize,
+        concat!("Offset of field: ", stringify!(Outer), "::", stringify!(inner)),
+    );
+}
diff --git a/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs b/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs
index f75a06e9..aef1a61a 100644
--- a/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs
+++ b/bindgen-tests/tests/expectations/tests/default_visibility_crate.rs
@@ -89,7 +89,7 @@ pub struct Point {
     pub(crate) x: ::std::os::raw::c_int,
     pub(crate) y: ::std::os::raw::c_int,
 }
-#[repr(C, packed)]
+#[repr(C)]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct Color {
     pub(crate) _bitfield_align_1: [u8; 0],
diff --git a/bindgen-tests/tests/expectations/tests/default_visibility_private.rs b/bindgen-tests/tests/expectations/tests/default_visibility_private.rs
index 9bd6409f..8b3099c0 100644
--- a/bindgen-tests/tests/expectations/tests/default_visibility_private.rs
+++ b/bindgen-tests/tests/expectations/tests/default_visibility_private.rs
@@ -89,7 +89,7 @@ pub struct Point {
     x: ::std::os::raw::c_int,
     y: ::std::os::raw::c_int,
 }
-#[repr(C, packed)]
+#[repr(C)]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct Color {
     _bitfield_align_1: [u8; 0],
diff --git a/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs b/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs
index a8b0d297..29fbb3a8 100644
--- a/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs
+++ b/bindgen-tests/tests/expectations/tests/default_visibility_private_respects_cxx_access_spec.rs
@@ -89,7 +89,7 @@ pub struct Point {
     pub x: ::std::os::raw::c_int,
     pub y: ::std::os::raw::c_int,
 }
-#[repr(C, packed)]
+#[repr(C)]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct Color {
     _bitfield_align_1: [u8; 0],
diff --git a/bindgen-tests/tests/expectations/tests/float16.rs b/bindgen-tests/tests/expectations/tests/float16.rs
new file mode 100644
index 00000000..b5471b1e
--- /dev/null
+++ b/bindgen-tests/tests/expectations/tests/float16.rs
@@ -0,0 +1,66 @@
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+#[derive(PartialEq, Copy, Clone, Hash, Debug, Default)]
+#[repr(transparent)]
+pub struct __BindgenFloat16(pub u16);
+extern "C" {
+    pub static mut global: __BindgenFloat16;
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone, PartialEq)]
+pub struct Test__Float16 {
+    pub f: __BindgenFloat16,
+}
+#[test]
+fn bindgen_test_layout_Test__Float16() {
+    const UNINIT: ::std::mem::MaybeUninit<Test__Float16> = ::std::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::std::mem::size_of::<Test__Float16>(),
+        2usize,
+        concat!("Size of: ", stringify!(Test__Float16)),
+    );
+    assert_eq!(
+        ::std::mem::align_of::<Test__Float16>(),
+        2usize,
+        concat!("Alignment of ", stringify!(Test__Float16)),
+    );
+    assert_eq!(
+        unsafe { ::std::ptr::addr_of!((*ptr).f) as usize - ptr as usize },
+        0usize,
+        concat!("Offset of field: ", stringify!(Test__Float16), "::", stringify!(f)),
+    );
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+pub struct Test__Float16Ref {
+    pub f: *mut __BindgenFloat16,
+}
+#[test]
+fn bindgen_test_layout_Test__Float16Ref() {
+    const UNINIT: ::std::mem::MaybeUninit<Test__Float16Ref> = ::std::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::std::mem::size_of::<Test__Float16Ref>(),
+        8usize,
+        concat!("Size of: ", stringify!(Test__Float16Ref)),
+    );
+    assert_eq!(
+        ::std::mem::align_of::<Test__Float16Ref>(),
+        8usize,
+        concat!("Alignment of ", stringify!(Test__Float16Ref)),
+    );
+    assert_eq!(
+        unsafe { ::std::ptr::addr_of!((*ptr).f) as usize - ptr as usize },
+        0usize,
+        concat!("Offset of field: ", stringify!(Test__Float16Ref), "::", stringify!(f)),
+    );
+}
+impl Default for Test__Float16Ref {
+    fn default() -> Self {
+        let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
+        unsafe {
+            ::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
+            s.assume_init()
+        }
+    }
+}
diff --git a/bindgen-tests/tests/expectations/tests/issue-1034.rs b/bindgen-tests/tests/expectations/tests/issue-1034.rs
index 0bd7647a..7848090f 100644
--- a/bindgen-tests/tests/expectations/tests/issue-1034.rs
+++ b/bindgen-tests/tests/expectations/tests/issue-1034.rs
@@ -83,7 +83,7 @@ where
         }
     }
 }
-#[repr(C, packed)]
+#[repr(C)]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct S2 {
     pub _bitfield_align_1: [u8; 0],
diff --git a/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs b/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs
index d8880695..89c09cc6 100644
--- a/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs
+++ b/bindgen-tests/tests/expectations/tests/issue-1076-unnamed-bitfield-alignment.rs
@@ -83,7 +83,7 @@ where
         }
     }
 }
-#[repr(C, packed)]
+#[repr(C)]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct S1 {
     pub _bitfield_align_1: [u8; 0],
diff --git a/bindgen-tests/tests/expectations/tests/issue-1947.rs b/bindgen-tests/tests/expectations/tests/issue-1947.rs
index 24aa3548..be623357 100644
--- a/bindgen-tests/tests/expectations/tests/issue-1947.rs
+++ b/bindgen-tests/tests/expectations/tests/issue-1947.rs
@@ -86,7 +86,6 @@ where
 pub type U8 = ::std::os::raw::c_uchar;
 pub type U16 = ::std::os::raw::c_ushort;
 #[repr(C)]
-#[repr(align(2))]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct V56AMDY {
     pub _bitfield_align_1: [u16; 0],
diff --git a/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs b/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs
index adea1cbe..7bc99336 100644
--- a/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs
+++ b/bindgen-tests/tests/expectations/tests/issue-739-pointer-wide-bitfield.rs
@@ -85,7 +85,6 @@ where
     }
 }
 #[repr(C)]
-#[repr(align(8))]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct Foo {
     pub _bitfield_align_1: [u64; 0],
diff --git a/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs b/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs
index 735cebfb..576f5758 100644
--- a/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs
+++ b/bindgen-tests/tests/expectations/tests/jsval_layout_opaque.rs
@@ -181,7 +181,6 @@ pub union jsval_layout {
     pub asUIntPtr: usize,
 }
 #[repr(C)]
-#[repr(align(8))]
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct jsval_layout__bindgen_ty_1 {
     pub _bitfield_align_1: [u64; 0],
diff --git a/bindgen-tests/tests/expectations/tests/jsval_layout_opaque_1_0.rs b/bindgen-tests/tests/expectations/tests/jsval_layout_opaque_1_0.rs
index 2e64796b..0889b652 100644
--- a/bindgen-tests/tests/expectations/tests/jsval_layout_opaque_1_0.rs
+++ b/bindgen-tests/tests/expectations/tests/jsval_layout_opaque_1_0.rs
@@ -229,7 +229,6 @@ pub struct jsval_layout {
 pub struct jsval_layout__bindgen_ty_1 {
     pub _bitfield_align_1: [u64; 0],
     pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>,
-    pub __bindgen_align: [u64; 0usize],
 }
 #[test]
 fn bindgen_test_layout_jsval_layout__bindgen_ty_1() {
diff --git a/bindgen-tests/tests/expectations/tests/only_bitfields.rs b/bindgen-tests/tests/expectations/tests/only_bitfields.rs
index 42ea60f1..fe216f4b 100644
--- a/bindgen-tests/tests/expectations/tests/only_bitfields.rs
+++ b/bindgen-tests/tests/expectations/tests/only_bitfields.rs
@@ -83,7 +83,7 @@ where
         }
     }
 }
-#[repr(C, packed)]
+#[repr(C)]
 #[derive(Debug, Default, Copy, Clone)]
 pub struct C {
     pub _bitfield_align_1: [u8; 0],
diff --git a/bindgen-tests/tests/expectations/tests/union_bitfield.rs b/bindgen-tests/tests/expectations/tests/union_bitfield.rs
index 096c0371..7f4bd37f 100644
--- a/bindgen-tests/tests/expectations/tests/union_bitfield.rs
+++ b/bindgen-tests/tests/expectations/tests/union_bitfield.rs
@@ -142,7 +142,6 @@ impl U4 {
     }
 }
 #[repr(C)]
-#[repr(align(4))]
 #[derive(Copy, Clone)]
 pub union B {
     pub _bitfield_align_1: [u32; 0],
diff --git a/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs b/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs
index 2f990271..48a1bda9 100644
--- a/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs
+++ b/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield.rs
@@ -90,7 +90,6 @@ pub union foo {
     pub __bindgen_anon_1: foo__bindgen_ty_1,
 }
 #[repr(C)]
-#[repr(align(4))]
 #[derive(Debug, Default, Copy, Clone, Hash, PartialEq, Eq)]
 pub struct foo__bindgen_ty_1 {
     pub _bitfield_align_1: [u32; 0],
diff --git a/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield_1_0.rs b/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield_1_0.rs
index dec7fc29..530cb7ea 100644
--- a/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield_1_0.rs
+++ b/bindgen-tests/tests/expectations/tests/union_with_anon_struct_bitfield_1_0.rs
@@ -138,7 +138,6 @@ pub struct foo {
 pub struct foo__bindgen_ty_1 {
     pub _bitfield_align_1: [u32; 0],
     pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>,
-    pub __bindgen_align: [u32; 0usize],
 }
 #[test]
 fn bindgen_test_layout_foo__bindgen_ty_1() {
diff --git a/bindgen-tests/tests/expectations/tests/win32-dtors.rs b/bindgen-tests/tests/expectations/tests/win32-dtors.rs
new file mode 100644
index 00000000..8739ef4b
--- /dev/null
+++ b/bindgen-tests/tests/expectations/tests/win32-dtors.rs
@@ -0,0 +1,201 @@
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+#[repr(C)]
+#[derive(Debug, Default)]
+pub struct CppObj {
+    pub x: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_CppObj() {
+    const UNINIT: ::std::mem::MaybeUninit<CppObj> = ::std::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::std::mem::size_of::<CppObj>(),
+        4usize,
+        concat!("Size of: ", stringify!(CppObj)),
+    );
+    assert_eq!(
+        ::std::mem::align_of::<CppObj>(),
+        4usize,
+        concat!("Alignment of ", stringify!(CppObj)),
+    );
+    assert_eq!(
+        unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize },
+        0usize,
+        concat!("Offset of field: ", stringify!(CppObj), "::", stringify!(x)),
+    );
+}
+extern "C" {
+    #[link_name = "\u{1}??0CppObj@@QEAA@H@Z"]
+    pub fn CppObj_CppObj(this: *mut CppObj, x: ::std::os::raw::c_int);
+}
+extern "C" {
+    #[link_name = "\u{1}??1CppObj@@QEAA@XZ"]
+    pub fn CppObj_CppObj_destructor(this: *mut CppObj);
+}
+impl CppObj {
+    #[inline]
+    pub unsafe fn new(x: ::std::os::raw::c_int) -> Self {
+        let mut __bindgen_tmp = ::std::mem::uninitialized();
+        CppObj_CppObj(&mut __bindgen_tmp, x);
+        __bindgen_tmp
+    }
+    #[inline]
+    pub unsafe fn destruct(&mut self) {
+        CppObj_CppObj_destructor(self)
+    }
+}
+#[repr(C)]
+pub struct CppObj2__bindgen_vtable(::std::os::raw::c_void);
+#[repr(C)]
+#[derive(Debug)]
+pub struct CppObj2 {
+    pub vtable_: *const CppObj2__bindgen_vtable,
+    pub x: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_CppObj2() {
+    const UNINIT: ::std::mem::MaybeUninit<CppObj2> = ::std::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::std::mem::size_of::<CppObj2>(),
+        16usize,
+        concat!("Size of: ", stringify!(CppObj2)),
+    );
+    assert_eq!(
+        ::std::mem::align_of::<CppObj2>(),
+        8usize,
+        concat!("Alignment of ", stringify!(CppObj2)),
+    );
+    assert_eq!(
+        unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize },
+        8usize,
+        concat!("Offset of field: ", stringify!(CppObj2), "::", stringify!(x)),
+    );
+}
+extern "C" {
+    #[link_name = "\u{1}??0CppObj2@@QEAA@H@Z"]
+    pub fn CppObj2_CppObj2(this: *mut CppObj2, x: ::std::os::raw::c_int);
+}
+impl Default for CppObj2 {
+    fn default() -> Self {
+        unsafe {
+            let mut s: Self = ::std::mem::uninitialized();
+            ::std::ptr::write_bytes(&mut s, 0, 1);
+            s
+        }
+    }
+}
+impl CppObj2 {
+    #[inline]
+    pub unsafe fn new(x: ::std::os::raw::c_int) -> Self {
+        let mut __bindgen_tmp = ::std::mem::uninitialized();
+        CppObj2_CppObj2(&mut __bindgen_tmp, x);
+        __bindgen_tmp
+    }
+}
+extern "C" {
+    #[link_name = "\u{1}??1CppObj2@@UEAA@XZ"]
+    pub fn CppObj2_CppObj2_destructor(this: *mut CppObj2);
+}
+#[repr(C)]
+#[derive(Debug)]
+pub struct CppObj3 {
+    pub _base: CppObj2,
+    pub x: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_CppObj3() {
+    const UNINIT: ::std::mem::MaybeUninit<CppObj3> = ::std::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::std::mem::size_of::<CppObj3>(),
+        24usize,
+        concat!("Size of: ", stringify!(CppObj3)),
+    );
+    assert_eq!(
+        ::std::mem::align_of::<CppObj3>(),
+        8usize,
+        concat!("Alignment of ", stringify!(CppObj3)),
+    );
+    assert_eq!(
+        unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize },
+        16usize,
+        concat!("Offset of field: ", stringify!(CppObj3), "::", stringify!(x)),
+    );
+}
+extern "C" {
+    #[link_name = "\u{1}??0CppObj3@@QEAA@H@Z"]
+    pub fn CppObj3_CppObj3(this: *mut CppObj3, x: ::std::os::raw::c_int);
+}
+impl Default for CppObj3 {
+    fn default() -> Self {
+        unsafe {
+            let mut s: Self = ::std::mem::uninitialized();
+            ::std::ptr::write_bytes(&mut s, 0, 1);
+            s
+        }
+    }
+}
+impl CppObj3 {
+    #[inline]
+    pub unsafe fn new(x: ::std::os::raw::c_int) -> Self {
+        let mut __bindgen_tmp = ::std::mem::uninitialized();
+        CppObj3_CppObj3(&mut __bindgen_tmp, x);
+        __bindgen_tmp
+    }
+}
+extern "C" {
+    #[link_name = "\u{1}??1CppObj3@@UEAA@XZ"]
+    pub fn CppObj3_CppObj3_destructor(this: *mut CppObj3);
+}
+#[repr(C)]
+#[derive(Debug)]
+pub struct CppObj4 {
+    pub _base: CppObj2,
+    pub x: ::std::os::raw::c_int,
+}
+#[test]
+fn bindgen_test_layout_CppObj4() {
+    const UNINIT: ::std::mem::MaybeUninit<CppObj4> = ::std::mem::MaybeUninit::uninit();
+    let ptr = UNINIT.as_ptr();
+    assert_eq!(
+        ::std::mem::size_of::<CppObj4>(),
+        24usize,
+        concat!("Size of: ", stringify!(CppObj4)),
+    );
+    assert_eq!(
+        ::std::mem::align_of::<CppObj4>(),
+        8usize,
+        concat!("Alignment of ", stringify!(CppObj4)),
+    );
+    assert_eq!(
+        unsafe { ::std::ptr::addr_of!((*ptr).x) as usize - ptr as usize },
+        16usize,
+        concat!("Offset of field: ", stringify!(CppObj4), "::", stringify!(x)),
+    );
+}
+extern "C" {
+    #[link_name = "\u{1}??0CppObj4@@QEAA@H@Z"]
+    pub fn CppObj4_CppObj4(this: *mut CppObj4, x: ::std::os::raw::c_int);
+}
+impl Default for CppObj4 {
+    fn default() -> Self {
+        unsafe {
+            let mut s: Self = ::std::mem::uninitialized();
+            ::std::ptr::write_bytes(&mut s, 0, 1);
+            s
+        }
+    }
+}
+impl CppObj4 {
+    #[inline]
+    pub unsafe fn new(x: ::std::os::raw::c_int) -> Self {
+        let mut __bindgen_tmp = ::std::mem::uninitialized();
+        CppObj4_CppObj4(&mut __bindgen_tmp, x);
+        __bindgen_tmp
+    }
+}
+extern "C" {
+    #[link_name = "\u{1}??1CppObj4@@UEAA@XZ"]
+    pub fn CppObj4_CppObj4_destructor(this: *mut CppObj4);
+}
diff --git a/bindgen-tests/tests/headers/bitfield_pragma_packed.h b/bindgen-tests/tests/headers/bitfield_pragma_packed.h
index b4011ca8..c18b80dd 100644
--- a/bindgen-tests/tests/headers/bitfield_pragma_packed.h
+++ b/bindgen-tests/tests/headers/bitfield_pragma_packed.h
@@ -7,3 +7,14 @@ struct Struct {
     unsigned char e : 8;
 };
 #pragma pack(pop)
+
+struct Inner {
+    unsigned short a: 16;
+    unsigned short b: 16;
+};
+
+#pragma pack(push, 1)
+struct Outer {
+    struct Inner inner;
+};
+#pragma pop
diff --git a/bindgen-tests/tests/headers/float16.h b/bindgen-tests/tests/headers/float16.h
new file mode 100644
index 00000000..3b105859
--- /dev/null
+++ b/bindgen-tests/tests/headers/float16.h
@@ -0,0 +1,36 @@
+// bindgen-flags: --with-derive-hash --with-derive-partialeq --with-derive-eq
+
+static __fp16 global;
+
+struct Test__Float16
+{
+    __fp16 f;
+};
+
+struct Test__Float16Ref
+{
+    __fp16 *f;
+};
+
+/*
+// This options are currently supported only on specific targets (eg. x86 with sse2)
+_Float16 returns_f16();
+
+void gets_f16(_Float16 arg);
+
+struct Test__Float16_Complex
+{
+    _Float16 _Complex mMember;
+};
+
+struct Test__Float16_ComplexPtr
+{
+    _Float16 _Complex *mMember;
+};
+
+_Float16 _Complex globalValueHalf;
+
+_Float16 _Complex returns_f16_complex();
+
+void gets_f16_complex(_Float16 _Complex arg);
+*/
\ No newline at end of file
diff --git a/bindgen-tests/tests/headers/win32-dtors.hpp b/bindgen-tests/tests/headers/win32-dtors.hpp
new file mode 100644
index 00000000..dc9b0fdc
--- /dev/null
+++ b/bindgen-tests/tests/headers/win32-dtors.hpp
@@ -0,0 +1,29 @@
+// bindgen-flags: --rust-target 1.0 -- --target=x86_64-pc-windows-msvc
+
+struct CppObj {
+    int x;
+
+    CppObj(int x);
+    ~CppObj();
+};
+
+struct CppObj2 {
+    int x;
+
+    CppObj2(int x);
+    virtual ~CppObj2();
+};
+
+struct CppObj3 : CppObj2 {
+    int x;
+
+    CppObj3(int x);
+    virtual ~CppObj3();
+};
+
+struct CppObj4 : CppObj2 {
+    int x;
+
+    CppObj4(int x);
+    ~CppObj4();
+};
\ No newline at end of file