Auto merge of #512 - emilio:bitfields, r=fitzgen

Rework how bitfields are handled.

This fixes #111, and unblocks stylo.

The problem with this as of right now is that it drops the accessors (though before that this code was buggy so I'm not sure it's a loss).

I can probably try to re-implement those (though it'd be more complex). WDYT @fitzgen?

Also, note that I changed the max_align_nonce because it was incorrect (we shouldn't generate padding, because `long double` was `128` bits).
diff --git a/Cargo.lock b/Cargo.lock
index 0ae1dc4..089e0f2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,12 +1,12 @@
 [root]
 name = "bindgen"
-version = "0.21.3"
+version = "0.22.0"
 dependencies = [
  "aster 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "clang-sys 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.20.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -21,7 +21,7 @@
 
 [[package]]
 name = "aho-corasick"
-version = "0.6.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -67,20 +67,20 @@
  "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "libloading 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libloading 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "clap"
-version = "2.19.3"
+version = "2.20.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
- "strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "term_size 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term_size 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -92,7 +92,7 @@
 
 [[package]]
 name = "dtoa"
-version = "0.2.2"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -111,7 +111,7 @@
 
 [[package]]
 name = "itoa"
-version = "0.1.1"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -135,12 +135,12 @@
 
 [[package]]
 name = "libloading"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "target_build_utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "target_build_utils 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -234,7 +234,7 @@
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "aho-corasick 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -253,18 +253,18 @@
 
 [[package]]
 name = "serde"
-version = "0.8.23"
+version = "0.9.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_json"
-version = "0.8.6"
+version = "0.9.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -279,7 +279,7 @@
 
 [[package]]
 name = "strsim"
-version = "0.5.2"
+version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -300,7 +300,7 @@
  "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -323,23 +323,23 @@
  "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_pos 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "target_build_utils"
-version = "0.1.2"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "term"
-version = "0.4.4"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -348,7 +348,7 @@
 
 [[package]]
 name = "term_size"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -376,7 +376,7 @@
 
 [[package]]
 name = "unicode-segmentation"
-version = "0.1.3"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -423,23 +423,23 @@
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
-"checksum aho-corasick 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4f660b942762979b56c9f07b4b36bb559776fbad102f05d6771e1b629e8fd5bf"
+"checksum aho-corasick 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0638fd549427caa90c499814196d1b9e3725eb4d15d7339d6de073a680ed0ca2"
 "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
 "checksum aster 0.38.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c9b49e42a449c0b79d8acb91db37621de0978064dca7d3288ddcf030123e5b3"
 "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
 "checksum cexpr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "393a5f0088efbe41f9d1fcd062f24e83c278608420e62109feb2c8abee07de7d"
 "checksum cfg-if 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de1e760d7b6535af4241fca8bd8adf68e2e7edacc6b29f5d399050c5e48cf88c"
 "checksum clang-sys 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f98f0715ff67f27ca6a2f8f0ffc2a56f8edbc7acd57489c29eadc3a15c4eafe"
-"checksum clap 2.19.3 (registry+https://github.com/rust-lang/crates.io-index)" = "95b78f3fe0fc94c13c731714363260e04b557a637166f33a4570d3189d642374"
+"checksum clap 2.20.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a60af5cb867dd4ee2378398acde80c73b466b58a963f598061ce7e394800998d"
 "checksum diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e48977eec6d3b7707462c2dc2e1363ad91b5dd822cf942537ccdc2085dc87587"
-"checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d"
+"checksum dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "80c8b71fd71146990a9742fc06dcbbde19161a267e0ad4e572c35162f4578c90"
 "checksum env_logger 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "99971fb1b635fe7a0ee3c4d065845bb93cca80a23b5613b5613391ece5de4144"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
-"checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1"
+"checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b"
 "checksum libc 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "684f330624d8c3784fb9558ca46c4ce488073a8d22450415c5eb4f4cfb0d11b5"
-"checksum libloading 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "84816a8c6ed8163dfe0dbdd2b09d35c6723270ea77a4c7afa4bedf038a36cb99"
+"checksum libloading 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fd1835a714c1f67ba073a493493c23686a480e2614e208c921834808b1f19d8f"
 "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054"
 "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
 "checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
@@ -454,21 +454,21 @@
 "checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01"
 "checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457"
 "checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b"
-"checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
-"checksum serde_json 0.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "67f7d2e9edc3523a9c8ec8cd6ec481b3a27810aafee3e625d311febd3e656b4c"
+"checksum serde 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1e0ed773960f90a78567fcfbe935284adf50c5d7cf119aa2cf43bb0b4afa69bb"
+"checksum serde_json 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e095e4e94e7382b76f48e93bd845ffddda62df8dfd4c163b1bfa93d40e22e13a"
 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
 "checksum siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ffc669b726f2bc9a3bcff66e5e23b56ba6bf70e22a34c3d7b6d0b3450b65b84"
-"checksum strsim 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "67f84c44fbb2f91db7fef94554e6b2ac05909c9c0b0bc23bb98d3a1aebfe7f7c"
+"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
 "checksum syntex 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb3f52553a966675982404dc34028291b347e0c9a9c0b0b34f2da6be8a0443f8"
 "checksum syntex_errors 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dee2f6e49c075f71332bb775219d5982bee6732d26227fa1ae1b53cdb12f5cc5"
 "checksum syntex_pos 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8df3921c7945dfb9ffc53aa35adb2cf4313b5ab5f079c3619b3d4eb82a0efc2b"
 "checksum syntex_syntax 0.54.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc960085bae44591e22d01f6c0e82a8aec832f8659aca556cdf8ecbdac2bb47b"
-"checksum target_build_utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54c550e226618cd35334b75e92bfa5437c61474bdb75c38bf330ab5a8037b77c"
-"checksum term 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3deff8a2b3b6607d6d7cc32ac25c0b33709453ca9cceac006caac51e963cf94a"
-"checksum term_size 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f7f5f3f71b0040cecc71af239414c23fd3c73570f5ff54cf50e03cef637f2a0"
+"checksum target_build_utils 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f42dc058080c19c6a58bdd1bf962904ee4f5ef1fe2a81b529f31dacc750c679f"
+"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
+"checksum term_size 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "71662702fe5cd2cf95edd4ad655eea42f24a87a0e44059cbaa4e55260b7bc331"
 "checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a"
 "checksum thread_local 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7793b722f0f77ce716e7f1acf416359ca32ff24d04ffbac4269f44a4a83be05d"
-"checksum unicode-segmentation 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c3bc443ded17b11305ffffe6b37e2076f328a5a8cb6aa877b1b98f77699e98b5"
+"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
 "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
diff --git a/Cargo.toml b/Cargo.toml
index c732337..a9521be 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@
 readme = "README.md"
 repository = "https://github.com/servo/rust-bindgen"
 documentation = "https://docs.rs/bindgen"
-version = "0.21.3"
+version = "0.22.0"
 build = "build.rs"
 
 exclude = ["tests/headers", "tests/expectations", "bindgen-integration", "ci"]
diff --git a/build.rs b/build.rs
index c3633cd..4e99c77 100644
--- a/build.rs
+++ b/build.rs
@@ -11,6 +11,7 @@
         quasi_codegen::expand(&src, &dst).unwrap();
         println!("cargo:rerun-if-changed=src/codegen/mod.rs");
         println!("cargo:rerun-if-changed=src/codegen/helpers.rs");
+        println!("cargo:rerun-if-changed=src/codegen/struct_layout.rs");
     }
 }
 
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index ad6736b..77f654e 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -2,7 +2,8 @@
 mod struct_layout;
 
 use self::helpers::{BlobTyBuilder, attributes};
-use self::struct_layout::StructLayoutTracker;
+use self::struct_layout::{align_to, bytes_from_bits};
+use self::struct_layout::{bytes_from_bits_pow2, StructLayoutTracker};
 use aster;
 
 use ir::annotations::FieldAccessorKind;
@@ -363,8 +364,7 @@
             }
 
             if item.id() == ctx.root_module() {
-                let saw_union = result.saw_union;
-                if saw_union && !ctx.options().unstable_rust {
+                if result.saw_union && !ctx.options().unstable_rust {
                     utils::prepend_union_types(ctx, &mut *result);
                 }
                 if result.saw_incomplete_array {
@@ -717,12 +717,12 @@
 }
 
 struct Bitfield<'a> {
-    index: usize,
+    index: &'a mut usize,
     fields: Vec<&'a Field>,
 }
 
 impl<'a> Bitfield<'a> {
-    fn new(index: usize, fields: Vec<&'a Field>) -> Self {
+    fn new(index: &'a mut usize, fields: Vec<&'a Field>) -> Self {
         Bitfield {
             index: index,
             fields: fields,
@@ -732,89 +732,96 @@
     fn codegen_fields(self,
                       ctx: &BindgenContext,
                       fields: &mut Vec<ast::StructField>,
-                      methods: &mut Vec<ast::ImplItem>)
+                      _methods: &mut Vec<ast::ImplItem>)
                       -> Layout {
         use aster::struct_field::StructFieldBuilder;
-        let mut total_width = self.fields
-            .iter()
-            .fold(0u32, |acc, f| acc + f.bitfield().unwrap());
 
-        if !total_width.is_power_of_two() || total_width < 8 {
-            total_width = cmp::max(8, total_width.next_power_of_two());
-        }
-        debug_assert_eq!(total_width % 8, 0);
-        let total_width_in_bytes = total_width as usize / 8;
+        // NOTE: What follows is reverse-engineered from LLVM's
+        // lib/AST/RecordLayoutBuilder.cpp
+        //
+        // FIXME(emilio): There are some differences between Microsoft and the
+        // Itanium ABI, but we'll ignore those and stick to Itanium for now.
+        //
+        // Also, we need to handle packed bitfields and stuff.
+        // TODO(emilio): Take into account C++'s wide bitfields, and
+        // packing, sigh.
+        let mut total_size_in_bits = 0;
+        let mut max_align = 0;
+        let mut unfilled_bits_in_last_unit = 0;
+        let mut field_size_in_bits = 0;
+        *self.index += 1;
+        let mut last_field_name = format!("_bitfield_{}", self.index);
+        let mut last_field_align = 0;
 
-        let bitfield_layout = Layout::new(total_width_in_bytes,
-                                          total_width_in_bytes);
-        let bitfield_type = BlobTyBuilder::new(bitfield_layout).build();
-        let field_name = format!("_bitfield_{}", self.index);
-        let field_ident = ctx.ext_cx().ident_of(&field_name);
-        let field = StructFieldBuilder::named(&field_name)
-            .pub_()
-            .build_ty(bitfield_type.clone());
-        fields.push(field);
-
-
-        let mut offset = 0;
         for field in self.fields {
             let width = field.bitfield().unwrap();
-            let field_name = field.name()
-                .map(ToOwned::to_owned)
-                .unwrap_or_else(|| format!("at_offset_{}", offset));
-
             let field_item = ctx.resolve_item(field.ty());
             let field_ty_layout = field_item.kind()
                 .expect_type()
                 .layout(ctx)
                 .expect("Bitfield without layout? Gah!");
 
-            let field_type = field_item.to_rust_ty(ctx);
-            let int_type = BlobTyBuilder::new(field_ty_layout).build();
+            let field_align = field_ty_layout.align;
 
-            let getter_name = ctx.rust_ident(&field_name);
-            let setter_name = ctx.ext_cx()
-                .ident_of(&format!("set_{}", &field_name));
-            let mask = ((1usize << width) - 1) << offset;
-            let prefix = ctx.trait_prefix();
-            // The transmute is unfortunate, but it's needed for enums in
-            // bitfields.
-            let item = quote_item!(ctx.ext_cx(),
-                impl X {
-                    #[inline]
-                    pub fn $getter_name(&self) -> $field_type {
-                        unsafe {
-                            ::$prefix::mem::transmute(
-                                (
-                                    (self.$field_ident &
-                                        ($mask as $bitfield_type))
-                                     >> $offset
-                                ) as $int_type
-                            )
-                        }
-                    }
+            if field_size_in_bits != 0 &&
+                (width == 0 || width as usize > unfilled_bits_in_last_unit) {
+                field_size_in_bits = align_to(field_size_in_bits, field_align);
+                // Push the new field.
+                let ty =
+                    BlobTyBuilder::new(Layout::new(bytes_from_bits_pow2(field_size_in_bits),
+                                                   bytes_from_bits_pow2(last_field_align)))
+                        .build();
 
-                    #[inline]
-                    pub fn $setter_name(&mut self, val: $field_type) {
-                        self.$field_ident &= !($mask as $bitfield_type);
-                        self.$field_ident |=
-                            (val as $int_type as $bitfield_type << $offset) &
-                                ($mask as $bitfield_type);
-                    }
-                }
-            )
-                .unwrap();
+                let field = StructFieldBuilder::named(&last_field_name)
+                    .pub_()
+                    .build_ty(ty);
+                fields.push(field);
 
-            let items = match item.unwrap().node {
-                ast::ItemKind::Impl(_, _, _, _, _, items) => items,
-                _ => unreachable!(),
-            };
+                // TODO(emilio): dedup this.
+                *self.index += 1;
+                last_field_name = format!("_bitfield_{}", self.index);
 
-            methods.extend(items.into_iter());
-            offset += width;
+                // Now reset the size and the rest of stuff.
+                // unfilled_bits_in_last_unit = 0;
+                field_size_in_bits = 0;
+                last_field_align = 0;
+            }
+
+            // TODO(emilio): Create the accessors. Problem here is that we still
+            // don't know which one is going to be the final alignment of the
+            // bitfield, and whether we have to index in it. Thus, we don't know
+            // which integer type do we need.
+            //
+            // We could push them to a Vec or something, but given how buggy
+            // they where maybe it's not a great idea?
+            field_size_in_bits += width as usize;
+            total_size_in_bits += width as usize;
+
+
+            let data_size = align_to(field_size_in_bits, field_align * 8);
+
+            max_align = cmp::max(max_align, field_align);
+
+            // NB: The width here is completely, absolutely intentional.
+            last_field_align = cmp::max(last_field_align, width as usize);
+
+            unfilled_bits_in_last_unit = data_size - field_size_in_bits;
         }
 
-        bitfield_layout
+        if field_size_in_bits != 0 {
+            // Push the last field.
+            let ty =
+                BlobTyBuilder::new(Layout::new(bytes_from_bits_pow2(field_size_in_bits),
+                                               bytes_from_bits_pow2(last_field_align)))
+                    .build();
+
+            let field = StructFieldBuilder::named(&last_field_name)
+                .pub_()
+                .build_ty(ty);
+            fields.push(field);
+        }
+
+        Layout::new(bytes_from_bits(total_size_in_bits), max_align)
     }
 }
 
@@ -1062,12 +1069,10 @@
                 debug_assert!(!current_bitfield_fields.is_empty());
                 let bitfield_fields =
                     mem::replace(&mut current_bitfield_fields, vec![]);
-                bitfield_count += 1;
-                let bitfield_layout = Bitfield::new(bitfield_count,
+                let bitfield_layout = Bitfield::new(&mut bitfield_count,
                                                     bitfield_fields)
                     .codegen_fields(ctx, &mut fields, &mut methods);
-
-                struct_layout.saw_bitfield(bitfield_layout);
+                struct_layout.saw_bitfield_batch(bitfield_layout);
 
                 current_bitfield_width = None;
                 current_bitfield_layout = None;
@@ -1099,8 +1104,7 @@
                 } else {
                     quote_ty!(ctx.ext_cx(), __BindgenUnionField<$ty>)
                 }
-            } else if let Some(item) =
-                field_ty.is_incomplete_array(ctx) {
+            } else if let Some(item) = field_ty.is_incomplete_array(ctx) {
                 result.saw_incomplete_array();
 
                 let inner = item.to_rust_ty(ctx);
@@ -1224,12 +1228,10 @@
             debug_assert!(!current_bitfield_fields.is_empty());
             let bitfield_fields = mem::replace(&mut current_bitfield_fields,
                                                vec![]);
-            bitfield_count += 1;
-            let bitfield_layout = Bitfield::new(bitfield_count,
+            let bitfield_layout = Bitfield::new(&mut bitfield_count,
                                                 bitfield_fields)
                 .codegen_fields(ctx, &mut fields, &mut methods);
-
-            struct_layout.saw_bitfield(bitfield_layout);
+            struct_layout.saw_bitfield_batch(bitfield_layout);
         }
         debug_assert!(current_bitfield_fields.is_empty());
 
@@ -1268,7 +1270,7 @@
             }
         } else if !is_union && !self.is_unsized(ctx) {
             if let Some(padding_field) =
-                layout.and_then(|layout| struct_layout.pad_struct(layout)) {
+                layout.and_then(|layout| struct_layout.pad_struct(&canonical_name, layout)) {
                 fields.push(padding_field);
             }
 
@@ -2174,8 +2176,8 @@
                 quote_ty!(ctx.ext_cx(), ::$prefix::option::Option<$ty>)
             }
             TypeKind::Array(item, len) => {
-                let inner = item.to_rust_ty(ctx);
-                aster::ty::TyBuilder::new().array(len).build(inner)
+                let ty = item.to_rust_ty(ctx);
+                aster::ty::TyBuilder::new().array(len).build(ty)
             }
             TypeKind::Enum(..) => {
                 let path = item.namespace_aware_canonical_path(ctx);
@@ -2190,7 +2192,7 @@
                         .map(|arg| arg.to_rust_ty(ctx))
                         .collect::<Vec<_>>();
 
-                    path.segments.last_mut().unwrap().parameters = if 
+                    path.segments.last_mut().unwrap().parameters = if
                         template_args.is_empty() {
                         None
                     } else {
diff --git a/src/codegen/struct_layout.rs b/src/codegen/struct_layout.rs
index f8a88bc..24938c1 100644
--- a/src/codegen/struct_layout.rs
+++ b/src/codegen/struct_layout.rs
@@ -7,7 +7,7 @@
 use ir::comp::CompInfo;
 use ir::context::BindgenContext;
 use ir::layout::Layout;
-use ir::ty::Type;
+use ir::ty::{Type, TypeKind};
 use std::cmp;
 use std::mem;
 
@@ -21,6 +21,84 @@
     padding_count: usize,
     latest_field_layout: Option<Layout>,
     max_field_align: usize,
+    last_field_was_bitfield: bool,
+}
+
+/// Returns a size aligned to a given value.
+pub fn align_to(size: usize, align: usize) -> usize {
+    if align == 0 {
+        return size;
+    }
+
+    let rem = size % align;
+    if rem == 0 {
+        return size;
+    }
+
+    size + align - rem
+}
+
+/// Returns the amount of bytes from a given amount of bytes, rounding up.
+pub fn bytes_from_bits(n: usize) -> usize {
+    if n % 8 == 0 {
+        return n / 8;
+    }
+
+    n / 8 + 1
+}
+
+/// Returns the lower power of two byte count that can hold at most n bits.
+pub fn bytes_from_bits_pow2(mut n: usize) -> usize {
+    if n == 0 {
+        return 0;
+    }
+
+    if n <= 8 {
+        return 1;
+    }
+
+    if !n.is_power_of_two() {
+        n = n.next_power_of_two();
+    }
+
+    n / 8
+}
+
+#[test]
+fn test_align_to() {
+    assert_eq!(align_to(1, 1), 1);
+    assert_eq!(align_to(1, 2), 2);
+    assert_eq!(align_to(1, 4), 4);
+    assert_eq!(align_to(5, 1), 5);
+    assert_eq!(align_to(17, 4), 20);
+}
+
+#[test]
+fn test_bytes_from_bits_pow2() {
+    assert_eq!(bytes_from_bits_pow2(0), 0);
+    for i in 1..9 {
+        assert_eq!(bytes_from_bits_pow2(i), 1);
+    }
+    for i in 9..17 {
+        assert_eq!(bytes_from_bits_pow2(i), 2);
+    }
+    for i in 17..33 {
+        assert_eq!(bytes_from_bits_pow2(i), 4);
+    }
+}
+
+#[test]
+fn test_bytes_from_bits() {
+    assert_eq!(bytes_from_bits(0), 0);
+    for i in 1..9 {
+        assert_eq!(bytes_from_bits(i), 1);
+    }
+    for i in 9..17 {
+        assert_eq!(bytes_from_bits(i), 2);
+    }
+    for i in 17..25 {
+        assert_eq!(bytes_from_bits(i), 3);
+    }
 }
 
 impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
@@ -32,6 +110,7 @@
             padding_count: 0,
             latest_field_layout: None,
             max_field_align: 0,
+            last_field_was_bitfield: false,
         }
     }
 
@@ -43,112 +122,149 @@
     }
 
     pub fn saw_base(&mut self, base_ty: &Type) {
-        self.align_to_latest_field();
-
         if let Some(layout) = base_ty.layout(self.ctx) {
+            self.align_to_latest_field(layout);
+
             self.latest_offset += self.padding_bytes(layout) + layout.size;
             self.latest_field_layout = Some(layout);
             self.max_field_align = cmp::max(self.max_field_align, layout.align);
         }
     }
 
-    pub fn saw_bitfield(&mut self, layout: Layout) {
-        self.align_to_latest_field();
+    pub fn saw_bitfield_batch(&mut self, layout: Layout) {
+        self.align_to_latest_field(layout);
 
-        self.latest_offset += self.padding_bytes(layout) + layout.size;
+        self.latest_offset += layout.size;
+
+        debug!("Offset: <bitfield>: {} -> {}",
+               self.latest_offset - layout.size,
+               self.latest_offset);
+
         self.latest_field_layout = Some(layout);
-        self.max_field_align = cmp::max(self.max_field_align, layout.align);
+        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.
     }
 
     pub fn saw_union(&mut self, layout: Layout) {
-        self.align_to_latest_field();
+        self.align_to_latest_field(layout);
 
         self.latest_offset += self.padding_bytes(layout) + layout.size;
         self.latest_field_layout = Some(layout);
         self.max_field_align = cmp::max(self.max_field_align, layout.align);
     }
 
+    /// Add a padding field if necessary for a given new field _before_ adding
+    /// that field.
     pub fn pad_field(&mut self,
                      field_name: &str,
                      field_ty: &Type,
                      field_offset: Option<usize>)
                      -> Option<ast::StructField> {
-        field_ty.layout(self.ctx).and_then(|field_layout| {
-            self.align_to_latest_field();
+        let mut field_layout = match field_ty.layout(self.ctx) {
+            Some(l) => l,
+            None => return None,
+        };
 
-            let padding_layout = if self.comp.packed() {
-                None
-            } else {
-                let calculated_layout = field_ty.as_comp()
-                    .and_then(|comp| comp.calc_layout(self.ctx))
-                    .unwrap_or(field_layout);
-
-                let align = cmp::min(calculated_layout.align, mem::size_of::<*mut ()>());
-
-                let (padding_bytes, need_padding) = match field_offset {
-                    Some(offset) if offset / 8  > self.latest_offset => {
-                        (offset / 8  - self.latest_offset, true)
-                    }
-                    _ if field_layout.align != 0 => {
-                        (self.padding_bytes(field_layout), (self.latest_offset % field_layout.align) != 0)
-                    }
-                    _ => {
-                        (0, false)
-                    }
-                };
-
-                self.latest_offset += padding_bytes;
-
-                debug!("align field {} to {}/{} with {} padding bytes {:?}, calculated {:?}",
-                    field_name,
-                    self.latest_offset,
-                    field_offset.unwrap_or(0) / 8,
-                    padding_bytes,
-                    field_layout,
-                    calculated_layout);
-
-                if need_padding &&
-                   (padding_bytes > calculated_layout.align ||
-                    field_layout.align > mem::size_of::<*mut ()>()) {
-                    Some(Layout::new(padding_bytes, align))
-                } else {
-                    None
+        if let TypeKind::Array(inner, len) = *field_ty.canonical_type(self.ctx).kind() {
+            // FIXME(emilio): As an _ultra_ hack, we correct the layout returned
+            // by arrays of structs that have a bigger alignment than what we
+            // can support.
+            //
+            // This means that the structs in the array are super-unsafe to
+            // access, since they won't be properly aligned, but *shrug*.
+            if let Some(layout) = self.ctx.resolve_type(inner).layout(self.ctx) {
+                if layout.align > mem::size_of::<*mut ()>() {
+                    field_layout.size =
+                        align_to(layout.size, layout.align) * len;
+                    field_layout.align = mem::size_of::<*mut ()>();
                 }
-            };
+            }
+        }
 
-            self.latest_offset += field_ty.calc_size(self.ctx).unwrap_or(field_layout.size);
+        let will_merge_with_bitfield = self.align_to_latest_field(field_layout);
 
-            self.latest_field_layout = Some(field_layout);
-            self.max_field_align = cmp::max(self.max_field_align, field_layout.align);
-
-            padding_layout.map(|layout| self.padding_field(layout))
-        })
-    }
-
-    pub fn pad_struct(&mut self, layout: Layout) -> Option<ast::StructField> {
-        if layout.size < self.latest_offset {
-            warn!("calculate struct layout incorrect, too more {} bytes",
-                  self.latest_offset - layout.size);
-
+        let padding_layout = if self.comp.packed() {
             None
         } else {
-            let padding_bytes = layout.size - self.latest_offset;
-            let struct_align = cmp::min(layout.align,
-                                        mem::size_of::<*mut ()>());
+            let padding_bytes = match field_offset {
+                Some(offset) if offset / 8 > self.latest_offset => {
+                    offset / 8 - self.latest_offset
+                }
+                _ if will_merge_with_bitfield || field_layout.align == 0 => 0,
+                _ => self.padding_bytes(field_layout),
+            };
 
-            if padding_bytes > struct_align ||
-               (layout.align > mem::size_of::<*mut ()>() && padding_bytes > 0) {
-                let padding_align = if self.comp.packed() {
-                    1
-                } else {
-                    cmp::min(1 << padding_bytes.trailing_zeros(),
-                             mem::size_of::<*mut ()>())
-                };
+            // Otherwise the padding is useless.
+            let need_padding = padding_bytes >= field_layout.align;
 
-                Some(self.padding_field(Layout::new(padding_bytes, padding_align)))
+            self.latest_offset += padding_bytes;
+
+            debug!("Offset: <padding>: {} -> {}",
+                   self.latest_offset - padding_bytes,
+                   self.latest_offset);
+
+            debug!("align field {} to {}/{} with {} padding bytes {:?}",
+                field_name,
+                self.latest_offset,
+                field_offset.unwrap_or(0) / 8,
+                padding_bytes,
+                field_layout);
+
+            if need_padding && padding_bytes != 0 {
+                Some(Layout::new(padding_bytes, field_layout.align))
             } else {
                 None
             }
+        };
+
+        self.latest_offset += field_layout.size;
+        self.latest_field_layout = Some(field_layout);
+        self.max_field_align = cmp::max(self.max_field_align, field_layout.align);
+        self.last_field_was_bitfield = false;
+
+        debug!("Offset: {}: {} -> {}",
+               field_name,
+               self.latest_offset - field_layout.size,
+               self.latest_offset);
+
+        padding_layout.map(|layout| self.padding_field(layout))
+    }
+
+    pub fn pad_struct(&mut self, name: &str, layout: Layout) -> Option<ast::StructField> {
+        if layout.size < self.latest_offset {
+            error!("Calculated wrong layout for {}, too more {} bytes",
+                   name, self.latest_offset - layout.size);
+            return None
+        }
+
+        let padding_bytes = layout.size - self.latest_offset;
+
+        // We always pad to get to the correct size if the struct is one of
+        // those we can't align properly.
+        //
+        // Note that if the last field we saw was a bitfield, we may need to pad
+        // regardless, because bitfields don't respect alignment as strictly as
+        // other fields.
+        if padding_bytes > 0 &&
+            (padding_bytes >= layout.align ||
+             (self.last_field_was_bitfield &&
+                padding_bytes >= self.latest_field_layout.unwrap().align) ||
+             layout.align > mem::size_of::<*mut ()>()) {
+            let layout = if self.comp.packed() {
+                Layout::new(padding_bytes, 1)
+            } else if self.last_field_was_bitfield ||
+                      layout.align > mem::size_of::<*mut ()>() {
+                // We've already given up on alignment here.
+                Layout::for_size(padding_bytes)
+            } else {
+                Layout::new(padding_bytes, layout.align)
+            };
+
+            Some(self.padding_field(layout))
+        } else {
+            None
         }
     }
 
@@ -166,15 +282,7 @@
     }
 
     fn padding_bytes(&self, layout: Layout) -> usize {
-        if layout.align == 0 {
-            warn!("try to padding bytes without layout");
-
-            0
-        } else if self.latest_offset % layout.align == 0 {
-            0
-        } else {
-            layout.align - (self.latest_offset % layout.align)
-        }
+        align_to(self.latest_offset, layout.align) - self.latest_offset
     }
 
     fn padding_field(&mut self, layout: Layout) -> ast::StructField {
@@ -190,11 +298,37 @@
         StructFieldBuilder::named(padding_field_name).pub_().build_ty(ty)
     }
 
-    fn align_to_latest_field(&mut self) {
+    /// Returns whether the new field is known to merge with a bitfield.
+    ///
+    /// This is just to avoid doing the same check also in pad_field.
+    fn align_to_latest_field(&mut self, new_field_layout: Layout) -> bool {
         if self.comp.packed() {
-            // skip to align field when packed
-        } else if let Some(layout) = self.latest_field_layout {
-            self.latest_offset += self.padding_bytes(layout);
+            // Skip to align fields when packed.
+            return false;
         }
+
+        let layout = match self.latest_field_layout {
+            Some(l) => l,
+            None => return false,
+        };
+
+        // If it was, we may or may not need to align, depending on what the
+        // current field alignment and the bitfield size and alignment are.
+        debug!("align_to_bitfield? {}: {:?} {:?}", self.last_field_was_bitfield,
+               layout, new_field_layout);
+
+        if self.last_field_was_bitfield &&
+            new_field_layout.align <= layout.size % layout.align &&
+            new_field_layout.size <= layout.size % layout.align {
+            // The new field will be coalesced into some of the remaining bits.
+            //
+            // FIXME(emilio): I think this may not catch everything?
+            debug!("Will merge with bitfield");
+            return true;
+        }
+
+        // Else, just align the obvious way.
+        self.latest_offset += self.padding_bytes(layout);
+        return false;
     }
 }
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index fff4655..ce6ec25 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -408,73 +408,25 @@
     /// members. This is not ideal, but clang fails to report the size for these
     /// kind of unions, see test/headers/template_union.hpp
     pub fn layout(&self, ctx: &BindgenContext) -> Option<Layout> {
+        use std::cmp;
         // We can't do better than clang here, sorry.
         if self.kind == CompKind::Struct {
-            None
-        } else {
-            self.calc_layout(ctx)
+            return None
         }
-    }
 
-    /// Compute the layout of this type.
-    pub fn calc_layout(&self, ctx: &BindgenContext) -> Option<Layout> {
-        use std::cmp;
-        use std::mem;
+        let mut max_size = 0;
+        let mut max_align = 0;
+        for field in &self.fields {
+            let field_layout = ctx.resolve_type(field.ty)
+                .layout(ctx);
 
-        if self.kind == CompKind::Struct {
-            let mut latest_offset_in_bits = 0;
-            let mut max_align = 0;
-
-            if self.needs_explicit_vtable(ctx) {
-                latest_offset_in_bits += mem::size_of::<*mut ()>() * 8;
-                max_align = mem::size_of::<*mut ()>();
+            if let Some(layout) = field_layout {
+                max_size = cmp::max(max_size, layout.size);
+                max_align = cmp::max(max_align, layout.align);
             }
-
-            for field in &self.fields {
-                if let Some(bits) = field.bitfield() {
-                    latest_offset_in_bits += bits as usize;
-                } else {
-                    let field_ty = ctx.resolve_type(field.ty);
-
-                    if let Some(field_layout) =
-                        field_ty.as_comp()
-                            .and_then(|comp| comp.calc_layout(ctx))
-                            .or_else(|| field_ty.layout(ctx)) {
-
-                        let n = (latest_offset_in_bits / 8) %
-                                field_layout.align;
-
-                        if !self.packed && n != 0 {
-                            latest_offset_in_bits += (field_layout.align - n) *
-                                                     8;
-                        }
-
-                        latest_offset_in_bits += field_layout.size * 8;
-                        max_align = cmp::max(max_align, field_layout.align);
-                    }
-                }
-            }
-
-            if latest_offset_in_bits == 0 && max_align == 0 {
-                None
-            } else {
-                Some(Layout::new((latest_offset_in_bits + 7) / 8, max_align))
-            }
-        } else {
-            let mut max_size = 0;
-            let mut max_align = 0;
-            for field in &self.fields {
-                let field_layout = ctx.resolve_type(field.ty)
-                    .layout(ctx);
-
-                if let Some(layout) = field_layout {
-                    max_size = cmp::max(max_size, layout.size);
-                    max_align = cmp::max(max_align, layout.align);
-                }
-            }
-
-            Some(Layout::new(max_size, max_align))
         }
+
+        Some(Layout::new(max_size, max_align))
     }
 
     /// Get this type's set of fields.
diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs
index 0a85577..3470e03 100644
--- a/src/ir/enum_ty.rs
+++ b/src/ir/enum_ty.rs
@@ -5,8 +5,6 @@
 use super::ty::TypeKind;
 use clang;
 use ir::annotations::Annotations;
-use ir::int::IntKind;
-use ir::layout::Layout;
 use parse::{ClangItemParser, ParseError};
 
 /// An enum representing custom handling that can be given to a variant.
@@ -51,19 +49,6 @@
         &self.variants
     }
 
-    /// Compute the layout of this type.
-    pub fn calc_layout(&self, ctx: &BindgenContext) -> Option<Layout> {
-        self.repr
-            .map(|repr| ctx.resolve_type(repr))
-            .and_then(|repr| match *repr.canonical_type(ctx).kind() {
-                TypeKind::Int(int_kind) => Some(int_kind),
-                _ => None,
-            })
-            .unwrap_or(IntKind::Int)
-            .known_size()
-            .map(|size| Layout::new(size, size))
-    }
-
     /// Construct an enumeration from the given Clang type.
     pub fn from_ty(ty: &clang::Type,
                    ctx: &mut BindgenContext)
@@ -114,7 +99,7 @@
                             Annotations::new(&cursor)
                                 .and_then(|anno| if anno.hide() {
                                     Some(EnumVariantCustomBehavior::Hide)
-                                } else if 
+                                } else if
                                     anno.constify_enum_variant() {
                                     Some(EnumVariantCustomBehavior::Constify)
                                 } else {
diff --git a/src/ir/layout.rs b/src/ir/layout.rs
index 03d43b5..3837926 100644
--- a/src/ir/layout.rs
+++ b/src/ir/layout.rs
@@ -3,10 +3,10 @@
 use super::context::BindgenContext;
 use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
 use super::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
-use std::cmp;
+use std::{cmp, mem};
 
 /// A type that represents the struct layout of a type.
-#[derive(Debug, Clone, Copy)]
+#[derive(Debug, Clone, Copy, PartialEq)]
 pub struct Layout {
     /// The size (in bytes) of this layout.
     pub size: usize,
@@ -16,6 +16,13 @@
     pub packed: bool,
 }
 
+#[test]
+fn test_layout_for_size() {
+    let ptr_size = mem::size_of::<*mut ()>();
+    assert_eq!(Layout::for_size(ptr_size), Layout::new(ptr_size, ptr_size));
+    assert_eq!(Layout::for_size(3 * ptr_size), Layout::new(3 * ptr_size, ptr_size));
+}
+
 impl Layout {
     /// Construct a new `Layout` with the given `size` and `align`. It is not
     /// packed.
@@ -27,6 +34,20 @@
         }
     }
 
+    /// Creates a non-packed layout for a given size, trying to use the maximum
+    /// alignment possible.
+    pub fn for_size(size: usize) -> Self {
+        let mut next_align = 2;
+        while size % next_align == 0 && next_align <= 2 * mem::size_of::<*mut ()>() {
+            next_align *= 2;
+        }
+        Layout {
+            size: size,
+            align: next_align / 2,
+            packed: false,
+        }
+    }
+
     /// Is this a zero-sized layout?
     pub fn is_zero(&self) -> bool {
         self.size == 0 && self.align == 0
diff --git a/src/ir/ty.rs b/src/ir/ty.rs
index 332ad23..c3ec403 100644
--- a/src/ir/ty.rs
+++ b/src/ir/ty.rs
@@ -382,41 +382,8 @@
             _ => false,
         }
     }
-
-    /// If this type has a known size, return it (in bytes).
-    pub fn calc_size(&self, ctx: &BindgenContext) -> Option<usize> {
-        match self.kind {
-            TypeKind::Comp(ref ci) => {
-                ci.calc_layout(ctx).map(|layout| layout.size)
-            }
-            TypeKind::Enum(ref enum_ty) => {
-                enum_ty.calc_layout(ctx).map(|layout| layout.size)
-            }
-            TypeKind::Int(int_kind) => int_kind.known_size(),
-            TypeKind::Float(float_kind) => Some(float_kind.known_size()),
-            TypeKind::Complex(float_kind) => Some(float_kind.known_size() * 2),
-            TypeKind::Reference(..) |
-            TypeKind::NullPtr |
-            TypeKind::Pointer(..) |
-            TypeKind::BlockPointer |
-            TypeKind::Function(..) |
-            TypeKind::ObjCInterface(..) => Some(mem::size_of::<*mut ()>()),
-            TypeKind::ResolvedTypeRef(inner) |
-            TypeKind::Alias(inner) |
-            TypeKind::TemplateAlias(inner, _) |
-            TypeKind::TemplateInstantiation(inner, _) => {
-                ctx.resolve_type(inner).calc_size(ctx)
-            }
-            TypeKind::Array(inner, len) => {
-                ctx.resolve_type(inner)
-                    .layout(ctx)
-                    .map(|layout| layout.size * len)
-            }
-            TypeKind::Void | TypeKind::Named => None,
-            TypeKind::UnresolvedTypeRef(..) => unreachable!(),
-        }
-    }
 }
+
 #[test]
 fn is_invalid_named_type_valid() {
     let ty = Type::new(Some("foo".into()), None, TypeKind::Named, false);
diff --git a/tests/expectations/tests/bitfield_align.rs b/tests/expectations/tests/bitfield_align.rs
new file mode 100644
index 0000000..ffc170b
--- /dev/null
+++ b/tests/expectations/tests/bitfield_align.rs
@@ -0,0 +1,114 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(non_snake_case)]
+
+
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct A {
+    pub x: ::std::os::raw::c_uchar,
+    pub _bitfield_1: [u8; 2usize],
+    pub y: ::std::os::raw::c_uchar,
+    pub __bindgen_align: [u32; 0usize],
+}
+#[test]
+fn bindgen_test_layout_A() {
+    assert_eq!(::std::mem::size_of::<A>() , 4usize , concat ! (
+               "Size of: " , stringify ! ( A ) ));
+    assert_eq! (::std::mem::align_of::<A>() , 4usize , concat ! (
+                "Alignment of " , stringify ! ( A ) ));
+    assert_eq! (unsafe { & ( * ( 0 as * const A ) ) . x as * const _ as usize
+                } , 0usize , concat ! (
+                "Alignment of field: " , stringify ! ( A ) , "::" , stringify
+                ! ( x ) ));
+    assert_eq! (unsafe { & ( * ( 0 as * const A ) ) . y as * const _ as usize
+                } , 3usize , concat ! (
+                "Alignment of field: " , stringify ! ( A ) , "::" , stringify
+                ! ( y ) ));
+}
+impl Clone for A {
+    fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct B {
+    pub _bitfield_1: u32,
+    pub __bindgen_align: [u32; 0usize],
+}
+#[test]
+fn bindgen_test_layout_B() {
+    assert_eq!(::std::mem::size_of::<B>() , 4usize , concat ! (
+               "Size of: " , stringify ! ( B ) ));
+    assert_eq! (::std::mem::align_of::<B>() , 4usize , concat ! (
+                "Alignment of " , stringify ! ( B ) ));
+}
+impl Clone for B {
+    fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct C {
+    pub x: ::std::os::raw::c_uchar,
+    pub _bitfield_1: u8,
+    pub baz: ::std::os::raw::c_uint,
+}
+#[test]
+fn bindgen_test_layout_C() {
+    assert_eq!(::std::mem::size_of::<C>() , 8usize , concat ! (
+               "Size of: " , stringify ! ( C ) ));
+    assert_eq! (::std::mem::align_of::<C>() , 4usize , concat ! (
+                "Alignment of " , stringify ! ( C ) ));
+    assert_eq! (unsafe { & ( * ( 0 as * const C ) ) . x as * const _ as usize
+                } , 0usize , concat ! (
+                "Alignment of field: " , stringify ! ( C ) , "::" , stringify
+                ! ( x ) ));
+    assert_eq! (unsafe {
+                & ( * ( 0 as * const C ) ) . baz as * const _ as usize } ,
+                4usize , concat ! (
+                "Alignment of field: " , stringify ! ( C ) , "::" , stringify
+                ! ( baz ) ));
+}
+impl Clone for C {
+    fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct Date1 {
+    pub _bitfield_1: [u8; 2usize],
+    pub _bitfield_2: u8,
+    pub __bindgen_align: [u16; 0usize],
+}
+#[test]
+fn bindgen_test_layout_Date1() {
+    assert_eq!(::std::mem::size_of::<Date1>() , 4usize , concat ! (
+               "Size of: " , stringify ! ( Date1 ) ));
+    assert_eq! (::std::mem::align_of::<Date1>() , 2usize , concat ! (
+                "Alignment of " , stringify ! ( Date1 ) ));
+}
+impl Clone for Date1 {
+    fn clone(&self) -> Self { *self }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy)]
+pub struct Date2 {
+    pub _bitfield_1: [u8; 2usize],
+    pub _bitfield_2: u8,
+    pub byte: ::std::os::raw::c_uchar,
+    pub __bindgen_align: [u16; 0usize],
+}
+#[test]
+fn bindgen_test_layout_Date2() {
+    assert_eq!(::std::mem::size_of::<Date2>() , 4usize , concat ! (
+               "Size of: " , stringify ! ( Date2 ) ));
+    assert_eq! (::std::mem::align_of::<Date2>() , 2usize , concat ! (
+                "Alignment of " , stringify ! ( Date2 ) ));
+    assert_eq! (unsafe {
+                & ( * ( 0 as * const Date2 ) ) . byte as * const _ as usize }
+                , 3usize , concat ! (
+                "Alignment of field: " , stringify ! ( Date2 ) , "::" ,
+                stringify ! ( byte ) ));
+}
+impl Clone for Date2 {
+    fn clone(&self) -> Self { *self }
+}
diff --git a/tests/expectations/tests/bitfield_method_mangling.rs b/tests/expectations/tests/bitfield_method_mangling.rs
index 0a6c9fd..f21b208 100644
--- a/tests/expectations/tests/bitfield_method_mangling.rs
+++ b/tests/expectations/tests/bitfield_method_mangling.rs
@@ -8,6 +8,7 @@
 #[derive(Debug, Default, Copy)]
 pub struct mach_msg_type_descriptor_t {
     pub _bitfield_1: u32,
+    pub __bindgen_align: [u32; 0usize],
 }
 #[test]
 fn bindgen_test_layout_mach_msg_type_descriptor_t() {
@@ -22,32 +23,3 @@
 impl Clone for mach_msg_type_descriptor_t {
     fn clone(&self) -> Self { *self }
 }
-impl mach_msg_type_descriptor_t {
-    #[inline]
-    pub fn pad3(&self) -> ::std::os::raw::c_uint {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (16777215usize as u32))
-                                       >> 0u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_pad3(&mut self, val: ::std::os::raw::c_uint) {
-        self._bitfield_1 &= !(16777215usize as u32);
-        self._bitfield_1 |=
-            ((val as u32 as u32) << 0u32) & (16777215usize as u32);
-    }
-    #[inline]
-    pub fn type_(&self) -> ::std::os::raw::c_uint {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 &
-                                        (4278190080usize as u32)) >> 24u32) as
-                                      u32)
-        }
-    }
-    #[inline]
-    pub fn set_type(&mut self, val: ::std::os::raw::c_uint) {
-        self._bitfield_1 &= !(4278190080usize as u32);
-        self._bitfield_1 |=
-            ((val as u32 as u32) << 24u32) & (4278190080usize as u32);
-    }
-}
diff --git a/tests/expectations/tests/jsval_layout_opaque.rs b/tests/expectations/tests/jsval_layout_opaque.rs
index 848286e..eb5306d 100644
--- a/tests/expectations/tests/jsval_layout_opaque.rs
+++ b/tests/expectations/tests/jsval_layout_opaque.rs
@@ -111,6 +111,7 @@
 #[derive(Debug, Copy)]
 pub struct jsval_layout__bindgen_ty_1 {
     pub _bitfield_1: u64,
+    pub __bindgen_align: [u64; 0usize],
 }
 #[test]
 fn bindgen_test_layout_jsval_layout__bindgen_ty_1() {
@@ -128,37 +129,6 @@
 impl Default for jsval_layout__bindgen_ty_1 {
     fn default() -> Self { unsafe { ::std::mem::zeroed() } }
 }
-impl jsval_layout__bindgen_ty_1 {
-    #[inline]
-    pub fn payload47(&self) -> u64 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 &
-                                        (140737488355327usize as u64)) >>
-                                       0u32) as u64)
-        }
-    }
-    #[inline]
-    pub fn set_payload47(&mut self, val: u64) {
-        self._bitfield_1 &= !(140737488355327usize as u64);
-        self._bitfield_1 |=
-            ((val as u64 as u64) << 0u32) & (140737488355327usize as u64);
-    }
-    #[inline]
-    pub fn tag(&self) -> JSValueTag {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 &
-                                        (18446603336221196288usize as u64)) >>
-                                       47u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_tag(&mut self, val: JSValueTag) {
-        self._bitfield_1 &= !(18446603336221196288usize as u64);
-        self._bitfield_1 |=
-            ((val as u32 as u64) << 47u32) &
-                (18446603336221196288usize as u64);
-    }
-}
 #[repr(C)]
 #[derive(Debug, Default, Copy)]
 pub struct jsval_layout__bindgen_ty_2 {
diff --git a/tests/expectations/tests/layout_align.rs b/tests/expectations/tests/layout_align.rs
index a21fa4d..9085480 100644
--- a/tests/expectations/tests/layout_align.rs
+++ b/tests/expectations/tests/layout_align.rs
@@ -71,6 +71,7 @@
     /**< ETH_SPEED_NUM_ */
     pub link_speed: u32,
     pub _bitfield_1: u8,
+    pub __bindgen_padding_0: [u8; 3usize],
     pub __bindgen_align: [u64; 0usize],
 }
 #[test]
@@ -88,41 +89,3 @@
 impl Clone for rte_eth_link {
     fn clone(&self) -> Self { *self }
 }
-impl rte_eth_link {
-    #[inline]
-    pub fn link_duplex(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (1usize as u8)) >>
-                                       0u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_link_duplex(&mut self, val: u16) {
-        self._bitfield_1 &= !(1usize as u8);
-        self._bitfield_1 |= ((val as u16 as u8) << 0u32) & (1usize as u8);
-    }
-    #[inline]
-    pub fn link_autoneg(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (2usize as u8)) >>
-                                       1u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_link_autoneg(&mut self, val: u16) {
-        self._bitfield_1 &= !(2usize as u8);
-        self._bitfield_1 |= ((val as u16 as u8) << 1u32) & (2usize as u8);
-    }
-    #[inline]
-    pub fn link_status(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (4usize as u8)) >>
-                                       2u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_link_status(&mut self, val: u16) {
-        self._bitfield_1 &= !(4usize as u8);
-        self._bitfield_1 |= ((val as u16 as u8) << 2u32) & (4usize as u8);
-    }
-}
diff --git a/tests/expectations/tests/layout_eth_conf.rs b/tests/expectations/tests/layout_eth_conf.rs
index 16788d0..ae46f5c 100644
--- a/tests/expectations/tests/layout_eth_conf.rs
+++ b/tests/expectations/tests/layout_eth_conf.rs
@@ -88,7 +88,7 @@
     pub max_rx_pkt_len: u32,
     /**< hdr buf size (header_split enabled).*/
     pub split_hdr_size: u16,
-    pub _bitfield_1: u16,
+    pub _bitfield_1: [u8; 2usize],
 }
 #[test]
 fn bindgen_test_layout_rte_eth_rxmode() {
@@ -118,116 +118,6 @@
 impl Default for rte_eth_rxmode {
     fn default() -> Self { unsafe { ::std::mem::zeroed() } }
 }
-impl rte_eth_rxmode {
-    #[inline]
-    pub fn header_split(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (1usize as u16)) >>
-                                       0u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_header_split(&mut self, val: u16) {
-        self._bitfield_1 &= !(1usize as u16);
-        self._bitfield_1 |= ((val as u16 as u16) << 0u32) & (1usize as u16);
-    }
-    #[inline]
-    pub fn hw_ip_checksum(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (2usize as u16)) >>
-                                       1u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_hw_ip_checksum(&mut self, val: u16) {
-        self._bitfield_1 &= !(2usize as u16);
-        self._bitfield_1 |= ((val as u16 as u16) << 1u32) & (2usize as u16);
-    }
-    #[inline]
-    pub fn hw_vlan_filter(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (4usize as u16)) >>
-                                       2u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_hw_vlan_filter(&mut self, val: u16) {
-        self._bitfield_1 &= !(4usize as u16);
-        self._bitfield_1 |= ((val as u16 as u16) << 2u32) & (4usize as u16);
-    }
-    #[inline]
-    pub fn hw_vlan_strip(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (8usize as u16)) >>
-                                       3u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_hw_vlan_strip(&mut self, val: u16) {
-        self._bitfield_1 &= !(8usize as u16);
-        self._bitfield_1 |= ((val as u16 as u16) << 3u32) & (8usize as u16);
-    }
-    #[inline]
-    pub fn hw_vlan_extend(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (16usize as u16)) >>
-                                       4u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_hw_vlan_extend(&mut self, val: u16) {
-        self._bitfield_1 &= !(16usize as u16);
-        self._bitfield_1 |= ((val as u16 as u16) << 4u32) & (16usize as u16);
-    }
-    #[inline]
-    pub fn jumbo_frame(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (32usize as u16)) >>
-                                       5u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_jumbo_frame(&mut self, val: u16) {
-        self._bitfield_1 &= !(32usize as u16);
-        self._bitfield_1 |= ((val as u16 as u16) << 5u32) & (32usize as u16);
-    }
-    #[inline]
-    pub fn hw_strip_crc(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (64usize as u16)) >>
-                                       6u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_hw_strip_crc(&mut self, val: u16) {
-        self._bitfield_1 &= !(64usize as u16);
-        self._bitfield_1 |= ((val as u16 as u16) << 6u32) & (64usize as u16);
-    }
-    #[inline]
-    pub fn enable_scatter(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (128usize as u16)) >>
-                                       7u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_enable_scatter(&mut self, val: u16) {
-        self._bitfield_1 &= !(128usize as u16);
-        self._bitfield_1 |= ((val as u16 as u16) << 7u32) & (128usize as u16);
-    }
-    #[inline]
-    pub fn enable_lro(&self) -> u16 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (256usize as u16)) >>
-                                       8u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_enable_lro(&mut self, val: u16) {
-        self._bitfield_1 &= !(256usize as u16);
-        self._bitfield_1 |= ((val as u16 as u16) << 8u32) & (256usize as u16);
-    }
-}
 #[repr(u32)]
 /**
  * A set of values to identify what method is to be used to transmit
@@ -250,6 +140,7 @@
     pub mq_mode: rte_eth_tx_mq_mode,
     pub pvid: u16,
     pub _bitfield_1: u8,
+    pub __bindgen_padding_0: u8,
 }
 #[test]
 fn bindgen_test_layout_rte_eth_txmode() {
@@ -274,44 +165,6 @@
 impl Default for rte_eth_txmode {
     fn default() -> Self { unsafe { ::std::mem::zeroed() } }
 }
-impl rte_eth_txmode {
-    #[inline]
-    pub fn hw_vlan_reject_tagged(&self) -> u8 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (1usize as u8)) >>
-                                       0u32) as u8)
-        }
-    }
-    #[inline]
-    pub fn set_hw_vlan_reject_tagged(&mut self, val: u8) {
-        self._bitfield_1 &= !(1usize as u8);
-        self._bitfield_1 |= ((val as u8 as u8) << 0u32) & (1usize as u8);
-    }
-    #[inline]
-    pub fn hw_vlan_reject_untagged(&self) -> u8 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (2usize as u8)) >>
-                                       1u32) as u8)
-        }
-    }
-    #[inline]
-    pub fn set_hw_vlan_reject_untagged(&mut self, val: u8) {
-        self._bitfield_1 &= !(2usize as u8);
-        self._bitfield_1 |= ((val as u8 as u8) << 1u32) & (2usize as u8);
-    }
-    #[inline]
-    pub fn hw_vlan_insert_pvid(&self) -> u8 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (4usize as u8)) >>
-                                       2u32) as u8)
-        }
-    }
-    #[inline]
-    pub fn set_hw_vlan_insert_pvid(&mut self, val: u8) {
-        self._bitfield_1 &= !(4usize as u8);
-        self._bitfield_1 |= ((val as u8 as u8) << 2u32) & (4usize as u8);
-    }
-}
 /**
  * A structure used to configure the Receive Side Scaling (RSS) feature
  * of an Ethernet port.
diff --git a/tests/expectations/tests/layout_mbuf.rs b/tests/expectations/tests/layout_mbuf.rs
index 5732831..8ad13f1 100644
--- a/tests/expectations/tests/layout_mbuf.rs
+++ b/tests/expectations/tests/layout_mbuf.rs
@@ -158,7 +158,8 @@
 #[repr(C)]
 #[derive(Debug, Default, Copy)]
 pub struct rte_mbuf__bindgen_ty_2__bindgen_ty_1 {
-    pub _bitfield_1: u32,
+    pub _bitfield_1: [u8; 4usize],
+    pub __bindgen_align: [u32; 0usize],
 }
 #[test]
 fn bindgen_test_layout_rte_mbuf__bindgen_ty_2__bindgen_ty_1() {
@@ -174,98 +175,6 @@
 impl Clone for rte_mbuf__bindgen_ty_2__bindgen_ty_1 {
     fn clone(&self) -> Self { *self }
 }
-impl rte_mbuf__bindgen_ty_2__bindgen_ty_1 {
-    #[inline]
-    pub fn l2_type(&self) -> u32 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (15usize as u32)) >>
-                                       0u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_l2_type(&mut self, val: u32) {
-        self._bitfield_1 &= !(15usize as u32);
-        self._bitfield_1 |= ((val as u32 as u32) << 0u32) & (15usize as u32);
-    }
-    #[inline]
-    pub fn l3_type(&self) -> u32 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (240usize as u32)) >>
-                                       4u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_l3_type(&mut self, val: u32) {
-        self._bitfield_1 &= !(240usize as u32);
-        self._bitfield_1 |= ((val as u32 as u32) << 4u32) & (240usize as u32);
-    }
-    #[inline]
-    pub fn l4_type(&self) -> u32 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (3840usize as u32)) >>
-                                       8u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_l4_type(&mut self, val: u32) {
-        self._bitfield_1 &= !(3840usize as u32);
-        self._bitfield_1 |=
-            ((val as u32 as u32) << 8u32) & (3840usize as u32);
-    }
-    #[inline]
-    pub fn tun_type(&self) -> u32 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (61440usize as u32)) >>
-                                       12u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_tun_type(&mut self, val: u32) {
-        self._bitfield_1 &= !(61440usize as u32);
-        self._bitfield_1 |=
-            ((val as u32 as u32) << 12u32) & (61440usize as u32);
-    }
-    #[inline]
-    pub fn inner_l2_type(&self) -> u32 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (983040usize as u32))
-                                       >> 16u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_inner_l2_type(&mut self, val: u32) {
-        self._bitfield_1 &= !(983040usize as u32);
-        self._bitfield_1 |=
-            ((val as u32 as u32) << 16u32) & (983040usize as u32);
-    }
-    #[inline]
-    pub fn inner_l3_type(&self) -> u32 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (15728640usize as u32))
-                                       >> 20u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_inner_l3_type(&mut self, val: u32) {
-        self._bitfield_1 &= !(15728640usize as u32);
-        self._bitfield_1 |=
-            ((val as u32 as u32) << 20u32) & (15728640usize as u32);
-    }
-    #[inline]
-    pub fn inner_l4_type(&self) -> u32 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 &
-                                        (251658240usize as u32)) >> 24u32) as
-                                      u32)
-        }
-    }
-    #[inline]
-    pub fn set_inner_l4_type(&mut self, val: u32) {
-        self._bitfield_1 &= !(251658240usize as u32);
-        self._bitfield_1 |=
-            ((val as u32 as u32) << 24u32) & (251658240usize as u32);
-    }
-}
 #[test]
 fn bindgen_test_layout_rte_mbuf__bindgen_ty_2() {
     assert_eq!(::std::mem::size_of::<rte_mbuf__bindgen_ty_2>() , 4usize ,
@@ -499,7 +408,8 @@
 #[repr(C)]
 #[derive(Debug, Default, Copy)]
 pub struct rte_mbuf__bindgen_ty_5__bindgen_ty_1 {
-    pub _bitfield_1: u64,
+    pub _bitfield_1: [u16; 4usize],
+    pub __bindgen_align: [u64; 0usize],
 }
 #[test]
 fn bindgen_test_layout_rte_mbuf__bindgen_ty_5__bindgen_ty_1() {
@@ -515,88 +425,6 @@
 impl Clone for rte_mbuf__bindgen_ty_5__bindgen_ty_1 {
     fn clone(&self) -> Self { *self }
 }
-impl rte_mbuf__bindgen_ty_5__bindgen_ty_1 {
-    #[inline]
-    pub fn l2_len(&self) -> u64 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (127usize as u64)) >>
-                                       0u32) as u64)
-        }
-    }
-    #[inline]
-    pub fn set_l2_len(&mut self, val: u64) {
-        self._bitfield_1 &= !(127usize as u64);
-        self._bitfield_1 |= ((val as u64 as u64) << 0u32) & (127usize as u64);
-    }
-    #[inline]
-    pub fn l3_len(&self) -> u64 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (65408usize as u64)) >>
-                                       7u32) as u64)
-        }
-    }
-    #[inline]
-    pub fn set_l3_len(&mut self, val: u64) {
-        self._bitfield_1 &= !(65408usize as u64);
-        self._bitfield_1 |=
-            ((val as u64 as u64) << 7u32) & (65408usize as u64);
-    }
-    #[inline]
-    pub fn l4_len(&self) -> u64 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (16711680usize as u64))
-                                       >> 16u32) as u64)
-        }
-    }
-    #[inline]
-    pub fn set_l4_len(&mut self, val: u64) {
-        self._bitfield_1 &= !(16711680usize as u64);
-        self._bitfield_1 |=
-            ((val as u64 as u64) << 16u32) & (16711680usize as u64);
-    }
-    #[inline]
-    pub fn tso_segsz(&self) -> u64 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 &
-                                        (1099494850560usize as u64)) >> 24u32)
-                                      as u64)
-        }
-    }
-    #[inline]
-    pub fn set_tso_segsz(&mut self, val: u64) {
-        self._bitfield_1 &= !(1099494850560usize as u64);
-        self._bitfield_1 |=
-            ((val as u64 as u64) << 24u32) & (1099494850560usize as u64);
-    }
-    #[inline]
-    pub fn outer_l3_len(&self) -> u64 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 &
-                                        (561850441793536usize as u64)) >>
-                                       40u32) as u64)
-        }
-    }
-    #[inline]
-    pub fn set_outer_l3_len(&mut self, val: u64) {
-        self._bitfield_1 &= !(561850441793536usize as u64);
-        self._bitfield_1 |=
-            ((val as u64 as u64) << 40u32) & (561850441793536usize as u64);
-    }
-    #[inline]
-    pub fn outer_l2_len(&self) -> u64 {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 &
-                                        (71494644084506624usize as u64)) >>
-                                       49u32) as u64)
-        }
-    }
-    #[inline]
-    pub fn set_outer_l2_len(&mut self, val: u64) {
-        self._bitfield_1 &= !(71494644084506624usize as u64);
-        self._bitfield_1 |=
-            ((val as u64 as u64) << 49u32) & (71494644084506624usize as u64);
-    }
-}
 #[test]
 fn bindgen_test_layout_rte_mbuf__bindgen_ty_5() {
     assert_eq!(::std::mem::size_of::<rte_mbuf__bindgen_ty_5>() , 8usize ,
diff --git a/tests/expectations/tests/only_bitfields.rs b/tests/expectations/tests/only_bitfields.rs
index 9252097..643725d 100644
--- a/tests/expectations/tests/only_bitfields.rs
+++ b/tests/expectations/tests/only_bitfields.rs
@@ -8,6 +8,7 @@
 #[derive(Debug, Default, Copy)]
 pub struct C {
     pub _bitfield_1: u8,
+    pub __bindgen_align: [u8; 0usize],
 }
 #[test]
 fn bindgen_test_layout_C() {
@@ -19,29 +20,3 @@
 impl Clone for C {
     fn clone(&self) -> Self { *self }
 }
-impl C {
-    #[inline]
-    pub fn a(&self) -> bool {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (1usize as u8)) >>
-                                       0u32) as u8)
-        }
-    }
-    #[inline]
-    pub fn set_a(&mut self, val: bool) {
-        self._bitfield_1 &= !(1usize as u8);
-        self._bitfield_1 |= ((val as u8 as u8) << 0u32) & (1usize as u8);
-    }
-    #[inline]
-    pub fn b(&self) -> bool {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (254usize as u8)) >>
-                                       1u32) as u8)
-        }
-    }
-    #[inline]
-    pub fn set_b(&mut self, val: bool) {
-        self._bitfield_1 &= !(254usize as u8);
-        self._bitfield_1 |= ((val as u8 as u8) << 1u32) & (254usize as u8);
-    }
-}
diff --git a/tests/expectations/tests/struct_with_bitfields.rs b/tests/expectations/tests/struct_with_bitfields.rs
index 861ad66..2f9ba42 100644
--- a/tests/expectations/tests/struct_with_bitfields.rs
+++ b/tests/expectations/tests/struct_with_bitfields.rs
@@ -27,103 +27,3 @@
 impl Clone for bitfield {
     fn clone(&self) -> Self { *self }
 }
-impl bitfield {
-    #[inline]
-    pub fn a(&self) -> ::std::os::raw::c_ushort {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (1usize as u8)) >>
-                                       0u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_a(&mut self, val: ::std::os::raw::c_ushort) {
-        self._bitfield_1 &= !(1usize as u8);
-        self._bitfield_1 |= ((val as u16 as u8) << 0u32) & (1usize as u8);
-    }
-    #[inline]
-    pub fn b(&self) -> ::std::os::raw::c_ushort {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (2usize as u8)) >>
-                                       1u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_b(&mut self, val: ::std::os::raw::c_ushort) {
-        self._bitfield_1 &= !(2usize as u8);
-        self._bitfield_1 |= ((val as u16 as u8) << 1u32) & (2usize as u8);
-    }
-    #[inline]
-    pub fn c(&self) -> ::std::os::raw::c_ushort {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (4usize as u8)) >>
-                                       2u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_c(&mut self, val: ::std::os::raw::c_ushort) {
-        self._bitfield_1 &= !(4usize as u8);
-        self._bitfield_1 |= ((val as u16 as u8) << 2u32) & (4usize as u8);
-    }
-    #[inline]
-    pub fn at_offset_3(&self) -> ::std::os::raw::c_ushort {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (8usize as u8)) >>
-                                       3u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_at_offset_3(&mut self, val: ::std::os::raw::c_ushort) {
-        self._bitfield_1 &= !(8usize as u8);
-        self._bitfield_1 |= ((val as u16 as u8) << 3u32) & (8usize as u8);
-    }
-    #[inline]
-    pub fn at_offset_4(&self) -> ::std::os::raw::c_ushort {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (48usize as u8)) >>
-                                       4u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_at_offset_4(&mut self, val: ::std::os::raw::c_ushort) {
-        self._bitfield_1 &= !(48usize as u8);
-        self._bitfield_1 |= ((val as u16 as u8) << 4u32) & (48usize as u8);
-    }
-    #[inline]
-    pub fn d(&self) -> ::std::os::raw::c_ushort {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (192usize as u8)) >>
-                                       6u32) as u16)
-        }
-    }
-    #[inline]
-    pub fn set_d(&mut self, val: ::std::os::raw::c_ushort) {
-        self._bitfield_1 &= !(192usize as u8);
-        self._bitfield_1 |= ((val as u16 as u8) << 6u32) & (192usize as u8);
-    }
-    #[inline]
-    pub fn f(&self) -> ::std::os::raw::c_uint {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_2 & (3usize as u8)) >>
-                                       0u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_f(&mut self, val: ::std::os::raw::c_uint) {
-        self._bitfield_2 &= !(3usize as u8);
-        self._bitfield_2 |= ((val as u32 as u8) << 0u32) & (3usize as u8);
-    }
-    #[inline]
-    pub fn g(&self) -> ::std::os::raw::c_uint {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_3 &
-                                        (4294967295usize as u32)) >> 0u32) as
-                                      u32)
-        }
-    }
-    #[inline]
-    pub fn set_g(&mut self, val: ::std::os::raw::c_uint) {
-        self._bitfield_3 &= !(4294967295usize as u32);
-        self._bitfield_3 |=
-            ((val as u32 as u32) << 0u32) & (4294967295usize as u32);
-    }
-}
diff --git a/tests/expectations/tests/union_with_anon_struct_bitfield.rs b/tests/expectations/tests/union_with_anon_struct_bitfield.rs
index d14a38b..f102117 100644
--- a/tests/expectations/tests/union_with_anon_struct_bitfield.rs
+++ b/tests/expectations/tests/union_with_anon_struct_bitfield.rs
@@ -39,6 +39,7 @@
 #[derive(Debug, Default, Copy)]
 pub struct foo__bindgen_ty_1 {
     pub _bitfield_1: u32,
+    pub __bindgen_align: [u32; 0usize],
 }
 #[test]
 fn bindgen_test_layout_foo__bindgen_ty_1() {
@@ -50,34 +51,6 @@
 impl Clone for foo__bindgen_ty_1 {
     fn clone(&self) -> Self { *self }
 }
-impl foo__bindgen_ty_1 {
-    #[inline]
-    pub fn b(&self) -> ::std::os::raw::c_int {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (127usize as u32)) >>
-                                       0u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_b(&mut self, val: ::std::os::raw::c_int) {
-        self._bitfield_1 &= !(127usize as u32);
-        self._bitfield_1 |= ((val as u32 as u32) << 0u32) & (127usize as u32);
-    }
-    #[inline]
-    pub fn c(&self) -> ::std::os::raw::c_int {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 &
-                                        (4294967168usize as u32)) >> 7u32) as
-                                      u32)
-        }
-    }
-    #[inline]
-    pub fn set_c(&mut self, val: ::std::os::raw::c_int) {
-        self._bitfield_1 &= !(4294967168usize as u32);
-        self._bitfield_1 |=
-            ((val as u32 as u32) << 7u32) & (4294967168usize as u32);
-    }
-}
 #[test]
 fn bindgen_test_layout_foo() {
     assert_eq!(::std::mem::size_of::<foo>() , 4usize , concat ! (
diff --git a/tests/expectations/tests/unknown_attr.rs b/tests/expectations/tests/unknown_attr.rs
index 2c50c36..23d9ff7 100644
--- a/tests/expectations/tests/unknown_attr.rs
+++ b/tests/expectations/tests/unknown_attr.rs
@@ -9,7 +9,7 @@
 pub struct max_align_t {
     pub __clang_max_align_nonce1: ::std::os::raw::c_longlong,
     pub __bindgen_padding_0: u64,
-    pub __clang_max_align_nonce2: f64,
+    pub __clang_max_align_nonce2: ::std::os::raw::c_longlong,
     pub __bindgen_padding_1: u64,
 }
 #[test]
diff --git a/tests/expectations/tests/weird_bitfields.rs b/tests/expectations/tests/weird_bitfields.rs
index a2841e3..466904e 100644
--- a/tests/expectations/tests/weird_bitfields.rs
+++ b/tests/expectations/tests/weird_bitfields.rs
@@ -15,7 +15,7 @@
 #[derive(Debug, Copy)]
 pub struct Weird {
     pub mStrokeDasharrayLength: ::std::os::raw::c_uint,
-    pub _bitfield_1: u32,
+    pub _bitfield_1: [u16; 2usize],
     pub mClipRule: ::std::os::raw::c_uchar,
     pub mColorInterpolation: ::std::os::raw::c_uchar,
     pub mColorInterpolationFilters: ::std::os::raw::c_uchar,
@@ -27,7 +27,8 @@
     pub mStrokeLinejoin: ::std::os::raw::c_uchar,
     pub mTextAnchor: ::std::os::raw::c_uchar,
     pub mTextRendering: ::std::os::raw::c_uchar,
-    pub _bitfield_2: u16,
+    pub _bitfield_2: u8,
+    pub _bitfield_3: u8,
 }
 #[test]
 fn bindgen_test_layout_Weird() {
@@ -102,92 +103,3 @@
 impl Default for Weird {
     fn default() -> Self { unsafe { ::std::mem::zeroed() } }
 }
-impl Weird {
-    #[inline]
-    pub fn bitTest(&self) -> ::std::os::raw::c_uint {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 & (65535usize as u32)) >>
-                                       0u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_bitTest(&mut self, val: ::std::os::raw::c_uint) {
-        self._bitfield_1 &= !(65535usize as u32);
-        self._bitfield_1 |=
-            ((val as u32 as u32) << 0u32) & (65535usize as u32);
-    }
-    #[inline]
-    pub fn bitTest2(&self) -> ::std::os::raw::c_uint {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_1 &
-                                        (2147418112usize as u32)) >> 16u32) as
-                                      u32)
-        }
-    }
-    #[inline]
-    pub fn set_bitTest2(&mut self, val: ::std::os::raw::c_uint) {
-        self._bitfield_1 &= !(2147418112usize as u32);
-        self._bitfield_1 |=
-            ((val as u32 as u32) << 16u32) & (2147418112usize as u32);
-    }
-    #[inline]
-    pub fn mFillOpacitySource(&self) -> nsStyleSVGOpacitySource {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_2 & (7usize as u16)) >>
-                                       0u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_mFillOpacitySource(&mut self, val: nsStyleSVGOpacitySource) {
-        self._bitfield_2 &= !(7usize as u16);
-        self._bitfield_2 |= ((val as u32 as u16) << 0u32) & (7usize as u16);
-    }
-    #[inline]
-    pub fn mStrokeOpacitySource(&self) -> nsStyleSVGOpacitySource {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_2 & (56usize as u16)) >>
-                                       3u32) as u32)
-        }
-    }
-    #[inline]
-    pub fn set_mStrokeOpacitySource(&mut self, val: nsStyleSVGOpacitySource) {
-        self._bitfield_2 &= !(56usize as u16);
-        self._bitfield_2 |= ((val as u32 as u16) << 3u32) & (56usize as u16);
-    }
-    #[inline]
-    pub fn mStrokeDasharrayFromObject(&self) -> bool {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_2 & (64usize as u16)) >>
-                                       6u32) as u8)
-        }
-    }
-    #[inline]
-    pub fn set_mStrokeDasharrayFromObject(&mut self, val: bool) {
-        self._bitfield_2 &= !(64usize as u16);
-        self._bitfield_2 |= ((val as u8 as u16) << 6u32) & (64usize as u16);
-    }
-    #[inline]
-    pub fn mStrokeDashoffsetFromObject(&self) -> bool {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_2 & (128usize as u16)) >>
-                                       7u32) as u8)
-        }
-    }
-    #[inline]
-    pub fn set_mStrokeDashoffsetFromObject(&mut self, val: bool) {
-        self._bitfield_2 &= !(128usize as u16);
-        self._bitfield_2 |= ((val as u8 as u16) << 7u32) & (128usize as u16);
-    }
-    #[inline]
-    pub fn mStrokeWidthFromObject(&self) -> bool {
-        unsafe {
-            ::std::mem::transmute(((self._bitfield_2 & (256usize as u16)) >>
-                                       8u32) as u8)
-        }
-    }
-    #[inline]
-    pub fn set_mStrokeWidthFromObject(&mut self, val: bool) {
-        self._bitfield_2 &= !(256usize as u16);
-        self._bitfield_2 |= ((val as u8 as u16) << 8u32) & (256usize as u16);
-    }
-}
diff --git a/tests/headers/bitfield_align.h b/tests/headers/bitfield_align.h
new file mode 100644
index 0000000..82b5309
--- /dev/null
+++ b/tests/headers/bitfield_align.h
@@ -0,0 +1,41 @@
+struct A {
+  unsigned char x;
+  unsigned b1 : 1;
+  unsigned b2 : 1;
+  unsigned b3 : 1;
+  unsigned b4 : 1;
+  unsigned b5 : 1;
+  unsigned b6 : 1;
+  unsigned b7 : 1;
+  unsigned b8 : 1;
+  unsigned b9 : 1;
+  unsigned b10 : 1;
+  unsigned char y;
+};
+
+struct B {
+  unsigned foo : 31;
+  unsigned char bar : 1;
+};
+
+struct C {
+  unsigned char x;
+  unsigned b1 : 1;
+  unsigned b2 : 1;
+  unsigned baz;
+};
+
+struct Date1 {
+   unsigned short nWeekDay  : 3;    // 0..7   (3 bits)
+   unsigned short nMonthDay : 6;    // 0..31  (6 bits)
+   unsigned short nMonth    : 5;    // 0..12  (5 bits)
+   unsigned short nYear     : 8;    // 0..100 (8 bits)
+};
+
+struct Date2 {
+   unsigned short nWeekDay  : 3;    // 0..7   (3 bits)
+   unsigned short nMonthDay : 6;    // 0..31  (6 bits)
+   unsigned short nMonth    : 5;    // 0..12  (5 bits)
+   unsigned short nYear     : 8;    // 0..100 (8 bits)
+   unsigned char byte;
+};
diff --git a/tests/headers/unknown_attr.h b/tests/headers/unknown_attr.h
index f87e9f0..1e89fb1 100644
--- a/tests/headers/unknown_attr.h
+++ b/tests/headers/unknown_attr.h
@@ -1,6 +1,6 @@
 typedef struct {
   long long __clang_max_align_nonce1
       __attribute__((__aligned__(__alignof__(long long))));
-  long double __clang_max_align_nonce2
+  long long __clang_max_align_nonce2
       __attribute__((__aligned__(__alignof__(long double))));
 } max_align_t;