summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml12
-rw-r--r--CHANGELOG.md115
-rw-r--r--CONTRIBUTING.md9
-rw-r--r--Cargo.lock16
-rw-r--r--Cargo.toml4
-rw-r--r--bindgen-integration/cpp/Test.h4
-rw-r--r--book/src/cpp.md6
-rw-r--r--book/src/nocopy.md2
-rwxr-xr-xci/script.sh5
-rwxr-xr-xcsmith-fuzzing/predicate.py16
-rw-r--r--rustfmt.toml4
-rw-r--r--src/clang.rs133
-rw-r--r--src/codegen/mod.rs87
-rw-r--r--src/ir/comp.rs71
-rw-r--r--src/ir/context.rs2
-rw-r--r--src/ir/enum_ty.rs14
-rw-r--r--src/ir/function.rs13
-rw-r--r--src/ir/item.rs4
-rw-r--r--src/ir/var.rs14
-rw-r--r--src/lib.rs15
-rw-r--r--src/options.rs6
-rw-r--r--tests/expectations/build.rs60
-rw-r--r--tests/expectations/tests/anon_enum.rs2
-rw-r--r--tests/expectations/tests/anon_enum_trait.rs2
-rw-r--r--tests/expectations/tests/anon_enum_whitelist.rs1
-rw-r--r--tests/expectations/tests/anon_union.rs1
-rw-r--r--tests/expectations/tests/anon_union_1_0.rs1
-rw-r--r--tests/expectations/tests/bitfield_align_2.rs1
-rw-r--r--tests/expectations/tests/class_with_inner_struct.rs1
-rw-r--r--tests/expectations/tests/class_with_inner_struct_1_0.rs1
-rw-r--r--tests/expectations/tests/const_enum_unnamed.rs2
-rw-r--r--tests/expectations/tests/constify-enum.rs1
-rw-r--r--tests/expectations/tests/empty-enum.rs36
-rw-r--r--tests/expectations/tests/enum.rs2
-rw-r--r--tests/expectations/tests/enum_alias.rs1
-rw-r--r--tests/expectations/tests/enum_and_vtable_mangling.rs1
-rw-r--r--tests/expectations/tests/enum_dupe.rs1
-rw-r--r--tests/expectations/tests/enum_explicit_type.rs6
-rw-r--r--tests/expectations/tests/enum_in_template_with_typedef.rs1
-rw-r--r--tests/expectations/tests/enum_negative.rs1
-rw-r--r--tests/expectations/tests/enum_packed.rs3
-rw-r--r--tests/expectations/tests/forward-enum-decl.rs1
-rw-r--r--tests/expectations/tests/func_ptr_in_struct.rs6
-rw-r--r--tests/expectations/tests/issue-1197-pure-virtual-stuff.rs29
-rw-r--r--tests/expectations/tests/issue-1216-variadic-member.rs42
-rw-r--r--tests/expectations/tests/issue-372.rs1
-rw-r--r--tests/expectations/tests/issue-410.rs6
-rw-r--r--tests/expectations/tests/issue-493.rs2
-rw-r--r--tests/expectations/tests/issue-493_1_0.rs2
-rw-r--r--tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs1
-rw-r--r--tests/expectations/tests/issue-816.rs767
-rw-r--r--tests/expectations/tests/issue-888-enum-var-decl-jump.rs6
-rw-r--r--tests/expectations/tests/jsval_layout_opaque.rs4
-rw-r--r--tests/expectations/tests/jsval_layout_opaque_1_0.rs4
-rw-r--r--tests/expectations/tests/layout_array_too_long.rs1
-rw-r--r--tests/expectations/tests/layout_cmdline_token.rs4
-rw-r--r--tests/expectations/tests/layout_eth_conf.rs8
-rw-r--r--tests/expectations/tests/layout_eth_conf_1_0.rs8
-rw-r--r--tests/expectations/tests/layout_large_align_field.rs1
-rw-r--r--tests/expectations/tests/libclang-3.8/constant-evaluate.rs1
-rw-r--r--tests/expectations/tests/libclang-3.9/constant-evaluate.rs1
-rw-r--r--tests/expectations/tests/libclang-4/constant-evaluate.rs1
-rw-r--r--tests/expectations/tests/libclang_version_specific_generated_tests.rs1
-rw-r--r--tests/expectations/tests/namespace.rs18
-rw-r--r--tests/expectations/tests/nsStyleAutoArray.rs1
-rw-r--r--tests/expectations/tests/overflowed_enum.rs2
-rw-r--r--tests/expectations/tests/prepend-enum-constified-variant.rs1
-rw-r--r--tests/expectations/tests/short-enums.rs3
-rw-r--r--tests/expectations/tests/struct_typedef.rs2
-rw-r--r--tests/expectations/tests/struct_typedef_ns.rs2
-rw-r--r--tests/expectations/tests/weird_bitfields.rs1
-rw-r--r--tests/headers/constify-module-enums-namespace.hpp2
-rw-r--r--tests/headers/constify-module-enums-simple-nonamespace.hpp2
-rw-r--r--tests/headers/empty-enum.h15
-rw-r--r--tests/headers/issue-1197-pure-virtual-stuff.hpp6
-rw-r--r--tests/headers/issue-1216-variadic-member.h4
-rw-r--r--tests/headers/issue-816.h49
-rw-r--r--tests/headers/namespace.hpp5
-rw-r--r--tests/headers/ref_argument_array.hpp2
-rw-r--r--tests/quickchecking/Cargo.toml32
-rw-r--r--tests/quickchecking/README.md39
-rw-r--r--tests/quickchecking/src/bin.rs110
-rw-r--r--tests/quickchecking/src/fuzzers.rs637
-rw-r--r--tests/quickchecking/src/lib.rs126
-rw-r--r--tests/quickchecking/tests/fuzzed-c-headers.rs95
-rw-r--r--tests/rustfmt.toml2
86 files changed, 2503 insertions, 227 deletions
diff --git a/.travis.yml b/.travis.yml
index e5d0e105..ee3f970b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,12 +1,5 @@
language: rust
-addons:
- apt:
- sources:
- - ubuntu-toolchain-r-test
- packages:
- - gcc-5
-
os:
- linux
@@ -21,14 +14,10 @@ env:
- LLVM_VERSION="3.8.1" BINDGEN_JOB="test" BINDGEN_PROFILE="--release"
- LLVM_VERSION="3.8.1" BINDGEN_JOB="integration" BINDGEN_PROFILE=
- LLVM_VERSION="3.8.1" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release"
- - LLVM_VERSION="3.8.1" BINDGEN_JOB="expectations" BINDGEN_PROFILE=
- - LLVM_VERSION="3.8.1" BINDGEN_JOB="expectations" BINDGEN_PROFILE="--release"
- LLVM_VERSION="3.9.0" BINDGEN_JOB="test" BINDGEN_PROFILE=
- LLVM_VERSION="3.9.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release"
- LLVM_VERSION="3.9.0" BINDGEN_JOB="integration" BINDGEN_PROFILE=
- LLVM_VERSION="3.9.0" BINDGEN_JOB="integration" BINDGEN_PROFILE="--release"
- - LLVM_VERSION="3.9.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE=
- - LLVM_VERSION="3.9.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE="--release"
- LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE=
- LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE="--release"
- LLVM_VERSION="4.0.0" BINDGEN_JOB="test" BINDGEN_PROFILE= BINDGEN_FEATURES="testing_only_extra_assertions"
@@ -38,6 +27,7 @@ env:
- LLVM_VERSION="4.0.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE=
- LLVM_VERSION="4.0.0" BINDGEN_JOB="expectations" BINDGEN_PROFILE="--release"
- LLVM_VERSION="4.0.0" BINDGEN_JOB="misc"
+ - LLVM_VERSION="4.0.0" BINDGEN_JOB="quickchecking"
matrix:
fast_finish: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea6e94e5..f877dd58 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,21 +9,25 @@
- [Removed](#removed)
- [Fixed](#fixed)
- [Security](#security)
-- [0.31.0](#0310)
+- [0.32.0](#0320)
- [Added](#added-1)
- [Changed](#changed-1)
- - [Deprecated](#deprecated-1)
- - [Removed](#removed-1)
- [Fixed](#fixed-1)
-- [0.30.0](#0300)
+- [0.31.0](#0310)
- [Added](#added-2)
- [Changed](#changed-2)
- - [Deprecated](#deprecated-2)
+ - [Deprecated](#deprecated-1)
+ - [Removed](#removed-1)
- [Fixed](#fixed-2)
-- [0.29.0](#0290)
+- [0.30.0](#0300)
- [Added](#added-3)
- [Changed](#changed-3)
+ - [Deprecated](#deprecated-2)
- [Fixed](#fixed-3)
+- [0.29.0](#0290)
+ - [Added](#added-4)
+ - [Changed](#changed-4)
+ - [Fixed](#fixed-4)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -59,6 +63,105 @@ Released YYYY/MM/DD
--------------------------------------------------------------------------------
+# 0.32.1
+
+Released 2017/12/18
+
+## Fixed
+
+* When translating C/C++ `enum`s into Rust `enum`s using `rustified_enum` /
+ `--rustified-enum`, properly add `#[repr(C)]` to the emitted `enum`. [#1183][]
+
+[#1183]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1183
+
+--------------------------------------------------------------------------------
+
+# 0.32.0
+
+Released 2017/12/08
+
+## Added
+
+* Added support for bit-field allocation units that are larger than 64 bits
+ wide. Note that individual bit-fields within such units are still restricted
+ to being no wider than 64 bits. [#1158][]
+
+* We can now generate random C header files and test that `bindgen` can process
+ them with the `quickcheck` crate. Initial support landed in [#1159][] with a
+ few more additions in follow up pull requests.
+
+## Changed
+
+* The `bindgen::Builder::{constified_enum_module,{bitfield,rustified}_enum}`
+ builder methods and their corresponding CLI flags now compare their argument
+ to the C/C++ `enum`'s "canonical path", which includes leading namespaces,
+ rather than its "canonical name", which does not. This is a breaking change
+ that requires callers which target a namespaced C++ enum to call e.g.
+ `bitfield_enum("<namespace>::<enum_name>")` rather than e.g.
+ `bitfield_enum("<enum_name>")`. [#1162][]
+
+* When a struct is packed to a smaller alignment that is still greater than one,
+ `bindgen` cannot emit Rust bindings that match the input source. Before, it
+ would emit `#[repr(packed)]` anyways, which packs to an alignment of one, but
+ this can lead to misalignment and UB. Now, `bindgen` will detect these
+ situations and convert the struct into an opaque blob of bytes with the proper
+ alignment. We are eagerly awaiting support for `#[repr(packed(N))]` in
+ Rust. [#1136][]
+
+## Fixed
+
+* There was a perfect storm of conditions that could cause `bindgen` not to emit
+ any bindings if spawning `rustfmt` to format the bindings failed. This is now
+ fixed. [#1112][]
+
+* In some circumstances, `bindgen` would emit type parameters twice for
+ references to template instantiations. This is now fixed. [#1113][]
+
+* When a C/C++ struct had a field named with a Rust keyword, and `impl_debug`
+ was enabled, the generated `impl Debug for ...` blocks could reference the
+ field by the Rust keyword name, rather than the non-keyword field name we
+ actually end up generating. This is now fixed. [#1123][]
+
+* There was a regression in 0.31.0 where C++ template aliases to opaque types
+ would sometimes not treat the aliased type as opaque. This is now
+ fixed. [#1118][]
+
+* There was a regression in 0.31.0 that could cause `bindgen` to panic when
+ parsing nested template classes. This is now fixed. [#1127][]
+
+* Unnamed bit-fields do not affect alignment of their struct or class in C/C++,
+ however `bindgen` interpreted them as doing so, which could generate
+ `#[repr(C)]` structs expecting to have an incorrect alignment. This is now
+ fixed. [#1076][]
+
+* When a zero-sized type was used in a bit-field, `bindgen` could
+ divide-by-zero. This is now fixed. [#1137][]
+
+* When a template parameter is used in a bit-field, `bindgen` would panic. This
+ is now fixed. [#1140][]
+
+* There was a regression in 0.31.0 where if `bindgen` was given a header file
+ that did not exist, it would panic. This is now fixed, and it will instead
+ properly report the error. [#1146][]
+
+* In some cases, generated bit-field getters and setters could access memory
+ beyond `self`. This is now fixed. [#954][]
+
+[#1162]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1162
+[#1113]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1113
+[#1112]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1112
+[#1123]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1123
+[#1127]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1127
+[#1136]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1136
+[#1137]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1137
+[#1140]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1140
+[#1146]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1146
+[#1118]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1118
+[#1076]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1076
+[#1158]: https://github.com/rust-lang-nursery/rust-bindgen/issues/1158
+
+--------------------------------------------------------------------------------
+
# 0.31.0
Released 2017/10/27
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 1fb9ca8c..99589438 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -21,6 +21,7 @@ out to us in a GitHub issue, or stop by
- [Test Expectations and `libclang` Versions](#test-expectations-and-libclang-versions)
- [Integration Tests](#integration-tests)
- [Fuzzing `bindgen` with `csmith`](#fuzzing-bindgen-with-csmith)
+ - [Property tests for `bindgen` with `quickchecking`](#property-tests-for-bindgen-with-quickchecking)
- [Code Overview](#code-overview)
- [Pull Requests and Code Reviews](#pull-requests-and-code-reviews)
- [Generating Graphviz Dot Files](#generating-graphviz-dot-files)
@@ -224,6 +225,14 @@ uncover hidden bugs is by running `csmith` to generate random headers to test
See [./csmith-fuzzing/README.md](./csmith-fuzzing/README.md) for details.
+### Property tests for `bindgen` with `quickchecking`
+
+The `tests/quickchecking` crate generates property tests for `bindgen`.
+From the crate's directory you can run the tests with `cargo run`. For details
+on additional configuration including how to preserve / inspect the generated
+property tests, see
+[./tests/quickchecking/README.md](./tests/quickchecking/README.md).
+
## Code Overview
`bindgen` takes C and C++ header files as input and generates corresponding Rust
diff --git a/Cargo.lock b/Cargo.lock
index 81551c76..00b76ef1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -23,7 +23,7 @@ dependencies = [
[[package]]
name = "bindgen"
-version = "0.31.3"
+version = "0.32.1"
dependencies = [
"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)",
@@ -31,7 +31,7 @@ dependencies = [
"clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)",
"diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -65,7 +65,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
- "libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@@ -113,7 +113,7 @@ dependencies = [
[[package]]
name = "lazy_static"
-version = "0.2.8"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
@@ -123,11 +123,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libloading"
-version = "0.4.0"
+version = "0.4.3"
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.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -278,9 +278,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b"
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
+"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d"
"checksum libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)" = "e7eb6b826bfc1fdea7935d46556250d1799b7fe2d9f7951071f4291710665e3e"
-"checksum libloading 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "be99f814beb3e9503a786a592c909692bb6d4fc5a695f6ed7987223acfbd5194"
+"checksum libloading 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fd38073de8f7965d0c17d30546d4bb6da311ab428d1c7a3fc71dff7f9d4979b9"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
"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"
diff --git a/Cargo.toml b/Cargo.toml
index eee82f0c..e89127d9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,7 +13,7 @@ name = "bindgen"
readme = "README.md"
repository = "https://github.com/rust-lang-nursery/rust-bindgen"
documentation = "https://docs.rs/bindgen"
-version = "0.31.3"
+version = "0.32.1"
build = "build.rs"
include = [
@@ -45,7 +45,7 @@ cfg-if = "0.1.0"
# This kinda sucks: https://github.com/rust-lang/cargo/issues/1982
clap = "2"
clang-sys = { version = "0.21.0", features = ["runtime", "clang_3_9"] }
-lazy_static = "0.2.1"
+lazy_static = "1"
peeking_take_while = "0.1.2"
quote = "0.3.15"
regex = "0.2"
diff --git a/bindgen-integration/cpp/Test.h b/bindgen-integration/cpp/Test.h
index 7ddb98bd..4ab8373e 100644
--- a/bindgen-integration/cpp/Test.h
+++ b/bindgen-integration/cpp/Test.h
@@ -15,6 +15,10 @@ public:
static const int* countdown();
};
+class ITest {
+ virtual void foo() = 0;
+};
+
namespace testing {
typedef Test TypeAlias;
diff --git a/book/src/cpp.md b/book/src/cpp.md
index d181dec4..03249016 100644
--- a/book/src/cpp.md
+++ b/book/src/cpp.md
@@ -65,3 +65,9 @@ cannot translate into Rust:
* Automatically calling copy and/or move constructors or destructors. Supporting
this isn't possible with Rust's move semantics.
+
+* Exceptions: if a function called through a `bindgen`-generated interface
+ raises an exception that is not caught by the function itself, this will
+ generate undefined behaviour. See
+ [the tracking issue for exceptions](https://github.com/rust-lang-nursery/rust-bindgen/issues/1208)
+ for more details.
diff --git a/book/src/nocopy.md b/book/src/nocopy.md
index 06879ed1..ec21f3ae 100644
--- a/book/src/nocopy.md
+++ b/book/src/nocopy.md
@@ -6,7 +6,7 @@ Clone)]` to a translated type definition will compile, it still shouldn't do
that for reasons it can't know. In these cases, the `nocopy` annotation can be
used to prevent bindgen to autoderive the `Copy` and `Clone` traits for a type.
-###Library
+### Library
* [`bindgen::Builder::no_copy`](https://docs.rs/bindgen/0.23.1/bindgen/struct.Builder.html#method.no_copy)
diff --git a/ci/script.sh b/ci/script.sh
index 7338dc0b..91ea7c13 100755
--- a/ci/script.sh
+++ b/ci/script.sh
@@ -38,6 +38,11 @@ case "$BINDGEN_JOB" in
# ./ci/assert-rustfmt.sh
;;
+ "quickchecking")
+ cd ./tests/quickchecking
+ # TODO: Actually run quickchecks once `bindgen` is reliable enough.
+ cargo test
+ ;;
*)
echo "Error! Unknown \$BINDGEN_JOB: '$BINDGEN_JOB'"
exit 1
diff --git a/csmith-fuzzing/predicate.py b/csmith-fuzzing/predicate.py
index 2f561148..3bf452ef 100755
--- a/csmith-fuzzing/predicate.py
+++ b/csmith-fuzzing/predicate.py
@@ -46,6 +46,11 @@ parser.add_argument(
help="An argument string that `bindgen` should be invoked with. By default, all traits are derived. Note that the input header and output bindings file will automatically be provided by this script, and you should not manually specify them.")
parser.add_argument(
+ "--save-temp-files",
+ action="store_true",
+ help="Do not delete temporary files.")
+
+parser.add_argument(
"input",
type=str,
default="input.h",
@@ -144,11 +149,12 @@ def main():
exit_code = 2
print("Unexpected exception:", e)
- for path in TEMP_FILES:
- try:
- os.remove(path)
- except Exception as e:
- print("Unexpected exception:", e)
+ if not args.save_temp_files:
+ for path in TEMP_FILES:
+ try:
+ os.remove(path)
+ except Exception as e:
+ print("Unexpected exception:", e)
sys.exit(exit_code)
diff --git a/rustfmt.toml b/rustfmt.toml
index 96d4ae47..0a24dd73 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -1,10 +1,6 @@
max_width = 80
-format_strings = false
fn_brace_style = "SameLineWhere"
item_brace_style = "SameLineWhere"
struct_lit_multiline_style = "ForceMulti"
where_trailing_comma = true
-reorder_imports = true
-reorder_imported_names = true
normalize_comments = false
-write_mode = "Overwrite"
diff --git a/src/clang.rs b/src/clang.rs
index a0e7fa3d..c0c96e5e 100644
--- a/src/clang.rs
+++ b/src/clang.rs
@@ -606,11 +606,16 @@ impl Cursor {
unsafe { clang_CXXMethod_isConst(self.x) != 0 }
}
- /// Is this cursor's referent a member function that is declared `const`?
+ /// Is this cursor's referent a member function that is virtual?
pub fn method_is_virtual(&self) -> bool {
unsafe { clang_CXXMethod_isVirtual(self.x) != 0 }
}
+ /// Is this cursor's referent a member function that is pure virtual?
+ pub fn method_is_pure_virtual(&self) -> bool {
+ unsafe { clang_CXXMethod_isPureVirtual(self.x) != 0 }
+ }
+
/// Is this cursor's referent a struct or class with virtual members?
pub fn is_virtual_base(&self) -> bool {
unsafe { clang_isVirtualBase(self.x) != 0 }
@@ -628,6 +633,67 @@ impl Cursor {
};
if rt.is_valid() { Some(rt) } else { None }
}
+
+ /// Gets the tokens that correspond to that cursor.
+ pub fn tokens(&self) -> Option<Vec<Token>> {
+ let range = self.extent();
+ let mut tokens = vec![];
+ unsafe {
+ let tu = clang_Cursor_getTranslationUnit(self.x);
+ let mut token_ptr = ptr::null_mut();
+ let mut num_tokens: c_uint = 0;
+ clang_tokenize(tu, range, &mut token_ptr, &mut num_tokens);
+ if token_ptr.is_null() {
+ return None;
+ }
+
+ let token_array =
+ slice::from_raw_parts(token_ptr, num_tokens as usize);
+ for &token in token_array.iter() {
+ let kind = clang_getTokenKind(token);
+ let spelling =
+ cxstring_into_string(clang_getTokenSpelling(tu, token));
+
+ tokens.push(Token {
+ kind: kind,
+ spelling: spelling,
+ });
+ }
+ clang_disposeTokens(tu, token_ptr, num_tokens);
+ }
+ Some(tokens)
+ }
+
+ /// Gets the tokens that correspond to that cursor as `cexpr` tokens.
+ pub fn cexpr_tokens(self) -> Option<Vec<cexpr::token::Token>> {
+ use cexpr::token;
+
+ self.tokens().map(|tokens| {
+ tokens
+ .into_iter()
+ .filter_map(|token| {
+ let kind = match token.kind {
+ CXToken_Punctuation => token::Kind::Punctuation,
+ CXToken_Literal => token::Kind::Literal,
+ CXToken_Identifier => token::Kind::Identifier,
+ CXToken_Keyword => token::Kind::Keyword,
+ // NB: cexpr is not too happy about comments inside
+ // expressions, so we strip them down here.
+ CXToken_Comment => return None,
+ _ => {
+ error!("Found unexpected token kind: {:?}", token);
+ return None;
+ }
+ };
+
+ Some(token::Token {
+ kind: kind,
+ raw: token.spelling.into_bytes().into_boxed_slice(),
+ })
+ })
+ .collect::<Vec<_>>()
+ })
+ }
}
/// Checks whether the name looks like an identifier, i.e. is alphanumeric
@@ -1346,71 +1412,6 @@ impl TranslationUnit {
pub fn is_null(&self) -> bool {
self.x.is_null()
}
-
- /// Invoke Clang's lexer on this translation unit and get the stream of
- /// tokens that come out.
- pub fn tokens(&self, cursor: &Cursor) -> Option<Vec<Token>> {
- let range = cursor.extent();
- let mut tokens = vec![];
- unsafe {
- let mut token_ptr = ptr::null_mut();
- let mut num_tokens: c_uint = 0;
- clang_tokenize(self.x, range, &mut token_ptr, &mut num_tokens);
- if token_ptr.is_null() {
- return None;
- }
-
- let token_array =
- slice::from_raw_parts(token_ptr, num_tokens as usize);
- for &token in token_array.iter() {
- let kind = clang_getTokenKind(token);
- let spelling =
- cxstring_into_string(clang_getTokenSpelling(self.x, token));
-
- tokens.push(Token {
- kind: kind,
- spelling: spelling,
- });
- }
- clang_disposeTokens(self.x, token_ptr, num_tokens);
- }
- Some(tokens)
- }
-
- /// Convert a set of tokens from clang into `cexpr` tokens, for further
- /// processing.
- pub fn cexpr_tokens(
- &self,
- cursor: &Cursor,
- ) -> Option<Vec<cexpr::token::Token>> {
- use cexpr::token;
-
- self.tokens(cursor).map(|tokens| {
- tokens
- .into_iter()
- .filter_map(|token| {
- let kind = match token.kind {
- CXToken_Punctuation => token::Kind::Punctuation,
- CXToken_Literal => token::Kind::Literal,
- CXToken_Identifier => token::Kind::Identifier,
- CXToken_Keyword => token::Kind::Keyword,
- // NB: cexpr is not too happy about comments inside
- // expressions, so we strip them down here.
- CXToken_Comment => return None,
- _ => {
- error!("Found unexpected token kind: {:?}", token);
- return None;
- }
- };
-
- Some(token::Token {
- kind: kind,
- raw: token.spelling.into_bytes().into_boxed_slice(),
- })
- })
- .collect::<Vec<_>>()
- })
- }
}
impl Drop for TranslationUnit {
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 784613ba..16ff79fb 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -26,7 +26,7 @@ use ir::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault,
CanDerivePartialEq, CanDeriveEq, CanDerive};
use ir::dot;
use ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
-use ir::function::{Abi, Function, FunctionSig, Linkage};
+use ir::function::{Abi, Function, FunctionKind, FunctionSig, Linkage};
use ir::int::IntKind;
use ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath};
use ir::item_kind::ItemKind;
@@ -1878,13 +1878,8 @@ impl CodeGenerator for CompInfo {
}
if ctx.options().codegen_config.destructors {
- if let Some((is_virtual, destructor)) = self.destructor() {
- let kind = if is_virtual {
- MethodKind::VirtualDestructor
- } else {
- MethodKind::Destructor
- };
-
+ if let Some((kind, destructor)) = self.destructor() {
+ debug_assert!(kind.is_destructor());
Method::new(kind, destructor, false).codegen_method(
ctx,
&mut methods,
@@ -1990,9 +1985,9 @@ impl MethodCodegen for Method {
match self.kind() {
MethodKind::Constructor => cc.constructors,
MethodKind::Destructor => cc.destructors,
- MethodKind::VirtualDestructor => cc.destructors,
+ MethodKind::VirtualDestructor { .. } => cc.destructors,
MethodKind::Static | MethodKind::Normal |
- MethodKind::Virtual => cc.methods,
+ MethodKind::Virtual { .. } => cc.methods,
}
});
@@ -2148,7 +2143,10 @@ impl EnumVariation {
/// A helper type to construct different enum variations.
enum EnumBuilder<'a> {
- Rust(quote::Tokens),
+ Rust {
+ tokens: quote::Tokens,
+ emitted_any_variants: bool,
+ },
Bitfield {
canonical_name: &'a str,
tokens: quote::Tokens,
@@ -2188,7 +2186,10 @@ impl<'a> EnumBuilder<'a> {
pub enum #ident
};
tokens.append("{");
- EnumBuilder::Rust(tokens)
+ EnumBuilder::Rust {
+ tokens,
+ emitted_any_variants: false,
+ }
}
EnumVariation::Consts => {
@@ -2229,12 +2230,15 @@ impl<'a> EnumBuilder<'a> {
};
match self {
- EnumBuilder::Rust(tokens) => {
+ EnumBuilder::Rust { tokens, emitted_any_variants: _ } => {
let name = ctx.rust_ident(variant_name);
- EnumBuilder::Rust(quote! {
- #tokens
- #name = #expr,
- })
+ EnumBuilder::Rust {
+ tokens: quote! {
+ #tokens
+ #name = #expr,
+ },
+ emitted_any_variants: true,
+ }
}
EnumBuilder::Bitfield { .. } => {
@@ -2295,9 +2299,12 @@ impl<'a> EnumBuilder<'a> {
result: &mut CodegenResult<'b>,
) -> quote::Tokens {
match self {
- EnumBuilder::Rust(mut t) => {
- t.append("}");
- t
+ EnumBuilder::Rust { mut tokens, emitted_any_variants } => {
+ if !emitted_any_variants {
+ tokens.append(quote! { __bindgen_cannot_repr_c_on_empty_enum = 0 });
+ }
+ tokens.append("}");
+ tokens
}
EnumBuilder::Bitfield {
canonical_name,
@@ -2419,8 +2426,6 @@ impl CodeGenerator for Enum {
}
};
- // FIXME(emilio): These should probably use the path so it can
- // disambiguate between namespaces, just like is_opaque etc.
let variation = if self.is_bitfield(ctx, item) {
EnumVariation::Bitfield
} else if self.is_rustified_enum(ctx, item) {
@@ -2434,15 +2439,12 @@ impl CodeGenerator for Enum {
let mut attrs = vec![];
- // FIXME: Rust forbids repr with empty enums. Remove this condition when
- // this is allowed.
- //
// TODO(emilio): Delegate this to the builders?
if variation.is_rust() {
- if !self.variants().is_empty() {
- attrs.push(attributes::repr(repr_name));
- }
- } else if variation.is_bitfield() {
+ attrs.push(attributes::repr(repr_name));
+ }
+
+ if variation.is_bitfield() || variation.is_rust() {
attrs.push(attributes::repr("C"));
}
@@ -3167,6 +3169,15 @@ impl CodeGenerator for Function {
Linkage::External => {}
}
+ // Pure virtual methods have no actual symbol, so we can't generate
+ // something meaningful for them.
+ match self.kind() {
+ FunctionKind::Method(ref method_kind) if method_kind.is_pure_virtual() => {
+ return;
+ }
+ _ => {},
+ }
+
// Similar to static member variables in a class template, we can't
// generate bindings to template functions, because the set of
// instantiations is open ended and we have no way of knowing which
@@ -3238,12 +3249,6 @@ impl CodeGenerator for Function {
abi => abi,
};
- let variadic = if signature.is_variadic() {
- quote! { ... }
- } else {
- quote! {}
- };
-
let ident = ctx.rust_ident(canonical_name);
let mut tokens = quote! { extern #abi };
tokens.append("{\n");
@@ -3251,8 +3256,6 @@ impl CodeGenerator for Function {
tokens.append_separated(attributes, "\n");
tokens.append("\n");
}
- let mut args = args;
- args.push(variadic);
tokens.append(quote! {
pub fn #ident ( #( #args ),* ) #ret;
});
@@ -3708,7 +3711,7 @@ mod utils {
use super::ToPtr;
let mut unnamed_arguments = 0;
- sig.argument_types().iter().map(|&(ref name, ty)| {
+ let mut args = sig.argument_types().iter().map(|&(ref name, ty)| {
let arg_item = ctx.resolve_item(ty);
let arg_ty = arg_item.kind().expect_type();
@@ -3755,6 +3758,12 @@ mod utils {
quote! {
#arg_name : #arg_ty
}
- }).collect()
+ }).collect::<Vec<_>>();
+
+ if sig.is_variadic() {
+ args.push(quote! { ... })
+ }
+
+ args
}
}
diff --git a/src/ir/comp.rs b/src/ir/comp.rs
index 58bd3d3c..5008dcfd 100644
--- a/src/ir/comp.rs
+++ b/src/ir/comp.rs
@@ -37,13 +37,40 @@ pub enum MethodKind {
/// A destructor.
Destructor,
/// A virtual destructor.
- VirtualDestructor,
+ VirtualDestructor {
+ /// Whether it's pure virtual.
+ pure_virtual: bool,
+ },
/// A static method.
Static,
/// A normal method.
Normal,
/// A virtual method.
- Virtual,
+ Virtual {
+ /// Whether it's pure virtual.
+ pure_virtual: bool,
+ },
+}
+
+
+impl MethodKind {
+ /// Is this a destructor method?
+ pub fn is_destructor(&self) -> bool {
+ match *self {
+ MethodKind::Destructor |
+ MethodKind::VirtualDestructor { .. } => true,
+ _ => false,
+ }
+ }
+
+ /// Is this a pure virtual method?
+ pub fn is_pure_virtual(&self) -> bool {
+ match *self {
+ MethodKind::Virtual { pure_virtual } |
+ MethodKind::VirtualDestructor { pure_virtual } => pure_virtual,
+ _ => false,
+ }
+ }
}
/// A struct representing a C++ method, either static, normal, or virtual.
@@ -73,12 +100,6 @@ impl Method {
self.kind
}
- /// Is this a destructor method?
- pub fn is_destructor(&self) -> bool {
- self.kind == MethodKind::Destructor ||
- self.kind == MethodKind::VirtualDestructor
- }
-
/// Is this a constructor?
pub fn is_constructor(&self) -> bool {
self.kind == MethodKind::Constructor
@@ -86,8 +107,11 @@ impl Method {
/// Is this a virtual method?
pub fn is_virtual(&self) -> bool {
- self.kind == MethodKind::Virtual ||
- self.kind == MethodKind::VirtualDestructor
+ match self.kind {
+ MethodKind::Virtual { .. } |
+ MethodKind::VirtualDestructor { .. } => true,
+ _ => false,
+ }
}
/// Is this a static method?
@@ -960,7 +984,7 @@ pub struct CompInfo {
/// The destructor of this type. The bool represents whether this destructor
/// is virtual.
- destructor: Option<(bool, FunctionId)>,
+ destructor: Option<(MethodKind, FunctionId)>,
/// Vector of classes this one inherits from.
base_members: Vec<Base>,
@@ -1104,7 +1128,7 @@ impl CompInfo {
}
/// Get this type's destructor.
- pub fn destructor(&self) -> Option<(bool, FunctionId)> {
+ pub fn destructor(&self) -> Option<(MethodKind, FunctionId)> {
self.destructor
}
@@ -1355,14 +1379,23 @@ impl CompInfo {
ci.constructors.push(signature);
}
CXCursor_Destructor => {
- ci.destructor = Some((is_virtual, signature));
+ let kind = if is_virtual {
+ MethodKind::VirtualDestructor {
+ pure_virtual: cur.method_is_pure_virtual(),
+ }
+ } else {
+ MethodKind::Destructor
+ };
+ ci.destructor = Some((kind, signature));
}
CXCursor_CXXMethod => {
let is_const = cur.method_is_const();
let method_kind = if is_static {
MethodKind::Static
} else if is_virtual {
- MethodKind::Virtual
+ MethodKind::Virtual {
+ pure_virtual: cur.method_is_pure_virtual(),
+ }
} else {
MethodKind::Normal
};
@@ -1658,11 +1691,11 @@ impl Trace for CompInfo {
}
for method in self.methods() {
- if method.is_destructor() {
- tracer.visit_kind(method.signature.into(), EdgeKind::Destructor);
- } else {
- tracer.visit_kind(method.signature.into(), EdgeKind::Method);
- }
+ tracer.visit_kind(method.signature.into(), EdgeKind::Method);
+ }
+
+ if let Some((_kind, signature)) = self.destructor() {
+ tracer.visit_kind(signature.into(), EdgeKind::Destructor);
}
for ctor in self.constructors() {
diff --git a/src/ir/context.rs b/src/ir/context.rs
index b2ebb929..258c6a0c 100644
--- a/src/ir/context.rs
+++ b/src/ir/context.rs
@@ -2092,7 +2092,7 @@ impl BindgenContext {
::clang_sys::CXCursor_Namespace,
"Be a nice person"
);
- let tokens = match self.translation_unit.tokens(&cursor) {
+ let tokens = match cursor.tokens() {
Some(tokens) => tokens,
None => return (None, ModuleKind::Normal),
};
diff --git a/src/ir/enum_ty.rs b/src/ir/enum_ty.rs
index d0968515..4df9fa3e 100644
--- a/src/ir/enum_ty.rs
+++ b/src/ir/enum_ty.rs
@@ -5,7 +5,7 @@ use super::item::Item;
use super::ty::TypeKind;
use clang;
use ir::annotations::Annotations;
-use ir::item::ItemCanonicalName;
+use ir::item::ItemCanonicalPath;
use parse::{ClangItemParser, ParseError};
/// An enum representing custom handling that can be given to a variant.
@@ -130,10 +130,10 @@ impl Enum {
/// Whether the enum should be a bitfield
pub fn is_bitfield(&self, ctx: &BindgenContext, item: &Item) -> bool {
- let name = item.canonical_name(ctx);
+ let path = item.canonical_path(ctx);
let enum_ty = item.expect_type();
- ctx.options().bitfield_enums.matches(&name) ||
+ ctx.options().bitfield_enums.matches(&path[1..].join("::")) ||
(enum_ty.name().is_none() &&
self.variants().iter().any(|v| {
ctx.options().bitfield_enums.matches(&v.name())
@@ -146,10 +146,10 @@ impl Enum {
ctx: &BindgenContext,
item: &Item,
) -> bool {
- let name = item.canonical_name(ctx);
+ let path = item.canonical_path(ctx);
let enum_ty = item.expect_type();
- ctx.options().constified_enum_modules.matches(&name) ||
+ ctx.options().constified_enum_modules.matches(&path[1..].join("::")) ||
(enum_ty.name().is_none() &&
self.variants().iter().any(|v| {
ctx.options().constified_enum_modules.matches(&v.name())
@@ -158,10 +158,10 @@ impl Enum {
/// Whether the enum should be a Rust enum
pub fn is_rustified_enum(&self, ctx: &BindgenContext, item: &Item) -> bool {
- let name = item.canonical_name(ctx);
+ let path = item.canonical_path(ctx);
let enum_ty = item.expect_type();
- ctx.options().rustified_enums.matches(&name) ||
+ ctx.options().rustified_enums.matches(&path[1..].join("::")) ||
(enum_ty.name().is_none() &&
self.variants().iter().any(|v| {
ctx.options().rustified_enums.matches(&v.name())
diff --git a/src/ir/function.rs b/src/ir/function.rs
index 62792484..7b8349a2 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -27,17 +27,26 @@ pub enum FunctionKind {
impl FunctionKind {
fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> {
+ // FIXME(emilio): Deduplicate logic with `ir::comp`.
Some(match cursor.kind() {
clang_sys::CXCursor_FunctionDecl => FunctionKind::Function,
clang_sys::CXCursor_Constructor => FunctionKind::Method(
MethodKind::Constructor,
),
clang_sys::CXCursor_Destructor => FunctionKind::Method(
- MethodKind::Destructor,
+ if cursor.method_is_virtual() {
+ MethodKind::VirtualDestructor {
+ pure_virtual: cursor.method_is_pure_virtual(),
+ }
+ } else {
+ MethodKind::Destructor
+ }
),
clang_sys::CXCursor_CXXMethod => {
if cursor.method_is_virtual() {
- FunctionKind::Method(MethodKind::Virtual)
+ FunctionKind::Method(MethodKind::Virtual {
+ pure_virtual: cursor.method_is_pure_virtual(),
+ })
} else if cursor.method_is_static() {
FunctionKind::Method(MethodKind::Static)
} else {
diff --git a/src/ir/item.rs b/src/ir/item.rs
index a9203639..89ab2569 100644
--- a/src/ir/item.rs
+++ b/src/ir/item.rs
@@ -944,12 +944,12 @@ impl Item {
cc.constructors
}
FunctionKind::Method(MethodKind::Destructor) |
- FunctionKind::Method(MethodKind::VirtualDestructor) => {
+ FunctionKind::Method(MethodKind::VirtualDestructor { .. }) => {
cc.destructors
}
FunctionKind::Method(MethodKind::Static) |
FunctionKind::Method(MethodKind::Normal) |
- FunctionKind::Method(MethodKind::Virtual) => cc.methods,
+ FunctionKind::Method(MethodKind::Virtual { .. }) => cc.methods,
}
}
}
diff --git a/src/ir/var.rs b/src/ir/var.rs
index 9d6c1452..db105da1 100644
--- a/src/ir/var.rs
+++ b/src/ir/var.rs
@@ -127,7 +127,7 @@ impl ClangSubItemParser for Var {
visitor.parsed_macro(&cursor.spelling());
}
- let value = parse_macro(ctx, &cursor, ctx.translation_unit());
+ let value = parse_macro(ctx, &cursor);
let (id, value) = match value {
Some(v) => v,
@@ -294,11 +294,10 @@ impl ClangSubItemParser for Var {
fn parse_macro(
ctx: &BindgenContext,
cursor: &clang::Cursor,
- unit: &clang::TranslationUnit,
) -> Option<(Vec<u8>, cexpr::expr::EvalResult)> {
use cexpr::{expr, nom};
- let mut cexpr_tokens = match unit.cexpr_tokens(cursor) {
+ let mut cexpr_tokens = match cursor.cexpr_tokens() {
None => return None,
Some(tokens) => tokens,
};
@@ -328,14 +327,11 @@ fn parse_macro(
}
}
-fn parse_int_literal_tokens(
- cursor: &clang::Cursor,
- unit: &clang::TranslationUnit,
-) -> Option<i64> {
+fn parse_int_literal_tokens(cursor: &clang::Cursor) -> Option<i64> {
use cexpr::{expr, nom};
use cexpr::expr::EvalResult;
- let cexpr_tokens = match unit.cexpr_tokens(cursor) {
+ let cexpr_tokens = match cursor.cexpr_tokens() {
None => return None,
Some(tokens) => tokens,
};
@@ -357,7 +353,7 @@ fn get_integer_literal_from_cursor(
match c.kind() {
CXCursor_IntegerLiteral |
CXCursor_UnaryOperator => {
- value = parse_int_literal_tokens(&c, unit);
+ value = parse_int_literal_tokens(&c);
}
CXCursor_UnexposedExpr => {
value = get_integer_literal_from_cursor(&c, unit);
diff --git a/src/lib.rs b/src/lib.rs
index aec901d4..e2dbf8b5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -178,6 +178,7 @@ impl Builder {
output_vector.push(header);
}
+ output_vector.push("--rust-target".into());
output_vector.push(self.options.rust_target.into());
self.options
@@ -1608,7 +1609,7 @@ impl Bindings {
if let Some(h) = options.input_header.as_ref() {
if let Ok(md) = std::fs::metadata(h) {
- if !md.is_file() {
+ if md.is_dir() {
eprintln!("error: '{}' is a folder", h);
return Err(());
}
@@ -1710,15 +1711,7 @@ impl Bindings {
let rustfmt = which::which("rustfmt")
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_owned()))?;
- // Prefer using the `rustfmt-nightly` version of `rustmft`, if
- // possible. It requires being run via `rustup run nightly ...`.
- let mut cmd = if let Ok(rustup) = which::which("rustup") {
- let mut cmd = Command::new(rustup);
- cmd.args(&["run", "nightly", "rustfmt", "--"]);
- cmd
- } else {
- Command::new(rustfmt)
- };
+ let mut cmd = Command::new(rustfmt);
cmd
.stdin(Stdio::piped())
@@ -1898,6 +1891,7 @@ fn commandline_flag_unit_test_function() {
let command_line_flags = bindings.command_line_flags();
let test_cases = vec![
+ "--rust-target",
"--no-derive-default",
"--generate",
"function,types,vars,methods,constructors,destructors",
@@ -1917,6 +1911,7 @@ fn commandline_flag_unit_test_function() {
let command_line_flags = bindings.command_line_flags();
let test_cases = vec![
+ "--rust-target",
"input_header",
"--no-derive-default",
"--generate",
diff --git a/src/options.rs b/src/options.rs
index 10c31234..6d6e712c 100644
--- a/src/options.rs
+++ b/src/options.rs
@@ -19,7 +19,7 @@ where
);
let matches = App::new("bindgen")
- .version(env!("CARGO_PKG_VERSION"))
+ .version(option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"))
.about("Generates Rust bindings from C/C++ headers.")
.usage("bindgen [FLAGS] [OPTIONS] <header> -- <clang-args>...")
.args(&[
@@ -237,9 +237,9 @@ where
.help("Generate inline functions."),
Arg::with_name("whitelist-type")
.long("whitelist-type")
- .help("Whitelist the type. Other non-whitelisted types will \
+ .help("Only generate types matching <regex>. Other non-whitelisted types will \
not be generated.")
- .value_name("type")
+ .value_name("regex")
.takes_value(true)
.multiple(true)
.number_of_values(1),
diff --git a/tests/expectations/build.rs b/tests/expectations/build.rs
new file mode 100644
index 00000000..0727ce51
--- /dev/null
+++ b/tests/expectations/build.rs
@@ -0,0 +1,60 @@
+//! Generate a module with a custom `#[path=...]` for each of the files in our
+//! libclang version-specific test expectations so that they get their layout
+//! tests run. We need to do this because cargo doesn't automatically detect
+//! tests subdirectories.
+
+use std::env;
+use std::fs;
+use std::io::Write;
+use std::path::Path;
+
+const LIBCLANG_VERSION_DIRS: &'static [&'static str] =
+ &["libclang-3.8", "libclang-3.9", "libclang-4"];
+
+fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+
+ let mut test_string = String::new();
+
+ for dir in LIBCLANG_VERSION_DIRS {
+ let dir = Path::new(&env::var_os("CARGO_MANIFEST_DIR").unwrap())
+ .join("tests")
+ .join(dir);
+
+ println!("cargo:rerun-if-changed={}", dir.display());
+
+ for entry in fs::read_dir(dir).unwrap() {
+ let entry = entry.unwrap();
+ let path = entry.path();
+ let path = path.canonicalize().unwrap_or_else(|_| path.into());
+ if path.extension().map(|e| e.to_string_lossy()) != Some("rs".into()) {
+ continue;
+ }
+
+ println!("cargo:rerun-if-changed={}", path.display());
+
+ let module_name: String = path.display()
+ .to_string()
+ .chars()
+ .map(|c| match c {
+ 'a'...'z' | 'A'...'Z' | '0'...'9' => c,
+ _ => '_',
+ })
+ .collect();
+
+ test_string.push_str(&format!(
+ r###"
+#[path = "{}"]
+mod {};
+"###,
+ path.display(),
+ module_name,
+ ));
+ }
+ }
+
+ let out_path = Path::new(&env::var_os("OUT_DIR").unwrap())
+ .join("libclang_version_specific_generated_tests.rs");
+ let mut test_file = fs::File::create(out_path).unwrap();
+ test_file.write_all(test_string.as_bytes()).unwrap();
+}
diff --git a/tests/expectations/tests/anon_enum.rs b/tests/expectations/tests/anon_enum.rs
index 718905d9..c482530c 100644
--- a/tests/expectations/tests/anon_enum.rs
+++ b/tests/expectations/tests/anon_enum.rs
@@ -12,6 +12,7 @@ pub struct Test {
}
pub const Test_T_NONE: Test__bindgen_ty_1 = Test__bindgen_ty_1::T_NONE;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Test__bindgen_ty_1 {
T_NONE = 0,
@@ -40,6 +41,7 @@ fn bindgen_test_layout_Test() {
);
}
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Baz {
Foo = 0,
diff --git a/tests/expectations/tests/anon_enum_trait.rs b/tests/expectations/tests/anon_enum_trait.rs
index 9f5a6c56..21d22879 100644
--- a/tests/expectations/tests/anon_enum_trait.rs
+++ b/tests/expectations/tests/anon_enum_trait.rs
@@ -19,6 +19,7 @@ pub const DataType_channels: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::ge
pub const DataType_fmt: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type;
pub const DataType_type_: DataType__bindgen_ty_1 = DataType__bindgen_ty_1::generic_type;
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum DataType__bindgen_ty_1 {
generic_type = 0,
@@ -31,6 +32,7 @@ pub struct Foo {
pub const Foo_Bar: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::Bar;
pub const Foo_Baz: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::Bar;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo__bindgen_ty_1 {
Bar = 0,
diff --git a/tests/expectations/tests/anon_enum_whitelist.rs b/tests/expectations/tests/anon_enum_whitelist.rs
index c639410f..45b858fd 100644
--- a/tests/expectations/tests/anon_enum_whitelist.rs
+++ b/tests/expectations/tests/anon_enum_whitelist.rs
@@ -7,6 +7,7 @@
pub const NODE_FLAG_FOO: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_FOO;
pub const NODE_FLAG_BAR: _bindgen_ty_1 = _bindgen_ty_1::NODE_FLAG_BAR;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
NODE_FLAG_FOO = 0,
diff --git a/tests/expectations/tests/anon_union.rs b/tests/expectations/tests/anon_union.rs
index fdf01a7a..da990ae9 100644
--- a/tests/expectations/tests/anon_union.rs
+++ b/tests/expectations/tests/anon_union.rs
@@ -14,6 +14,7 @@ pub struct TErrorResult {
pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState =
TErrorResult_UnionState::HasMessage;
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TErrorResult_UnionState {
HasMessage = 0,
diff --git a/tests/expectations/tests/anon_union_1_0.rs b/tests/expectations/tests/anon_union_1_0.rs
index 8d19c9fc..67a332c0 100644
--- a/tests/expectations/tests/anon_union_1_0.rs
+++ b/tests/expectations/tests/anon_union_1_0.rs
@@ -58,6 +58,7 @@ pub struct TErrorResult {
pub const TErrorResult_UnionState_HasException: TErrorResult_UnionState =
TErrorResult_UnionState::HasMessage;
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum TErrorResult_UnionState {
HasMessage = 0,
diff --git a/tests/expectations/tests/bitfield_align_2.rs b/tests/expectations/tests/bitfield_align_2.rs
index 6f4a0f69..5174d1aa 100644
--- a/tests/expectations/tests/bitfield_align_2.rs
+++ b/tests/expectations/tests/bitfield_align_2.rs
@@ -84,6 +84,7 @@ where
}
}
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MyEnum {
ONE = 0,
diff --git a/tests/expectations/tests/class_with_inner_struct.rs b/tests/expectations/tests/class_with_inner_struct.rs
index ecdbdf9f..f6560125 100644
--- a/tests/expectations/tests/class_with_inner_struct.rs
+++ b/tests/expectations/tests/class_with_inner_struct.rs
@@ -214,6 +214,7 @@ fn bindgen_test_layout_B() {
);
}
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum StepSyntax {
Keyword = 0,
diff --git a/tests/expectations/tests/class_with_inner_struct_1_0.rs b/tests/expectations/tests/class_with_inner_struct_1_0.rs
index 1236950c..e8072362 100644
--- a/tests/expectations/tests/class_with_inner_struct_1_0.rs
+++ b/tests/expectations/tests/class_with_inner_struct_1_0.rs
@@ -272,6 +272,7 @@ impl Clone for B {
}
}
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum StepSyntax {
Keyword = 0,
diff --git a/tests/expectations/tests/const_enum_unnamed.rs b/tests/expectations/tests/const_enum_unnamed.rs
index 539c8916..833f8351 100644
--- a/tests/expectations/tests/const_enum_unnamed.rs
+++ b/tests/expectations/tests/const_enum_unnamed.rs
@@ -7,6 +7,7 @@
pub const FOO_BAR: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAR;
pub const FOO_BAZ: _bindgen_ty_1 = _bindgen_ty_1::FOO_BAZ;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
FOO_BAR = 0,
@@ -19,6 +20,7 @@ pub struct Foo {
}
pub const Foo_FOO_BAR: Foo__bindgen_ty_1 = Foo__bindgen_ty_1::FOO_BAR;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo__bindgen_ty_1 {
FOO_BAR = 10,
diff --git a/tests/expectations/tests/constify-enum.rs b/tests/expectations/tests/constify-enum.rs
index 78644ae4..79fc4dff 100644
--- a/tests/expectations/tests/constify-enum.rs
+++ b/tests/expectations/tests/constify-enum.rs
@@ -9,6 +9,7 @@ pub const nsCSSPropertyID_eCSSProperty_COUNT_unexistingVariantValue: nsCSSProper
pub const nsCSSPropertyID_eCSSProperty_COUNT: nsCSSPropertyID =
nsCSSPropertyID::eCSSPropertyAlias_aa;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsCSSPropertyID {
eCSSProperty_a = 0,
diff --git a/tests/expectations/tests/empty-enum.rs b/tests/expectations/tests/empty-enum.rs
new file mode 100644
index 00000000..4ec7df8a
--- /dev/null
+++ b/tests/expectations/tests/empty-enum.rs
@@ -0,0 +1,36 @@
+/* automatically generated by rust-bindgen */
+
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+
+pub type EmptyConstified = ::std::os::raw::c_uint;
+#[repr(u32)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum EmptyRustified {
+ __bindgen_cannot_repr_c_on_empty_enum = 0,
+}
+pub mod EmptyModule {
+ pub type Type = ::std::os::raw::c_uint;
+}
+#[repr(i8)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum EmptyClassRustified {
+ __bindgen_cannot_repr_c_on_empty_enum = 0,
+}
+pub type EmptyClassConstified = ::std::os::raw::c_char;
+pub mod EmptyClassModule {
+ pub type Type = ::std::os::raw::c_char;
+}
+#[repr(i8)]
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum ForwardClassRustified {
+ __bindgen_cannot_repr_c_on_empty_enum = 0,
+}
+pub type ForwardClassConstified = ::std::os::raw::c_char;
+pub mod ForwardClassModule {
+ pub type Type = ::std::os::raw::c_char;
+}
diff --git a/tests/expectations/tests/enum.rs b/tests/expectations/tests/enum.rs
index 70c30830..b1920aae 100644
--- a/tests/expectations/tests/enum.rs
+++ b/tests/expectations/tests/enum.rs
@@ -5,12 +5,14 @@
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 0,
Qux = 1,
}
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Neg {
MinusOne = -1,
diff --git a/tests/expectations/tests/enum_alias.rs b/tests/expectations/tests/enum_alias.rs
index f12c08d3..cde429f7 100644
--- a/tests/expectations/tests/enum_alias.rs
+++ b/tests/expectations/tests/enum_alias.rs
@@ -5,6 +5,7 @@
#[repr(u8)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Bar {
VAL = 0,
diff --git a/tests/expectations/tests/enum_and_vtable_mangling.rs b/tests/expectations/tests/enum_and_vtable_mangling.rs
index e9e6f13c..42ee3832 100644
--- a/tests/expectations/tests/enum_and_vtable_mangling.rs
+++ b/tests/expectations/tests/enum_and_vtable_mangling.rs
@@ -7,6 +7,7 @@
pub const match_: _bindgen_ty_1 = _bindgen_ty_1::match_;
pub const whatever_else: _bindgen_ty_1 = _bindgen_ty_1::whatever_else;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
match_ = 0,
diff --git a/tests/expectations/tests/enum_dupe.rs b/tests/expectations/tests/enum_dupe.rs
index a91999ed..151b2cd0 100644
--- a/tests/expectations/tests/enum_dupe.rs
+++ b/tests/expectations/tests/enum_dupe.rs
@@ -6,6 +6,7 @@
pub const Foo_Dupe: Foo = Foo::Bar;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 1,
diff --git a/tests/expectations/tests/enum_explicit_type.rs b/tests/expectations/tests/enum_explicit_type.rs
index 7ff0ef51..644a1cea 100644
--- a/tests/expectations/tests/enum_explicit_type.rs
+++ b/tests/expectations/tests/enum_explicit_type.rs
@@ -5,34 +5,40 @@
#[repr(u8)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 0,
Qux = 1,
}
#[repr(i8)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Neg {
MinusOne = -1,
One = 1,
}
#[repr(u16)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Bigger {
Much = 255,
Larger = 256,
}
#[repr(i64)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MuchLong {
MuchLow = -4294967296,
}
#[repr(i64)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MuchLongLong {
I64_MIN = -9223372036854775808,
}
#[repr(u64)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum MuchULongLong {
MuchHigh = 4294967296,
diff --git a/tests/expectations/tests/enum_in_template_with_typedef.rs b/tests/expectations/tests/enum_in_template_with_typedef.rs
index 06dea126..588bb42b 100644
--- a/tests/expectations/tests/enum_in_template_with_typedef.rs
+++ b/tests/expectations/tests/enum_in_template_with_typedef.rs
@@ -13,6 +13,7 @@ pub type std_fbstring_core_category_type = u8;
pub const std_fbstring_core_Category_Bar: std_fbstring_core_Category =
std_fbstring_core_Category::Foo;
#[repr(u8)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum std_fbstring_core_Category {
Foo = 0,
diff --git a/tests/expectations/tests/enum_negative.rs b/tests/expectations/tests/enum_negative.rs
index 100f27db..1fe2f6a4 100644
--- a/tests/expectations/tests/enum_negative.rs
+++ b/tests/expectations/tests/enum_negative.rs
@@ -5,6 +5,7 @@
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = -2,
diff --git a/tests/expectations/tests/enum_packed.rs b/tests/expectations/tests/enum_packed.rs
index cc85b553..d8e96b0f 100644
--- a/tests/expectations/tests/enum_packed.rs
+++ b/tests/expectations/tests/enum_packed.rs
@@ -5,18 +5,21 @@
#[repr(u8)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
Bar = 0,
Qux = 1,
}
#[repr(i8)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Neg {
MinusOne = -1,
One = 1,
}
#[repr(u16)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Bigger {
Much = 255,
diff --git a/tests/expectations/tests/forward-enum-decl.rs b/tests/expectations/tests/forward-enum-decl.rs
index 5502c4c4..c2dea97a 100644
--- a/tests/expectations/tests/forward-enum-decl.rs
+++ b/tests/expectations/tests/forward-enum-decl.rs
@@ -5,6 +5,7 @@
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum CSSPseudoClassType {
empty = 0,
diff --git a/tests/expectations/tests/func_ptr_in_struct.rs b/tests/expectations/tests/func_ptr_in_struct.rs
index 290a148c..33d908e2 100644
--- a/tests/expectations/tests/func_ptr_in_struct.rs
+++ b/tests/expectations/tests/func_ptr_in_struct.rs
@@ -4,8 +4,12 @@
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
-pub enum baz {}
+pub enum baz {
+ __bindgen_cannot_repr_c_on_empty_enum = 0,
+}
#[repr(C)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Foo {
diff --git a/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs b/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs
new file mode 100644
index 00000000..a3c5f4f6
--- /dev/null
+++ b/tests/expectations/tests/issue-1197-pure-virtual-stuff.rs
@@ -0,0 +1,29 @@
+/* automatically generated by rust-bindgen */
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+#[repr(C)]
+pub struct Foo__bindgen_vtable(::std::os::raw::c_void);
+#[repr(C)]
+#[derive(Debug)]
+pub struct Foo {
+ pub vtable_: *const Foo__bindgen_vtable,
+}
+#[test]
+fn bindgen_test_layout_Foo() {
+ assert_eq!(
+ ::std::mem::size_of::<Foo>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Foo))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Foo>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(Foo))
+ );
+}
+impl Default for Foo {
+ fn default() -> Self {
+ unsafe { ::std::mem::zeroed() }
+ }
+}
diff --git a/tests/expectations/tests/issue-1216-variadic-member.rs b/tests/expectations/tests/issue-1216-variadic-member.rs
new file mode 100644
index 00000000..677993c0
--- /dev/null
+++ b/tests/expectations/tests/issue-1216-variadic-member.rs
@@ -0,0 +1,42 @@
+/* automatically generated by rust-bindgen */
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+extern "C" {
+ pub fn f(a: ::std::os::raw::c_int, ...);
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct Foo {
+ pub f: ::std::option::Option<
+ unsafe extern "C" fn(
+ p: *mut ::std::os::raw::c_void,
+ obj: *mut ::std::os::raw::c_void,
+ a: ::std::os::raw::c_int,
+ ...
+ ),
+ >,
+}
+#[test]
+fn bindgen_test_layout_Foo() {
+ assert_eq!(
+ ::std::mem::size_of::<Foo>(),
+ 8usize,
+ concat!("Size of: ", stringify!(Foo))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<Foo>(),
+ 8usize,
+ concat!("Alignment of ", stringify!(Foo))
+ );
+ assert_eq!(
+ unsafe { &(*(::std::ptr::null::<Foo>())).f as *const _ as usize },
+ 0usize,
+ concat!("Offset of field: ", stringify!(Foo), "::", stringify!(f))
+ );
+}
+impl Default for Foo {
+ fn default() -> Self {
+ unsafe { ::std::mem::zeroed() }
+ }
+}
diff --git a/tests/expectations/tests/issue-372.rs b/tests/expectations/tests/issue-372.rs
index b2949da3..f9040a99 100644
--- a/tests/expectations/tests/issue-372.rs
+++ b/tests/expectations/tests/issue-372.rs
@@ -77,6 +77,7 @@ pub mod root {
}
}
#[repr(u32)]
+ #[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum n {
o = 0,
diff --git a/tests/expectations/tests/issue-410.rs b/tests/expectations/tests/issue-410.rs
index 928701ef..f23462bf 100644
--- a/tests/expectations/tests/issue-410.rs
+++ b/tests/expectations/tests/issue-410.rs
@@ -40,6 +40,10 @@ pub mod root {
}
}
}
+ #[repr(u32)]
+ #[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
- pub enum JSWhyMagic {}
+ pub enum JSWhyMagic {
+ __bindgen_cannot_repr_c_on_empty_enum = 0,
+ }
}
diff --git a/tests/expectations/tests/issue-493.rs b/tests/expectations/tests/issue-493.rs
index 8975938d..d338e30c 100644
--- a/tests/expectations/tests/issue-493.rs
+++ b/tests/expectations/tests/issue-493.rs
@@ -70,6 +70,7 @@ impl Default for basic_string___long {
pub const basic_string___min_cap: basic_string__bindgen_ty_1 =
basic_string__bindgen_ty_1::__min_cap;
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum basic_string__bindgen_ty_1 {
__min_cap = 0,
@@ -109,6 +110,7 @@ impl Default for basic_string___ulx {
pub const basic_string___n_words: basic_string__bindgen_ty_2 =
basic_string__bindgen_ty_2::__n_words;
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum basic_string__bindgen_ty_2 {
__n_words = 0,
diff --git a/tests/expectations/tests/issue-493_1_0.rs b/tests/expectations/tests/issue-493_1_0.rs
index da6dac77..4dfc26d8 100644
--- a/tests/expectations/tests/issue-493_1_0.rs
+++ b/tests/expectations/tests/issue-493_1_0.rs
@@ -70,6 +70,7 @@ impl Default for basic_string___long {
pub const basic_string___min_cap: basic_string__bindgen_ty_1 =
basic_string__bindgen_ty_1::__min_cap;
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum basic_string__bindgen_ty_1 {
__min_cap = 0,
@@ -107,6 +108,7 @@ impl Default for basic_string___ulx {
pub const basic_string___n_words: basic_string__bindgen_ty_2 =
basic_string__bindgen_ty_2::__n_words;
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum basic_string__bindgen_ty_2 {
__n_words = 0,
diff --git a/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs b/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs
index b2ddf713..3029a670 100644
--- a/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs
+++ b/tests/expectations/tests/issue-569-non-type-template-params-causing-layout-test-failures.rs
@@ -7,6 +7,7 @@
pub const ENUM_VARIANT_1: _bindgen_ty_1 = _bindgen_ty_1::ENUM_VARIANT_1;
pub const ENUM_VARIANT_2: _bindgen_ty_1 = _bindgen_ty_1::ENUM_VARIANT_2;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
ENUM_VARIANT_1 = 0,
diff --git a/tests/expectations/tests/issue-816.rs b/tests/expectations/tests/issue-816.rs
new file mode 100644
index 00000000..555769a2
--- /dev/null
+++ b/tests/expectations/tests/issue-816.rs
@@ -0,0 +1,767 @@
+/* automatically generated by rust-bindgen */
+
+#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub struct __BindgenBitfieldUnit<Storage, Align>
+where
+ Storage: AsRef<[u8]> + AsMut<[u8]>,
+{
+ storage: Storage,
+ align: [Align; 0],
+}
+
+impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
+where
+ Storage: AsRef<[u8]> + AsMut<[u8]>,
+{
+ #[inline]
+ pub fn new(storage: Storage) -> Self {
+ Self { storage, align: [] }
+ }
+
+ #[inline]
+ pub fn get_bit(&self, index: usize) -> bool {
+ debug_assert!(index / 8 < self.storage.as_ref().len());
+
+ let byte_index = index / 8;
+ let byte = self.storage.as_ref()[byte_index];
+
+ let bit_index = index % 8;
+ let mask = 1 << bit_index;
+
+ byte & mask == mask
+ }
+
+ #[inline]
+ pub fn set_bit(&mut self, index: usize, val: bool) {
+ debug_assert!(index / 8 < self.storage.as_ref().len());
+
+ let byte_index = index / 8;
+ let byte = &mut self.storage.as_mut()[byte_index];
+
+ let bit_index = index % 8;
+ let mask = 1 << bit_index;
+
+ if val {
+ *byte |= mask;
+ } else {
+ *byte &= !mask;
+ }
+ }
+
+ #[inline]
+ pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
+ debug_assert!(bit_width <= 64);
+ debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
+ debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
+
+ let mut val = 0;
+
+ for i in 0..(bit_width as usize) {
+ if self.get_bit(i + bit_offset) {
+ val |= 1 << i;
+ }
+ }
+
+ val
+ }
+
+ #[inline]
+ pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
+ debug_assert!(bit_width <= 64);
+ debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
+ debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
+
+ for i in 0..(bit_width as usize) {
+ let mask = 1 << i;
+ let val_bit_is_set = val & mask == mask;
+ self.set_bit(i + bit_offset, val_bit_is_set);
+ }
+ }
+}
+#[repr(C)]
+#[derive(Debug, Default, Copy, Clone)]
+pub struct capabilities {
+ pub _bitfield_1: __BindgenBitfieldUnit<[u8; 16usize], u8>,
+ pub __bindgen_align: [u32; 0usize],
+}
+#[test]
+fn bindgen_test_layout_capabilities() {
+ assert_eq!(
+ ::std::mem::size_of::<capabilities>(),
+ 16usize,
+ concat!("Size of: ", stringify!(capabilities))
+ );
+ assert_eq!(
+ ::std::mem::align_of::<capabilities>(),
+ 4usize,
+ concat!("Alignment of ", stringify!(capabilities))
+ );
+}
+impl capabilities {
+ #[inline]
+ pub fn bit_1(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_1(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(0usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_2(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_2(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(1usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_3(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_3(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(2usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_4(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_4(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(3usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_5(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_5(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(4usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_6(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_6(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(5usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_7(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_7(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(6usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_8(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_8(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(7usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_9(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_9(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(8usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_10(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_10(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(9usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_11(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_11(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(10usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_12(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_12(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(11usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_13(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(12usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_13(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(12usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_14(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(13usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_14(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(13usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_15(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(14usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_15(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(14usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_16(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(15usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_16(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(15usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_17(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_17(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(16usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_18(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(17usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_18(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(17usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_19(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(18usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_19(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(18usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_20(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(19usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_20(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(19usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_21(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(20usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_21(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(20usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_22(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(21usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_22(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(21usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_23(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(22usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_23(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(22usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_24(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(23usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_24(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(23usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_25(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_25(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(24usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_26(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(25usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_26(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(25usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_27(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(26usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_27(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(26usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_28(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(27usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_28(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(27usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_29(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(28usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_29(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(28usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_30(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(29usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_30(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(29usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_31(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(30usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_31(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(30usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_32(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_32(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(31usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_33(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(32usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_33(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(32usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_34(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(33usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_34(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(33usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_35(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(34usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_35(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(34usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_36(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(35usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_36(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(35usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_37(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(36usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_37(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(36usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_38(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(37usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_38(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(37usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_39(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(38usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_39(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(38usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_40(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(39usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_40(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(39usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn bit_41(&self) -> ::std::os::raw::c_uint {
+ unsafe { ::std::mem::transmute(self._bitfield_1.get(40usize, 1u8) as u32) }
+ }
+ #[inline]
+ pub fn set_bit_41(&mut self, val: ::std::os::raw::c_uint) {
+ unsafe {
+ let val: u32 = ::std::mem::transmute(val);
+ self._bitfield_1.set(40usize, 1u8, val as u64)
+ }
+ }
+ #[inline]
+ pub fn new_bitfield_1(
+ bit_1: ::std::os::raw::c_uint,
+ bit_2: ::std::os::raw::c_uint,
+ bit_3: ::std::os::raw::c_uint,
+ bit_4: ::std::os::raw::c_uint,
+ bit_5: ::std::os::raw::c_uint,
+ bit_6: ::std::os::raw::c_uint,
+ bit_7: ::std::os::raw::c_uint,
+ bit_8: ::std::os::raw::c_uint,
+ bit_9: ::std::os::raw::c_uint,
+ bit_10: ::std::os::raw::c_uint,
+ bit_11: ::std::os::raw::c_uint,
+ bit_12: ::std::os::raw::c_uint,
+ bit_13: ::std::os::raw::c_uint,
+ bit_14: ::std::os::raw::c_uint,
+ bit_15: ::std::os::raw::c_uint,
+ bit_16: ::std::os::raw::c_uint,
+ bit_17: ::std::os::raw::c_uint,
+ bit_18: ::std::os::raw::c_uint,
+ bit_19: ::std::os::raw::c_uint,
+ bit_20: ::std::os::raw::c_uint,
+ bit_21: ::std::os::raw::c_uint,
+ bit_22: ::std::os::raw::c_uint,
+ bit_23: ::std::os::raw::c_uint,
+ bit_24: ::std::os::raw::c_uint,
+ bit_25: ::std::os::raw::c_uint,
+ bit_26: ::std::os::raw::c_uint,
+ bit_27: ::std::os::raw::c_uint,
+ bit_28: ::std::os::raw::c_uint,
+ bit_29: ::std::os::raw::c_uint,
+ bit_30: ::std::os::raw::c_uint,
+ bit_31: ::std::os::raw::c_uint,
+ bit_32: ::std::os::raw::c_uint,
+ bit_33: ::std::os::raw::c_uint,
+ bit_34: ::std::os::raw::c_uint,
+ bit_35: ::std::os::raw::c_uint,
+ bit_36: ::std::os::raw::c_uint,
+ bit_37: ::std::os::raw::c_uint,
+ bit_38: ::std::os::raw::c_uint,
+ bit_39: ::std::os::raw::c_uint,
+ bit_40: ::std::os::raw::c_uint,
+ bit_41: ::std::os::raw::c_uint,
+ ) -> __BindgenBitfieldUnit<[u8; 16usize], u8> {
+ let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 16usize], u8> =
+ Default::default();
+ __bindgen_bitfield_unit.set(0usize, 1u8, {
+ let bit_1: u32 = unsafe { ::std::mem::transmute(bit_1) };
+ bit_1 as u64
+ });
+ __bindgen_bitfield_unit.set(1usize, 1u8, {
+ let bit_2: u32 = unsafe { ::std::mem::transmute(bit_2) };
+ bit_2 as u64
+ });
+ __bindgen_bitfield_unit.set(2usize, 1u8, {
+ let bit_3: u32 = unsafe { ::std::mem::transmute(bit_3) };
+ bit_3 as u64
+ });
+ __bindgen_bitfield_unit.set(3usize, 1u8, {
+ let bit_4: u32 = unsafe { ::std::mem::transmute(bit_4) };
+ bit_4 as u64
+ });
+ __bindgen_bitfield_unit.set(4usize, 1u8, {
+ let bit_5: u32 = unsafe { ::std::mem::transmute(bit_5) };
+ bit_5 as u64
+ });
+ __bindgen_bitfield_unit.set(5usize, 1u8, {
+ let bit_6: u32 = unsafe { ::std::mem::transmute(bit_6) };
+ bit_6 as u64
+ });
+ __bindgen_bitfield_unit.set(6usize, 1u8, {
+ let bit_7: u32 = unsafe { ::std::mem::transmute(bit_7) };
+ bit_7 as u64
+ });
+ __bindgen_bitfield_unit.set(7usize, 1u8, {
+ let bit_8: u32 = unsafe { ::std::mem::transmute(bit_8) };
+ bit_8 as u64
+ });
+ __bindgen_bitfield_unit.set(8usize, 1u8, {
+ let bit_9: u32 = unsafe { ::std::mem::transmute(bit_9) };
+ bit_9 as u64
+ });
+ __bindgen_bitfield_unit.set(9usize, 1u8, {
+ let bit_10: u32 = unsafe { ::std::mem::transmute(bit_10) };
+ bit_10 as u64
+ });
+ __bindgen_bitfield_unit.set(10usize, 1u8, {
+ let bit_11: u32 = unsafe { ::std::mem::transmute(bit_11) };
+ bit_11 as u64
+ });
+ __bindgen_bitfield_unit.set(11usize, 1u8, {
+ let bit_12: u32 = unsafe { ::std::mem::transmute(bit_12) };
+ bit_12 as u64
+ });
+ __bindgen_bitfield_unit.set(12usize, 1u8, {
+ let bit_13: u32 = unsafe { ::std::mem::transmute(bit_13) };
+ bit_13 as u64
+ });
+ __bindgen_bitfield_unit.set(13usize, 1u8, {
+ let bit_14: u32 = unsafe { ::std::mem::transmute(bit_14) };
+ bit_14 as u64
+ });
+ __bindgen_bitfield_unit.set(14usize, 1u8, {
+ let bit_15: u32 = unsafe { ::std::mem::transmute(bit_15) };
+ bit_15 as u64
+ });
+ __bindgen_bitfield_unit.set(15usize, 1u8, {
+ let bit_16: u32 = unsafe { ::std::mem::transmute(bit_16) };
+ bit_16 as u64
+ });
+ __bindgen_bitfield_unit.set(16usize, 1u8, {
+ let bit_17: u32 = unsafe { ::std::mem::transmute(bit_17) };
+ bit_17 as u64
+ });
+ __bindgen_bitfield_unit.set(17usize, 1u8, {
+ let bit_18: u32 = unsafe { ::std::mem::transmute(bit_18) };
+ bit_18 as u64
+ });
+ __bindgen_bitfield_unit.set(18usize, 1u8, {
+ let bit_19: u32 = unsafe { ::std::mem::transmute(bit_19) };
+ bit_19 as u64
+ });
+ __bindgen_bitfield_unit.set(19usize, 1u8, {
+ let bit_20: u32 = unsafe { ::std::mem::transmute(bit_20) };
+ bit_20 as u64
+ });
+ __bindgen_bitfield_unit.set(20usize, 1u8, {
+ let bit_21: u32 = unsafe { ::std::mem::transmute(bit_21) };
+ bit_21 as u64
+ });
+ __bindgen_bitfield_unit.set(21usize, 1u8, {
+ let bit_22: u32 = unsafe { ::std::mem::transmute(bit_22) };
+ bit_22 as u64
+ });
+ __bindgen_bitfield_unit.set(22usize, 1u8, {
+ let bit_23: u32 = unsafe { ::std::mem::transmute(bit_23) };
+ bit_23 as u64
+ });
+ __bindgen_bitfield_unit.set(23usize, 1u8, {
+ let bit_24: u32 = unsafe { ::std::mem::transmute(bit_24) };
+ bit_24 as u64
+ });
+ __bindgen_bitfield_unit.set(24usize, 1u8, {
+ let bit_25: u32 = unsafe { ::std::mem::transmute(bit_25) };
+ bit_25 as u64
+ });
+ __bindgen_bitfield_unit.set(25usize, 1u8, {
+ let bit_26: u32 = unsafe { ::std::mem::transmute(bit_26) };
+ bit_26 as u64
+ });
+ __bindgen_bitfield_unit.set(26usize, 1u8, {
+ let bit_27: u32 = unsafe { ::std::mem::transmute(bit_27) };
+ bit_27 as u64
+ });
+ __bindgen_bitfield_unit.set(27usize, 1u8, {
+ let bit_28: u32 = unsafe { ::std::mem::transmute(bit_28) };
+ bit_28 as u64
+ });
+ __bindgen_bitfield_unit.set(28usize, 1u8, {
+ let bit_29: u32 = unsafe { ::std::mem::transmute(bit_29) };
+ bit_29 as u64
+ });
+ __bindgen_bitfield_unit.set(29usize, 1u8, {
+ let bit_30: u32 = unsafe { ::std::mem::transmute(bit_30) };
+ bit_30 as u64
+ });
+ __bindgen_bitfield_unit.set(30usize, 1u8, {
+ let bit_31: u32 = unsafe { ::std::mem::transmute(bit_31) };
+ bit_31 as u64
+ });
+ __bindgen_bitfield_unit.set(31usize, 1u8, {
+ let bit_32: u32 = unsafe { ::std::mem::transmute(bit_32) };
+ bit_32 as u64
+ });
+ __bindgen_bitfield_unit.set(32usize, 1u8, {
+ let bit_33: u32 = unsafe { ::std::mem::transmute(bit_33) };
+ bit_33 as u64
+ });
+ __bindgen_bitfield_unit.set(33usize, 1u8, {
+ let bit_34: u32 = unsafe { ::std::mem::transmute(bit_34) };
+ bit_34 as u64
+ });
+ __bindgen_bitfield_unit.set(34usize, 1u8, {
+ let bit_35: u32 = unsafe { ::std::mem::transmute(bit_35) };
+ bit_35 as u64
+ });
+ __bindgen_bitfield_unit.set(35usize, 1u8, {
+ let bit_36: u32 = unsafe { ::std::mem::transmute(bit_36) };
+ bit_36 as u64
+ });
+ __bindgen_bitfield_unit.set(36usize, 1u8, {
+ let bit_37: u32 = unsafe { ::std::mem::transmute(bit_37) };
+ bit_37 as u64
+ });
+ __bindgen_bitfield_unit.set(37usize, 1u8, {
+ let bit_38: u32 = unsafe { ::std::mem::transmute(bit_38) };
+ bit_38 as u64
+ });
+ __bindgen_bitfield_unit.set(38usize, 1u8, {
+ let bit_39: u32 = unsafe { ::std::mem::transmute(bit_39) };
+ bit_39 as u64
+ });
+ __bindgen_bitfield_unit.set(39usize, 1u8, {
+ let bit_40: u32 = unsafe { ::std::mem::transmute(bit_40) };
+ bit_40 as u64
+ });
+ __bindgen_bitfield_unit.set(40usize, 1u8, {
+ let bit_41: u32 = unsafe { ::std::mem::transmute(bit_41) };
+ bit_41 as u64
+ });
+ __bindgen_bitfield_unit
+ }
+}
diff --git a/tests/expectations/tests/issue-888-enum-var-decl-jump.rs b/tests/expectations/tests/issue-888-enum-var-decl-jump.rs
index 61cbfc3a..c0ac112d 100644
--- a/tests/expectations/tests/issue-888-enum-var-decl-jump.rs
+++ b/tests/expectations/tests/issue-888-enum-var-decl-jump.rs
@@ -34,6 +34,10 @@ pub mod root {
);
}
}
+ #[repr(u32)]
+ #[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
- pub enum a {}
+ pub enum a {
+ __bindgen_cannot_repr_c_on_empty_enum = 0,
+ }
}
diff --git a/tests/expectations/tests/jsval_layout_opaque.rs b/tests/expectations/tests/jsval_layout_opaque.rs
index 80526b3e..2b2d0d77 100644
--- a/tests/expectations/tests/jsval_layout_opaque.rs
+++ b/tests/expectations/tests/jsval_layout_opaque.rs
@@ -87,6 +87,7 @@ pub const JSVAL_TAG_SHIFT: ::std::os::raw::c_uint = 47;
pub const JSVAL_PAYLOAD_MASK: ::std::os::raw::c_ulonglong = 140737488355327;
pub const JSVAL_TAG_MASK: ::std::os::raw::c_longlong = -140737488355328;
#[repr(u8)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSValueType {
JSVAL_TYPE_DOUBLE = 0,
@@ -102,6 +103,7 @@ pub enum JSValueType {
JSVAL_TYPE_MISSING = 33,
}
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSValueTag {
JSVAL_TAG_MAX_DOUBLE = 131056,
@@ -115,6 +117,7 @@ pub enum JSValueTag {
JSVAL_TAG_OBJECT = 131064,
}
#[repr(u64)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSValueShiftedTag {
JSVAL_SHIFTED_TAG_MAX_DOUBLE = 18444492278190833663,
@@ -128,6 +131,7 @@ pub enum JSValueShiftedTag {
JSVAL_SHIFTED_TAG_OBJECT = 18445618173802708992,
}
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSWhyMagic {
JS_ELEMENTS_HOLE = 0,
diff --git a/tests/expectations/tests/jsval_layout_opaque_1_0.rs b/tests/expectations/tests/jsval_layout_opaque_1_0.rs
index cac9b0b8..ab11a231 100644
--- a/tests/expectations/tests/jsval_layout_opaque_1_0.rs
+++ b/tests/expectations/tests/jsval_layout_opaque_1_0.rs
@@ -130,6 +130,7 @@ pub const JSVAL_TAG_SHIFT: ::std::os::raw::c_uint = 47;
pub const JSVAL_PAYLOAD_MASK: ::std::os::raw::c_ulonglong = 140737488355327;
pub const JSVAL_TAG_MASK: ::std::os::raw::c_longlong = -140737488355328;
#[repr(u8)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSValueType {
JSVAL_TYPE_DOUBLE = 0,
@@ -145,6 +146,7 @@ pub enum JSValueType {
JSVAL_TYPE_MISSING = 33,
}
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSValueTag {
JSVAL_TAG_MAX_DOUBLE = 131056,
@@ -158,6 +160,7 @@ pub enum JSValueTag {
JSVAL_TAG_OBJECT = 131064,
}
#[repr(u64)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSValueShiftedTag {
JSVAL_SHIFTED_TAG_MAX_DOUBLE = 18444492278190833663,
@@ -171,6 +174,7 @@ pub enum JSValueShiftedTag {
JSVAL_SHIFTED_TAG_OBJECT = 18445618173802708992,
}
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum JSWhyMagic {
JS_ELEMENTS_HOLE = 0,
diff --git a/tests/expectations/tests/layout_array_too_long.rs b/tests/expectations/tests/layout_array_too_long.rs
index b7677573..59884451 100644
--- a/tests/expectations/tests/layout_array_too_long.rs
+++ b/tests/expectations/tests/layout_array_too_long.rs
@@ -11,6 +11,7 @@ pub const IP_FIRST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_FIRST_FRAG_IDX;
pub const IP_MIN_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MIN_FRAG_NUM;
pub const IP_MAX_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MAX_FRAG_NUM;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
IP_LAST_FRAG_IDX = 0,
diff --git a/tests/expectations/tests/layout_cmdline_token.rs b/tests/expectations/tests/layout_cmdline_token.rs
index 91157416..2cde7c42 100644
--- a/tests/expectations/tests/layout_cmdline_token.rs
+++ b/tests/expectations/tests/layout_cmdline_token.rs
@@ -83,8 +83,7 @@ pub struct cmdline_token_ops {
>,
/// return the num of possible choices for this token
pub complete_get_nb: ::std::option::Option<
- unsafe extern "C" fn(arg1: *mut cmdline_parse_token_hdr_t)
- -> ::std::os::raw::c_int,
+ unsafe extern "C" fn(arg1: *mut cmdline_parse_token_hdr_t) -> ::std::os::raw::c_int,
>,
/// return the elt x for this token (token, idx, dstbuf, size)
pub complete_get_elt: ::std::option::Option<
@@ -167,6 +166,7 @@ impl Default for cmdline_token_ops {
}
}
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum cmdline_numtype {
UINT8 = 0,
diff --git a/tests/expectations/tests/layout_eth_conf.rs b/tests/expectations/tests/layout_eth_conf.rs
index 9721fb7b..599f9788 100644
--- a/tests/expectations/tests/layout_eth_conf.rs
+++ b/tests/expectations/tests/layout_eth_conf.rs
@@ -116,6 +116,7 @@ pub const RTE_ETH_FLOW_GENEVE: ::std::os::raw::c_uint = 20;
pub const RTE_ETH_FLOW_NVGRE: ::std::os::raw::c_uint = 21;
pub const RTE_ETH_FLOW_MAX: ::std::os::raw::c_uint = 22;
#[repr(u32)]
+#[repr(C)]
/// A set of values to identify what method is to be used to route
/// packets to multiple queues.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -343,6 +344,7 @@ impl rte_eth_rxmode {
}
}
#[repr(u32)]
+#[repr(C)]
/// A set of values to identify what method is to be used to transmit
/// packets using multi-TCs.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -532,6 +534,7 @@ impl Default for rte_eth_rss_conf {
}
}
#[repr(u32)]
+#[repr(C)]
/// This enum indicates the possible number of traffic classes
/// in DCB configratioins
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -540,6 +543,7 @@ pub enum rte_eth_nb_tcs {
ETH_8_TCS = 8,
}
#[repr(u32)]
+#[repr(C)]
/// This enum indicates the possible number of queue pools
/// in VMDQ configurations.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -1054,6 +1058,7 @@ impl Default for rte_eth_vmdq_rx_conf {
}
}
#[repr(u32)]
+#[repr(C)]
/// Flow Director setting modes: none, signature or perfect.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_fdir_mode {
@@ -1064,6 +1069,7 @@ pub enum rte_fdir_mode {
RTE_FDIR_MODE_PERFECT_TUNNEL = 4,
}
#[repr(u32)]
+#[repr(C)]
/// Memory space that can be configured to store Flow Director filters
/// in the board memory.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -1073,6 +1079,7 @@ pub enum rte_fdir_pballoc_type {
RTE_FDIR_PBALLOC_256K = 2,
}
#[repr(u32)]
+#[repr(C)]
/// Select report mode of FDIR hash information in RX descriptors.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_fdir_status_mode {
@@ -1366,6 +1373,7 @@ fn bindgen_test_layout_rte_eth_fdir_masks() {
);
}
#[repr(u32)]
+#[repr(C)]
/// Payload type
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_eth_payload_type {
diff --git a/tests/expectations/tests/layout_eth_conf_1_0.rs b/tests/expectations/tests/layout_eth_conf_1_0.rs
index ad37574d..532fcae8 100644
--- a/tests/expectations/tests/layout_eth_conf_1_0.rs
+++ b/tests/expectations/tests/layout_eth_conf_1_0.rs
@@ -159,6 +159,7 @@ pub const RTE_ETH_FLOW_GENEVE: ::std::os::raw::c_uint = 20;
pub const RTE_ETH_FLOW_NVGRE: ::std::os::raw::c_uint = 21;
pub const RTE_ETH_FLOW_MAX: ::std::os::raw::c_uint = 22;
#[repr(u32)]
+#[repr(C)]
/// A set of values to identify what method is to be used to route
/// packets to multiple queues.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -391,6 +392,7 @@ impl rte_eth_rxmode {
}
}
#[repr(u32)]
+#[repr(C)]
/// A set of values to identify what method is to be used to transmit
/// packets using multi-TCs.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -590,6 +592,7 @@ impl Default for rte_eth_rss_conf {
}
}
#[repr(u32)]
+#[repr(C)]
/// This enum indicates the possible number of traffic classes
/// in DCB configratioins
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -598,6 +601,7 @@ pub enum rte_eth_nb_tcs {
ETH_8_TCS = 8,
}
#[repr(u32)]
+#[repr(C)]
/// This enum indicates the possible number of queue pools
/// in VMDQ configurations.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -1152,6 +1156,7 @@ impl Default for rte_eth_vmdq_rx_conf {
}
}
#[repr(u32)]
+#[repr(C)]
/// Flow Director setting modes: none, signature or perfect.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_fdir_mode {
@@ -1162,6 +1167,7 @@ pub enum rte_fdir_mode {
RTE_FDIR_MODE_PERFECT_TUNNEL = 4,
}
#[repr(u32)]
+#[repr(C)]
/// Memory space that can be configured to store Flow Director filters
/// in the board memory.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -1171,6 +1177,7 @@ pub enum rte_fdir_pballoc_type {
RTE_FDIR_PBALLOC_256K = 2,
}
#[repr(u32)]
+#[repr(C)]
/// Select report mode of FDIR hash information in RX descriptors.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_fdir_status_mode {
@@ -1479,6 +1486,7 @@ impl Clone for rte_eth_fdir_masks {
}
}
#[repr(u32)]
+#[repr(C)]
/// Payload type
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum rte_eth_payload_type {
diff --git a/tests/expectations/tests/layout_large_align_field.rs b/tests/expectations/tests/layout_large_align_field.rs
index 21f84546..501e1bce 100644
--- a/tests/expectations/tests/layout_large_align_field.rs
+++ b/tests/expectations/tests/layout_large_align_field.rs
@@ -48,6 +48,7 @@ pub const IP_FIRST_FRAG_IDX: _bindgen_ty_1 = _bindgen_ty_1::IP_FIRST_FRAG_IDX;
pub const IP_MIN_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MIN_FRAG_NUM;
pub const IP_MAX_FRAG_NUM: _bindgen_ty_1 = _bindgen_ty_1::IP_MAX_FRAG_NUM;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
IP_LAST_FRAG_IDX = 0,
diff --git a/tests/expectations/tests/libclang-3.8/constant-evaluate.rs b/tests/expectations/tests/libclang-3.8/constant-evaluate.rs
index 8faddfe9..1b6aca15 100644
--- a/tests/expectations/tests/libclang-3.8/constant-evaluate.rs
+++ b/tests/expectations/tests/libclang-3.8/constant-evaluate.rs
@@ -7,6 +7,7 @@
pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo;
pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 { foo = 4, bar = 8, }
pub type EasyToOverflow = ::std::os::raw::c_ulonglong;
diff --git a/tests/expectations/tests/libclang-3.9/constant-evaluate.rs b/tests/expectations/tests/libclang-3.9/constant-evaluate.rs
index 096bc182..76cbf24e 100644
--- a/tests/expectations/tests/libclang-3.9/constant-evaluate.rs
+++ b/tests/expectations/tests/libclang-3.9/constant-evaluate.rs
@@ -7,6 +7,7 @@
pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo;
pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
foo = 4,
diff --git a/tests/expectations/tests/libclang-4/constant-evaluate.rs b/tests/expectations/tests/libclang-4/constant-evaluate.rs
index 096bc182..76cbf24e 100644
--- a/tests/expectations/tests/libclang-4/constant-evaluate.rs
+++ b/tests/expectations/tests/libclang-4/constant-evaluate.rs
@@ -7,6 +7,7 @@
pub const foo: _bindgen_ty_1 = _bindgen_ty_1::foo;
pub const bar: _bindgen_ty_1 = _bindgen_ty_1::bar;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_1 {
foo = 4,
diff --git a/tests/expectations/tests/libclang_version_specific_generated_tests.rs b/tests/expectations/tests/libclang_version_specific_generated_tests.rs
new file mode 100644
index 00000000..93cf0d47
--- /dev/null
+++ b/tests/expectations/tests/libclang_version_specific_generated_tests.rs
@@ -0,0 +1 @@
+include!(concat!(env!("OUT_DIR"), "/libclang_version_specific_generated_tests.rs"));
diff --git a/tests/expectations/tests/namespace.rs b/tests/expectations/tests/namespace.rs
index 961ed447..726383d0 100644
--- a/tests/expectations/tests/namespace.rs
+++ b/tests/expectations/tests/namespace.rs
@@ -1,9 +1,7 @@
/* automatically generated by rust-bindgen */
-
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
-
#[allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
pub mod root {
#[allow(unused_imports)]
@@ -24,10 +22,6 @@ pub mod root {
pub mod _bindgen_mod_id_13 {
#[allow(unused_imports)]
use self::super::super::root;
- extern "C" {
- #[link_name = "\u{1}_ZN12_GLOBAL__N_13fooEv"]
- pub fn foo();
- }
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct A {
@@ -51,18 +45,6 @@ pub mod root {
concat!("Offset of field: ", stringify!(A), "::", stringify!(b))
);
}
- extern "C" {
- #[link_name = "\u{1}_ZN12_GLOBAL__N_11A20lets_hope_this_worksEv"]
- pub fn A_lets_hope_this_works(
- this: *mut root::_bindgen_mod_id_13::A,
- ) -> ::std::os::raw::c_int;
- }
- impl A {
- #[inline]
- pub unsafe fn lets_hope_this_works(&mut self) -> ::std::os::raw::c_int {
- A_lets_hope_this_works(self)
- }
- }
}
#[repr(C)]
#[derive(Debug)]
diff --git a/tests/expectations/tests/nsStyleAutoArray.rs b/tests/expectations/tests/nsStyleAutoArray.rs
index 0c9f1ec6..199222ec 100644
--- a/tests/expectations/tests/nsStyleAutoArray.rs
+++ b/tests/expectations/tests/nsStyleAutoArray.rs
@@ -23,6 +23,7 @@ pub struct nsStyleAutoArray<T> {
pub _phantom_0: ::std::marker::PhantomData<::std::cell::UnsafeCell<T>>,
}
#[repr(i32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsStyleAutoArray_WithSingleInitialElement {
WITH_SINGLE_INITIAL_ELEMENT = 0,
diff --git a/tests/expectations/tests/overflowed_enum.rs b/tests/expectations/tests/overflowed_enum.rs
index 0e8700dc..9104867d 100644
--- a/tests/expectations/tests/overflowed_enum.rs
+++ b/tests/expectations/tests/overflowed_enum.rs
@@ -5,6 +5,7 @@
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Foo {
BAP_ARM = 9698489,
@@ -12,6 +13,7 @@ pub enum Foo {
BAP_X86_64 = 3128633167,
}
#[repr(u16)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum Bar {
One = 1,
diff --git a/tests/expectations/tests/prepend-enum-constified-variant.rs b/tests/expectations/tests/prepend-enum-constified-variant.rs
index df9ecf3c..afe2c0b1 100644
--- a/tests/expectations/tests/prepend-enum-constified-variant.rs
+++ b/tests/expectations/tests/prepend-enum-constified-variant.rs
@@ -6,6 +6,7 @@
pub const AV_CODEC_ID_TTF: AVCodecID = AVCodecID::AV_CODEC_ID_FIRST_UNKNOWN;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum AVCodecID {
AV_CODEC_ID_FIRST_UNKNOWN = 98304,
diff --git a/tests/expectations/tests/short-enums.rs b/tests/expectations/tests/short-enums.rs
index c3b26da9..882b368c 100644
--- a/tests/expectations/tests/short-enums.rs
+++ b/tests/expectations/tests/short-enums.rs
@@ -5,16 +5,19 @@
#[repr(u8)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum one_byte_t {
SOME_VALUE = 1,
}
#[repr(u16)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum two_byte_t {
SOME_OTHER_VALUE = 256,
}
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum four_byte_t {
SOME_BIGGER_VALUE = 16777216,
diff --git a/tests/expectations/tests/struct_typedef.rs b/tests/expectations/tests/struct_typedef.rs
index d153aa08..0e615144 100644
--- a/tests/expectations/tests/struct_typedef.rs
+++ b/tests/expectations/tests/struct_typedef.rs
@@ -68,12 +68,14 @@ impl Default for _bindgen_ty_1 {
pub type struct_ptr_t = *mut _bindgen_ty_1;
pub type struct_ptr_ptr_t = *mut *mut _bindgen_ty_1;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum typedef_named_enum {
ENUM_HAS_NAME = 1,
}
pub const ENUM_IS_ANON: _bindgen_ty_2 = _bindgen_ty_2::ENUM_IS_ANON;
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_2 {
ENUM_IS_ANON = 0,
diff --git a/tests/expectations/tests/struct_typedef_ns.rs b/tests/expectations/tests/struct_typedef_ns.rs
index 42dfbb52..cbbdaa7b 100644
--- a/tests/expectations/tests/struct_typedef_ns.rs
+++ b/tests/expectations/tests/struct_typedef_ns.rs
@@ -40,6 +40,7 @@ pub mod root {
);
}
#[repr(u32)]
+ #[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum typedef_enum {
BAR = 1,
@@ -80,6 +81,7 @@ pub mod root {
pub const _bindgen_mod_id_12_BAR: root::_bindgen_mod_id_12::_bindgen_ty_2 =
_bindgen_ty_2::BAR;
#[repr(u32)]
+ #[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum _bindgen_ty_2 {
BAR = 1,
diff --git a/tests/expectations/tests/weird_bitfields.rs b/tests/expectations/tests/weird_bitfields.rs
index 6a4d0589..22cd8ea5 100644
--- a/tests/expectations/tests/weird_bitfields.rs
+++ b/tests/expectations/tests/weird_bitfields.rs
@@ -84,6 +84,7 @@ where
}
}
#[repr(u32)]
+#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum nsStyleSVGOpacitySource {
eStyleSVGOpacitySource_Normal = 0,
diff --git a/tests/headers/constify-module-enums-namespace.hpp b/tests/headers/constify-module-enums-namespace.hpp
index 397f700f..5d8ea23a 100644
--- a/tests/headers/constify-module-enums-namespace.hpp
+++ b/tests/headers/constify-module-enums-namespace.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: --enable-cxx-namespaces --constified-enum-module foo
+// bindgen-flags: --enable-cxx-namespaces --constified-enum-module ns1::ns2::foo
namespace ns1 {
namespace ns2 {
diff --git a/tests/headers/constify-module-enums-simple-nonamespace.hpp b/tests/headers/constify-module-enums-simple-nonamespace.hpp
index 54631451..5b15f5c8 100644
--- a/tests/headers/constify-module-enums-simple-nonamespace.hpp
+++ b/tests/headers/constify-module-enums-simple-nonamespace.hpp
@@ -1,4 +1,4 @@
-// bindgen-flags: --constified-enum-module one_Foo
+// bindgen-flags: --constified-enum-module one::Foo
namespace one {
enum class Foo {
diff --git a/tests/headers/empty-enum.h b/tests/headers/empty-enum.h
new file mode 100644
index 00000000..8b7502e6
--- /dev/null
+++ b/tests/headers/empty-enum.h
@@ -0,0 +1,15 @@
+// bindgen-flags: --rustified-enum '.*Rustified.*' --constified-enum-module '.*Module.*' -- -x c++ --std=c++14
+
+// Constified is default, so no flag for that.
+
+enum EmptyConstified {};
+enum EmptyRustified {};
+enum EmptyModule {};
+
+enum class EmptyClassRustified : char {};
+enum class EmptyClassConstified : char {};
+enum class EmptyClassModule : char {};
+
+enum class ForwardClassRustified : char;
+enum class ForwardClassConstified : char;
+enum class ForwardClassModule : char;
diff --git a/tests/headers/issue-1197-pure-virtual-stuff.hpp b/tests/headers/issue-1197-pure-virtual-stuff.hpp
new file mode 100644
index 00000000..a0da90c9
--- /dev/null
+++ b/tests/headers/issue-1197-pure-virtual-stuff.hpp
@@ -0,0 +1,6 @@
+class Foo
+{
+public:
+ virtual void Bar() = 0;
+ virtual ~Foo() = 0;
+};
diff --git a/tests/headers/issue-1216-variadic-member.h b/tests/headers/issue-1216-variadic-member.h
new file mode 100644
index 00000000..b8bc0b81
--- /dev/null
+++ b/tests/headers/issue-1216-variadic-member.h
@@ -0,0 +1,4 @@
+void f(int a, ...);
+struct Foo {
+ void (*f)(void *p, void *obj, int a, ...);
+};
diff --git a/tests/headers/issue-816.h b/tests/headers/issue-816.h
new file mode 100644
index 00000000..5f16a178
--- /dev/null
+++ b/tests/headers/issue-816.h
@@ -0,0 +1,49 @@
+typedef struct {
+ unsigned int bit_1 : 1;
+ unsigned int bit_2 : 1;
+ unsigned int bit_3 : 1;
+ unsigned int bit_4 : 1;
+ unsigned int bit_5 : 1;
+ unsigned int bit_6 : 1;
+ unsigned int bit_7 : 1;
+ unsigned int bit_8 : 1;
+ unsigned int bit_9 : 1;
+ unsigned int bit_10 : 1;
+ unsigned int bit_11 : 1;
+ unsigned int bit_12 : 1;
+ unsigned int bit_13 : 1;
+ unsigned int bit_14 : 1;
+ unsigned int bit_15 : 1;
+ unsigned int bit_16 : 1;
+ unsigned int bit_17 : 1;
+ unsigned int bit_18 : 1;
+ unsigned int bit_19 : 1;
+ unsigned int bit_20 : 1;
+ unsigned int bit_21 : 1;
+ unsigned int bit_22 : 1;
+ unsigned int bit_23 : 1;
+ unsigned int bit_24 : 1;
+ unsigned int bit_25 : 1;
+ unsigned int bit_26 : 1;
+ unsigned int bit_27 : 1;
+ unsigned int bit_28 : 1;
+ unsigned int bit_29 : 1;
+ unsigned int bit_30 : 1;
+ unsigned int bit_31 : 1;
+ unsigned int bit_32 : 1;
+ unsigned int bit_33 : 1;
+ unsigned int bit_34 : 1;
+ unsigned int bit_35 : 1;
+ unsigned int bit_36 : 1;
+ unsigned int bit_37 : 1;
+ unsigned int bit_38 : 1;
+ unsigned int bit_39 : 1;
+ unsigned int bit_40 : 1;
+ unsigned int bit_41 : 1;
+ unsigned int : 7;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+ unsigned int : 16;
+} capabilities;
diff --git a/tests/headers/namespace.hpp b/tests/headers/namespace.hpp
index 65788539..408207f2 100644
--- a/tests/headers/namespace.hpp
+++ b/tests/headers/namespace.hpp
@@ -11,11 +11,8 @@ namespace whatever {
namespace {
namespace empty {}
- void foo();
struct A {
whatever::whatever_int_t b;
- public:
- int lets_hope_this_works();
};
}
@@ -26,11 +23,9 @@ class C: public A {
T m_c_arr[10];
};
-
template<>
class C<int>;
-
namespace w {
typedef unsigned int whatever_int_t;
diff --git a/tests/headers/ref_argument_array.hpp b/tests/headers/ref_argument_array.hpp
index dc73fd62..53f66950 100644
--- a/tests/headers/ref_argument_array.hpp
+++ b/tests/headers/ref_argument_array.hpp
@@ -2,5 +2,5 @@
#define NSID_LENGTH 10
class nsID {
public:
- virtual void ToProvidedString(char (&aDest)[NSID_LENGTH]) = 0;
+ virtual void ToProvidedString(char (&aDest)[NSID_LENGTH]);
};
diff --git a/tests/quickchecking/Cargo.toml b/tests/quickchecking/Cargo.toml
new file mode 100644
index 00000000..ddefb33d
--- /dev/null
+++ b/tests/quickchecking/Cargo.toml
@@ -0,0 +1,32 @@
+[package]
+name = "quickchecking"
+description = "Bindgen property tests with quickcheck. Generate random valid C code and pass it to the csmith/predicate.py script"
+version = "0.1.0"
+authors = ["Shea Newton <sheanewt@gmail.com>"]
+
+[lib]
+name = "quickchecking"
+path = "src/lib.rs"
+
+[[bin]]
+name = "quickchecking"
+path = "src/bin.rs"
+
+[dependencies]
+clap = "2.28"
+lazy_static = "1.0"
+quickcheck = "0.4"
+rand = "0.3"
+tempdir = "0.3"
+
+[features]
+# No features by default.
+default = []
+
+# Enable the generation of code that allows for zero sized arrays as struct
+# fields. Until issues #684 and #1153 are resolved this can result in failing tests.
+zero-sized-arrays = []
+
+# Enable the generation of code that allows for long double types as struct
+# fields. Until issue #550 is resolved this can result in failing tests.
+long-doubles = []
diff --git a/tests/quickchecking/README.md b/tests/quickchecking/README.md
new file mode 100644
index 00000000..d3cfe170
--- /dev/null
+++ b/tests/quickchecking/README.md
@@ -0,0 +1,39 @@
+# Property tests for `bindgen` with `quickchecking`
+
+`quickchecking` generates random C headers to test `bindgen`
+using the [`quickcheck`][quickcheck] property testing crate. When testing
+`bindgen` with `quickchecking`, the generated header files are passed to
+`bindgen`'s `csmith-fuzzing/predicate.py` script. If that script fails,
+`quickchecking` panics, and you can report an issue containing the test case!
+
+<!-- START doctoc generated TOC please keep comment here to allow auto update -->
+<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
+
+
+- [Prerequisites](#prerequisites)
+- [Running](#running)
+
+<!-- END doctoc generated TOC please keep comment here to allow auto update -->
+
+## Prerequisites
+
+Requires `python3` to be in `$PATH`.
+
+Many systems have `python3` by default but if your OS doesn't, its package
+manager may make it available:
+
+```
+$ sudo apt install python3
+$ brew install python3
+$ # Etc...
+```
+
+## Running
+
+Run `quickchecking` binary to generate and test fuzzed C headers with
+`cargo run`. Additional configuration is exposed through the binary's CLI.
+
+```
+$ cargo run --bin=quickchecking -- -h
+```
+[quickcheck]: https://github.com/BurntSushi/quickcheck
diff --git a/tests/quickchecking/src/bin.rs b/tests/quickchecking/src/bin.rs
new file mode 100644
index 00000000..d2774eb0
--- /dev/null
+++ b/tests/quickchecking/src/bin.rs
@@ -0,0 +1,110 @@
+//! An application to run property tests for `bindgen` with _fuzzed_ C headers
+//! using `quickcheck`
+//!
+//! ## Usage
+//!
+//! Print help
+//! ```bash
+//! $ cargo run --bin=quickchecking -- -h
+//! ```
+//!
+//! Run with default values
+//! ```bash
+//! $ cargo run --bin=quickchecking
+//! ```
+//!
+#![deny(missing_docs)]
+extern crate clap;
+extern crate quickchecking;
+
+use clap::{App, Arg};
+use std::path::Path;
+
+// Validate CLI argument input for generation range.
+fn validate_generate_range(v: String) -> Result<(), String> {
+ match v.parse::<usize>() {
+ Ok(_) => Ok(()),
+ Err(_) => Err(String::from(
+ "Generate range could not be converted to a usize.",
+ )),
+ }
+}
+
+// Validate CLI argument input for tests count.
+fn validate_tests_count(v: String) -> Result<(), String> {
+ match v.parse::<usize>() {
+ Ok(_) => Ok(()),
+ Err(_) => Err(String::from(
+ "Tests count could not be converted to a usize.",
+ )),
+ }
+}
+
+// Validate CLI argument input for fuzzed headers output path.
+fn validate_path(v: String) -> Result<(), String> {
+ match Path::new(&v).is_dir() {
+ true => Ok(()),
+ false => Err(String::from("Provided directory path does not exist.")),
+ }
+}
+
+fn main() {
+ let matches = App::new("quickchecking")
+ .version("0.2.0")
+ .about(
+ "Bindgen property tests with quickcheck. \
+ Generate random valid C code and pass it to the \
+ csmith/predicate.py script",
+ )
+ .arg(
+ Arg::with_name("path")
+ .short("p")
+ .long("path")
+ .value_name("PATH")
+ .help(
+ "Optional. Preserve generated headers for inspection, \
+ provide directory path for header output. [default: None] ",
+ )
+ .takes_value(true)
+ .validator(validate_path),
+ )
+ .arg(
+ Arg::with_name("range")
+ .short("r")
+ .long("range")
+ .value_name("RANGE")
+ .help(
+ "Sets the range quickcheck uses during generation. \
+ Corresponds to things like arbitrary usize and \
+ arbitrary vector length. This number doesn't have \
+ to grow much for execution time to increase \
+ significantly.",
+ )
+ .takes_value(true)
+ .default_value("32")
+ .validator(validate_generate_range),
+ )
+ .arg(
+ Arg::with_name("count")
+ .short("c")
+ .long("count")
+ .value_name("COUNT")
+ .help(
+ "Count / number of tests to run. Running a fuzzed \
+ header through the predicate.py script can take a \
+ long time, especially if the generation range is \
+ large. Increase this number if you're willing to \
+ wait a while.",
+ )
+ .takes_value(true)
+ .default_value("2")
+ .validator(validate_tests_count),
+ )
+ .get_matches();
+
+ let output_path: Option<&str> = matches.value_of("path");
+ let generate_range: usize = matches.value_of("range").unwrap().parse::<usize>().unwrap();
+ let tests: usize = matches.value_of("count").unwrap().parse::<usize>().unwrap();
+
+ quickchecking::test_bindgen(generate_range, tests, output_path)
+}
diff --git a/tests/quickchecking/src/fuzzers.rs b/tests/quickchecking/src/fuzzers.rs
new file mode 100644
index 00000000..2876da86
--- /dev/null
+++ b/tests/quickchecking/src/fuzzers.rs
@@ -0,0 +1,637 @@
+use quickcheck::{Arbitrary, Gen, StdGen};
+use std::fmt;
+use rand::thread_rng;
+
+/// BaseTypeC is used in generation of C headers to represent the C language's
+/// primitive types as well as `void*`.
+#[derive(Debug, Clone)]
+pub struct BaseTypeC {
+ /// String representation of C type.
+ pub def: String,
+}
+
+/// TypeQualifierC is used in generation of C headers to represent qualifiers
+/// such as `const`.
+#[derive(Debug, Clone)]
+pub struct TypeQualifierC {
+ /// String representation of C type qualifier.
+ pub def: String,
+}
+
+/// PointerLevelC is used in generation of C headers to represent number of
+/// `*` for pointer types.
+#[derive(Debug, Clone)]
+pub struct PointerLevelC {
+ /// String representation of C declaration's pointer level.
+ pub def: String,
+}
+
+/// ArrayDimensionC is used in generation of C headers to represent number of
+/// `[]` used to define array types.
+#[derive(Debug, Clone)]
+pub struct ArrayDimensionC {
+ /// String representation of C declaration's array dimension.
+ pub def: String,
+}
+
+/// BasicTypeDeclarationC is used in generation of C headers to represent
+/// declarations outside of function pointers that take the form
+/// `BaseTypeC` + `TypeQualifierC` + `PointerLevelC` + `ident_id`.
+#[derive(Debug, Clone)]
+pub struct BasicTypeDeclarationC {
+ /// The declaration's base type, i.e. `int`.
+ pub type_name: BaseTypeC,
+ /// The declaration's type qualifier, i.e. `const`.
+ pub type_qualifier: TypeQualifierC,
+ /// The declaration's pointer level, i.e. `***`.
+ pub pointer_level: PointerLevelC,
+ /// The declaration's array dimension, i.e. [][][].
+ pub array_dimension: ArrayDimensionC,
+ /// The declaration's identifier, i.e. ident_N.
+ pub ident_id: String,
+}
+
+/// StructDeclarationC is used in generation of C headers to represent the
+/// definition of a struct type.
+#[derive(Debug, Clone)]
+pub struct StructDeclarationC {
+ /// The declaration's fields.
+ pub fields: DeclarationListC,
+ /// The declaration's array dimension, i.e. [][][].
+ pub array_dimension: ArrayDimensionC,
+ /// The declaration's identifier, i.e. struct_N.
+ pub ident_id: String,
+}
+
+/// UnionDeclarationC is used in generation of C headers to represent the
+/// definition of a union type.
+#[derive(Debug, Clone)]
+pub struct UnionDeclarationC {
+ /// The declaration's fields.
+ pub fields: DeclarationListC,
+ /// The declaration's array dimension, i.e. [][][].
+ pub array_dimension: ArrayDimensionC,
+ /// The declaration's identifier, i.e. union_N.
+ pub ident_id: String,
+}
+
+/// FunctionPointerDeclarationC is used in generation of C headers to represent
+/// the definition of a function pointer type.
+#[derive(Debug, Clone)]
+pub struct FunctionPointerDeclarationC {
+ /// The function's type qualifier, i.e. `const`.
+ pub type_qualifier: TypeQualifierC,
+ /// The function's return type, i.e. `int`.
+ pub type_name: BaseTypeC,
+ /// The function's pointer level, i.e. `***`.
+ pub pointer_level: PointerLevelC,
+ /// The function's parameters.
+ pub params: ParameterListC,
+ /// The declaration's identifier, i.e. func_ptr_N.
+ pub ident_id: String,
+}
+
+/// FunctionPrototypeC is used in generation of C headers to represent the
+/// definition of a function prototype.
+#[derive(Debug, Clone)]
+pub struct FunctionPrototypeC {
+ /// The function's type qualifier, i.e. `const`.
+ pub type_qualifier: TypeQualifierC,
+ /// The function's return type, i.e. `int`.
+ pub type_name: BaseTypeC,
+ /// The function's pointer level, i.e. `***`.
+ pub pointer_level: PointerLevelC,
+ /// The function's parameters.
+ pub params: ParameterListC,
+ /// The prototype's identifier, i.e. `func_N`.
+ pub ident_id: String,
+}
+
+/// ParameterC is used in generation of C headers to represent the
+/// definition function parameters.
+#[derive(Debug, Clone)]
+pub struct ParameterC {
+ /// The parameter's type qualifier, i.e. `const`.
+ pub type_qualifier: TypeQualifierC,
+ /// The parameter's base type, i.e. `int`.
+ pub type_name: BaseTypeC,
+ /// The parameter's pointer level, i.e. `***`.
+ pub pointer_level: PointerLevelC,
+}
+
+/// ParameterListC is used in generation of C headers to represent a list of
+/// definitions of function parameters.
+#[derive(Debug, Clone)]
+pub struct ParameterListC {
+ /// Parameters that define a C function signature.
+ pub params: Vec<ParameterC>,
+}
+
+/// DeclarationC is used in generation of C headers to represent all supported
+/// C type declarations allowed in the generated header.
+#[derive(Debug, Clone)]
+pub enum DeclarationC {
+ /// Function prototype declaration kind.
+ FunctionDecl(FunctionPrototypeC),
+ /// Function pointer declaration kind.
+ FunctionPtrDecl(FunctionPointerDeclarationC),
+ /// Struct declaration kind.
+ StructDecl(StructDeclarationC),
+ /// Union declaration kind.
+ UnionDecl(UnionDeclarationC),
+ /// Basic type declaration kind.
+ VariableDecl(BasicTypeDeclarationC),
+}
+
+/// DeclarationListC is used in generation of C headers to represent a list of
+/// declarations.
+#[derive(Debug, Clone)]
+pub struct DeclarationListC {
+ /// Grouping of C declarations.
+ pub decls: Vec<DeclarationC>,
+}
+
+/// HeaderC is used in generation of C headers to represent a collection of
+/// declarations.
+#[derive(Clone)]
+pub struct HeaderC {
+ /// The header's declarations.
+ pub def: DeclarationListC,
+}
+
+/// MakeUnique is used in generation of C headers to make declaration
+/// identifiers unique by incorporating the `stamp` parameter into it's name.
+trait MakeUnique {
+ fn make_unique(&mut self, stamp: usize);
+}
+
+/// MakeUnique is used in generation of C headers to make DeclarationC
+/// identifiers unique.
+impl MakeUnique for DeclarationC {
+ fn make_unique(&mut self, stamp: usize) {
+ match *self {
+ DeclarationC::FunctionDecl(ref mut d) => d.make_unique(stamp),
+ DeclarationC::FunctionPtrDecl(ref mut d) => d.make_unique(stamp),
+ DeclarationC::StructDecl(ref mut d) => d.make_unique(stamp),
+ DeclarationC::UnionDecl(ref mut d) => d.make_unique(stamp),
+ DeclarationC::VariableDecl(ref mut d) => d.make_unique(stamp),
+ }
+ }
+}
+
+/// A qucickcheck trait for describing how DeclarationC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for DeclarationC {
+ fn arbitrary<G: Gen>(g: &mut G) -> DeclarationC {
+ match g.gen_range(0, 5) {
+ 0 => DeclarationC::FunctionDecl(FunctionPrototypeC::arbitrary(g)),
+ 1 => DeclarationC::FunctionPtrDecl(FunctionPointerDeclarationC::arbitrary(g)),
+ 2 => DeclarationC::StructDecl(StructDeclarationC::arbitrary(g)),
+ 3 => DeclarationC::UnionDecl(UnionDeclarationC::arbitrary(g)),
+ 4 => DeclarationC::VariableDecl(BasicTypeDeclarationC::arbitrary(g)),
+ _ => unreachable!(),
+ }
+ }
+}
+
+/// Enables to string and format for DeclarationC types.
+impl fmt::Display for DeclarationC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ DeclarationC::FunctionPtrDecl(ref d) => write!(f, "{}", d),
+ DeclarationC::StructDecl(ref d) => write!(f, "{}", d),
+ DeclarationC::UnionDecl(ref d) => write!(f, "{}", d),
+ DeclarationC::VariableDecl(ref d) => write!(f, "{}", d),
+ DeclarationC::FunctionDecl(ref d) => write!(f, "{}", d),
+ }
+ }
+}
+
+/// A qucickcheck trait for describing how DeclarationListC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for DeclarationListC {
+ fn arbitrary<G: Gen>(g: &mut G) -> DeclarationListC {
+ DeclarationListC {
+ decls: Arbitrary::arbitrary(g),
+ }
+ }
+}
+
+/// Enables to string and format for DeclarationListC types.
+impl fmt::Display for DeclarationListC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut display = String::new();
+ for decl in &self.decls {
+ display += &format!("{}", decl);
+ }
+ write!(f, "{}", display)
+ }
+}
+
+/// A qucickcheck trait for describing how BaseTypeC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for BaseTypeC {
+ fn arbitrary<G: Gen>(g: &mut G) -> BaseTypeC {
+ // Special case `long double` until issue #550 is resolved.
+ let base_type = vec![
+ "char",
+ "signed char",
+ "unsigned char",
+ "short",
+ "short int",
+ "signed short",
+ "signed short int",
+ "unsigned short",
+ "unsigned short int",
+ "int",
+ "signed",
+ "signed int",
+ "unsigned",
+ "unsigned int",
+ "long",
+ "long int",
+ "signed long",
+ "signed long int",
+ "unsigned long",
+ "unsigned long int",
+ "long long",
+ "long long int",
+ "signed long long",
+ "signed long long int",
+ "unsigned long long",
+ "unsigned long long int",
+ "float",
+ "double",
+ #[cfg(feature = "long-doubles")]
+ "long double",
+ "void*",
+ ];
+ BaseTypeC {
+ def: String::from(*g.choose(&base_type).unwrap()),
+ }
+ }
+}
+
+/// Enables to string and format for BaseTypeC types,
+impl fmt::Display for BaseTypeC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.def)
+ }
+}
+
+/// A qucickcheck trait for describing how TypeQualifierC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for TypeQualifierC {
+ fn arbitrary<G: Gen>(g: &mut G) -> TypeQualifierC {
+ let qualifier = vec!["const", ""];
+ TypeQualifierC {
+ def: String::from(*g.choose(&qualifier).unwrap()),
+ }
+ }
+}
+
+/// Enables to string and format for TypeQualifierC types.
+impl fmt::Display for TypeQualifierC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.def)
+ }
+}
+
+/// A qucickcheck trait for describing how PointerLevelC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for PointerLevelC {
+ fn arbitrary<G: Gen>(g: &mut G) -> PointerLevelC {
+ PointerLevelC {
+ // 16 is an arbitrary "not too big" number for capping pointer level.
+ def: (0..g.gen_range(0, 16)).map(|_| "*").collect::<String>(),
+ }
+ }
+}
+
+/// Enables to string and format for PointerLevelC types.
+impl fmt::Display for PointerLevelC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.def)
+ }
+}
+
+/// A qucickcheck trait for describing how ArrayDimensionC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for ArrayDimensionC {
+ fn arbitrary<G: Gen>(g: &mut G) -> ArrayDimensionC {
+ // Keep these small, clang complains when they get too big.
+ let dimensions = g.gen_range(0, 5);
+ let mut def = String::new();
+
+ let lower_bound;
+ if cfg!(feature = "zero-sized-arrays") {
+ lower_bound = 0;
+ } else {
+ lower_bound = 1;
+ }
+
+ for _ in 1..dimensions {
+ // 16 is an arbitrary "not too big" number for capping array size.
+ def += &format!("[{}]", g.gen_range(lower_bound, 16));
+ }
+ ArrayDimensionC { def }
+ }
+}
+
+/// Enables to string and format for ArrayDimensionC types.
+impl fmt::Display for ArrayDimensionC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.def)
+ }
+}
+
+/// MakeUnique is used in generation of C headers to make BasicTypeDeclarationC
+/// identifiers unique.
+impl MakeUnique for BasicTypeDeclarationC {
+ fn make_unique(&mut self, stamp: usize) {
+ self.ident_id += &format!("_{}", stamp);
+ }
+}
+
+/// A qucickcheck trait for describing how BasicTypeDeclarationC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for BasicTypeDeclarationC {
+ fn arbitrary<G: Gen>(g: &mut G) -> BasicTypeDeclarationC {
+ BasicTypeDeclarationC {
+ type_qualifier: Arbitrary::arbitrary(g),
+ type_name: Arbitrary::arbitrary(g),
+ pointer_level: Arbitrary::arbitrary(g),
+ array_dimension: Arbitrary::arbitrary(g),
+ ident_id: format!("{}", usize::arbitrary(g)),
+ }
+ }
+}
+
+/// Enables to string and format for BasicTypeDeclarationC types.
+impl fmt::Display for BasicTypeDeclarationC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "{} {} {} ident_{}{};",
+ self.type_qualifier,
+ self.type_name,
+ self.pointer_level,
+ self.ident_id,
+ self.array_dimension
+ )
+ }
+}
+
+/// MakeUnique is used in generation of C headers to make StructDeclarationC
+/// identifiers unique.
+impl MakeUnique for StructDeclarationC {
+ fn make_unique(&mut self, stamp: usize) {
+ self.ident_id += &format!("_{}", stamp);
+ }
+}
+
+/// A qucickcheck trait for describing how StructDeclarationC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for StructDeclarationC {
+ fn arbitrary<G: Gen>(g: &mut G) -> StructDeclarationC {
+ // Reduce generator size as a method of putting a bound on recursion.
+ // When size < 1 the empty list is generated.
+ let reduced_size: usize = (g.size() / 2) as usize + 1;
+ let mut decl_list: DeclarationListC =
+ Arbitrary::arbitrary(&mut StdGen::new(thread_rng(), reduced_size));
+ let mut fields: DeclarationListC = DeclarationListC { decls: vec![] };
+
+ for (i, decl) in decl_list.decls.iter_mut().enumerate() {
+ match *decl {
+ DeclarationC::FunctionDecl(_) => {}
+ ref mut decl => {
+ decl.make_unique(i);
+ fields.decls.push(decl.clone());
+ }
+ }
+ }
+
+ StructDeclarationC {
+ fields,
+ ident_id: format!("{}", usize::arbitrary(g)),
+ array_dimension: Arbitrary::arbitrary(g),
+ }
+ }
+}
+
+/// Enables to string and format for StructDeclarationC types.
+impl fmt::Display for StructDeclarationC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "struct {{ {} }} struct_{}{};",
+ self.fields,
+ self.ident_id,
+ self.array_dimension
+ )
+ }
+}
+
+/// MakeUnique is used in generation of C headers to make UnionDeclarationC
+/// identifiers unique.
+impl MakeUnique for UnionDeclarationC {
+ fn make_unique(&mut self, stamp: usize) {
+ self.ident_id += &format!("_{}", stamp);
+ }
+}
+
+/// A qucickcheck trait for describing how UnionDeclarationC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for UnionDeclarationC {
+ fn arbitrary<G: Gen>(g: &mut G) -> UnionDeclarationC {
+ // Reduce generator size as a method of putting a bound on recursion.
+ // When size < 1 the empty list is generated.
+ let reduced_size: usize = (g.size() / 2) as usize + 1;
+ let mut decl_list: DeclarationListC =
+ Arbitrary::arbitrary(&mut StdGen::new(thread_rng(), reduced_size));
+ let mut fields: DeclarationListC = DeclarationListC { decls: vec![] };
+
+ for (i, decl) in decl_list.decls.iter_mut().enumerate() {
+ match *decl {
+ DeclarationC::FunctionDecl(_) => {}
+ ref mut decl => {
+ decl.make_unique(i);
+ fields.decls.push(decl.clone());
+ }
+ }
+ }
+
+ UnionDeclarationC {
+ fields,
+ ident_id: format!("{}", usize::arbitrary(g)),
+ array_dimension: Arbitrary::arbitrary(g),
+ }
+ }
+}
+
+/// Enables to string and format for UnionDeclarationC types.
+impl fmt::Display for UnionDeclarationC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "union {{ {} }} union_{}{};",
+ self.fields,
+ self.ident_id,
+ self.array_dimension
+ )
+ }
+}
+
+/// MakeUnique is used in generation of C headers to make
+/// FunctionPointerDeclarationC identifiers unique.
+impl MakeUnique for FunctionPointerDeclarationC {
+ fn make_unique(&mut self, stamp: usize) {
+ self.ident_id += &format!("_{}", stamp);
+ }
+}
+
+/// A qucickcheck trait for describing how FunctionPointerDeclarationC types can
+/// be randomly generated and shrunk.
+impl Arbitrary for FunctionPointerDeclarationC {
+ fn arbitrary<G: Gen>(g: &mut G) -> FunctionPointerDeclarationC {
+ FunctionPointerDeclarationC {
+ type_qualifier: Arbitrary::arbitrary(g),
+ type_name: Arbitrary::arbitrary(g),
+ pointer_level: Arbitrary::arbitrary(g),
+ params: Arbitrary::arbitrary(g),
+ ident_id: format!("{}", usize::arbitrary(g)),
+ }
+ }
+}
+
+/// Enables to string and format for FunctionPointerDeclarationC types.
+impl fmt::Display for FunctionPointerDeclarationC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "{} {} {} (*func_ptr_{})({});",
+ self.type_qualifier,
+ self.type_name,
+ self.pointer_level,
+ self.ident_id,
+ self.params
+ )
+ }
+}
+
+/// MakeUnique is used in generation of C headers to make FunctionPrototypeC
+/// identifiers unique.
+impl MakeUnique for FunctionPrototypeC {
+ fn make_unique(&mut self, stamp: usize) {
+ self.ident_id += &format!("_{}", stamp);
+ }
+}
+
+/// A qucickcheck trait for describing how FunctionPrototypeC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for FunctionPrototypeC {
+ fn arbitrary<G: Gen>(g: &mut G) -> FunctionPrototypeC {
+ FunctionPrototypeC {
+ type_qualifier: Arbitrary::arbitrary(g),
+ type_name: Arbitrary::arbitrary(g),
+ pointer_level: Arbitrary::arbitrary(g),
+ params: Arbitrary::arbitrary(g),
+ ident_id: format!("{}", usize::arbitrary(g)),
+ }
+ }
+}
+
+/// Enables to string and format for FunctionPrototypeC types.
+impl fmt::Display for FunctionPrototypeC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "{} {} {} func_{}({});",
+ self.type_qualifier,
+ self.type_name,
+ self.pointer_level,
+ self.ident_id,
+ self.params
+ )
+ }
+}
+
+/// A qucickcheck trait for describing how ParameterC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for ParameterC {
+ fn arbitrary<G: Gen>(g: &mut G) -> ParameterC {
+ ParameterC {
+ type_qualifier: Arbitrary::arbitrary(g),
+ type_name: Arbitrary::arbitrary(g),
+ pointer_level: Arbitrary::arbitrary(g),
+ }
+ }
+}
+
+/// Enables to string and format for ParameterC types.
+impl fmt::Display for ParameterC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(
+ f,
+ "{} {} {}",
+ self.type_qualifier,
+ self.type_name,
+ self.pointer_level
+ )
+ }
+}
+
+/// A qucickcheck trait for describing how ParameterListC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for ParameterListC {
+ fn arbitrary<G: Gen>(g: &mut G) -> ParameterListC {
+ ParameterListC {
+ params: Arbitrary::arbitrary(g),
+ }
+ }
+}
+
+/// Enables to string and format for ParameterListC types.
+impl fmt::Display for ParameterListC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut display = String::new();
+ for (i, p) in self.params.iter().enumerate() {
+ match i {
+ 0 => display += &format!("{}", p),
+ _ => display += &format!(",{}", p),
+ }
+ }
+ write!(f, "{}", display)
+ }
+}
+
+/// A qucickcheck trait for describing how HeaderC types can be
+/// randomly generated and shrunk.
+impl Arbitrary for HeaderC {
+ fn arbitrary<G: Gen>(g: &mut G) -> HeaderC {
+ let mut decl_list: DeclarationListC = Arbitrary::arbitrary(g);
+ for (i, decl) in decl_list.decls.iter_mut().enumerate() {
+ decl.make_unique(i);
+ }
+ HeaderC { def: decl_list }
+ }
+}
+
+/// Enables to string and format for HeaderC types.
+impl fmt::Display for HeaderC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut display = String::new();
+ for decl in &self.def.decls {
+ display += &format!("{}", decl);
+ }
+ write!(f, "{}", display)
+ }
+}
+
+/// Use Display trait for Debug so that any failing property tests report
+/// generated C code rather than the data structures that contain it.
+impl fmt::Debug for HeaderC {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self)
+ }
+}
diff --git a/tests/quickchecking/src/lib.rs b/tests/quickchecking/src/lib.rs
new file mode 100644
index 00000000..d8633dfb
--- /dev/null
+++ b/tests/quickchecking/src/lib.rs
@@ -0,0 +1,126 @@
+//! A library to generate __fuzzed__ C headers for use with `quickcheck`
+//!
+//! ## Example
+//!
+//! ```rust
+//! extern crate quickcheck;
+//! extern crate quickchecking;
+//! extern crate rand;
+//! use quickcheck::{Arbitrary, Gen, StdGen};
+//! use quickchecking::fuzzers;
+//! use rand::thread_rng;
+//!
+//! fn main() {
+//! let generate_range: usize = 10; // Determines things like the length of
+//! // arbitrary vectors generated.
+//! let header = fuzzers::HeaderC::arbitrary(
+//! &mut StdGen::new(thread_rng(), generate_range));
+//! println!("{}", header);
+//! }
+//! ```
+//!
+#![deny(missing_docs)]
+#[macro_use]
+extern crate lazy_static;
+extern crate quickcheck;
+extern crate rand;
+extern crate tempdir;
+
+use std::sync::Mutex;
+use quickcheck::{QuickCheck, StdGen, TestResult};
+use std::fs::File;
+use std::io::Write;
+use tempdir::TempDir;
+use std::process::{Command, Output};
+use std::path::PathBuf;
+use std::error::Error;
+use rand::thread_rng;
+
+/// Contains definitions of and impls for types used to fuzz C declarations.
+pub mod fuzzers;
+
+// Global singleton, manages context across tests. For now that context is
+// only the output_path for inspecting fuzzed headers (if specified).
+struct Context {
+ output_path: Option<String>,
+}
+
+// Initialize global context.
+lazy_static! {
+ static ref CONTEXT: Mutex<Context> = Mutex::new(Context { output_path: None });
+}
+
+// Passes fuzzed header to the `csmith-fuzzing/predicate.py` script, returns
+// output of the associated command.
+fn run_predicate_script(header: fuzzers::HeaderC) -> Result<Output, Box<Error>> {
+ let dir = TempDir::new("bindgen_prop")?;
+ let header_path = dir.path().join("prop_test.h");
+
+ let mut header_file = File::create(&header_path)?;
+ header_file.write_all(header.to_string().as_bytes())?;
+ header_file.sync_all()?;
+
+ let header_path_string;
+ match header_path.into_os_string().into_string() {
+ Ok(s) => header_path_string = s,
+ Err(_) => return Err(From::from("error converting path into String")),
+ }
+
+ let mut predicate_script_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
+ predicate_script_path.push("../../csmith-fuzzing/predicate.py");
+
+ let predicate_script_path_string;
+ match predicate_script_path.into_os_string().into_string() {
+ Ok(s) => predicate_script_path_string = s,
+ Err(_) => return Err(From::from("error converting path into String")),
+ }
+
+ // Copy generated temp files to output_path directory for inspection.
+ // If `None`, output path not specified, don't copy.
+ match CONTEXT.lock().unwrap().output_path {
+ Some(ref path) => {
+ Command::new("cp")
+ .arg("-a")
+ .arg(&dir.path().to_str().unwrap())
+ .arg(&path)
+ .output()?;
+ }
+ None => {}
+ }
+
+ Ok(Command::new(&predicate_script_path_string)
+ .arg(&header_path_string)
+ .output()?)
+}
+
+// Generatable property. Pass generated headers off to run through the
+// `csmith-fuzzing/predicate.py` script. Success is measured by the success
+// status of that command.
+fn bindgen_prop(header: fuzzers::HeaderC) -> TestResult {
+ match run_predicate_script(header) {
+ Ok(o) => return TestResult::from_bool(o.status.success()),
+ Err(e) => {
+ println!("{:?}", e);
+ return TestResult::from_bool(false);
+ }
+ }
+}
+
+/// Instantiate a Quickcheck object and use it to run property tests using
+/// fuzzed C headers generated with types defined in the `fuzzers` module.
+/// Success/Failure is dictated by the result of passing the fuzzed headers
+/// to the `csmith-fuzzing/predicate.py` script.
+pub fn test_bindgen(generate_range: usize, tests: usize, output_path: Option<&str>) {
+ match output_path {
+ Some(path) => {
+ CONTEXT.lock().unwrap().output_path =
+ Some(String::from(PathBuf::from(path).to_str().unwrap()));
+ }
+ None => {} // Path not specified, don't provide output.
+ }
+
+ QuickCheck::new()
+ .tests(tests)
+ .gen(StdGen::new(thread_rng(), generate_range))
+ .quickcheck(bindgen_prop as fn(fuzzers::HeaderC) -> TestResult)
+}
diff --git a/tests/quickchecking/tests/fuzzed-c-headers.rs b/tests/quickchecking/tests/fuzzed-c-headers.rs
new file mode 100644
index 00000000..6b58d24b
--- /dev/null
+++ b/tests/quickchecking/tests/fuzzed-c-headers.rs
@@ -0,0 +1,95 @@
+
+extern crate quickcheck;
+extern crate quickchecking;
+extern crate rand;
+
+use quickchecking::fuzzers::{ArrayDimensionC, BaseTypeC, BasicTypeDeclarationC, DeclarationC,
+ DeclarationListC, FunctionPointerDeclarationC, FunctionPrototypeC,
+ HeaderC, ParameterC, ParameterListC, PointerLevelC,
+ StructDeclarationC, TypeQualifierC, UnionDeclarationC};
+use quickcheck::{Arbitrary, StdGen};
+use rand::thread_rng;
+
+#[test]
+fn test_declaraion_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: DeclarationC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_declaraion_list_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: DeclarationListC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_base_type_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: BaseTypeC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_type_qualifier_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: TypeQualifierC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_pointer_level_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: PointerLevelC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_array_dimension_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: ArrayDimensionC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_basic_type_declaration_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: BasicTypeDeclarationC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_struct_declaration_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: StructDeclarationC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_union_declaration_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: UnionDeclarationC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_function_pointer_declaration_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: FunctionPointerDeclarationC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_function_prototype_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: FunctionPrototypeC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_parameter_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: ParameterC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_parameter_list_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: ParameterListC = Arbitrary::arbitrary(gen);
+}
+
+#[test]
+fn test_header_c_does_not_panic() {
+ let ref mut gen = StdGen::new(thread_rng(), 50);
+ let _: HeaderC = Arbitrary::arbitrary(gen);
+}
diff --git a/tests/rustfmt.toml b/tests/rustfmt.toml
index a9e57337..80a6663b 100644
--- a/tests/rustfmt.toml
+++ b/tests/rustfmt.toml
@@ -1 +1 @@
-error_on_line_overflow_comments = false
+# Intentionally left blank.